Author Topic: Fillet question  (Read 2291 times)

0 Members and 1 Guest are viewing this topic.

WOWENS

  • Newt
  • Posts: 59
Fillet question
« on: July 13, 2012, 11:18:19 AM »
I wrote this code (with help from reading other peoples posted code)  and it seems to work but sometimes the Arc is counterclockwise and other times clockwise.
maybe one of you could tell me were i went wrong with what part of my code.

Imports System

Imports System.Runtime.InteropServices
Imports Autodesk.AutoCAD
Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.Geometry
Imports Autodesk.AutoCAD.EditorInput
Imports Autodesk.AutoCAD.LayerManager
Imports Autodesk.AutoCAD.Windows
Imports Autodesk.AutoCAD.ApplicationServices.Application
Imports Autodesk.AutoCAD.PlottingServices


Namespace AutoCAD_VB_plug_in1

    Public Class MyCommands

        <CommandMethod("Test", CommandFlags.UsePickSet + CommandFlags.Session)> _
        Public Sub TestFillet()

            Dim db As Database = HostApplicationServices.WorkingDatabase
            Dim doc As Document = Application.DocumentManager.MdiActiveDocument

            Using acLckDocCur As DocumentLock = doc.LockDocument
                Using tr As Transaction = db.TransactionManager.StartTransaction()
                    Try

                        Dim Line1ID As ObjectId = PickEntity()
                        Dim ent1 As Entity = tr.GetObject(Line1ID, OpenMode.ForRead)
                        Dim Newline1 As Line = TryCast(ent1, Line)

                        Dim Line2ID As ObjectId = PickEntity()
                        Dim ent2 As Entity = tr.GetObject(Line2ID, OpenMode.ForRead)
                        Dim Newline2 As Line = TryCast(ent2, Line)

                        Dim Rad As Double = GetDouble("Enter Fillet Radius")

                        Dim MYFillet As List(Of Object) = AddFillet(db, Newline1, Newline2, Rad)

                        If MYFillet.Item(0) = True Then
                            Dim ConLine1 As Geometry.LineSegment3d = MYFillet.Item(1)
                            Dim ConLine2 As Geometry.LineSegment3d = MYFillet.Item(2)
                            Dim ConArc3d As Geometry.CircularArc3d = MYFillet.Item(3)
                            Dim MyMatrix3d As Matrix3d = MYFillet.Item(4)

                            'sometimes the arc is counterclockwise other times clockwise
                            Dim arc As Arc = New Arc(ConArc3d.Center, ConArc3d.Radius, ConArc3d.StartAngle, ConArc3d.EndAngle)
                            arc.TransformBy(MyMatrix3d)

                            Newline1.UpgradeOpen()
                            Newline1.StartPoint = ConLine1.StartPoint
                            Newline1.EndPoint = ConLine1.EndPoint

                            Newline2.UpgradeOpen()
                            Newline2.StartPoint = ConLine2.StartPoint
                            Newline2.EndPoint = ConLine2.EndPoint

                            AddToCurrentSpace(db, arc)
                        Else
                            ShowAlertDialog(MYFillet.Item(1).ToString)
                        End If

                        tr.Commit()

                    Catch ex As Autodesk.AutoCAD.Runtime.Exception

                    End Try

                End Using
            End Using

        End Sub

        'credit to Hallex one of his post was really helpful
        Private Function AddFillet(ByVal MyDB As Database, ByVal Line1 As Line, ByVal Line2 As Line, ByVal Radius As Double) As List(Of Object)
            Dim DicOBJS As List(Of Object) = New List(Of Object)
            Dim bFlipLine1 As Boolean = False
            Dim bFlipLine2 As Boolean = False

            Try
                Dim intpts As New Point3dCollection()

                Line1.IntersectWith(Line2, Intersect.ExtendBoth, intpts, IntPtr.Zero, IntPtr.Zero)

                If intpts.Count <> 1 Then
                    DicOBJS.Add(False)
                    DicOBJS.Add("Lines are colinear or does not intersects")
                    Return DicOBJS
                End If

                Dim IntPoint As Point3d = intpts(0)

                Dim Line1SP As Point3d = IntPoint
                Dim Line1EP As Point3d

                Dim Line2SP As Point3d = IntPoint
                Dim Line2EP As Point3d

                If IntPoint.DistanceTo(Line1.StartPoint) >= IntPoint.DistanceTo(Line1.EndPoint) Then
                    Line1EP = Line1.StartPoint
                    bFlipLine1 = True
                Else
                    Line1EP = Line1.EndPoint
                End If

                If IntPoint.DistanceTo(Line2.StartPoint) >= IntPoint.DistanceTo(Line2.EndPoint) Then
                    Line2EP = Line2.StartPoint
                    bFlipLine2 = True
                Else
                    Line2EP = Line2.EndPoint
                End If

                Dim MyMatrix3d As Matrix3d = UCS_Create(IntPoint, Line1EP, Line2EP)

                'Transform points to new Matrix3d
                Dim Newip As Point3d = IntPoint.TransformBy(MyMatrix3d.Inverse)
                Dim SP1 As Point3d = Line1SP.TransformBy(MyMatrix3d.Inverse)
                Dim EP1 As Point3d = Line1EP.TransformBy(MyMatrix3d.Inverse)
                Dim SP2 As Point3d = Line2SP.TransformBy(MyMatrix3d.Inverse)
                Dim EP2 As Point3d = Line2EP.TransformBy(MyMatrix3d.Inverse)

                'calculate angle of lines
                Dim ang1 As Double = AngleFromX(Newip, EP1)
                Dim ang2 As Double = AngleFromX(Newip, EP2)

                'calculate angle between lines
                Dim angc As Double = Math.Abs(ang2 - ang1)

                'Get Distance to Tangent along Lines
                Dim DistTOTangent As Double = (Radius + (Radius * Math.Cos(angc))) / Math.Sin(angc)

                'Move Start Point of Lines to The Tangent Point
                SP1 = PolarPoint3D(Newip, ang1, DistTOTangent)
                SP2 = PolarPoint3D(Newip, ang2, DistTOTangent)

                If Newip.DistanceTo(EP1) < DistTOTangent Then
                    DicOBJS.Add(False)
                    DicOBJS.Add("Radius to Large")
                    Return DicOBJS
                End If

                If Newip.DistanceTo(EP2) < DistTOTangent Then
                    DicOBJS.Add(False)
                    DicOBJS.Add("Radius to Large")
                    Return DicOBJS
                End If

                Dim ArcCenterPoint As Point3d = PolarPoint3D(Newip, angc * 0.5, Math.Sqrt((DistTOTangent * DistTOTangent) + (Radius * Radius)))

                Dim ArcStartAngle As Double
                Dim ArcEndAngle As Double

                ' check on direction of points
                If isLeft(EP2, Newip, EP1) Then
                    ArcStartAngle = AngleFromX(ArcCenterPoint, SP2)
                    ArcEndAngle = AngleFromX(ArcCenterPoint, SP1)
                Else
                    ArcStartAngle = AngleFromX(ArcCenterPoint, SP1)
                    ArcEndAngle = AngleFromX(ArcCenterPoint, SP2)
                End If

                If bFlipLine1 = True Then
                    Dim TempSP1 As Point3d = SP1
                    SP1 = EP1
                    EP1 = TempSP1
                End If

                If bFlipLine2 = True Then
                    Dim TempSP2 As Point3d = SP2
                    SP2 = EP2
                    EP2 = TempSP2
                End If

                Dim ConArc3d As Geometry.CircularArc3d = New Geometry.CircularArc3d(ArcCenterPoint, Vector3d.ZAxis, Vector3d.ZAxis, Radius, ArcStartAngle, ArcEndAngle)
                Dim ConLine1 As Geometry.LineSegment3d = New Geometry.LineSegment3d(SP1.TransformBy(MyMatrix3d), EP1.TransformBy(MyMatrix3d))
                Dim ConLine2 As Geometry.LineSegment3d = New Geometry.LineSegment3d(SP2.TransformBy(MyMatrix3d), EP2.TransformBy(MyMatrix3d))

                DicOBJS.Add(True)
                DicOBJS.Add(ConLine1)
                DicOBJS.Add(ConLine2)
                DicOBJS.Add(ConArc3d)
                DicOBJS.Add(MyMatrix3d)

                Return DicOBJS
            Catch ex As Autodesk.AutoCAD.Runtime.Exception
                DicOBJS.Add(False)
                DicOBJS.Add("UnKnown Error")
                Return DicOBJS
            End Try

        End Function

        Private Function PickEntity() As ObjectId
            Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor

            Dim peo As PromptEntityOptions = New PromptEntityOptions("\nSelect AutoCad Entity :")
            Dim per As PromptEntityResult = ed.GetEntity(peo)

            If (per.Status = PromptStatus.OK) Then
                Return per.ObjectId
            Else
                Return ObjectId.Null
            End If

        End Function

        Private Function GetDouble(ByVal sPrompt As String, Optional ByVal AllowNegative As Boolean = False, Optional ByVal AllowNone As Boolean = False, Optional ByVal AllowZero As Boolean = False, Optional ByVal DefaultValue As Double = 0, Optional ByVal UseDefaultValue As Boolean = False) As Double
            Dim DwgEditor As Editor = DocumentManager.MdiActiveDocument.Editor

            Dim myPDO As New PromptDoubleOptions(sPrompt)

            Try
                myPDO.AllowNegative = AllowNegative
                myPDO.AllowNone = AllowNone
                myPDO.AllowZero = AllowZero
                myPDO.DefaultValue = DefaultValue
                myPDO.UseDefaultValue = UseDefaultValue

                Dim myPDR As PromptDoubleResult = DwgEditor.GetDouble(myPDO)

                DwgEditor.WriteMessage(vbCrLf)

                Select Case myPDR.Status
                    Case PromptStatus.OK
                        Return myPDR.Value
                    Case PromptStatus.Cancel
                        Return 0
                End Select

            Catch
                Return 0
            End Try

        End Function


        Private Function AddToCurrentSpace(ByVal MyDB As Database, ByVal EntityIn As Entity) As DatabaseServices.ObjectId
            Dim DwgEditor As Editor = TryCast(Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor, Editor)

            Using myTrans As Transaction = MyDB.TransactionManager.StartTransaction
                Try
                    Dim myBT As BlockTable = TryCast(MyDB.BlockTableId.GetObject(OpenMode.ForRead), BlockTable)
                    Dim myCurrentSpace As BlockTableRecord = TryCast(myBT.Database.CurrentSpaceId.GetObject(OpenMode.ForWrite), BlockTableRecord)

                    myCurrentSpace.AppendEntity(EntityIn)
                    myTrans.AddNewlyCreatedDBObject(EntityIn, True)
                    myTrans.Commit()

                    Return EntityIn.ObjectId
                Catch ex As Autodesk.AutoCAD.Runtime.Exception
                    DwgEditor.WriteMessage(ex.Message + vbLf + ex.StackTrace)
                    myTrans.Abort()
                    Return ObjectId.Null
                End Try
            End Using

        End Function

        Private Function UCS_Create(ByVal OriginPoint As Point3d, ByVal XAxisPoint As Point3d, ByVal YAxisPoint As Point3d) As Matrix3d
            Dim xAxis As Vector3d
            Dim yAxis As Vector3d
            Dim ZAxis As Vector3d

            If OriginPoint.IsEqualTo(XAxisPoint) Or OriginPoint.IsEqualTo(YAxisPoint) Or XAxisPoint.IsEqualTo(YAxisPoint) Then
                Return Nothing
            End If

            Try
                xAxis = OriginPoint.GetVectorTo(XAxisPoint).GetNormal
                ZAxis = xAxis.CrossProduct(YAxisPoint.GetVectorTo(OriginPoint).GetNormal).GetNormal
                yAxis = xAxis.CrossProduct(ZAxis).GetNormal

                Dim NewMatrix3d As Matrix3d = Matrix3d.AlignCoordinateSystem(Point3d.Origin, Vector3d.XAxis, Vector3d.YAxis, Vector3d.ZAxis, OriginPoint, xAxis, yAxis, ZAxis)

                Return NewMatrix3d
            Catch
                Return Nothing
            End Try
        End Function

        Private Function PolarPoint3D(ByVal BasePoint As Point3d, ByVal angle As Double, ByVal distance As Double) As Point3d
            Dim x As Double = distance * Math.Cos(angle)
            Dim y As Double = distance * Math.Sin(angle)

            Return New Point3d(BasePoint.X + x, BasePoint.Y + y, BasePoint.Z)
        End Function

        '''author Unknown
        Private Function AngleFromX(ByVal pt1 As Point3d, ByVal pt2 As Point3d) As Double
            Dim ucsplane As New Plane(New Point3d(0, 0, 0), New Vector3d(0, 0, 1))

            Dim vec As Vector3d = pt2 - pt1
            Dim ang As Double = vec.AngleOnPlane(ucsplane)

            If ang * 180 / Math.PI = 360 Then
                ang = 0
            End If

            Return ang
        End Function

        '''isleft function (edited) // credit to Bryco
        Private Function isLeft(ByVal spt As Point3d, ByVal ept As Point3d, ByVal apt As Point3d) As Boolean
            Dim result As Boolean = False

            Dim Ans As Double = ((ept.X - spt.X) * (apt.Y - spt.Y) - (apt.X - spt.X) * (ept.Y - spt.Y))

            If Ans > 0 Then
                result = True
            Else
                result = False
            End If

            Return result
        End Function

    End Class

End Namespace

WOWENS

  • Newt
  • Posts: 59
Re: Fillet question
« Reply #1 on: July 13, 2012, 03:30:03 PM »
after thinking about my code i have decided the problem is in this one function,
because it will set the Z axis opposite of what autocad has.
when using the same UCS
example Z Axis from code 0,0,-1  but the Z axis from the current UCS will be 0,0,1
or
example Z Axis from code 0,0,1  but the Z axis from the current UCS will be 0,0,-1

so as you can tell i'm not real sure about how to fix this so does anyone have a idea?

Private Function UCS_Create(ByVal OriginPoint As Point3d, ByVal XAxisPoint As Point3d, ByVal YAxisPoint As Point3d) As Matrix3d
        Dim xAxis As Vector3d
        Dim yAxis As Vector3d
        Dim ZAxis As Vector3d

        If OriginPoint.IsEqualTo(XAxisPoint) Or OriginPoint.IsEqualTo(YAxisPoint) Or XAxisPoint.IsEqualTo(YAxisPoint) Then
            Return Nothing
        End If

        Try
            xAxis = OriginPoint.GetVectorTo(XAxisPoint).GetNormal
            ZAxis = xAxis.CrossProduct(YAxisPoint.GetVectorTo(OriginPoint).GetNormal).GetNormal
            yAxis = xAxis.CrossProduct(ZAxis).GetNormal

            Dim NewMatrix3d As Matrix3d = Matrix3d.AlignCoordinateSystem(Point3d.Origin, Vector3d.XAxis, Vector3d.YAxis, Vector3d.ZAxis, OriginPoint, xAxis, yAxis, ZAxis)

            Return NewMatrix3d
        Catch
            Return Nothing
        End Try
    End Function

fixo

  • Guest
Re: Fillet question
« Reply #2 on: July 14, 2012, 07:09:22 AM »
Not sure about, perhaps you may want to change on:
   xAxis = OriginPoint.GetVectorTo(XAxisPoint).GetNormal
                ZAxis = xAxis.CrossProduct(YAxisPoint.GetVectorTo(OriginPoint).GetNormal).GetNormal
                yAxis = xAxis.CrossProduct(ZAxis).GetNormal.Negate

Found also:
http://adndevblog.typepad.com/autocad/2012/07/align-the-ucs-to-an-entity.html

~'J'~
« Last Edit: July 14, 2012, 09:19:09 AM by fixo »

WOWENS

  • Newt
  • Posts: 59
Re: Fillet question
« Reply #3 on: July 16, 2012, 08:08:38 AM »
thanks for the help. but it did not work, this is how i got it to work.
            xAxis = OriginPoint.GetVectorTo(XAxisPoint).GetNormal
            ZAxis = xAxis.CrossProduct(YAxisPoint.GetVectorTo(OriginPoint).GetNormal).GetNormal
            yAxis = xAxis.CrossProduct(ZAxis).GetNormal
             
            'reset the Zaxis once more
            ZAxis = xAxis.CrossProduct(yAxis).GetNormal

            Dim NewMatrix3d As Matrix3d = Matrix3d.AlignCoordinateSystem(Point3d.Origin, Vector3d.XAxis, Vector3d.YAxis, Vector3d.ZAxis, OriginPoint, xAxis, yAxis, ZAxis)

fixo

  • Guest
Re: Fillet question
« Reply #4 on: July 16, 2012, 08:34:52 AM »
Thanks for the sharing the solution

~'J'~