### Author Topic: Circle Norm  (Read 5678 times)

0 Members and 1 Guest are viewing this topic.

#### Bryco

• Water Moccasin
• Posts: 1850 ##### Circle Norm
« on: August 02, 2007, 07:21:56 PM »
I knew that a circle will take the current ucs normal when being inserted but I didn't know it also took that normal when being added to the block record.
I guess the answer is to set the active ucs to world before creating any block with vba.
Somewhat tedious.
Any better ideas? ##### Re: Circle Norm
« Reply #1 on: August 02, 2007, 07:27:31 PM »
You should be able to calculate the normal in wcs terms given the current ucs normal you are using, same as getting points can sometimes trip you up with different ucs's, the bt record only sees the normal in the current ucs context which is quite different to wcs.
Forth is like the Tao: it is a Way, and is realized when followed.
Its fragility is its strength; its simplicity is its direction - Michael Ham

Lao Tzu: To attain knowledge, add things
every day; to obtain wisdom, remove things every day.

#### Bryco

• Water Moccasin
• Posts: 1850 ##### Re: Circle Norm
« Reply #2 on: August 02, 2007, 07:38:09 PM »
So either I set every objects normal or I make world current, it's probably a wash.
Mick is this happen in C# as well? ##### Re: Circle Norm
« Reply #3 on: August 02, 2007, 08:10:33 PM »
yes, and ARX.
The db does not know the difference between a normal in a ucs or a wcs, it's just a value but all values are stored as 'world' values so when everything gets drawn it doesn't need to change between ucs's for every object that was created in a different ucs if that makes sense.
Either way you will need to calculate your normal or orientation in space, ie. even if you do set ucs to world you still need to calculate the >rotated< normal in wcs before you add your circle to the db.

edit: clarified that normal needed is the rotated from world normal
« Last Edit: August 02, 2007, 10:13:41 PM by MickD »
Forth is like the Tao: it is a Way, and is realized when followed.
Its fragility is its strength; its simplicity is its direction - Michael Ham

Lao Tzu: To attain knowledge, add things
every day; to obtain wisdom, remove things every day.

#### Bryco

• Water Moccasin
• Posts: 1850 ##### Re: Circle Norm
« Reply #4 on: August 02, 2007, 09:52:23 PM »
actually if I make Wcs current the normal is fine (0,0,1).
The blockref also receives the ucs normal when inserted so I was looking at working out the rotation and leaving the normal as is. The math is a bit tricky (I can see it all but I seem to need a matrix so it's not worth while) so I think I'll insert it set the normal to 0,0,1 then transform it using the ucs matrix. It's the easy solution but I wouldn't say the best.

#### Bryco

• Water Moccasin
• Posts: 1850 ##### Re: Circle Norm
« Reply #5 on: August 02, 2007, 10:00:57 PM »
In case someone knows the math. The rotation would be found by transforming the ucs xdir vector from the ucs normal (crossproduct x and y) to a world normal, then comparing the new vector angle to the world x axis. ##### Re: Circle Norm
« Reply #6 on: August 02, 2007, 10:20:13 PM »
it sounds like you need to do what you said in the op, create the block in wcs then xform it to its required position, this is good practice anyway and keeps the origin-al math simple. If you can get the destination ucs when inserting the block it will be easy -

create block @ origin,
get current ucs (or similar)
build matrix with ucs
xform block and done.

hth
Forth is like the Tao: it is a Way, and is realized when followed.
Its fragility is its strength; its simplicity is its direction - Michael Ham

Lao Tzu: To attain knowledge, add things
every day; to obtain wisdom, remove things every day.

#### Bryco

• Water Moccasin
• Posts: 1850 ##### Re: Circle Norm
« Reply #7 on: August 03, 2007, 05:03:29 PM »
As an insert function the following works fine, but I do have to change the insertion point later (oBref.InsertionPoint = insPt), don't know why.

Code: [Select]
`Function InsertBlockref(Space As AcadBlock, insPt As Variant, sName As String, Optional Sc As Double = 1, Optional Rot As Double = 0) As AcadBlockReference    Dim oBref As AcadBlockReference    Dim Zero(2) As Double    Dim N(2) As Double, oUcs As AcadUCS    Dim Att        Set oBref = Space.InsertBlock(Zero, sName, Sc, Sc, Sc, Rot)    If ThisDrawing.GetVariable("Worlducs") = 1 Then        Set InsertBlockref = oBref        Exit Function    End If        N(2) = 1    oBref.Normal = N    If oBref.HasAttributes Then        For Each Att In oBref.GetAttributes            Att.Normal = N        Next Att    End If    Set oUcs = GetActiveUcs    oBref.TransformBy oUcs.GetUCSMatrix    oBref.InsertionPoint = insPt    Set InsertBlockref = oBrefEnd Function`
and a function

Code: [Select]
`Function GetActiveUcs() As AcadUCS    Dim Origin    Dim Xaxis    Dim Yaxis    Dim strNm As String, sUcs As String    sUcs = ThisDrawing.GetVariable("UCSNAME")    If sUcs = "" Then        ' Current UCS is not saved so get the data and save it        'A ucs is saved when a user makes and saves one or        ' a user clicks on an isoview button        With ThisDrawing            If .GetVariable("WORLDUCS") = 1 Then                Xaxis = Zero: Yaxis = Zero                Xaxis(0) = 1: Yaxis(1) = 1                Set GetActiveUcs = ThisDrawing.UserCoordinateSystems.Add(Zero, Xaxis, Yaxis, "World")                Exit Function            End If            Origin = .GetVariable("UCSORG")            Xaxis = .GetVariable("UCSXDIR")            Yaxis = .GetVariable("UCSYDIR")            strNm = "Active"        End With        Set GetActiveUcs = ThisDrawing.UserCoordinateSystems.Add(Zero, Xaxis, Yaxis, strNm)        'Changing the origin later stops the error message        '-2145320930   UCS X axis and Y axis are not perpendicular        GetActiveUcs.Origin = Origin        ThisDrawing.ActiveUCS = GetActiveUcs    Else        Select Case sUcs            Case "*TOP*", "TOP"                Set GetActiveUcs = SetOrthoUCS("Top")            Case "*BOTTOM*"                Set GetActiveUcs = SetOrthoUCS("Bottom")            Case "*LEFT*"                Set GetActiveUcs = SetOrthoUCS("Left")            Case "*RIGHT*"                Set GetActiveUcs = SetOrthoUCS("Right")            Case "*FRONT*"                Set GetActiveUcs = SetOrthoUCS("Front")            Case "*BACK*"                Set GetActiveUcs = SetOrthoUCS("Back")            Case Else                Set GetActiveUcs = ThisDrawing.ActiveUCS  'current UCS is saved            End Select    End IfEnd Function`
« Last Edit: August 03, 2007, 05:16:12 PM by Bryco » ##### Re: Circle Norm
« Reply #8 on: January 02, 2008, 05:47:44 PM »
Hi Bryco, thought I'd resurrect this thread as I'm having the same problem myself now, I can't for the life of me know why they didn't implement more geometry classes in vba, particularly the matrix. Oh well...

I take it from the function above that if there is no ucs name i.e. it is "" that we will get a null object id error so we have to save the current ucs to the ucs table and grab it from there to transform an object to current ucs, is this right??

Also, do you have the SetOrthoUCS function handy?
thanks,
Mick.
Forth is like the Tao: it is a Way, and is realized when followed.
Its fragility is its strength; its simplicity is its direction - Michael Ham

Lao Tzu: To attain knowledge, add things
every day; to obtain wisdom, remove things every day.

#### Bryco

• Water Moccasin
• Posts: 1850 ##### Re: Circle Norm
« Reply #9 on: January 02, 2008, 07:17:00 PM »
Agreed Mick, C# has so much good math on tap.
Code: [Select]
`Public Function SetOrthoUCS(Optional strUcs As String = "Top") As AcadUCS    Dim dOrigin(2) As Double    Dim dXaxisPnt(2) As Double    Dim dYaxisPnt(2) As Double    'all the ucs' will originate from 0,0,0 as per the behavior in acad    Select Case strUcs        Case "Top"            dXaxisPnt(0) = 1: dXaxisPnt(1) = 0: dXaxisPnt(2) = 0            dYaxisPnt(0) = 0: dYaxisPnt(1) = 1: dYaxisPnt(2) = 0               Case "Bottom"            dXaxisPnt(0) = -1: dXaxisPnt(1) = 0: dXaxisPnt(2) = 0            dYaxisPnt(0) = 0: dYaxisPnt(1) = 1: dYaxisPnt(2) = 0                Case "Right"            dXaxisPnt(0) = 0: dXaxisPnt(1) = 1: dXaxisPnt(2) = 0            dYaxisPnt(0) = 0: dYaxisPnt(1) = 0: dYaxisPnt(2) = 1                    Case "Left"            dXaxisPnt(0) = 0: dXaxisPnt(1) = -1: dXaxisPnt(2) = 0            dYaxisPnt(0) = 0: dYaxisPnt(1) = 0: dYaxisPnt(2) = 1                    Case "Front"            dXaxisPnt(0) = 1: dXaxisPnt(1) = 0: dXaxisPnt(2) = 0            dYaxisPnt(0) = 0: dYaxisPnt(1) = 0: dYaxisPnt(2) = 1                  Case "Back"            dXaxisPnt(0) = -1: dXaxisPnt(1) = 0: dXaxisPnt(2) = 0            dYaxisPnt(0) = 0: dYaxisPnt(1) = 0: dYaxisPnt(2) = 1                    Case Else            Exit Function    End Select    Set SetOrthoUCS = ThisDrawing.UserCoordinateSystems.Add(dOrigin, dXaxisPnt, dYaxisPnt, strUcs)    ThisDrawing.ActiveUCS = SetOrthoUCSEnd Function` ##### Re: Circle Norm
« Reply #10 on: January 02, 2008, 07:30:10 PM »
Thanks Bryco, I'll give those a run and see how it goes.
Forth is like the Tao: it is a Way, and is realized when followed.
Its fragility is its strength; its simplicity is its direction - Michael Ham

Lao Tzu: To attain knowledge, add things
every day; to obtain wisdom, remove things every day.

#### Bryco

• Water Moccasin
• Posts: 1850 ##### Re: Circle Norm
« Reply #11 on: January 02, 2008, 07:32:17 PM »
As far as matrices. You are ok for the ucs as the getvars are updated
Code: [Select]
`Function UcsM() As Variant    Dim M(3, 3) As Double    Dim Orig As Variant    Orig = ThisDrawing.GetVariable("Ucsorg")    Dim x, Y, Z    x = ThisDrawing.GetVariable("UCSXDIR")    Y = ThisDrawing.GetVariable("UCSYDIR")    Z = Crossproduct(x, Y)    M(0, 0) = x(0): M(0, 1) = Y(0): M(0, 2) = Z(0): M(0, 3) = Orig(0)    M(1, 0) = x(1): M(1, 1) = Y(1): M(1, 2) = Z(1): M(1, 3) = Orig(1)    M(2, 0) = x(2): M(2, 1) = Y(2): M(2, 2) = Z(2): M(2, 3) = Orig(2)    M(3, 0) = 0: M(3, 1) = 0: M(3, 2) = 0: M(3, 3) = 1        UcsM = M    End Function'VectorsFunction XYZ(x As Double, Y As Double, Z As Double) As Variant    Dim P(2) As Double    P(0) = x: P(1) = Y: P(2) = Z    XYZ = PEnd FunctionFunction AddVectors(v1, v2) As Variant    Dim V3(2) As Double    V3(0) = v1(0) + v2(0)    V3(1) = v1(1) + v2(1)    V3(2) = v1(2) + v2(2)    AddVectors = V3End FunctionFunction SubtractVectors(v1, v2) As Variant    Dim V3(2) As Double    V3(0) = v1(0) - v2(0)    V3(1) = v1(1) - v2(1)    V3(2) = v1(2) - v2(2)    SubtractVectors = V3End FunctionFunction DotProduct(v1, v2)    Dim V3(2) As Double    V3(0) = v1(0) * v2(0)    V3(1) = v1(1) * v2(1)    V3(2) = v1(2) * v2(2)    DotProduct = V3End FunctionFunction Crossproduct(A, b) As Variant    Dim Ax As Double, Ay As Double, Az As Double    Dim Bx As Double, By As Double, Bz As Double    Dim Unit As Double    Dim c(2) As Double    'get CrossProduct    Ax = A(0): Ay = A(1): Az = A(2)    Bx = b(0): By = b(1): Bz = b(2)        c(0) = Ay * Bz - Az * By    c(1) = Az * Bx - Ax * Bz    c(2) = Ax * By - Ay * Bx        'Convert to unit normal    Unit = Sqr(c(0) * c(0) + c(1) * c(1) + c(2) * c(2))    c(0) = c(0) / Unit: c(1) = c(1) / Unit: c(2) = c(2) / Unit    Crossproduct = cEnd FunctionFunction NormaliseVector(V As Variant) As Variant    Dim Unit As Double    Dim Vn(2) As Double    Unit = Sqr(V(0) * V(0) + V(1) * V(1) + V(2) * V(2))    Vn(0) = V(0) / Unit: Vn(1) = V(1) / Unit: Vn(2) = V(2) / Unit    NormaliseVector = VnEnd Function`
Mick there's some matrix stuff in the text file.
The inverse matrix will be handy as it is a bear to write ##### Re: Circle Norm
« Reply #12 on: January 02, 2008, 07:42:01 PM »
Nice code there Bryco! will come in handy for sure.
thanks again.
Forth is like the Tao: it is a Way, and is realized when followed.
Its fragility is its strength; its simplicity is its direction - Michael Ham

Lao Tzu: To attain knowledge, add things
every day; to obtain wisdom, remove things every day.

#### Bryco

• Water Moccasin
• Posts: 1850 ##### Re: Circle Norm
« Reply #13 on: January 02, 2008, 08:00:57 PM »
No wuckers Mick,  I still owe you I reckon. ##### Re: Circle Norm
« Reply #14 on: January 02, 2008, 09:42:29 PM »
I don't know about that, what I do know though is the UCS is a pig to work with in vba though!

All I'm trying to do is save the current ucs, set the ucs to world, do my mojo then set it back. How I have it 'should' work though I still get strange results if a user picked ucs's vector lines up with a std ucs...strange

Code: [Select]
`Dim ucs As AcadUCSSet ucs = GetActiveUcsSetOrthoUCSent.TransformBy (ThisDrawing.ActiveUCS.GetUCSMatrix)ThisDrawing.ActiveUCS = ucs`
The SetOrthoUcs sets the ucs to 'top' by default so it should be going to 'world' and it also looks after any conditions where it is set to world.

It's no real biggie and I can live with it, just annoying.
Forth is like the Tao: it is a Way, and is realized when followed.
Its fragility is its strength; its simplicity is its direction - Michael Ham

Lao Tzu: To attain knowledge, add things
every day; to obtain wisdom, remove things every day.