問題描述
我的問題類似于 如何制作點軌道一條線,3D 但那里的答案似乎沒有解決我的問題.而我正在尋找的是一個通用的解決方案.
My question is similar to How to Make a Point Orbit a Line, 3D but the answer there didn't seem to solve my problem. And what I am looking for is a general solution.
為了記錄,我正在嘗試解決 OpenGL ES (Java/Android) 中的一個問題.
For the record I am trying to solve an issue in OpenGL ES (Java/Android).
我有一個圓,它的中心有一個 3D 點、一個半徑和一個 3D 矢量,指定圓所在平面的法線.
I have a circle with a 3D point for its center, a radius, and a 3D vector specifying the normal to the plane the circle lies in.
我需要找到表示圓周上點的 3D 點,該點與旋轉"X 軸(根據法線向量旋轉)成給定角度.
I need to find the 3D point representing the point on the circumference at a given angle from the 'rotated' X-axis (rotated according to the normal vector).
我已經在 Circle
類的成員函數 pointAt
中有一個實現,它在有限的情況下工作.具體來說,在我當前的實現中,我假設圓位于 XY 平面中并相應地返回一個點,然后,由于我知道圓實際上位于 XZ 平面中,我只需交換返回點中的 Y 和 Z 值就可以了.但是,這不是一個通用的解決方案,而這正是我所需要的.
I already have an implementation in a Circle
class of a member function, pointAt
, which works under limited circumstances. Specifically, in my current implementation I assume the circle lies in the X-Y plane and return a point accordingly and then, since I know the circle is actually lying in the X-Z plane I simply swap the Y and Z values in the returned point and it works. However, this is not a general solution and that is what I am going to need.
當我嘗試 如何制作Point Orbit a Line, 3D,我得到的點離它們應該在的位置很遠.
When I tried the algorithm given in How to Make a Point Orbit a Line, 3D, I got points pretty far removed from where they should have been.
那么,我怎樣才能在這樣一個圓的圓周上計算一個點呢?
So, how, can I calculate a point on the circumference of such a circle?
我想我的解釋是不夠的.我的假設是一個圓在 X-Y 平面上是正常"的,Z 方向的法向量為 (0, 0, 1) - 1.如果需要圓周上的一個點,則該點由以下定義:
I guess my explanation wasn't sufficient. My assumption is that a circle is 'normally' in the X-Y plane with a normal vector of (0, 0, 1) - 1 in the Z direction. If a point on the circumference is needed the point is defined by:
x = R*cos(a) + Cx
y = R*sin(a) + Cy
其中 R
是半徑,Cx
和 Cy
是 X
和 Y
圓心坐標,a
是一個向量與圓心的夾角,與 X 軸平行.
where R
is the radius, Cx
and Cy
are the X
and Y
coordinates of the center of the circle, and a
is the angle from a vector through the circle's center point and parallel with the X-axis.
現在,如果圓沒有指向 Z 軸的法線向量,而是某個任意 (x, y, z) 向量,我如何找到同一個點?
Now, if the circle doesn't have a normal vector pointing along the Z-axis but, instead, is some arbitrary (x, y, z) vector, how do I find that same point?
推薦答案
你需要一個新的坐標系來放置圓.與任何常見的坐標系一樣,我們希望基向量彼此正交,并且每個長度為 1.我將基向量命名為 v1
、v2
和 v3
,它們依次對應 x、y 和 z.
What you need is a new coordinate system to place the circle. As any common coordinate system, we'll want the base vectors to be orthogonal to each other, and have length 1 each. I'll name the base vectors v1
, v2
, and v3
, which correspond to x, y, and z in order.
替換z的新基向量,即v3
由圓的法線向量給出.如果它還沒有標準化,您需要在這里對其進行標準化:
The new base vector that replaces z, which is v3
is given by the normal vector of the circle. If it's not normalized yet, you'll want to normalize it here:
[ v3x ]
v3 = [ v3y ] = normalize(circleNormal)
[ v3z ]
接下來,我們將選擇 v1
.這可以是與 v3
正交的任意向量.由于我們希望它代替 x 軸,我們可以選擇它的 y 分量為 0:
Next, we'll chose v1
. This can be an arbitrary vector that is orthogonal to v3
. Since we want it to take the place of the x-axis, we can choose it to have an y-component of 0:
[ v3z ]
v1 = normalize([ 0 ])
[ -v3x]
注意這個向量與v3
的點積為0,說明這兩個向量確實是正交的.如果圓的法向量正好指向 y 方向,則該向量將退化.如果您在使用中遇到問題,我會讓您弄清楚如何處理.
Note that the dot product of this vector with v3
is 0, which means that the two vectors are indeed orthogonal. The vector will be degenerate if the normal vector of the circle points exactly in the y-direction. I'll let you figure out how to handle that if it's a concern in your usage.
現在我們只需要最后一個向量,它可以計算為其他兩個的叉積:
Now we just need the last vector, which can be calculated as the cross product of the other two:
v2 = v3 x v1
因為 v1
和 v3
已經過標準化,并且是正交的,所以這已經被標準化了.
This will already be normalized since v1
and v3
were normalized, and are orthogonal.
有了這個新的基礎,圓上的點現在可以計算為:
With this new basis, points on the circle can now be calculated as:
p = centerPoint + R * (cos(a) * v1 + sin(a) * v2)
讓整個事情更接近代碼形式(未經測試):
Putting the whole thing closer to code form (untested):
// Only needed if normal vector (nx, ny, nz) is not already normalized.
float s = 1.0f / (nx * nx + ny * ny + nz * nz);
float v3x = s * nx;
float v3y = s * ny;
float v3z = s * nz;
// Calculate v1.
s = 1.0f / (v3x * v3x + v3z * v3z);
float v1x = s * v3z;
float v1y = 0.0f;
float v1z = s * -v3x;
// Calculate v2 as cross product of v3 and v1.
// Since v1y is 0, it could be removed from the following calculations. Keeping it for consistency.
float v2x = v3y * v1z - v3z * v1y;
float v2y = v3z * v1x - v3x * v1z;
float v2z = v3x * v1y - v3y * v1x;
// For each circle point.
px = cx + r * (v1x * cos(a) + v2x * sin(a))
py = cy + r * (v1y * cos(a) + v2y * sin(a))
pz = cz + r * (v1z * cos(a) + v2z * sin(a))
這篇關于具有中心、半徑和法線向量的圓圓周上的 3d 點的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!