Author Topic: What is the TransMatrix in getsubentity?  (Read 5167 times)

0 Members and 1 Guest are viewing this topic.

Bryco

  • Water Moccasin
  • Posts: 1882
What is the TransMatrix in getsubentity?
« on: July 26, 2006, 10:34:28 PM »
ThisDrawing.Utility.GetSubEntity ent, varPick, TransMatrix,  ContextData, vbCrLf & "p"
I haven't messed alot with transformations so I'm not sure what this means.

Aim: I have a function that adds a leader and note to a block with the mtext showing either tha name of the block or the xdata attached to the block. It works very well and is handy. But I would like to pick a point on the block (This point is really just the center of the pick box) and have that point change to the nearest point on the block for my leader arrowhead.
I have a nearestpointtoEnt function worked out nicely but the ent passes by the GetSubEntity function is not the entity in the blockref but the entity in the block at 0,0.
The TransMatrix is presumably the translation matrix the blockref underwent, but picking an object and applying the same TransMatrix to it makes it go all curly wobbler.
Any ideas?

DaveW

  • Guest
Re: What is the TransMatrix in getsubentity?
« Reply #1 on: July 26, 2006, 10:47:22 PM »
Sorry Bryco,

I do not follow what you are doing. From what I can tell, you just need to get each entity inside of the block, then for each type of ent, ie line or arc, find the end points, midpoints, etc., add all you find to an array, find the shortest distance from where you picked to the closest ent and use that point for your leader. It seems pretty simple and I know you are a much better programmer then me, so I must not understand why you would need a matrix at all.

With that said, I do have code that goes inside block entities, but I only yank xdata from them, so you may need that matrix after all because I cannot say for sure I would be able to get that geometry info correct because I have never actually tried it.

Bryco

  • Water Moccasin
  • Posts: 1882
Re: What is the TransMatrix in getsubentity?
« Reply #2 on: July 27, 2006, 12:22:39 AM »
Well I would like to translate the picked point to its equivalent position next to the block entity (not the blockref),
then I can find the nearest point on the entity, then translate that back to the blockref.
I suspect that the transmatrix has the right info in it but I don't know how to use it.

MickD

  • King Gator
  • Posts: 3619
  • (x-in)->[process]->(y-out) ... simples!
Re: What is the TransMatrix in getsubentity?
« Reply #3 on: July 27, 2006, 12:58:51 AM »
so, you are picking a sub ent of the inserted block ref which gives you a point which after calculating a nearest point on sub ent is given back to you in relation to the block table record (as if inserted at 0,0,0) and you can't xform your leader to the inserted ref using the block xform matrix, is that what you are saying?
"Short cuts make long delays,' argued Pippin.”
J.R.R. Tolkien

Bryco

  • Water Moccasin
  • Posts: 1882
Re: What is the TransMatrix in getsubentity?
« Reply #4 on: July 27, 2006, 01:55:18 AM »
Not quite Mick. The ent given is part of the blockrecord not part of the blockref. (I can copy it using copyobjects,using modelspace as the new owner, but it will be as if inserted at 0,0,0). In fact I cant tell which blockref I picked. The picked point is the actual point I picked .
So I have an odd mix. The tie is definately in the transmatrix

MickD

  • King Gator
  • Posts: 3619
  • (x-in)->[process]->(y-out) ... simples!
Re: What is the TransMatrix in getsubentity?
« Reply #5 on: July 27, 2006, 02:27:46 AM »
Ok, that's sort of what I meant/thought :)
Try inverting the matrix from the picked block ref, transform your picked point, do your calc's then xform back. I wouldn't have a clue if vba can do this but if you have to  you would simply negate each value in the matrix given which should do the trick.
"Short cuts make long delays,' argued Pippin.”
J.R.R. Tolkien

Bryco

  • Water Moccasin
  • Posts: 1882
Re: What is the TransMatrix in getsubentity?
« Reply #6 on: July 27, 2006, 10:20:14 PM »
Thanks Mick. My mate at work knows a bit of maths and after transposing the matrix it works backwards. So now I think if I can figure out the inverting I may have something.(There is no native function). The bummer is that I would rather just translate the pickedpoint but I dont know how to feed that into a transforation matrix. The vba one only accepts objects.
I guess I'm going to have to read up on linear algebra, ruin a good beer that stuff.

Bryco

  • Water Moccasin
  • Posts: 1882
Re: What is the TransMatrix in getsubentity?
« Reply #7 on: July 31, 2006, 12:37:36 AM »
Made a bit of progress.
Still this InverseMatrix stuff is bizarre.
The function I made seems to be ok but throws a wobbler.
It relies on adding an identity matrix to the matrix then
doing some pivot stuff and checking to see if the first part tuned into an identity matrix.
Well I don't know for sure makes them work or not.
Doesn't really sound like  proress does it?

MickD

  • King Gator
  • Posts: 3619
  • (x-in)->[process]->(y-out) ... simples!
Re: What is the TransMatrix in getsubentity?
« Reply #8 on: July 31, 2006, 12:47:34 AM »
Can't you just create a matrix out of the info from the inserted block ref (normalised normal, x and y directions with the vector to inseted point) and negate each element to invert the matrix??
"Short cuts make long delays,' argued Pippin.”
J.R.R. Tolkien

MickD

  • King Gator
  • Posts: 3619
  • (x-in)->[process]->(y-out) ... simples!
Re: What is the TransMatrix in getsubentity?
« Reply #9 on: July 31, 2006, 01:00:38 AM »
Ok, I see you have the normal and rotation prop's available in vba.
lets try this -
create a point (inspntX + 1, inspntY, inspntZ) '// one unit along the xaxis:
rotate this new point by the given rot angle
get the cross product of the vector from the inspnt to new point and the block's normal, this will give you a Y axis.
now cross product the new Yaxis with the normal to orthoganlise (is that a word) the axis.
You should now have enough info to construct a matrix given your new 3 axes and the translation vector to the insert point. Negate them all to reverse the directions and transform your point.
Does that sound doable??
"Short cuts make long delays,' argued Pippin.”
J.R.R. Tolkien

Bryco

  • Water Moccasin
  • Posts: 1882
Re: What is the TransMatrix in getsubentity?
« Reply #10 on: July 31, 2006, 10:17:33 AM »
Might end up that way Mick.
A blockref has those proprties but i don't have a blockref. (Point and block item)
I can get the blockref with a selectatpoint selectionset but I would like to learn how to use what I have first.
Here is a debug.print of  the matricies given for 2 blocks
TransMatrix for insertpt 4,4 0 rotation
 1             0             0             0
 0             1             0             0
 0             0             1             0
 4             4             0             1

TransposedMatrix
 1             0             0             4
 0             1             0             4
 0             0             1             0
 0             0             0             1


TransMatrix   insertpt 4,4 0 rotation
 0.707106781186547           0.707106781186548           0             0
-0.707106781186548           0.707106781186547           0             0
 0             0             1             0
 4             2             0             1

TransposedMatrix
 0.707106781186547          -0.707106781186548           0             4
 0.707106781186548           0.707106781186547           0             2
 0             0             1             0
 0             0             0             1

The transposed look kosher and works perfectly to bring an ent copied  from  the blockrecord to the blockref.
I just got to work on the inverse.
I might have a mix up between integers and doubles

MickD

  • King Gator
  • Posts: 3619
  • (x-in)->[process]->(y-out) ... simples!
Re: What is the TransMatrix in getsubentity?
« Reply #11 on: July 31, 2006, 09:38:16 PM »
Something doesn't look right, the bottom row below the vectors should be all 0's, these are there only to 'square' up the matrix or maybe for projection calc's, your translation vector should be down the right. I attached an image from the help doc's that may help. They definitely shouldn't be swapping from bottom to right side anyway I wouldn't think.
"Short cuts make long delays,' argued Pippin.”
J.R.R. Tolkien

MickD

  • King Gator
  • Posts: 3619
  • (x-in)->[process]->(y-out) ... simples!
Re: What is the TransMatrix in getsubentity?
« Reply #12 on: July 31, 2006, 09:45:45 PM »
I think all you need is to 'invert' it not transpose, try negating the values instead of swapping them around.
i.e. you can move something by a vector (3,2,1) and to move it the other way would be the vector negated (-3,-2,-1) which should point the other direction. Same should apply for rotations.
hth,
Mick.
"Short cuts make long delays,' argued Pippin.”
J.R.R. Tolkien

Bryco

  • Water Moccasin
  • Posts: 1882
Re: What is the TransMatrix in getsubentity?
« Reply #13 on: July 31, 2006, 10:25:07 PM »
Well Mick, you cracked it for a win.
Invert then transpose seems to work.
Thanks for the tip.
Now I'll have to tackle the multiplying formulae.

Bryco

  • Water Moccasin
  • Posts: 1882
Re: What is the TransMatrix in getsubentity?
« Reply #14 on: August 03, 2006, 11:44:38 PM »
These seem to work so far, they up for discussion and I,m sure they could be better
Code: [Select]
Function Transpose(Matrix As Variant) As Variant
    Dim transMat(0 To 3, 0 To 3) As Double
    Dim i As Integer, j As Integer
    For i = 0 To 3
        For j = 0 To 3
            transMat(i, j) = Matrix(j, i)
        Next j
    Next i
    Transpose = transMat
End Function



Function InverseMatrix(M As Variant) As Variant

    Dim Matrix() As Double
    Dim RowCt As Integer, ColCt As Integer
    Dim NewColCt As Integer
    Dim NoInverse As Boolean
    Dim i As Integer, j As Integer
   
    RowCt = UBound(M, 1)
    ColCt = UBound(M, 2)
    NewColCt = ColCt + RowCt + 1
    ReDim Matrix(RowCt, NewColCt)
   
    For i = 0 To RowCt
        'add the given matrix
        For j = 0 To ColCt
            If Rd(M(i, j), 0) Then
                Matrix(i, j) = 0
            Else
                Matrix(i, j) = M(i, j)
            End If
        Next j
        'add an identity crisis
        For j = ColCt + 1 To NewColCt
            If j - (ColCt + 1) = i Then
                Matrix(i, j) = 1
            Else
                Matrix(i, j) = 0
            End If
        Next
    Next i
   
    Matrix = MPivot(Matrix)
   
    'now see if it worked
   
    For i = 0 To RowCt
        For j = 0 To ColCt
            If j = i Then
                If Not Rd(Matrix(i, j), 1) Then
                    NoInverse = True
                    Debug.Print Matrix(i, j)
                    'Exit Function
                End If
            Else
                If Not Rd(Matrix(i, j), 0) Then
                    NoInverse = True
                    'Exit Function
                End If
            End If
        Next
     Next i
    If NoInverse Then
        'MsgBox "nope"
'        Debug.Print
'        For i = 0 To 3
'            Debug.Print Matrix(i, 0), Matrix(i, 1), Matrix(i, 2), Matrix(i, 3), Matrix(i, 4), Matrix(i, 5), Matrix(i, 6), Matrix(i, 7)
'        Next
        Matrix = OrderMatrix(Matrix)
    End If
    'If Not NoInverse Then
        ReDim InVMatrix(RowCt, ColCt)
        For i = 0 To RowCt
            For j = ColCt + 1 To NewColCt
                InVMatrix(i, j - (ColCt + 1)) = Matrix(i, j)
            Next j
        Next i
    'End If
   
    InverseMatrix = InVMatrix
   
End Function

Function MPivot(Matrix) As Variant

    Dim j As Integer, i As Integer, k As Integer
    Dim iP As Integer
    Dim Pivot As Double
    Dim ColCt As Integer
    Dim RowCt As Integer
    Dim PC As Double
    Dim Sign As Integer
    Dim Den As Integer
    Dim dTemp As Double
   
    RowCt = UBound(Matrix, 1)
    ColCt = UBound(Matrix, 2)
    'ij is row,column
   
    For i = 0 To RowCt
        For j = 0 To ColCt
            If Matrix(i, j) <> 0 Then
                Pivot = Matrix(i, j)
                iP = j
                Exit For
            End If
        Next j
        For k = 0 To RowCt
            If Not k = i Then
                PC = Matrix(k, iP)
                If PC = 0 Then GoTo Skip
                Sign = 1
                If Pivot < 0 Then
                    If PC < 0 Then
                        Sign = -1
                    End If
                Else
                    If PC > 0 Then
                        Sign = -1
                    End If
                End If
               
                Dim N1 As Double, N2 As Double
                N1 = Abs(Pivot): N2 = Abs(PC)
                Den = LCD(N1, N2)
           
                For j = 0 To ColCt
                    dTemp = Matrix(k, j) * N1 / Den + (Matrix(i, j) * N2 / Den * Sign)
                    If Rd(dTemp, 0) Then
                        Matrix(k, j) = 0
                    Else
                        Matrix(k, j) = dTemp
                    End If
                Next j
            End If
Skip:
        Next k
    Next i
   
   
    For i = 0 To RowCt
        For j = 0 To ColCt
            If Matrix(i, j) <> 0 Then
                Pivot = 1 / Matrix(i, j)
                Exit For
            End If
        Next j
        For j = 0 To ColCt
            Matrix(i, j) = Matrix(i, j) * Pivot
        Next j
    Next i
   
    MPivot = Matrix
End Function

Function OrderMatrix(Matrix As Variant) As Variant

    Dim i As Integer, j As Integer
    Dim k As Integer, l As Integer
    Dim RowCt As Integer, ColCt As Integer

    RowCt = UBound(Matrix, 1)
    ColCt = UBound(Matrix, 2)
    ReDim tempRow(ColCt) As Double
    'ij is row,column
   
    For i = 0 To RowCt
        For j = 0 To ColCt
            If j = i Then
                If Not Rd(Matrix(i, j), 1) Then
                    For k = 0 To RowCt
                        If Not k = i Then
                            If Rd(Matrix(k, j), 1) Then
                                For l = 0 To ColCt
                                    tempRow(l) = Matrix(k, l)
                                    Matrix(k, l) = Matrix(i, l)
                                    Matrix(i, l) = tempRow(l)
                                Next l
                            End If
                        End If
                    Next k
                End If
            End If
        Next j
    Next i

    OrderMatrix = Matrix

End Function





Function LCD(N1, N2) As Integer
'LowestCommonDenominator
    Dim iCt As Integer, i As Integer
    Dim Ans As Integer
    Ans = 1
    If N1 < N2 Then
        iCt = N1
    Else
        iCt = N2
    End If
   
    If iCt > 1 Then
        For i = 1 To iCt
            If (N1 Mod i = 0 And N2 Mod i = 0) Then Ans = i
        Next i
    End If
    LCD = Ans
   
End Function





Function TransformPt(M As Variant, P1 As Variant) As Variant
    Dim i As Integer
    Dim x As Double, y As Double, z As Double, D As Double
    Dim P(3) As Double
    For i = 0 To 2
        P(i) = P1(i)
    Next
    P(3) = 1
    For i = 0 To 3
        x = x + P(i) * M(i, 0)
        y = y + P(i) * M(i, 1)
        z = z + P(i) * M(i, 2)
        D = D + P(i) * M(i, 3)
    Next
    P1(0) = x: P1(1) = y: P1(2) = z
    TransformPt = P1

End Function


And this is the reason I wanted to use a matrix
Code: [Select]
Sub TestMultiplyMatrix()

    Dim P, Ent As AcadEntity
    Dim i As Integer
    Dim M, ContextData, TransMatrix
   
    ThisDrawing.Utility.GetSubEntity Ent, P, TransMatrix, ContextData
    ThisDrawing.ModelSpace.AddPoint P
    If VarType(ContextData) = vbEmpty Then
        MsgBox "This is not a block"
        Exit Sub
    End If
    M = InverseMatrix(TransMatrix)
     
    P = TransformPt(M, P)
    P = NearestPtOnObject(Ent, P)
    P = TransformPt(TransMatrix, P)
    ThisDrawing.ModelSpace.AddPoint P
   
End Sub

The NearestPtOnObject(Ent, P) function is not included as I'm still working on it.
I thought  getting this far was going to give me a little break from math but instead I just seemed to have opened Pandora's box.
The nearest point to an ellipse is insane. I dont even know if the article is offering a proof or a question. I'm inclined to go with the one that mentions "best guess",