根据一条线的2个点计算4个正方形点

时间:2014-04-22 00:09:33

标签: java geometry line point trigonometry

我不是这个网站的新手,因为我之前使用过它,但这是我第一次发帖提问:D

首先,我使用Y轴上下。

我试图计算三维空间中4个正方形的点,该点与两个给定点形成的直线垂直。这个方块必须是:

  1. 垂直于由两个给定点定义的直线
  2. 厚度(或宽度/长度)1
  3. 对齐,使两边始终垂直于Y轴
  4. 我自己尝试过编码,我有点成功,但这并不是我想要的。这是我所拥有的代码片段:

    注意:Vert是一个将坐标存储在3个变量x,y和z中的类。 FourVert是一个存储4个Verts的类,构造函数是我想要开发的。两个Vert参数是给定点,浮点t是输出4点之间所需的厚度或间隔。 Add是一个函数,它将给定的Vert坐标值作为偏移添加到FourVert的所有4个点。这仅用于重新定位右侧位置的第一个Vert。我可能有奇怪的命名约定,但我以我理解的方式编写它。

    编辑:根据评论中的要求添加了评论。 (没有双关语)

    public FourVert(Vert V1, Vert V2, float t)
    {
        float dx = V2.x - V1.x; //Position our points at the origin to convert into
        float dy = V2.y - V1.y; //polar coordinates using Math.atan2();
        float dz = V2.z - V1.z;
        float d = (float) Math.sqrt(dx*dx+dz*dz); //Get the lateral distance to use
        float axz = (float) -Math.atan2(dx, dz);  //in relation with the y value to
        float ady = (float) Math.atan2(d, dy);    //calculate the altitude angle
        float px = (float) (Math.cos(axz) * t);
        float py = (float) (Math.cos(ady + 1.570796327) * t); //add half PI
        float ny = (float) (Math.cos(ady - 1.570796327) * t);
        float pz = (float) (Math.sin(axz) * t);
        v1 = new Vert(px, py, pz);   //Use the calculated values to produce 4 points
        v2 = new Vert(-px, py, -pz); //v1, v2, v3, and v4 are our Vert fields of the
        v3 = new Vert(-px, ny, -pz); //FourVert class
        v4 = new Vert(px, ny, pz);
        add(V1); //take our FourVert back to where we want it, not on the origin.
    }
    

    我已经完成了渲染,并且我知道它运行良好,因为我已经测试过它。

    这里有效的是方位角值,它们功能完美(横向移动)。垂直移动或高度或“音高”无法正常工作。我已经尝试了很多其他方法来做到这一点无济于事。

    我认为问题/不起作用的部分在这里:

        float py = (float) (Math.cos(ady + 1.570796327) * t);
        float ny = (float) (Math.cos(ady - 1.570796327) * t);
    

    这对我来说是很多三角函数,我让自己疯了。提前谢谢。

    我的代码可能看起来效率低下,但之后会进行优化,我需要先让它运行然后才能优化我想要的。

1 个答案:

答案 0 :(得分:0)

我会避免所有那些三角学。对于其中一个边缘方向,您需要一个同时垂直于 V 1 - V 2的矢量 Y 轴。交叉积可用于获得垂直于两个给定的矢量。所以你计算它是这样的:

[ 0 ]   [ x2 − x1 ]   [ z2 − z1 ]   [  dz ]
[ 1 ] × [ y2 - y1 ] = [    0    ] = [  0  ] = w₁
[ 0 ]   [ z2 - z1 ]   [ x1 − x2 ]   [ −dx ]

对于第二个边缘方向,您希望垂直于第一个边缘方向,并且还垂直于 V 1 - V 2 。所以同样的故事:

[  dz ]   [ dx ]   [    dx*dy    ]    [ ex ]
[  0  ] × [ dy ] = [ − dx² − dz² ] =: [ ey ] = w₂
[ −dx ]   [ dz ]   [    dz*dy    ]    [ ez ]

你必须规范化这些向量以确保它们的长度为1,然后你就完成了。在。事实上我将它们标准化为长度½因为那时你可以使用±该向量来描述在原点周围对称的位置,也就是你自己的代码所做的那样。对于角落,您需要± w 1 ± w 2 ,这提供了四种可能的符号组合。

public FourVert(Vert V1, Vert V2, float t)
{
    float dx = V2.x - V1.x;
    float dy = V2.y - V1.y;
    float dz = V2.z - V1.z;
    float ex = dx*dz;
    float ey = -dx*dx-dz*dz;
    float ez = dz*dy;
    float d = (float)(t/(2*Math.sqrt(dx*dx+dz*dz)));
    float e = (float)(t/(2*Math.sqrt(ex*ex+ey*ey+ez*ez)));
    dx *= d; dz *= d;
    ex *= e; ey *= e; ez *= e;
    v1 = new Vert( dz+ex,  ey, -dx+ez);
    v2 = new Vert( dz-ex, -ey, -dx-ez);
    v3 = new Vert(-dz-ex, -ey,  dx-ez);
    v4 = new Vert(-dz+ex,  ey,  dx+ez);
    add(V1);
}

你现在可能不再需要这个,但为了完整起见:而不是

float py = (float) (Math.cos(ady + 1.570796327) * t);
float ny = (float) (Math.cos(ady - 1.570796327) * t);

我会写

float py = (float) (-Math.sin(ady) * t);
float ny = (float) ( Math.sin(ady) * t);

这利用了sin和cos相差π/ 2的事实。