Get an ordered list of points that describe an edgeloop.

Get an ordered list of points that describe an edgeloop.

gerrardhickson
Collaborator Collaborator
393 Views
4 Replies
Message 1 of 5

Get an ordered list of points that describe an edgeloop.

gerrardhickson
Collaborator
Collaborator

Hi all,

I'm looking for a way to get a list of the points for a given edgeloop in order.

 

I've tried a bunch of things, and so far I have two solutions that give the wrong result. The image below shows the result of both attempts so far. the red dashed line shows that the short horizontal line is effectively inverted.

The problem is that the edgeloop contains edges - each with a startvertex and stopvertex. however, the direction of the edges aren't head to tail. In the case below, two edges are backwards (head to head/tail to tail) so iterating through the list of edges and selecting all heads or all tails doesn't work. Similarly, iterating through the list of edges, building a list of points then removing the duplicates doesn't work since the order you iterate over them is incorrect.

 

I'm about to try building a list of known edge loop points, and comparing that with the list of face vertices in the hope that the face verticies are ordered correctly, but I'd like a more elegant way if possible.

gerrardhickson_0-1692318384801.png

 

Any suggestions?

 

0 Likes
394 Views
4 Replies
Replies (4)
Message 2 of 5

Michael.Navara
Advisor
Advisor

You need to handle this by yourself. Edges in EdgeLoop are ordered, but its Start and End points may be swapped.

Here is my approach how to fix it

 

Sub Main()
    Dim pick = ThisApplication.CommandManager.Pick(SelectionFilterEnum.kPartFacePlanarFilter, "Select planar face")
    Dim face As Face = pick

    Dim edgeLoop As EdgeLoop = face.EdgeLoops(1)

    Dim points As New List(Of Point)
    Dim startPoint As Point
    Dim endPoint As Point

    'Check if the first edge in edgeLoop is not reversed
    Dim e1Start As Point = edgeLoop.Edges(1).StartVertex.Point
    Dim e1End As Point = edgeLoop.Edges(1).StopVertex.Point
    Dim e2Start As Point = edgeLoop.Edges(2).StartVertex.Point
    Dim e2End As Point = edgeLoop.Edges(2).StopVertex.Point

    If DistanceOrZero(e1End, e2Start) = 0 Then
        startPoint = e1Start
        endPoint = e1End
    ElseIf DistanceOrZero(e1End, e2End) = 0 Then
        startPoint = e1Start
        endPoint = e1End
    ElseIf DistanceOrZero(e1Start, e2Start) = 0 Then
        startPoint = e1End
        endPoint = e1Start
    ElseIf DistanceOrZero(e1Start, e2End) = 0 Then
        startPoint = e1End
        endPoint = e1Start
    End If

    points.Add(startPoint)
    points.Add(endPoint)

    'Get the rest of points from the second edge
    For i As Integer = 2 To edgeLoop.Edges.Count
        Dim e As Edge = edgeLoop.Edges(i)

        Dim p1 = e.StartVertex.Point
        Dim p2 = e.StopVertex.Point

        Dim d1 = DistanceOrZero(endPoint, p1)
        Dim d2 = DistanceOrZero(endPoint, p2)

        If d1 = 0 AndAlso d2 > 0 Then
            endPoint = p2
        ElseIf d2 = 0 AndAlso d1 > 0 Then
            endPoint = p1
        Else
            Throw New InvalidOperationException("Invalid edge order in EdgeLoop")
        End If
        points.Add(endPoint)
    Next

    'Check the edgeLoop is closed
    If DistanceOrZero(startPoint, endPoint) > 0 Then
        Throw New InvalidOperationException("Invalid unclosed EdgeLoop")
    End If

    'FOR DEBUGGING PURPOSES ONLY
    TestPoints(face, points)

End Sub


''' <summary>
''' Returns distance between two points and when distance is smaller then tolerance, returns 0
''' </summary>
''' <param name="p1"></param>
''' <param name="p2"></param>
''' <param name="tolerance"></param>
''' <returns></returns>
Function DistanceOrZero(p1 As Point, p2 As Point, Optional tolerance As Double = 0.000001) As Double
    Dim distanceTo = p1.DistanceTo(p2)
    If distanceTo < tolerance Then
        Return 0
    End If
    Return distanceTo
End Function

Private Sub TestPoints(face As Face, points As List(Of Point))
    Dim partDef As PartComponentDefinition = face.Parent.Parent
    Dim sk As PlanarSketch = partDef.Sketches.Add(face)

    For i As Integer = 0 To points.Count - 2
        Dim p1 = sk.ModelToSketchSpace(points(i))
        Dim p2 = sk.ModelToSketchSpace(points(i + 1))
        sk.SketchLines.AddByTwoPoints(p1, p2)
    Next
End Sub

 

Message 3 of 5

gerrardhickson
Collaborator
Collaborator

Thanks for the response. 

Here's what I ended up doing - it relies on the vertices of the face object being in the correct order, which seems to be true.
Note, I've eliminated a lot of code before this, but TempArea and Area are basically edgeloops. So the logic is to build an unordered list of vertices on the temporary edgeloop of interest, and compare this with the ordered vertices of the face - if the face vertices exist in the temporary edgeloop of interest, then add them to the final edgeloop in the order they appear on the face. There may be some fringe cases where the vertices of the face don't appear in the correct order, but I haven't encountered that yet.

        ' GET A LIST OF ALL VERTICES IN THE EDGELOOP - NOTE THAT THESE MAY NOT BE IN ORDER
        'For Each Vert In EdgeLoop
        For Each Edge In EdgeLoop.Edges
            ' If a vertex is the same as the previous vertex added, then skip it.
            ' Presumably, this only needs to be done to the start vertex, since the end vertex won't be the same as the start vertex.
            If TempArea.Points.Count = 0 Then
                TempArea.AddPoints oTG.CreatePoint2d(Edge.StartVertex.Point.Y, Edge.StartVertex.Point.Z)
            End If
            If TempArea.Points(TempArea.Points.Count).X <> Edge.StartVertex.Point.Y And TempArea.Points(TempArea.Points.Count).Y <> Edge.StartVertex.Point.Z Then
                TempArea.AddPoints oTG.CreatePoint2d(Edge.StartVertex.Point.Y, Edge.StartVertex.Point.Z)
            End If
            TempArea.AddPoints oTG.CreatePoint2d(Edge.StopVertex.Point.Y, Edge.StopVertex.Point.Z)
        Next Edge
        
        'GET A LIST OF ALL VERTICES IN THE FACE THIS SHOULD BE IN ORDER, BUT MAY CONTAIN VERTICES FOR MULTIPLE EDGE LOOPS
        bPointExists = False
        For Each oV In EdgeLoop.face.Vertices
            For Each oV2 In TempArea.Points
                If oV.Point.Y = oV2.X And oV.Point.Z = oV2.Y Then
                    bPointExists = True
                    Exit For
                End If
            Next oV2
            If bPointExists Then Area.AddPoints oTG.CreatePoint2d(oV.Point.Y, oV.Point.Z)
            bPointExists = False
        Next oV

 

Would you mind explaining the logic behind your code? it seems that you're taking one edge, then calculating the distance to points from the next edge - if the distance is zero then you're adding it to a selection?

0 Likes
Message 4 of 5

Michael.Navara
Advisor
Advisor

If you have an EdgeLoop, the edges are in appropriate order.

  1. (Line 7) Variable points contains the ordered list of Points of edgeLoop. This is a result of this process.
  2. (Line 11) I get the first and second edge and test how the first edge is oriented against the edges order
  3. I set the startPoint and endPoint variables according to edge loop order
  4. (Line 31) I add the first two points to final list of points
  5. (Line 35) I get the rest of edges (from the second to the last) in edge loop and test which point (start or end) is the last known endPoint
  6. (Line 44) I choose the new endPoint from edge
  7. (Line 51) I add the new endPoint at the end of list of points
  8. (Line 55) I check if the edge loop is closed
  9. (Line 60) I create new sketch on given planar face and draw lines defined by points. This is only for visual check of result.

 

Message 5 of 5

gerrardhickson
Collaborator
Collaborator

Well explained. Thanks.

0 Likes