向量数学,在两个向量之间的平面上查找坐标

发布于 2024-10-08 20:16:16 字数 1212 浏览 7 评论 0原文

我正在尝试沿着样条线生成 3d 管。我有样条线的坐标(x1,y1,z1 - x2,y2,z2 - 等),您可以在黄色插图中看到。在这些点上,我需要生成圆圈,其顶点将在稍后的体育场连接。这些圆需要垂直于样条线两条线段的“角”才能形成正确的管。请注意,出于说明目的,这些段保持较低。

[显然我不允许发布图片,所以请在此链接查看图片] http://img191.imageshack.us/img191/6863/18720019.jpg

我尽可能计算出样条线每个点处每个环的顶点,但它们都在同一平面上,即相同的角度。我需要它们根据它们的“腿”进行旋转(例如,A 和 B 相对于 C)。

我一直在思考这个问题并想到以下内容:

  • 两条线段可以被视为2个向量(在插图A和B中),
  • 角点(在插图C中)是需要计算顶点环的地方
  • 我需要找到所有顶点所在的平面
  • 然后我可以使用这个平面(=向量?)从中心点(C)计算新向量,
  • 并使用半径* sin和cos找到它们的x,y,z

但是,我对这个的数学部分真的很困惑。我读过有关点积的内容,但它返回一个标量,我不知道如何在这种情况下应用它。

有人能指出我正确的方向吗?

[编辑] 为了提供有关这种情况的更多信息:

我需要构造一个浮点缓冲区,它以 3 个为一组描述顶点位置,并将由 OpenGL ES 连接,给定另一个带有索引的缓冲区以形成多边形。

为了赋予管子形状,我首先创建了一个浮点数组,每 3 个浮点数组描述 3d 空间中的控制点。

然后,与段密度变量一起,我将这些控制点传递给一个函数,该函数使用这些控制点创建 CatmullRom 样条曲线,并以另一个浮点数数组的形式返回该数组,该浮点数同样以 3 个为一组,描述了Catmull ROM 样条线。

在每个顶点上,我想创建一个顶点环,其密度也可以不同(平滑度/每个环的顶点数)。

所有以前的顶点(控制点和描述 catmull rom 样条线的顶点)都将被丢弃。

只有形成管环的顶点才会传递给 OpenGL,Op​​enGL 又会将这些顶点连接起来形成最终的管。

我尽可能创建 catmullrom 样条线,并在其顶点位置创建环,但是,它们都位于相同角度的平面上,而不是遵循样条线路径。

[/编辑]

谢谢!

I am trying to generate a 3d tube along a spline. I have the coördinates of the spline (x1,y1,z1 - x2,y2,z2 - etc) which you can see in the illustration in yellow. At those points I need to generate circles, whose vertices are to be connected at a later stadium. The circles need to be perpendicular to the 'corners' of two line segments of the spline to form a correct tube. Note that the segments are kept low for illustration purpose.

[apparently I'm not allowed to post images so please view the image at this link]
http://img191.imageshack.us/img191/6863/18720019.jpg

I am as far as being able to calculate the vertices of each ring at each point of the spline, but they are all on the same planar ie same angled. I need them to be rotated according to their 'legs' (which A & B are to C for instance).

I've been thinking this over and thought of the following:

  • two line segments can be seen as 2 vectors (in illustration A & B)
  • the corner (in illustraton C) is where a ring of vertices need to be calculated
  • I need to find the planar on which all of the vertices will reside
  • I then can use this planar (=vector?) to calculate new vectors from the center point, which is C
  • and find their x,y,z using radius * sin and cos

However, I'm really confused on the math part of this. I read about the dot product but that returns a scalar which I don't know how to apply in this case.

Can someone point me into the right direction?

[edit]
To give a bit more info on the situation:

I need to construct a buffer of floats, which -in groups of 3- describe vertex positions and will be connected by OpenGL ES, given another buffer with indices to form polygons.

To give shape to the tube, I first created an array of floats, which -in groups of 3- describe control points in 3d space.

Then along with a variable for segment density, I pass these control points to a function that uses these control points to create a CatmullRom spline and returns this in the form of another array of floats which -again in groups of 3- describe vertices of the catmull rom spline.

On each of these vertices, I want to create a ring of vertices which also can differ in density (amount of smoothness / vertices per ring).

All former vertices (control points and those that describe the catmull rom spline) are discarded.

Only the vertices that form the tube rings will be passed to OpenGL, which in turn will connect those to form the final tube.

I am as far as being able to create the catmullrom spline, and create rings at the position of its vertices, however, they are all on a planars that are in the same angle, instead of following the splines path.

[/edit]

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

新人笑 2024-10-15 20:16:16

假设您有一条参数曲线,例如:

xx[t_] := Sin[t];
yy[t_] := Cos[t];
zz[t_] := t;  

给出:
alt text

曲线的切向量由每个方向的导数形成。在我们的例子中,

Tg[t_]:= {Cos[t], -Sin[t], 1}  

该向量的正交平面来求解隐式方程:

Tg[t].{x - xx[t], y - yy[t], z - zz[t]} == 0  

在我们的例子中,这是:

-t + z + Cos[t] (x - Sin[t]) - (y - Cos[t]) Sin[t] == 0  

现在我们在该平面中找到一个以曲线为中心的圆。即:

c[{x_, y_, z_, t_}] := (x - xx[t])^2 + (y - yy[t])^2 + (z - zz[t])^2 == r^2  

求解两个方程,您将得到圆的方程:

alt text

HTH!

编辑

通过绘制大量圆圈,您可能会得到一个(效率不高)管:

alt text

或者使用良好的图形 3D 库:

alt text

编辑

既然你坚持:)这里是一个计算交叉点圆的程序。

a = {1, 2, 3}; b = {3, 2, 1}; c = {2, 3, 4};
l1 = Line[{a, b}];
l2 = Line[{b, c}];

k = Cross[(b - a), (c - b)] + b; (*Cross Product*)
angle = -ArcCos[(a - b).(c - b)/(Norm[(a - b)] Norm[(c - b)])]/2;
q = RotationMatrix[angle, k - b].(a - b);
circle[t_] := (k - b)/Norm[k - b] Sin@t + (q)/Norm[q] Cos@t + b;

Show[{Graphics3D[{
    Red, l1,
    Blue, l2,
    Black, Line[{b, k}],
    Green, Line[{b, q + b}]}, Axes -> True],
  ParametricPlot3D[circle[t], {t, 0, 2 Pi}]}]

alt text

编辑

这里您拥有通过此方法构建的网格。恕我直言,这并不漂亮:

alt text

Suppose you have a parametric curve such as:

xx[t_] := Sin[t];
yy[t_] := Cos[t];
zz[t_] := t;  

Which gives:
alt text

The tangent vector to our curve is formed by the derivatives in each direction. In our case

Tg[t_]:= {Cos[t], -Sin[t], 1}  

The orthogonal plane to that vector comes solving the implicit equation:

Tg[t].{x - xx[t], y - yy[t], z - zz[t]} == 0  

In our case this is:

-t + z + Cos[t] (x - Sin[t]) - (y - Cos[t]) Sin[t] == 0  

Now we find a circle in that plane, centered at the curve. i.e:

c[{x_, y_, z_, t_}] := (x - xx[t])^2 + (y - yy[t])^2 + (z - zz[t])^2 == r^2  

Solving both equations, you get the equation for the circles:

alt text

HTH!

Edit

And by drawing a lot of circles, you may get a (not efficient) tube:

alt text

Or with a good Graphics 3D library:

alt text

Edit

Since you insist :) here is a program to calculate the circle at junctions.

a = {1, 2, 3}; b = {3, 2, 1}; c = {2, 3, 4};
l1 = Line[{a, b}];
l2 = Line[{b, c}];

k = Cross[(b - a), (c - b)] + b; (*Cross Product*)
angle = -ArcCos[(a - b).(c - b)/(Norm[(a - b)] Norm[(c - b)])]/2;
q = RotationMatrix[angle, k - b].(a - b);
circle[t_] := (k - b)/Norm[k - b] Sin@t + (q)/Norm[q] Cos@t + b;

Show[{Graphics3D[{
    Red, l1,
    Blue, l2,
    Black, Line[{b, k}],
    Green, Line[{b, q + b}]}, Axes -> True],
  ParametricPlot3D[circle[t], {t, 0, 2 Pi}]}]

alt text

Edit

Here you have the mesh constructed by this method. It is not pretty, IMHO:

alt text

凡间太子 2024-10-15 20:16:16

我不知道您选择的语言是什么,但如果您使用 MatLab,则已经有一些可用的实现。即使您使用另一种语言,某些代码也可能足够清晰,足以激发重新实现的灵感。

关键点是,如果您不希望管在连接顶点时扭曲,则无法在本地确定基础,而是需要沿曲线传播它。 Jalexiou 提出的 Frenet 框架 是一种选择,但更简单东西也很好用。

我做了一个简单的 MatLab 实现,名为 tubeplot.m 在我的成长岁月中(基于简单的非 Frenet 传播),通过谷歌搜索,我可以看到来自 kth.se 的 Anders Sandberg 已经做了一个(重新?)同名的实现,可在 http://www.nada.kth.se/~asa/Ray/Tubeplot/tubeplot .html

TubePlot.m illustration

编辑:
以下是在 tubeplot.m 中简单实现的伪代码。我发现它非常坚固。

计划是沿曲线传播两个法线 ab,因此
曲线上的每个点 ab 以及曲线的切线
将形成一个“尽可能接近”的正交基
上一点中使用的基础。
利用这个基础,我们可以找到管圆周上的点。

// *** Input/output ***
// v[0]..v[N-1]: Points on your curve as vectors
//               No neighbours should overlap
// nvert: Number of vertices around tube, integer.
// rtube: Radius of tube, float.
// xyz: (N, nvert)-array with vertices of the tube as vectors


// *** Initialization ***
// 1: Tangent vectors
for i=1 to N-2:
    dv[i]=v[i+1]-v[i-1]
dv[0]=v[1]-v[0], dv[N-1]=v[N-1]-v[N-2]

// 2: An initial value for a (must not be pararllel to dv[0]):
idx=<index of smallest component of abs(dv[0])>
a=[0,0,0], a[idx]=1.0

// *** Loop ***
for i = 0 to N-1:
    b=normalize(cross(a,dv[i]));
    a=normalize(cross(dv[i],b));
    for j = 0 to nvert-1:
        th=j*2*pi/nvert 
        xyz[i,j]=v[i] + cos(th)*rtube*a + sin(th)*rtube*b

实现细节:您可以通过预先计算 cossin 来加快速度。此外,为了获得强大的性能,您应该将输入点融合得比 0.1*rtube 更近,或者至少测试所有 dv 向量均非零。

华泰

I don't know what your language of choice is, but if you speak MatLab there are already a few implementations available. Even if you are using another language, some of the code might be clear enough to inspire a reimplementation.

The key point is that if you don't want your tube to twist when you connect the vertices, you cannot determine the basis locally, but need to propagate it along the curve. The Frenet frame, as proposed by jalexiou, is one option but simpler stuff works fine as well.

I did a simple MatLab implementation called tubeplot.m in my formative years (based on a simple non-Frenet propagation), and googling it, I can see that Anders Sandberg from kth.se has done a (re?)implementation with the same name, available at http://www.nada.kth.se/~asa/Ray/Tubeplot/tubeplot.html.

TubePlot.m illustration

Edit:
The following is pseudocode for the simple implementation in tubeplot.m. I have found it to be quite robust.

The plan is to propagate two normals a and b along the curve, so
that at each point on the curve a, b and the tangent to the curve
will form an orthogonal basis which is "as close as possible" to the
basis used in the previous point.
Using this basis we can find points on the circumference of the tube.

// *** Input/output ***
// v[0]..v[N-1]: Points on your curve as vectors
//               No neighbours should overlap
// nvert: Number of vertices around tube, integer.
// rtube: Radius of tube, float.
// xyz: (N, nvert)-array with vertices of the tube as vectors


// *** Initialization ***
// 1: Tangent vectors
for i=1 to N-2:
    dv[i]=v[i+1]-v[i-1]
dv[0]=v[1]-v[0], dv[N-1]=v[N-1]-v[N-2]

// 2: An initial value for a (must not be pararllel to dv[0]):
idx=<index of smallest component of abs(dv[0])>
a=[0,0,0], a[idx]=1.0

// *** Loop ***
for i = 0 to N-1:
    b=normalize(cross(a,dv[i]));
    a=normalize(cross(dv[i],b));
    for j = 0 to nvert-1:
        th=j*2*pi/nvert 
        xyz[i,j]=v[i] + cos(th)*rtube*a + sin(th)*rtube*b

Implementation details: You can probably speed up things by precalculating the cos and sin. Also, to get a robust performance, you should fuse input points closer than, say, 0.1*rtube, or a least test that all the dv vectors are non-zero.

HTH

短暂陪伴 2024-10-15 20:16:16

您需要查看微分几何中的 Fenet 公式。参见图 2.1 的螺旋示例。

表面和表面曲线

You need to look at Fenet formulas in Differential Geometry. See figure 2.1 for an example with a helix.

Surfaces & Curves

冬天旳寂寞 2024-10-15 20:16:16

取线段和向上向量的叉积将得到一个与它们都成直角的向量(除非线段完全指向上方或下方),我将其称为水平向量。取水平线和线段的叉积,得到另一个与线段和另一个向量成直角的向量(我们称之为垂直向量)。然后,您可以通过 lineStart + cos theta * 水平 + sin theta * 垂直(0 - 2Pi 范围内的 theta)获得圆坐标。

编辑:要获取两条线段之间的中点,请使用两条线段向量的总和来查找平均值。

Taking the cross product of the line segment and the up vector will give you a vector at right-angles to them both (unless the line segment points exactly up or down) which I'll call horizontal. Taking the cross product of horizontal and the line segment with give you another vector that's at right angles to the line segment and the other one (let's call it vertical). You can then get the circle coords by lineStart + cos theta * horizontal + sin theta * vertical for theta in 0 - 2Pi.

Edit: To get the points for the mid-point between two segments, use the sum of the two line segment vectors to find the average.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文