【问题标题】:Determine affine transformation that transform one plane into a parallel plane to another确定将一个平面转换为与另一个平面平行的仿射变换
【发布时间】:2023-03-17 18:03:01
【问题描述】:

如何确定将一个平面 (plane1) 转换为与另一个 (plane2) 平行的平面的 CGAL 仿射变换 (Aff_transformation_3)?

假设我有两个对象平面:

Plane_3  pl1;
Plane_3  pl2;

而且它们不是平行的,这种仿射变换如何确定?

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

我咨询了这个问题和你的答案:CGAL: Transformation Matrix for Rotation given two lines/vectors/directions,但我不知道它对我有什么帮助。我有两个平面,但是是 3d 维度的。

谢谢。

【问题讨论】:

  • 是实际代码问题还是理论问题?
  • 原来是代码问题。
  • 我找到了一个奇怪的解决方案来解决我的问题。由于答案被禁用,我如何发布它?
  • 我已请求重新打开该问题。
  • @GilbertoCuba 您现在可以发布您的自我回答吗?这个问题似乎又重新开始了。

标签: c++ cgal affinetransform


【解决方案1】:

我不知道 2d 仿射变换 (Aff_transformation_2) 如何帮助我应用 3d 仿射变换 (Aff_transformation_3)。

但是,我找到了问题的解决方案。这可能是我希望对某人有所帮助的代码。

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);
}

然后,我可以像这样使用那里:

RAxisAngle aa = axis_angle_from_planes(plane1, plane2);
Transform3 t3 = axis_angle_to_matrix(aa);

Plane2 new_transform_plane = plane1.transform(t3);

或者可能是这个平面的一个点:

Point3 new_transform_point = point_of_plane1.transform(t3);

感谢您让我有机会发布我的小解决方案。

【讨论】:

  • 感谢吉尔伯托分享您的解决方案。我赞成你的回答。
猜你喜欢
  • 2012-10-10
  • 2017-01-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-25
  • 1970-01-01
相关资源
最近更新 更多