Here's a sub ('test' at the bottom) using the methods above, it xforms an object to the same direction of a given line, it will later be modified for my 3dsolid section creator that creates the section, transforms and translates the object to the 'construction line' or wire frame line in steel modeling terms if you like.
There is no error checking so it will fail if you do the wrong thing, error checking is next on my hit list before going too much further.
Here's the code, I have altered the MatFrom line function also to cater for strange lines like these (it didn't build an orthoganal matrix).
There's a dwg attached with a cylinder and a line at a strange angle in space if you like but it should work with any object, run the sub, follow the prompts and it should xform the cylinder to the same direction as the line.
''''''''------- Vector Methods --------------'''''''''''
Public Function VecNorm(ByRef vec() As Double)
'Normalises the incoming vector.
Dim unit As Double
unit = Sqr(vec(0) * vec(0) + vec(1) * vec(1) + vec(2) * vec(2))
vec(0) = vec(0) / unit: vec(1) = vec(1) / unit: vec(2) = vec(2) / unit
End Function
Function VecCross(ByRef retvec() As Double, ByRef v1() As Double, ByRef v2() As Double)
retvec(0) = v1(1) * v2(2) - v2(1) * v1(2)
retvec(1) = v1(2) * v2(0) - v2(2) * v1(0)
retvec(2) = v1(0) * v2(1) - v2(0) * v1(1)
End Function
'''''''''--------- Matrix Methods ------------'''''''''''
Public Function BuildMat(ByRef mat() As Double, ByRef vx() As Double, _
ByRef vy() As Double, ByRef vz() As Double)
'Uses the incoming vectors to transform the entity being passed in
mat(0, 0) = vx(0): mat(0, 1) = vy(0): mat(0, 2) = vz(0): mat(0, 3) = 0#
mat(1, 0) = vx(1): mat(1, 1) = vy(1): mat(1, 2) = vz(1): mat(1, 3) = 0#
mat(2, 0) = vx(2): mat(2, 1) = vy(2): mat(2, 2) = vz(2): mat(2, 3) = 0#
mat(3, 0) = 0#: mat(3, 1) = 0#: mat(3, 2) = 0#: mat(3, 3) = 1#
End Function
Public Function MatFromLine(line As AcadLine, ByRef mat() As Double)
'builds the matrix passed in based on the line's sp, ep and normal
Dim vx(2) As Double, vy(2) As Double, vz(2) As Double
'get the lines ep-sp vector to create the z axis:
vz(0) = line.EndPoint(0) - line.StartPoint(0)
vz(1) = line.EndPoint(1) - line.StartPoint(1)
vz(2) = line.EndPoint(2) - line.StartPoint(2)
'normalise it:
VecNorm vz
'get the line's normal for the x vector:
vx(0) = line.Normal(0)
vx(1) = line.Normal(1)
vx(2) = line.Normal(2)
'create the y vector by xproduct of z over x:
VecCross vy, vz, vx
'normalise it:
VecNorm vy
'we need an extra step here as the line may not
'have been drawn in the same plane as it's ucs when drawn
'so we have to 'square up' the x axis, the order of the
'2 vars to cross is important here!
VecCross vx, vy, vz
'now plug 'em into the matrix:
BuildMat mat, vx, vy, vz
End Function
Public Sub test()
'transforms an ent to the same ucs as a given line
'needs error checking so be careful! ;)
Dim line As AcadEntity, obj As AcadEntity
Dim pnt As Variant
Dim transmat(3, 3) As Double
'get the obj and line from user:
ThisDrawing.Utility.GetEntity obj, pnt, "Pick object to xform: "
ThisDrawing.Utility.GetEntity line, pnt, "Pick line to xform to: "
'get the xform matrix from the line:
MatFromLine line, transmat
'xform the obj:
obj.TransformBy (transmat)
obj.Update
End Sub
<edit> Just a quick note, if you use the function again and pick another line, or even the same line again you will get unexpected results.
The reason for this is that the transformations are cumulative. The way around this is to add a user 'ocs' to the solid, retrieve it and for the sake fo simplicity, invert the matrix of the object to transform it back to world then transform it with the given line ocs...hope that makes sense.