// triangle "edges"
const Vector3d t = p2-p1;
const Vector3d u = p3-p1;
const Vector3d v = p3-p2;
// triangle normal
const Vector3d w = t.crossProduct(u);
const double wsl = w.getSqrLength();
if (wsl<10e-14) return false; // area of the triangle is too small (you may additionally check the points for colinearity if you are paranoid)
// helpers
const double iwsl2 = 1.0 / (2.0*wsl);
const double tt = t*t;
const double uu = u*u;
// result circle
Vector3d circCenter = p1 + (u*tt*(u*v) - t*uu*(t*v)) * iwsl2;
double circRadius = sqrt(tt * uu * (v*v) * iwsl2*0.5);
Vector3d circAxis = w / sqrt(wsl);
// find orthogonal vector to the circle axis
const Vector3d an = circAxis.getNormalized();
const Vector3d ao = Vector3d(4.0+an[0], 4.0+an[0]+an[1], 4.0+an[0]+an[1]+an[2]).crossProduct(an).getNormalized();
// 4x4 rotation matrix around the circle axis
const int steps = 360; // maybe adjust according to circle size on screen
Matrix4d R = makeRotMatrix4d(circCenter, circAxis, 2.0*M_PI/double(steps));
// one point on the circle
Vector3d cp = circCenter + ao*circRadius;
// rotate point on the circle
for (int i=0; i<steps; ++i)
{
circlePoints.push_back(cp);
cp = transformPoint(cp, R); // apply the matrix
}
// triangle "edges"
var t = p2 - p1;
var u = p3 - p1;
var v = p3 - p2;
// triangle normal
var w = Vector3.Cross(t, u);
var wsl = Vector3.Dot(w, w);
// TODO: if (wsl<10e-14) return false; // area of the triangle is too small (you may additionally check the points for colinearity if you are paranoid)
// helpers
var iwsl2 = 1f / (2f * wsl);
var tt = Vector3.Dot(t, t);
var uu = Vector3.Dot(u, u);
// result circle
Vector3 circCenter = p1 + (u * tt * (Vector3.Dot(u, v)) - t * uu * (Vector3.Dot(t, v))) * iwsl2;
var circRadius = Mathf.Sqrt(tt * uu * (Vector3.Dot(v, v)) * iwsl2 * 0.5f);
Vector3 circAxis = w / Mathf.Sqrt(wsl);
3条答案
按热度按时间ax6ht2ek1#
在真实的3D中找到圆参数有一个更简单的解决方案,只需查看http://en.wikipedia.org/wiki/Circumscribed_circle中的“重心坐标”部分。您可以从中提取以下优化代码:
字符串
然后你也可以在真实的3D中计算圆上的点,例如在OpenGL中使用GL_LINE_STRIP绘制它们。这应该比使用2D sin/cos方法快得多。
型
有关转换矩阵(即makeRotMatrix 4d())的创建,请参见http://paulbourke.net/geometry/rotate/示例。
请注意,我没有测试上面的代码是否真的编译,但它应该给你给予足够的提示。
c9qzyr3d2#
下面是Mark的answer的C#/Unity端口,它使用Unity's scripting API的类型和实用函数。
字符串
使用Unity's Gizmos,可以如下绘制圆(在这种情况下使用30条线段近似它):
型
对于顶点位置,结果如下所示
var p2 = new Vector3(0f, 0.73f, 0.65f);
的var p3 = new Vector3(0f, -1.04f, 0f);
:x1c 0d1x的数据
uxhixvfz3#
有一篇很好的文章和一个代码示例,介绍如何在2D,XY平面上通过3个点构建一个圆。
http://paulbourke.net/geometry/circlesphere/
http://paulbourke.net/geometry/circlesphere/Circle.cpp的
要创建一个3D圆,我们必须:
对于旋转,最好使用四元数。
为了找到正确的四元数,我查看了Ogre3d源代码:void Quaternion::FromAngleAxis(const Radian& rfAngle,const Vector3& rkAxis)
这里还有一个更有用的函数:Quaternion getRotationTo(const Vector3& dest,const Vector3& fallbackAxis = Vector3::ZERO)const但我没有使用它。
对于四元数和向量,我使用了我们自己的类。下面是完成这项工作的函数的完整源代码:
字符串