C++ 在圆柱体表面上找到距离c+中给定直线最近的点+;

C++ 在圆柱体表面上找到距离c+中给定直线最近的点+;,c++,geometry,intersection,C++,Geometry,Intersection,我需要一个函数,可以找到圆柱体表面上离给定直线最近的点。假设圆柱体沿z轴({0,0,0})居中,由半径R和半长z定义,(无限)线由两个3D点A(x1,x2)和B(y1,y2)定义。计算圆柱体表面上最靠近这条线的点的最佳方法是什么 考虑3D-z轴上的斜线和你的线 在它们之间建立最短的线(这是两条线的基础) 此计算的数学在“最短线”部分中进行了描述,并给出了实现示例 如果z轴上的点S(最短直线与z轴相交处)位于圆柱体外部,则最近的点位于圆柱体顶部或底部的圆周上(使用下面描述的方向向量和零z分量) 否

我需要一个函数,可以找到圆柱体表面上离给定直线最近的点。假设圆柱体沿z轴({0,0,0})居中,由半径R和半长z定义,(无限)线由两个3D点A(x1,x2)和B(y1,y2)定义。计算圆柱体表面上最靠近这条线的点的最佳方法是什么

考虑3D-z轴上的斜线和你的线

在它们之间建立最短的线(这是两条线的基础)

此计算的数学在“最短线”部分中进行了描述,并给出了实现示例

如果z轴上的点S(最短直线与z轴相交处)位于圆柱体外部,则最近的点位于圆柱体顶部或底部的圆周上(使用下面描述的方向向量和零z分量)

否则,计算最短直线方向的单位矢量,将其乘以圆柱体半径,再加上点S

同时检查直线与圆柱体相交时距离

见上图。这个想法是:

1-因为圆柱体在Z轴上,所以我们可以在上面投影所有东西 (X,Y)平面,所以我们可以在二维中工作。例如:A(-2,1,10) 变为(-2,1)。此外,圆柱体被视为一个圆

让我们调用(D)经过A和B的无限线,以及(C)经过A和B的无限线 圆(在2D中表示圆柱体)

我们画一个三角形,由三个点组成:a,B和物体的中心 圆(C)(作为原点(0,0)), 如图所示

3-设(L)为穿过(C)中心并垂直的线 如图所示

4-最近的点将是(C)和(L)的交点

现在所有这些都可以通过简单的数学方程来完成

首先是一些定义:

ax+by+c=0:是(X,Y)平面上二维直线的方程

在直线(D)上有两个点A和B,我们可以计算(D)的方向向量Vd

Vd(B.x-A.x,B.y-A.y)

利用这个方向向量,我们可以计算(D)的方程(ax+by+c)

a=Vd.y
b=-Vd.x
c=Vd.xA.y-A.xVd.y

用这个方程我们可以计算(D)的法向量Vn

Vn(a,b)

将这些公式应用于您的问题:

1-我们计算通过A和B的无限直线(D)的方向向量Vd。

2-从Vd我们得到(D)

3-从方程中我们得到Vn

4-因为Vn是从(D)指向(C),我们必须通过将每个坐标乘以(-1)来翻转它。所以我们创建了一个新的方向向量:Vd2(-Vn.x,-Vn.y)

5-现在Vd2是(L)的方向向量,它是图中的红线。

6-现在我们只需要得到Vd2后面圆(C)(圆柱)上的点,这将是圆表面上最接近直线(D)的最近点。
为了做到这一点,我们将Vd2标准化,并将其乘以圆(C)半径。我们将得到最近点的X和Y坐标:X=Vd.normalized*(C).radius和Y=Vd.normalized*(C).radius

7-现在你得到了仅在2d中放置的最近点,我们称之为点J。因此你得到了J的x和y坐标。
要得到z坐标,你用J的x和y替换线3D方程中的x和y,你求解它并得到J的z坐标

下面的代码是用C#编写的,并在Unity 3D中进行了可视化测试。在理解上面写的东西之后,C++应该是简单的。 注:此处Vector2还用于保存二维点的坐标,而不仅仅是二维向量。它只是一个具有两个属性的类:intx和inty。droite在法语中是line的意思

    public Transform A, B ;
    public Transform cylinder ;
    public Transform closest ;

    Vector3 pointA ;
    Vector3 pointB ;

    Vector2 a, b ;
    Vector2 vd, vn ;

    Droite d ;
    Cylinder c ;

    Vector2 inter;

    public void Start () {
        c = new Cylinder (0.5f, 10);
    }

    public void Update () {
        pointA = A.transform.localPosition;
        pointB = B.transform.localPosition;

        a = (Vector2) pointA;
        b = (Vector2) pointB;
        vd = b-a;

        d = new Droite (pointA, vd);
        d.cal_euqation ();

        Vector3 result = closest_point_on_cylinder (d,c);

        closest.transform.localPosition = result;

    }

    public Vector2 closest_point_on_cylinder (Droite d, Cylinder c){
        Droite d2= new Droite (Vector2.zero, d.vn);
        return Vector2.one * (-d2.vd.normalized) * c.r;
    }


}

public class Droite {

    public float a,b,c;
    public Vector2 pointA, vd, vn;

    public Droite (Vector2 _pointA, Vector2 _vd){
        pointA = _pointA;
        vd = _vd ;
    }

    public void cal_euqation () {
        a = vd.y;
        b = -vd.x;
        c = (vd.x*pointA.y - pointA.x*vd.y);

        vn = new Vector2 (a,b);
    }

    public float getX (float y){
        return -(b*y + c) / a ;
    }

}

public class Cylinder {

    public float x,y,h,r; // s  y  height  radius

    public Cylinder (float _r, float _h){
        r = _r ;
        h = _h;
    }

}

如果你不知道如何找到最近的点,那么就不是问这个问题的地方。如果你知道如何,并且你在执行方面有问题,那么展示你的尝试和问题,这不是C++;这是一般几何。比C++更重要的是数学问题。嗨,ELA,谢谢你的回答,你能详细说明一下如何获得Z分量吗?谢谢1