Author Topic: Polylines and Mathematics  (Read 3678 times)

0 Members and 1 Guest are viewing this topic.

robplatt

  • Guest
Polylines and Mathematics
« on: March 18, 2007, 01:02:35 AM »
Hi,
I think this is mainly a maths problem, but I'm posting it here because I need a VBA solution.
One property of a Polyline is .GetBulge, which is used to describe an arc segment. The online manual describes .GetBulge as being equal to: "...the tangent of 1/4 of the included angle for the arc between the selected vertex and the next vertex in the polyline's vertex list..."
I need to establish the radius and centerpoint of the arc segment from this information. I thought my trig. was reasonable, but I've tried everything I can think of and just can't see how to do it.
DXF codes are no help because they also only list the bulge factor.
It is obviously possible because if I "list" the polyline up comes all the information I need.
Any help in translating this will be very gratefully received.
Thanks.

Bryco

  • Water Moccasin
  • Posts: 1882
Re: Polylines and Mathematics
« Reply #1 on: March 18, 2007, 11:45:36 AM »
A better description of a bulge is the tangent of the arc's rise/1/2 the segment length
Code: [Select]
Function RadiusFromBulge(Bulge As Double, pt1, pt2) As Double
    Dim Dist As Double, Rad As Double
    Dist = 0.5 * Length(pt1, pt2)
    RadiusFromBulge = Abs(Dist / Sin(Atn(Bulge) * 2))

End Function

Code: [Select]
Public Function CenterFromBulge(P1, P2, Bulge As Double)
   
    If UBound(P1) = 1 Then
        ReDim Preserve P1(2)
    End If
    If UBound(P2) = 1 Then
        ReDim Preserve P2(2)
    End If
    Dim Ang As Double, CenPt(2) As Double
    Dim Rad As Double, Dist As Double
    Dist = Length(P1, P2) 'Use your length function
    Rad = Abs(0.5 * Dist / Sin(Atn(Bulge) * 2))
    Ang = ThisDrawing.Utility.AngleFromXAxis(P1, P2)
    If Bulge > 0 Then
        Ang = Ang + ((0.5 * pi) - (Atn(Bulge) * 2))
    Else
        Ang = Ang - ((0.5 * pi) + (Atn(Bulge) * 2))
    End If
    CenPt(0) = P1(0) + Cos(Ang) * Rad
    CenPt(1) = P1(1) + Sin(Ang) * Rad
    CenPt(2) = 0
    CenterFromBulge = CenPt
 
End Function
This looks long winded but it's optimised for x,y points(pline coordinates)  or x,y,z points
Kerry asked the question "Is it better to multiply or use ^2.
It goes faster using multiplication.
Code: [Select]
Public Function Length(StartPoint As Variant, EndPoint As Variant) As Double

    Dim Stx As Double, Sty As Double, Stz As Double
    Dim Enx As Double, Eny As Double, Enz As Double
    Dim dX As Double, dY As Double, Dz As Double
    Dim i As Integer
    If IsEmpty(StartPoint) Then Err.Raise 13
    i = UBound(StartPoint)
    If UBound(EndPoint) = i Then
        If i > 0 Then
            Stx = StartPoint(0): Sty = StartPoint(1)
            Enx = EndPoint(0): Eny = EndPoint(1)
            dX = Stx - Enx
            dY = Sty - Eny
            If i = 1 Then
                Length = Sqr(dX * dX + dY * dY)
            Else
                Stz = StartPoint(2): Enz = EndPoint(2)
                Dz = Stz - Enz
                Length = Sqr((dX * dX) + (dY * dY) + (Dz * Dz))
            End If
        Else
            Exit Function
        End If
    Else
        Exit Function
    End If

End Function

DaveW

  • Guest
Re: Polylines and Mathematics
« Reply #2 on: March 18, 2007, 11:55:53 AM »
Better code above while typing...
« Last Edit: March 18, 2007, 11:57:56 AM by DaveW »

robplatt

  • Guest
Re: Polylines and Mathematics
« Reply #3 on: March 19, 2007, 04:52:50 AM »
Thanks Bryco, suddenly life seems a whole lot brighter!

SEANT

  • Bull Frog
  • Posts: 345
Re: Polylines and Mathematics
« Reply #4 on: March 19, 2007, 06:15:24 AM »
Nice.  These are useful functions.

Quote
Code: [Select]
    CenPt(0) = P1(0) + Cos(Ang) * Rad
    CenPt(1) = P1(1) + Sin(Ang) * Rad
    CenPt(2) = 0
    CenterFromBulge = CenPt
 
End Function

They appear optimized for WCS.  Is the notion that translation to and from OCS is the responsibility of a separate routine?
Sean Tessier
AutoCAD 2016 Mechanical

Bryco

  • Water Moccasin
  • Posts: 1882
Re: Polylines and Mathematics
« Reply #5 on: March 19, 2007, 10:41:55 AM »
Good point, it needs to be rewritten for 3d

Bryco

  • Water Moccasin
  • Posts: 1882
Re: Polylines and Mathematics
« Reply #6 on: March 24, 2007, 12:47:17 PM »
3d version
Code: [Select]
Public Function CenterFromBulge(oPline As AcadLWPolyline, index As Integer) As Variant

    If oPline Is Nothing Then Exit Function
    If (UBound(oPline.Coordinates) - 1) / 2 < index + 1 Then Exit Function
    Dim P1, P2
    Dim Ang As Double, BulgeAng As Double
    Dim CenPt(2) As Double
    Dim Rad As Double, Dist As Double
    Dim Bulge As Double
   
    P1 = oPline.Coordinate(index)
    P2 = oPline.Coordinate(index + 1)
    Bulge = oPline.GetBulge(index)
    If Bulge = 0 Or Bulge = 1 Or Bulge = -1 Then
        CenPt(0) = (P1(0) + P2(0)) / 2
        CenPt(1) = (P1(1) + P2(1)) / 2
        GoTo Skip
    End If
   
    BulgeAng = Atn(Bulge) * 2
    Dist = Length(P1, P2) 'Use your length function
    Rad = Abs(0.5 * Dist / Sin(BulgeAng))
    Ang = AngFromX(P1, P2)
    Debug.Print Ang, BulgeAng, (0.5 * pi) - (pi - BulgeAng)
    Debug.Print 0.5 * pi, pi - Abs(BulgeAng)
    If Bulge > 0 Then
        If Bulge > 1 Then
            Ang = Ang - ((0.5 * pi) - (pi - BulgeAng))
        Else
            Ang = Ang + ((0.5 * pi) - BulgeAng)
        End If
    Else
        If Bulge < -1 Then
            Ang = Ang + ((0.5 * pi) - (pi + BulgeAng))
        Else
            Ang = Ang - ((0.5 * pi) + BulgeAng) 'bulgeang is negative
        End If
    End If
   
    CenPt(0) = P1(0) + Cos(Ang) * Rad
    CenPt(1) = P1(1) + Sin(Ang) * Rad
Skip:
    CenPt(2) = oPline.Elevation
    CenterFromBulge = ThisDrawing.Utility.TranslateCoordinates(CenPt, acOCS, acWorld, 0, oPline.Normal)

End Function

Function
Code: [Select]
Public Function AngFromX(P1, P2) As Double
   
    'If Not PointCheck(p1, p2) Then Exit Function
    Dim dX As Double, dY As Double
    Dim dAng As Double
    dY = P2(1) - P1(1): dX = P2(0) - P1(0)
    If Rd(dY, 0) Then  'Line is horizontal
        If Rd(dX, 0) Then Exit Function
        If dX > 0 Then
            dAng = 0
        Else
            dAng = pi '180
        End If
    ElseIf Rd(dX, 0) Then  'Line is vertical
        If dY > 0 Then
            dAng = 0.5 * pi '90
        Else
            dAng = 1.5 * pi '270
        End If
    Else
        dAng = Atn(dY / dX)
        If dAng < 0 Then '90->270
            If dX < 0 Then '90->270
                dAng = pi + dAng '90->180
            Else '270->360
                dAng = 2 * pi + dAng
            End If
        Else
            If dX < 0 And dY < 0 Then '180->270
                dAng = pi + dAng
            End If
        End If
    End If
    AngFromX = dAng
End Function

Function Rd(num1 As Variant, num2 As Variant) As Boolean
    Dim dRet As Double
    dRet = num1 - num2
    If Abs(dRet) < 0.00000001 Then Rd = True
End Function


« Last Edit: March 26, 2007, 10:59:56 PM by Bryco »

SEANT

  • Bull Frog
  • Posts: 345
Re: Polylines and Mathematics
« Reply #7 on: March 26, 2007, 06:53:06 AM »
This 3D update works nicely and will be even more useful. 

On quick note, this updated code includes a Constant - PI - and a function - Rd() - not present.  It's not a big deal but may discourage others from using the code.
Sean Tessier
AutoCAD 2016 Mechanical

Bryco

  • Water Moccasin
  • Posts: 1882
Re: Polylines and Mathematics
« Reply #8 on: March 26, 2007, 11:02:22 PM »
Fixed.
I've almost given up posting code having to include the the same functions time and time again.

SEANT

  • Bull Frog
  • Posts: 345
Re: Polylines and Mathematics
« Reply #9 on: March 27, 2007, 06:21:56 AM »
I'm familiar with the effort required for a successful "Pack 'n Go" of a routine from local DVB to forum post (i.e., http://discussion.autodesk.com/thread.jspa?messageID=17866) Actually, that example post had issues that needed to be addressed.

What is the best method to minimize the effort?  Would the posting of, and subsequent reference to, a library file (SEANTLib.bas) to the Lilly Pond be the recommended?
Sean Tessier
AutoCAD 2016 Mechanical

Bryco

  • Water Moccasin
  • Posts: 1882
Re: Polylines and Mathematics
« Reply #10 on: March 27, 2007, 10:03:22 AM »
That sounds pretty good.
I get sick of making a new project just to check.
It is probably possible to debug.print all the functions used in a sub.