VBA
Discuss AutoCAD ActiveX and VBA (Visual Basic for Applications) questions here.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

How to copy part of polyline from a start point to and end point

7 REPLIES 7
SOLVED
Reply
Message 1 of 8
imagination_s
2719 Views, 7 Replies

How to copy part of polyline from a start point to and end point

Hello Everyone,

I have a problem with autocad  Pline that i want to copy one part of the Pline and put it in another Layer and so on

But doing this through  Autocad 2008 VBA Macro.

Can someone Help?

Please.

 

The pictures show what i want to do

7 REPLIES 7
Message 2 of 8
norman.yuan
in reply to: imagination_s

Since you only need part of the polyline to be "copied", you cannot use AcadEntity/AcadLWPolyline.Copy() to get what you want.

 

You need to create a new poyline based on the vertices of the partial polyline, up to the point where the partial polyline ends. So, you need to obtain a point on the polyline where the the partial polyline ends and then count each vertex from one end of the polyline all the way to the point. Now you have all the vertices of the new polyline, you simply create a new polyline with AcadModelSpace/PaperSpace.AddLightWeightPolyline().

 

The steps of doing it could be like these:

 

1. You ask user to pick a point on the polyline. You may want to validtate the picked point to make sure it exactly sits on the poilyline by using IntersectWith() to test an AcadPoint with the polyline;

 

2. use AcadLWPolyline.Coordinates to obtain the veritces of the polyline;

 

3. add up the distance from one end of the polyline, vertext by vertex. For each vertex being added, also try to add the point to compare the increased distance, so that you can decide whether the point is between 2 vertices. If yes, the partial polyline ends at the point. Now you have all the vertices of the new polyline.

 

4. use AcadModelSpace/PaperSpace.AddLightWeightPolyline() to create the "partial" polyline.

Norman Yuan

Drive CAD With Code

EESignature

Message 3 of 8
imagination_s
in reply to: norman.yuan


hellow Norman

Pretty much i have done this stepts



1. You ask user to pick a point on the polyline. You may want to validtate the picked point to make sure it exactly sits on the poilyline by using IntersectWith() to test an AcadPoint with the polyline;



2. use AcadLWPolyline.Coordinates to obtain the veritces of the polyline;



but you lost me there with step 3

Can you explain to me in details what is need to be done?
How can i add the distance vertext by vertex?

Thankyou very much.
Message 4 of 8
norman.yuan
in reply to: imagination_s

I have not worked with AutoCAD VBA for quite a while, thus a bit rusty with VBA code. But I wrote following code to do what you want. Some explanation:

 

1. I used AcadUtility.GetEntity() instead of GetPoint(), because GetEntity() allows the code to return the picked point along with the entity being selected. This way, the point reurned is guaranteed sitting on the entity. However, based on your need, you may still use GetPoint() to obtain the point, and if so, you need to make sure the point sits on the polyline;

 

2. In order to tell picked point is between which 2 vertices (so that you can cut off the rest of polyline), I used method Distance(A, B)=Distance(A,C) + Distance(C,B) to determine if point C is on a line between A and B. There are other way to determine if a point is on a line. Googling the web would give you some links.

 

Option Explicit

Public Sub CopyPartialPolyline()

    Dim poly As AcadLWPolyline
    Dim point As Variant
    
    '' Pick polyline and a point on the polyline
    PickPolyline poly, point
    If poly Is Nothing Then
        ThisDrawing.Utility.Prompt vbCr & "*Cancel*"
        Exit Sub
    End If
    
    '' Get vertices of selected polyline
    Dim points() As Variant
    GetVertices poly, points
    
    MsgBox (UBound(points) + 1) & " verices!"
    
    ''Get partial polyline vertices
    Dim newPoints() As Variant
    If Not GetPartialVertices(points, point, newPoints) Then
        MsgBox "Picked point is not on polyline!"
        ThisDrawing.Utility.Prompt vbCr & "*Cancel*"
        Exit Sub
    End If
    
    '' drawing the partial polyline
    DrawingPartialPolyline newPoints
    

End Sub

Private Sub PickPolyline(pline As AcadLWPolyline, pt As Variant)

    Set pline = Nothing
    
    Dim ent As AcadEntity
    Dim point As Variant
    
    On Error Resume Next
    
    Do
    
        ThisDrawing.Utility.GetEntity ent, point, vbCr & "Pick a point on a polyline:"
        If Err Then Exit Do
        
        If TypeOf ent Is AcadLWPolyline Then
        
            Set pline = ent
            pt = point
            Exit Do
        Else
            ThisDrawing.Utility.Prompt vbCr & "Invalid pick: not a polyline!"
            Set ent = Nothing
        End If
    
    Loop While ent Is Nothing
    
    On Error GoTo 0

End Sub

Private Sub GetVertices(poly As AcadLWPolyline, points() As Variant)

    Dim coords As Variant
    coords = poly.Coordinates
    
    Dim count As Integer
    count = (UBound(coords) + 1) / 2 - 1
    ReDim points(0 To count)
    
    Dim pt(0 To 1) As Double
    
    Dim i As Integer
    Dim j As Integer
    For i = 0 To UBound(coords) Step 2
    
        pt(0) = coords(i)
        pt(1) = coords(i + 1)
    
        points(j) = pt
        j = j + 1
        
    Next
    
End Sub

Private Function GetPartialVertices( _
    vertices As Variant, _
    point As Variant, newPts() As Variant) As Boolean

    Dim startP(0 To 1) As Double
    Dim endP(0 To 1) As Double
    
    Dim i As Integer
    
    For i = 0 To UBound(vertices) - 1
        
        ReDim Preserve newPts(i)
        
        startP(0) = vertices(i)(0): startP(1) = vertices(i)(1)
        endP(0) = vertices(i + 1)(0): endP(1) = vertices(i + 1)(1)
        
        If i = 0 Then
            newPts(i) = startP
        Else
            If IsPointOnSegment(startP, endP, point) Then
            
                newPts(i) = startP
                
                endP(0) = point(0): endP(1) = point(1)
                ReDim Preserve newPts(i + 1)
                newPts(i + 1) = endP
                GetPartialVertices = True
                Exit Function
            Else
                newPts(i) = startP
            End If
        
        End If
        
    Next
    
    GetPartialVertices = False

End Function

Private Function IsPointOnSegment( _
    startP As Variant, endP As Variant, _
    point As Variant, Optional tolerance As Double = 0.001) As Boolean

    Dim dist1 As Double
    Dim dist2 As Double
    Dim dist As Double
    
    dist = DistBetweenPoints(startP, endP)
    dist1 = DistBetweenPoints(startP, point)
    dist2 = DistBetweenPoints(point, endP)
    
    Dim diff As Double
    diff = Abs(dist - dist1 - dist2)
    
    IsPointOnSegment = diff <= tolerance

End Function

Private Function DistBetweenPoints(pt1 As Variant, pt2 As Variant) As Double

    Dim dX As Double
    dX = Abs(pt2(0) - pt1(0))
    
    Dim dy As Double
    dy = Abs(pt2(1) - pt1(1))
    
    DistBetweenPoints = Sqr(dX * dX + dy * dy)
    
End Function

Private Sub DrawingPartialPolyline(vertices As Variant)
    
    Dim coords() As Double
    Dim count As Integer
    count = (UBound(vertices) + 1) * 2
    
    ReDim coords(0 To count - 1)
    
    Dim i As Integer
    Dim j As Integer
    For i = 0 To UBound(vertices)
        
        j = i * 2
        coords(j) = vertices(i)(0)
        coords(j + 1) = vertices(i)(1)
        
    Next
    
    Dim pline As AcadLWPolyline
    Set pline = ThisDrawing.ModelSpace.AddLightWeightPolyline(coords)
    
    Dim fromPt(0 To 2) As Double
    Dim toPt(0 To 2) As Double
    fromPt(0) = coords(0): fromPt(1) = coords(1): fromPt(2) = 0#
    toPt(0) = 0#: toPt(1) = 0#: toPt(2) = 0#
    
    pline.Move fromPt, toPt
    
    pline.Update
    
End Sub

 

 

Norman Yuan

Drive CAD With Code

EESignature

Message 5 of 8
imagination_s
in reply to: norman.yuan

Hello Norman

Appreciate the effort.You save my project.

I hope wii this help from you to get the idea done.I will send you a feedback.

Thanyou again for your help.

Message 6 of 8
imagination_s
in reply to: norman.yuan

hello Norman,

The functions your created work perfect.

I ask the user to pick a point and then the program copy part of a line intro a Layout.

Sory for disturbing you agan.I wonder how can a get a start point and a and point and for that the  part of the polyline is copy?

my conde for user is :

  Dim vGetPoint As Variant, objPickedPoint As AcadPoint, objPickedPoint2 As AcadPoint
vGetPoint = ThisDrawing.Utility.GetPoint(, vbCr & "Create start point on the polyline: ")
Set objPickedPoint = ThisDrawing.ModelSpace.AddPoint(vGetPoint)
vGetPoint = ThisDrawing.Utility.GetPoint(, vbCr & "Create end point on the polyline: ")
Set objPickedPoint2 = ThisDrawing.ModelSpace.AddPoint(vGetPoint)

 

Please give me a clue for each point copy part of pline

Thankyou very much

Message 7 of 8
norman.yuan
in reply to: imagination_s

I am not sure I understand your further question correctly: now you want to get 2 points on a polyline, and then recreate the portion of polyline between the 2 points.

 

If this is what you want to do, you simply find a way to count the polyline's vertices between the 2 points, then in conjunction with the 2 points, you now have a new set of vertex points that can be used to create needed polyline. If you want the new polyline's vertices created in the order that the first point as start point and the second point as end point, you just need to pay attention to how the vertices in between is added.

 

If you have understood the code clearly I replied previously, you can easily find out the vertices between the 2 points. I went ahead with some modifictions to the previous code, as shown below:

 

Option Explicit

Public Sub CopyPartialPolyline2()

    Dim poly As AcadLWPolyline
    Dim startPt As Variant
    Dim endPt
    
    PickPolyline poly, startPt, endPt
    If poly Is Nothing Then
        ThisDrawing.Utility.Prompt vbCr & "*Cancel*"
        Exit Sub
    End If
    
    '' Get vertices of selected polyline
    Dim points() As Variant
    GetVertices poly, points
    
    ''Get partial polyline vertices
    Dim newPoints() As Variant
    If Not GetPartialVertices(points, startPt, endPt, newPoints) Then
        MsgBox "Picked point is not on polyline!"
        ThisDrawing.Utility.Prompt vbCr & "*Cancel*"
        Exit Sub
    End If
    
    '' drawing the partial polyline
    DrawingPartialPolyline newPoints
    
End Sub


Private Sub PickPolyline(pline As AcadLWPolyline, ptStart As Variant, ptEnd As Variant)

    Set pline = Nothing
    
    Dim ent As AcadEntity
    Dim point As Variant
    
    On Error Resume Next
    
    ''Pick first point on the polyline
    Do
        ThisDrawing.Utility.GetEntity ent, point, vbCr & "Pick first point on a polyline:"
        If Err Then
            Set pline = Nothing
            Exit Do
        End If
        
        If TypeOf ent Is AcadLWPolyline Then
            Set pline = ent
            ptStart = point
            Exit Do
        Else
            ThisDrawing.Utility.Prompt vbCr & "Invalid pick: not a polyline!"
            Set ent = Nothing
        End If
    
    Loop While ent Is Nothing
    
    ''pick econd point o the polyline
    If Not pline Is Nothing Then
        
        Do
            ThisDrawing.Utility.GetEntity ent, point, vbCr & "Pick second point on a polyline:"
            If Err Then
                Set pline = Nothing
                Exit Do
            End If
            
            If TypeOf ent Is AcadLWPolyline Then
                If ent.Handle = pline.Handle Then
                    ptEnd = point
                    Exit Do
                Else
                    ThisDrawing.Utility.Prompt vbCr & "Invalid pick: point not on the same polyline!"
                Set ent = Nothing
                End If
            Else
                ThisDrawing.Utility.Prompt vbCr & "Invalid pick: not a polyline!"
                Set ent = Nothing
            End If
        
        Loop While ent Is Nothing
        
    End If
    
    On Error GoTo 0

End Sub

Private Sub GetVertices(poly As AcadLWPolyline, points() As Variant)

    Dim coords As Variant
    coords = poly.Coordinates
    
    Dim count As Integer
    count = (UBound(coords) + 1) / 2 - 1
    ReDim points(0 To count)
    
    Dim pt(0 To 1) As Double
    
    Dim i As Integer
    Dim j As Integer
    For i = 0 To UBound(coords) Step 2
    
        pt(0) = coords(i)
        pt(1) = coords(i + 1)
    
        points(j) = pt
        j = j + 1
        
    Next
    
End Sub

Private Function GetPartialVertices( _
    vertices As Variant, startPt As Variant, _
    endPt As Variant, newPts() As Variant) As Boolean
    
    Dim startIndex As Integer
    startIndex = FindVertexIndex(vertices, startPt)
    
    Dim endIndex As Integer
    endIndex = FindVertexIndex(vertices, endPt)
    
    If startIndex = -1 Or endIndex = -1 Then
        GetPartialVertices = False
        Exit Function
    End If
    
    Dim sameOrder As Boolean
    If startIndex > endIndex Then
        '' The direction from fist point to second point is
        '' different from the polyline's vertices order
        endIndex = endIndex + 1
        sameOrder = False
    Else
        '' The direction from fist point to second point is
        '' the same as the polyline's vertices order
        startIndex = startIndex + 1
        sameOrder = True
    End If
    
    ''Create vertex point array for the partial polyline
    Dim pt(0 To 1) As Double
    Dim arrayCount As Integer
    Dim i As Integer
    
    '' Start point
    arrayCount = 0
    ReDim Preserve newPts(arrayCount)
    pt(0) = startPt(0): pt(1) = startPt(1)
    newPts(arrayCount) = pt
    
    '' points in between
    If sameOrder Then
    
        For i = startIndex To endIndex Step 1
            arrayCount = arrayCount + 1
            ReDim Preserve newPts(arrayCount)
            pt(0) = vertices(i)(0): pt(1) = vertices(i)(1)
            newPts(arrayCount) = pt
        Next
    
    Else
    
        For i = startIndex To endIndex Step -1
            arrayCount = arrayCount + 1
            ReDim Preserve newPts(arrayCount)
            pt(0) = vertices(i)(0): pt(1) = vertices(i)(1)
            newPts(arrayCount) = pt
        Next
        
    End If
    
    '' End point
    arrayCount = arrayCount + 1
    ReDim Preserve newPts(arrayCount)
    pt(0) = endPt(0): pt(1) = endPt(1)
    newPts(arrayCount) = pt
    
    GetPartialVertices = True

End Function

Private Function FindVertexIndex(vertices As Variant, point As Variant) As Integer

    Dim pt1(0 To 1) As Double
    Dim pt2(0 To 1) As Double
    Dim i As Integer
    
    For i = 0 To UBound(vertices)
    
        pt1(0) = vertices(i)(0): pt1(1) = vertices(i)(1)
        pt2(0) = vertices(i + 1)(0): pt2(1) = vertices(i + 1)(1)
        If IsPointOnSegment(pt1, pt2, point) Then
            FindVertexIndex = i
            Exit Function
        End If
        
    Next
    
    FindVertexIndex = -1
    
End Function

Private Function IsPointOnSegment( _
    startP As Variant, endP As Variant, _
    point As Variant, Optional tolerance As Double = 0.001) As Boolean

    Dim dist1 As Double
    Dim dist2 As Double
    Dim dist As Double
    
    dist = DistBetweenPoints(startP, endP)
    dist1 = DistBetweenPoints(startP, point)
    dist2 = DistBetweenPoints(point, endP)
    
    Dim diff As Double
    diff = Abs(dist - dist1 - dist2)
    
    IsPointOnSegment = diff <= tolerance

End Function

Private Function DistBetweenPoints(pt1 As Variant, pt2 As Variant) As Double

    Dim dX As Double
    dX = Abs(pt2(0) - pt1(0))
    
    Dim dy As Double
    dy = Abs(pt2(1) - pt1(1))
    
    DistBetweenPoints = Sqr(dX * dX + dy * dy)
    
End Function

Private Sub DrawingPartialPolyline(vertices As Variant)
    
    Dim coords() As Double
    Dim count As Integer
    count = (UBound(vertices) + 1) * 2
    
    ReDim coords(0 To count - 1)
    
    Dim i As Integer
    Dim j As Integer
    For i = 0 To UBound(vertices)
        
        j = i * 2
        coords(j) = vertices(i)(0)
        coords(j + 1) = vertices(i)(1)
        
    Next
    
    Dim pline As AcadLWPolyline
    Set pline = ThisDrawing.ModelSpace.AddLightWeightPolyline(coords)
    
    Dim fromPt(0 To 2) As Double
    Dim toPt(0 To 2) As Double
    fromPt(0) = coords(0): fromPt(1) = coords(1): fromPt(2) = 0#
    toPt(0) = 0#: toPt(1) = 0#: toPt(2) = 0#
    
    pline.Move fromPt, toPt
    
    pline.Update
    
End Sub

 

Norman Yuan

Drive CAD With Code

EESignature

Message 8 of 8
imagination_s
in reply to: norman.yuan

Hello Norman and Thankyou very much for all your help

Realy aprecciate what you have done here for me

Your code work perfect.It is what i needed.

Have a nice day

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report

”Boost