문제

There are two Point3D's (A and B) and I want to calculate the points of a cuboid (a,b,c ... h) surrounding the line between A and B like a hull:

enter image description here

There is one degree of freedom, the angle of the cuboid, because it can rotate around the line AB. I am not sure yet if this is a problem.

I tried to calculate a vector normal to AB, D, and then the cross product of ABAD = E. In the code, C is A - B so its the offset parallel to AB.

I normalized these three vectors (C, D and E) and multiplied it with an offset to add / subtract them from A and B. It's not quite working yet.

EDIT: see ja72's code for solution

i also implemented a way of finding a normal vector:

                double ax = Vector3D.AngleBetween(E, new Vector3D(1, 0, 0));
                double ay = Vector3D.AngleBetween(E, new Vector3D(0, 1, 0));
                double az = Vector3D.AngleBetween(E, new Vector3D(0, 0, 1));

                ax = Math.Abs(ax - 90);
                ay = Math.Abs(ay - 90);
                az = Math.Abs(az - 90);

                if (ax <= ay & ax <= az)
                {
                    n = Vector3D.CrossProduct(E, new Vector3D(1, 0, 0));
                }
                else if (az <= ax && az <= ay)
                {
                    n = Vector3D.CrossProduct(E, new Vector3D(0, 0, 1));
                }
                else
                {
                    n = Vector3D.CrossProduct(E, new Vector3D(0, 1, 0));
                }
                n = normalize(n);
도움이 되었습니까?

해결책

You need two direction vectors. One is along the line AB given by

Vector3D e = Normalize(B-A)

and one to descibe the "up" direction for the cross section. This can be given, or it can be calculated with the following algorithm (with preference towards +y)

if( e.X != 0 || e.Z != 0 ) 
{
    // choose direction perpendicular to line closest to +y direction
    Vector3D n = [-e.X*e.Y, e.X*e.X+e.Z*e.Z, -e.Z*e.Y];
} else {
    // if line along +y already then choose +z for up vector
    Vector3D n = [ 0, 0, 1];
}

Now you can calculate the 3rd direction to form a coordinate system

Vector3D k = Normalize( Cross(e,n) )

And you assemble the 3×3 rotation matrix that transforms local coordinates to world coordinates with

    | k.X  n.X  e.X |
R = | k.Y  n.Y  e.Y | 
    | k.Z  n.Z  e.Z |

The local coordinate have the direction along the line as +z such that

Point3D a = A + R*[w,h,0]
Point3D b = A + R*[-w,h,0]
Point3D c = A + R*[w,-h,0]
Point3D d = A + R*[-w,-h,0]

Point3D e = B + R*[w,h,0]
Point3D f = B + R*[-w,h,0]
Point3D g = B + R*[w,-h,0]
Point3D h = B + R*[-w,-h,0]

where R*[x,y,z] designates a matrix-vector multiplication, w and h are the width and height of the rectangular cross section, and A, B are the point A and B position vectors. Addition here between vectors is element by element.


I have checked the code in my own code and it works. vec3 is alias for a 3D vector, mat3 is alias for 3×3 matrix.

Cube

    vec3 u=(B-A).Normalized();

    vec3 n = vec3.O;
    if(Math.Abs(u.X)<=Math.Abs(u.Y)&&Math.Abs(u.X)<=Math.Abs(u.Z))
    {
        n=new vec3(u.Y*u.Y+u.Z*u.Z, -u.Y*u.X, -u.Z*u.X);
    }
    else if(Math.Abs(u.Y)<=Math.Abs(u.X)&&Math.Abs(u.Y)<=Math.Abs(u.Z))
    {
        n=new vec3(-u.X*u.Y, u.X*u.X+u.Z*u.Z, -u.Z*u.Y);
    }
    else if(Math.Abs(u.Z)<=Math.Abs(u.X)&&Math.Abs(u.Z)<=Math.Abs(u.Y))
    {
        n=new vec3(-u.X*u.Z, -u.Y*u.Z, u.X*u.X+u.Y*u.Y);
    }
    vec3 v=n.Cross(u);

    mat3 R=mat3.Combine(v, n, u);

    var a=A+R*new vec3(wt, ht, 0);
    var b=A+R*new vec3(-wt, ht, 0);
    var c=A+R*new vec3(wt, -ht, 0);
    var d=A+R*new vec3(-wt, -ht, 0);
    var e=B+R*new vec3(wt, ht, 0);
    var f=B+R*new vec3(-wt, ht, 0);
    var g=B+R*new vec3(wt, -ht, 0);
    var h=B+R*new vec3(-wt, -ht, 0);

다른 팁

I can't give you a real piece of code, but I can give you an idea.

Ok, suppose you are already have a proper cuboid. I mean it has right width and height. Lets locate it on plane xy. After that you need to offset it to center (minus offset vector). The last thing is to rotate it according to your line rotation.

Again:

  • Create cuboid and locate it on xy plane
  • Move it according to your offsets
  • Rotate it according to your line rotation

You may use matrix multiplication to achieve this transformations.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top