Double values comparison w/ tolerance for "point" equality in a DXF drawing

Viewed 173

I have a simple algorithm that fails sometimes because it is comparing doubles. I look at a DXF drawing and get all the line segments, and also break it down into a series of points. When looping through all the points to identify if it forms a cycle (ie if a line touches, I should get 2 hits on a point) and inspecting the output they are close. So sometimes this algorithm and the equals with a delta comparison method gets a pass, then sometimes it fails...

So how close should a point be to consider it the same point or overlapping?

These should be the same, but then i think rounding happens and the numbers slightly adjust based on what I set the tolerance too making it sometimes equal and sometimes not..

Point: [4.6408, 14.8708] Point: [4.6799, 14.8156]

Even though it's a DXF file it doesn't seem to be exact or setup in a way to get identical values they are extremely approximate and fine grained, so I am not even sure how the DXF file itself works because when you use a drawing program you can make a distinct line entities that actually touch each other and the UI snaps the lines together...so should I compare it to one decimal place only? No decimal places?

I guess the issue is these drawings are made from a variety of different programs in a variety of different ways, maybe the DXF file format has something else I can inspect to identify this? For now I am doing it this way and it seems "buggy".

Any thoughts or suggestions? I do have a comparison / equals method that takes a tolerance, should I just make it really tight?

Thanks,

1 Answers

I know this is VBA but I just wanted to convey the principles involved:

Private Function ComparePoints(ptPoint() As Double, ptVariant As Variant, Optional ByVal dElevation As Double = 0#) As Boolean
    ComparePoints = False
    
    If (UBound(ptVariant) = 1) Then
        If (ptPoint(0) = Round(ptVariant(0), 3) And _
            ptPoint(1) = Round(ptVariant(1), 3) And _
            ptPoint(2) = Round(dElevation, 3)) Then
           ComparePoints = True
        End If
    Else
        If (ptPoint(0) = Round(ptVariant(0), 3) _
             And ptPoint(1) = Round(ptVariant(1), 3) _
             And ptPoint(2) = Round(ptVariant(2), 3)) Then
           ComparePoints = True
        End If
    End If
End Function

Public Function Round(ByVal dValue As Double, ByVal iPrec As Integer) As Double
    Dim strText As String
    Dim strNumber As String
    Dim strFormatString As String
    
    If (iPrec <= 0) Then
        strFormatString = "0"
    Else
        strFormatString = "0." & String$(iPrec, "0")
    End If
    
    strText = CStr(dValue)
    strNumber = Format$(strText, strFormatString)

    Round = CDbl(strNumber)
End Function

Code would be a bit different for C#. In the above ComparePoints is designed for testing:

  • a 3D coordinate against another 3D coordinate
  • a 3D coordinate against a 2D coordinate (with elevation).

The latter applies when using LWPOLYLINE elements.

Note that the above assumes all coordinates are in the World Coordinate System for the comparisons to work. Transformation of coordinates is another issue.

Related