【问题标题】:Plotting an Ellipse in 3D在 3D 中绘制椭圆
【发布时间】:2012-08-29 10:45:30
【问题描述】:

不久前,我在 3D 空间中绘制椭圆时遇到了问题。我的解决方案似乎有效,并以我需要的方式(当时)旋转了东西。我的解决方案几乎完美。它将椭圆旋转到正确的方向......但是,椭圆的起点和终点(在图片中由青色和红色十字表示)始终未正确对齐。这里有一些图片来显示正在发生的事情以及我需要发生的事情。

如您所见,第一张图片显示了仅在 y 轴上发生旋转时的结果,青色十字位于脚部,红色位于椭圆的另一端。然而,第二张图片的椭圆方向正确,但十字架似乎没有出现在正确的位置。 (它们应该在黑线连接椭圆的点上。

目前的代码是这样的。

public static void DrawEllipse(Vector3 p1, Vector3 p2, float height, Vector3 up)
{
    Quaternion quat = Quaternion.identity;
    int halfPoints = 25;
    int totalPoints = halfPoints*2;
    Vector3[] points1 = new Vector3[halfPoints];
    Vector3[] points2 = new Vector3[halfPoints];
    Vector3 midPoint = (p1 + ((p2 - p1)) * 0.5f);
    Vector3 tmp = Vector3.zero;

    quat *= Quaternion.LookRotation(Vector3.Cross(up,p2-p1));

    for (int i = 0; i < totalPoints; i++)
    {
       // build the coordinates in arbitrary space.
       tmp = Vector3.zero;
       tmp.x = Mathf.Cos(((float)i / totalPoints) * (Mathf.PI * 2)) * (Vector3.Distance(p1, p2) * 0.5f);
       tmp.y = Mathf.Sin(((float)i / totalPoints) * (Mathf.PI * 2)) * height;

       // modify the point for correct orientation.
       tmp = (quat * tmp);

       // push to the arrays (split to show outward and return halves)
       if (i < halfPoints)
         points1[i] = tmp + midPoint;
       else
         points2[i - halfPoints] = tmp + midPoint;
    }
    DrawPath(points1, Color.cyan, false);
    DrawPath(points2, Color.red, false);
    Debug.DrawLine(p1, p2, Color.black);
    DrawCross(points1[0], 0.2f, Color.cyan);
    DrawCross(points2[0], 0.2f, Color.red);
}

毫无疑问,这是一个愚蠢的问题,我错过了额外的旋转,或者我在旋转之前错过了对椭圆生成的调整,但我一直在绕圈跑现在是时候问任何可能更了解的人了。

【问题讨论】:

  • 我将您的解决方案移至社区 wiki 答案。

标签: c# 3d path plot ellipse


【解决方案1】:

OP 的解决方案。

现在解决方案似乎很明显,简化定向过程。所以我调整了坐标生成以强制在 z/y 平面中生成椭圆,通过此修改在 0,0,0 处生成第一个点,方向变为具有指定向上向量的简单 LookRotation,然后是偏移以将其放置在正确的位置。 (有时您只需要从代码中休息一下)这可能只是一种解决方案,因此如果有人有更好的想法,请随时发布它们,但这对我现在有用。

这是可以正常工作的新代码

public static void DrawEllipse(Vector3 p1, Vector3 p2, float height, Vector3 up)
{
    Quaternion quat = Quaternion.identity;
    int halfPoints = 25;
    int totalPoints = halfPoints*2;
    Vector3[] points1 = new Vector3[halfPoints];
    Vector3[] points2 = new Vector3[halfPoints];
    Vector3 midPoint = (p1 + ((p2 - p1)) * 0.5f);
    Vector3 tmp = Vector3.zero;
    Vector3 firstPoint = Vector3.zero;
    quat *= Quaternion.LookRotation(p2-p1, up);

    for (int i = 0; i < totalPoints; i++)
    {
        tmp = Vector3.zero;

        // build the coordinates in arbitrary space.
        tmp.z = -Mathf.Cos(((float)i / totalPoints) * (Mathf.PI * 2)) * (Vector3.Distance(p1, p2) * 0.5f);
        tmp.y = Mathf.Sin(((float)i / totalPoints) * (Mathf.PI * 2)) * height;

        if (i == 0) firstPoint = tmp;
        tmp -= firstPoint;
        // modify the point for correct orientation.
        tmp = (quat * tmp);

        // push to the arrays (split to show outward and return halves)
        if (i < halfPoints)
        {
            points1[i] = tmp + p1;
        }
        else
        {
            points2[i - halfPoints] = tmp + p1;
        }
    }

    //draw the results.
    DrawPath(points1, Color.cyan, false);
    DrawPath(points2, Color.red, false);
    Debug.DrawLine(p1, p2, Color.black);
    DrawCross(points1[0], 0.2f, Color.cyan);
    DrawCross(points2[0], 0.2f, Color.red);
}

【讨论】: