Click here to Skip to main content
15,883,901 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
See more:
My question this time is to figure out how to properly place (create) a cylinder in space to exactly fit into a line (so the line is exactly in the center of the cylinder). Here is what I am working with:

http://i60.tinypic.com/2njxa95.png

As you can see, I have tried to create the cylinders from the axis X (1,0,0), Y(0,1,0), and Z(0,0,1).

Some gave a different result than others.

I have both start and end points of the line [(x,y,z) values], the angle of it (degrees/rad)

As for the cylinder, I am able to create it based off of radius, height, location in space, workplane x and z axis.

I am able to rotate the cylinder using a function .SetRotate(Axis, vPoint, deg)

Which works based off an axis, location (same used to create) and the angle in degrees.

I am using the same angle value I am obtaining from the line, and my guess is I must somehow figure out the correct axis (the same one as the line).

I am trying to achieve the following: http://i62.tinypic.com/n62aa8.png[^]

If you need more information please let me know. Thanks.

EDIT: My code that might help:

VB
Dim PickObj As New VISIPick
        Dim FaceList As New VISIList
        Dim db As New VISIDatabase
        Dim OldElList As New VISIList

        '* new var
        Dim mwp, mpw, matT, matR As New VISIMatrix
        Dim P2 As New VISIPoint
        Dim Axis As New VISIVector
        '---

        'PickObj.Filter = SEARCH_SEGM
        PickObj.Message = "Pick a Line"
        'PickObj.MoreElements = True
        If PickObj.Pick = False Then
            Exit Sub
        End If
        'PickObj.ClearSelection()

        FaceList.Init(5, LTYPE_FACE)

        db.WorkDBKey = PickObj.PickedKey
        db.GetElement()

        'Make element variable compatible with workplane - add to list
        '*FaceList.AddItem(db.WorkElement)

        '*WPL.Create(FaceList)
        'Dim mwp, mpw As New VISIMatrix

        WPL.GetDefault()
        WPL.CreateFromZAxis(PickObj.PickedPoint, WPL.ZAxis)
        WPL.WorkPlaneWorld(mwp, mpw)

        If WPL.LastError <> V_NOERROR Then
            MsgBox(WPL.LastError)
            Exit Sub
        End If

        'Display existence of workplane
        lblDebug.Text = "(" & WPL.Origin.X.ToString() & "," & WPL.Origin.Y.ToString() & "," & WPL.Origin.Z.ToString() & ")" & vbNewLine & _
            WPL.XAxis.CX.ToString() & " " & WPL.XAxis.CY.ToString() & " " & WPL.XAxis.CZ.ToString() & vbNewLine & _
              " " & WPL.YAxis.CX.ToString() & " " & WPL.YAxis.CY.ToString() & " " & WPL.YAxis.CZ.ToString() & vbNewLine & _
              " " & WPL.ZAxis.CX.ToString() & " " & WPL.ZAxis.CY.ToString() & " " & WPL.ZAxis.CZ.ToString()

        'MsgBox(WPL.XAxis.CX.ToString() & " " & WPL.XAxis.CY.ToString() & " " & WPL.XAxis.CZ.ToString() & vbNewLine & _
        '      " " & WPL.YAxis.CX.ToString() & " " & WPL.YAxis.CY.ToString() & " " & WPL.YAxis.CZ.ToString() & vbNewLine & _
        '      " " & WPL.ZAxis.CX.ToString() & " " & WPL.ZAxis.CY.ToString() & " " & WPL.ZAxis.CZ.ToString())

        Dim x, y, z, rad, deg As Double

        x = db.WorkElement.EndPoint.X - db.WorkElement.StartPoint.X
        y = db.WorkElement.EndPoint.Y - db.WorkElement.StartPoint.Y
        z = db.WorkElement.EndPoint.Z - db.WorkElement.StartPoint.Z

        rad = (Math.Asin(z / Math.Sqrt((x ^ 2) + (y ^ 2) + (z ^ 2)))).ToString()
        deg = (rad * (180 / Math.PI)).ToString()

        If (deg > 0) Then
            vPoint.Put(db.WorkElement.StartPoint.X, db.WorkElement.StartPoint.Y, db.WorkElement.StartPoint.Z)
        Else
            vPoint.Put(db.WorkElement.EndPoint.X, db.WorkElement.EndPoint.Y, db.WorkElement.EndPoint.Z)
        End If
        lblDeg.Text = deg.ToString()

        SolFac.CreateCylinder(0.006, db.WorkElement.Length, vPoint, WPL.XAxis, WPL.ZAxis)
        vList.Init(10, LTYPE_BODY)

        Axis.Put(1, 0, 0)

        If SolFac.LastError <> V_NOERROR Then
            MsgBox(SolFac.LastError)
        Else
            vList.AddItem(SolFac.Result)
            mwp.SetRotate(Axis, vPoint, deg) 'rotate a body based off an angle
            'matT.SetTranslate(vPoint, P2) ' move body from one point to another
            'mwp.Mul(matR, matT) 'apply both
            SolFac.WorkMatrix = mwp
            SolFac.ApplyMatrix(vList)
            Appl.UpdateSolidsOnScreen()
        End If
Posted
Updated 28-Jan-15 7:29am
v3
Comments
Sergey Alexandrovich Kryukov 27-Jan-15 15:22pm    
If you mean that your red ray marked with green line around it represents "true axis", this notion remains undefined. You need to give normal mathematical definition of this notion. Your mention of "center of the sphere" is confusing, because it's not clear which sphere, you never depict anything like sphere.
—SA
jk0391 28-Jan-15 13:30pm    
Sorry, I meant to say CYLINDER and not SPHERE. My mistake there. I updated the question. Basically, I need to generate this cylinder so it wraps around the line, the line being exactly in the center.
Sergey Alexandrovich Kryukov 28-Jan-15 13:49pm    
All right. Anyway, you need clearer explanation and mathematically-strict definition of what you want to achieve. You just need to add more text, in more precise terms, face it. You need to define what exactly you mean by "true axis". Sorry, I cannot promise the solution, but I am nearly sure that no one will give your the solution before you provide much stricter and more detailed formulation of the problem.
—SA
Kenneth Haugland 28-Jan-15 14:21pm    
http://gamedev.stackexchange.com/questions/34105/finding-the-normal-from-one-3d-vector-line-to-any-point-on-another-3d-vector-lin

Than its just a matter of calculating the desired point.
[no name] 28-Jan-15 15:57pm    
Sorry maybe a question because the leak of my noob english: Does it mean in easy words, if you rotate your cylinder and rotate also the same the 'line' the resulted positions of both objects are not more longer what you expect? If this is right, then think about the 'rotation center' of both objects.

1 solution

You have a red line defined by two points (in your code I think it's the vector from db.WorkElement.StartPoint to db.WorkElement.EndPoint), call that redLineDirection;
redLineDirection = normalize(db.WorkElement.EndPoint - db.WorkElement.StartPoint);

Then you have the direction in which the cylinder extends when you create it (I think this is along the positive Y-axis [0,1,0] in your case, but I am not sure), call that cylinderDirection, let this vector be a unit vector of length one.

Now figure out the angle between those vectors using the dot product[^], it will be something like
angle = arccos(dot(redLineDirection, cylinderDirection))); 

No need to divide by the lengths as they're both of length one. Unit is radians.

At this point, you know how much to rotate the cylinder, angle, but you also need to figure out about which axis to do this.

Using the cross product[^] you'll be able to find this.
rotateAxis = cross(redLineDirection, cylinderDirection);

Call SetRotate with the new values;
mwp.SetRotate(rotateAxis, vPoint, angle); // might have to convert angle to degrees here.

I've not considered the translation of the cylinder as you seem to have that under control.

Hope this helps,
Fredrik
 
Share this answer
 
Comments
jk0391 29-Jan-15 11:07am    
Here is my code, see if it looks OK to you. Please ignore the commented code. Thank you again for helping me. I tried it and it did not work, I am thinking I need to adjust my CreateCylinder call (WPL axis values...)

Dim PickObj As New VISIPick
Dim FaceList As New VISIList
Dim db As New VISIDatabase
Dim OldElList As New VISIList

'* new var
Dim mwp, mpw, matT, matR As New VISIMatrix
Dim P2 As New VISIPoint
Dim Axis As New VISIVector
'---

'PickObj.Filter = SEARCH_SEGM
PickObj.Message = "Pick a Line"
'PickObj.MoreElements = True
If PickObj.Pick = False Then
Exit Sub
End If
'PickObj.ClearSelection()

FaceList.Init(5, LTYPE_FACE)

db.WorkDBKey = PickObj.PickedKey
db.GetElement()

'Make element variable compatible with workplane - add to list
'*FaceList.AddItem(db.WorkElement)

WPL.GetDefault()
WPL.CreateFromZAxis(PickObj.PickedPoint, WPL.ZAxis)
WPL.WorkPlaneWorld(mwp, mpw)

If WPL.LastError <> V_NOERROR Then
MsgBox(WPL.LastError)
Exit Sub
End If

Dim p As New VISIPoint
Dim pick As New VISIPick

p.Put(0, 0, 0)
pick.VectorPoint = p
pick.Filter = SEARCH_DIRECTION
pick.MoreElements = False
If (pick.Pick() = False) Then
pick.ClearSelection()
Exit Sub
End If
pick.ClearSelection()

'Display existence of workplane
lblDebug.Text = "(" & WPL.Origin.X.ToString() & "," & WPL.Origin.Y.ToString() & "," & WPL.Origin.Z.ToString() & ")" & vbNewLine & _
WPL.XAxis.CX.ToString() & " " & WPL.XAxis.CY.ToString() & " " & WPL.XAxis.CZ.ToString() & vbNewLine & _
" " & WPL.YAxis.CX.ToString() & " " & WPL.YAxis.CY.ToString() & " " & WPL.YAxis.CZ.ToString() & vbNewLine & _
" " & WPL.ZAxis.CX.ToString() & " " & WPL.ZAxis.CY.ToString() & " " & WPL.ZAxis.CZ.ToString()

Dim x, y, z, rad, deg As Double

x = db.WorkElement.EndPoint.X - db.WorkElement.StartPoint.X
y = db.WorkElement.EndPoint.Y - db.WorkElement.StartPoint.Y
z = db.WorkElement.EndPoint.Z - db.WorkElement.StartPoint.Z

rad = (Math.Asin(z / Math.Sqrt((x ^ 2) + (y ^ 2) + (z ^ 2)))).ToString()
deg = (rad * (180 / Math.PI)).ToString()

'WPL = Util.rotateWorkPlane(WPL, deg)

If (deg > 0) Then
vPoint.Put(db.WorkElement.StartPoint.X, db.WorkElement.StartPoint.Y, db.WorkElement.StartPoint.Z)
Else
vPoint.Put(db.WorkElement.EndPoint.X, db.WorkElement.EndPoint.Y, db.WorkElement.EndPoint.Z)
End If
lblDeg.Text = deg.ToString()

Dim redLine As New Vector3D(x, y, z)
redLine.Normalize()
Dim vectorD As New Vector3D(0, 1, 0)

Dim crossP As New Vector3D()
Dim angle As Double

angle = Math.Acos(Vector3D.DotProduct(redLine, vectorD))
angle = (angle * (180 / Math.PI))
crossP = Vector3D.CrossProduct(redLine, vectorD)
'--
'Dim v1 As New Vector3D(db.WorkElement.EndPoint.X, db.WorkElement.EndPoint.Y, db.WorkElement.EndPoint.Z)
'Dim v2 As New Vector3D(db.WorkElement.StartPoint.X, db.WorkElement.StartPoint.Y, db.WorkElement.StartPoint.Z)

'MsgBox(Vector3D.AngleBetween(v1, v2))
'--

'crossP = Vector3D.CrossProduct(vectorD, vectorN)
'angleBetween = Vector3D.AngleBetween(vectorD, vectorN)

'WPL.ZAxis.CX = pick.PickedVector.CX
'WPL.ZAxis.CY = pick.PickedVector.CY
'WPL.ZAxis.CZ = pick.PickedVector.CZ

SolFac.CreateCylinder(0.006, db.WorkElement.Length, vPoint, WPL.XAxis, WPL.ZAxis)
vList.Init(10, LTYPE_BODY)

Axis.Put(crossP.X, crossP.Y, crossP.Z)

'Axis = Util
Fredrik Bornander 30-Jan-15 7:59am    
I can't read that code and tell you what's wrong, I don't know how all the used methods work.
jk0391 30-Jan-15 13:55pm    
Sorry I know you can't compile it to test it yourself, I was just asking you to go over it because you already traced my code before to post the solution you proposed. Can you not trace it? Again, thank you for your time.
Fredrik Bornander 31-Jan-15 4:19am    
Can you show me a image of what the result was, maybe I can deduce what went wrong from that.
jk0391 3-Feb-15 9:27am    
Apologies for the delay. Here is my full code as I noticed it cut off before:

WPL.GetDefault()
WPL.CreateFromZAxis(PickObj.PickedPoint, WPL.ZAxis)
WPL.WorkPlaneWorld(mwp, mpw)

If WPL.LastError <> V_NOERROR Then
MsgBox(WPL.LastError)
Exit Sub
End If

Dim p As New VISIPoint
Dim pick As New VISIPick

p.Put(0, 0, 0)
pick.VectorPoint = p
pick.Filter = SEARCH_DIRECTION
pick.MoreElements = False
If (pick.Pick() = False) Then
pick.ClearSelection()
Exit Sub
End If
pick.ClearSelection()

'Display existence of workplane
lblDebug.Text = "(" & WPL.Origin.X.ToString() & "," & WPL.Origin.Y.ToString() & "," & WPL.Origin.Z.ToString() & ")" & vbNewLine & _
WPL.XAxis.CX.ToString() & " " & WPL.XAxis.CY.ToString() & " " & WPL.XAxis.CZ.ToString() & vbNewLine & _
" " & WPL.YAxis.CX.ToString() & " " & WPL.YAxis.CY.ToString() & " " & WPL.YAxis.CZ.ToString() & vbNewLine & _
" " & WPL.ZAxis.CX.ToString() & " " & WPL.ZAxis.CY.ToString() & " " & WPL.ZAxis.CZ.ToString()

Dim x, y, z, rad, deg As Double

x = db.WorkElement.EndPoint.X - db.WorkElement.StartPoint.X
y = db.WorkElement.EndPoint.Y - db.WorkElement.StartPoint.Y
z = db.WorkElement.EndPoint.Z - db.WorkElement.StartPoint.Z

rad = (Math.Asin(z / Math.Sqrt((x ^ 2) + (y ^ 2) + (z ^ 2)))).ToString()
deg = (rad * (180 / Math.PI)).ToString()

'WPL = Util.rotateWorkPlane(WPL, deg)

If (deg > 0) Then
vPoint.Put(db.WorkElement.StartPoint.X, db.WorkElement.StartPoint.Y, db.WorkElement.StartPoint.Z)
Else
vPoint.Put(db.WorkElement.EndPoint.X, db.WorkElement.EndPoint.Y, db.WorkElement.EndPoint.Z)
End If
lblDeg.Text = deg.ToString()

Dim redLine As New Vector3D(x, y, z)
redLine.Normalize()
Dim vectorD As New Vector3D(0, 1, 0)

Dim crossP As New Vector3D()
Dim angle As Double

angle = Math.Acos(Vector3D.DotProduct(redLine, vectorD))
angle = angle * (180 / Math.PI)
crossP = Vector3D.CrossProduct(redLine, vectorD)
'--
'Dim v1 As New Vector3D(db.WorkElement.EndPoint.X, db.WorkElement.EndPoint.Y, db.WorkElement.EndPoint.Z)
'Dim v2 As New Vector3D(db.WorkElement.StartPoint.X, db.WorkElement.StartPoint.Y, db.WorkElement.StartPoint.Z)

'MsgBox(Vector3D.AngleBetween(v1, v2))
'--

'crossP = Vector3D.CrossProduct(vectorD, vectorN)
'angleBetween = Vector3D.AngleBetween(vectorD, vectorN)

'WPL.ZAxis.CX = pick.PickedVector.CX
'WPL.ZAxis.CY = pick.PickedVector.CY
'WPL.ZAxis.CZ = pick.PickedVector.CZ

SolFac.CreateCylinder(0.006, db.WorkElement.Length, vPoint, WPL.XAxis, WPL.ZAxis)
vList.Init(10, LTYPE_BODY)

Axis.Put(crossP.X, crossP.Y, crossP.Z)

'Axis = Util.rotateVector(Axis, Axis, deg)

If SolFac.LastError <> V_NOERROR Then
MsgBox(SolFac.LastError)
Else
vList.AddItem(SolFac.Result)
mwp.SetRotate(Axis, vPoint, angle) 'rotate a body based off an angle
'matT.SetTranslate(vPoint, P2) ' move body from one point to another
'mwp.TransformVector(Axis)
'mwp.Mul(matR, matT) 'apply new changes
SolFac.WorkMatrix = mwp
SolFac.ApplyMatrix(vList)
'SolFac.RotateBodies(vList, Axis, vPoint, deg)
Appl.UpdateSolidsOnScreen()
End If

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900