Search code examples
c++cgalaffinetransform

Determine affine transformation that transform one plane into a parallel plane to another


How i can determine the CGAL affine transformation (Aff_transformation_3) that transform one plane (plane1) into a parallel plane to another (plane2)?

Suppose that i have two object planes:

Plane_3  pl1;
Plane_3  pl2;

and they are not parallels, how determine this kind of affine transformation?

Aff_transformation_3 t3 = ??? (pl1, pl2);

I consulted this question and your answer: CGAL: Transformation Matrix for Rotation given two lines/vectors/directions, but i don't know how it may helpme. I have two planes, but in 3d dimensions.

Thanks.


Solution

  • I don't know how a 2d affine transformation (Aff_transformation_2) may helpme to apply a 3d affine transformation (Aff_transformation_3).

    However, i found the solution to my question. This is may bit code that i hope to help someone.

    typedef CGAL::Cartesian<double>         KC;
    
    typedef KC::Line_3                      Line3;
    typedef KC::Vector_3                    Vector3;
    typedef KC::Plane_3                     Plane3;
    typedef CGAL::Aff_transformation_3<KC>  Transform3;
    
    // forwards
    struct axis_angle;
    
    typedef boost::shared_ptr<axis_angle>   RAxisAngle;
    
    struct axis_angle
    {
        axis_angle()
        {
            angle = 0;
            axis = Vector3(0.0, 0.0, 0.0);
        }
    
        double  angle;
        Vector3 axis;
    };
    
    Vector3 normalize(const Vector3 &v)
    {
        ldouble len = ::sqrt(v.squared_length());
    
        if (len == 0.0)
            return v;
    
        return v / len;
    }
    
    // return the angle and axis from two planes that there are not parallels
    RAxisAngle axis_angle_from_planes(const Plane3 &pln1, const Plane3 &pln2)
    {
        RAxisAngle result = RAxisAngle(new axis_angle());
    
        Vector3 norm1 = pln1.orthogonal_vector();
        Vector3 norm2 = pln2.orthogonal_vector();
    
        double dot_r = norm1 * norm2;
        double len_r = ::sqrt(norm1.squared_length() * norm2.squared_length());
    
        if (len_r)
            result->angle = ::acos(dot_r / len_r);
        else
            result->angle = 0.0;
    
        Line3 l1;
        CGAL::Object obj_cgal = CGAL::intersection(pln1, pln2);
        if (CGAL::assign(l1, obj_cgal))
        {
            result->axis = normalize(l1.to_vector());
        }
        else
        {
            // when planes are parallels, then use some basic axis
            result->axis = Vector3(1.0, 0.0, 0.0);
        }
    
        return result;
    }
    
    // return a CGAL affine transformation that is builded from a 3x3 matrix
    // this transformation is for rotate an object from axis and angle
    // http://en.wikipedia.org/wiki/Transformation_matrix
    // http://en.wikipedia.org/wiki/Rotation_matrix
    // http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToMatrix/index.htm
    Transform3 axis_angle_to_matrix(const RAxisAngle &aa)
    {
        double tmp1, tmp2;
    
        double c = ::cos(aa->angle);
        double s = ::sin(aa->angle);
        double t = 1.0 - c;
    
        double m00 = c + aa->axis.x() * aa->axis.x() * t;
        double m11 = c + aa->axis.y() * aa->axis.y() * t;
        double m22 = c + aa->axis.z() * aa->axis.z() * t;
    
        tmp1 = aa->axis.x() * aa->axis.y() * t;
        tmp2 = aa->axis.z() * s;
        double m10 = tmp1 + tmp2;
        double m01 = tmp1 - tmp2;
    
        tmp1 = aa->axis.x() * aa->axis.z() * t;
        tmp2 = aa->axis.y() * s;
        double m20 = tmp1 - tmp2;
        double m02 = tmp1 + tmp2;
    
        tmp1 = aa->axis.y() * aa->axis.z() * t;
        tmp2 = aa->axis.x() * s;
        double m21 = tmp1 + tmp2;
        double m12 = tmp1 - tmp2;
    
        return Transform3(m00, m01, m02, m10, m11, m12, m20, m21, m22);
    }
    

    Then, i can use there as this:

    RAxisAngle aa = axis_angle_from_planes(plane1, plane2);
    Transform3 t3 = axis_angle_to_matrix(aa);
    
    Plane2 new_transform_plane = plane1.transform(t3);
    

    or maybe a point of this plane:

    Point3 new_transform_point = point_of_plane1.transform(t3);
    

    Thanks for giveme the posibility to post my little solution.