Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
253 views
in Technique[技术] by (71.8m points)

java - 3d point on circumference of a circle with a center, radius and normal vector

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.

For the record I am trying to solve an issue in OpenGL ES (Java/Android).

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.

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).

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.

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?

[Edit] 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

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.

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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.

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 ]

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]

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

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))

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...