Author Topic: Wierd discovery, at least for me: Points HAVE dimensions!  (Read 2436 times)

0 Members and 1 Guest are viewing this topic.

ReneRam

  • Newt
  • Posts: 80
  • The great gig in the sky
Wierd discovery, at least for me: Points HAVE dimensions!
« on: June 08, 2009, 05:21:50 AM »
I came out with this discovery, at least for me starting a new program that fills a closed area with blocks. It's just the head start of a bigger thing but usually I give it the first try with VBA since I find faster to develop.

The code that follows creates a sample closed area and then checks if a point, in my case it was the insertion point of the block, is inside the area; a common problem that has different solutions. In my case a simply created a temporary point and checked if it was inside my area, if the result was true then ... insert the block, otherwise skip to next point. Doing my tests I found out that the PointStyle and PointSize variable, that I thought as a graphical display in AutoCAD have real dimensions. I had changed the point style to visually see where my point was going. I you run the code twice commenting on the second run the part where the PDMODE variable is changed, you'll see the differences. Also if you change with the Zoom part before testing if the point is inside you will get different results. I thought a point was was a location with no dimensions.  :?
I'm just sharing my discovery in case someone didn't know about it.

Code: [Select]

Option Explicit


Sub TestPointDimension()

    ' Draw a closed polyline
    Dim points(7) As Double
    points(0) = 100#: points(1) = 10#
    points(2) = 200#: points(3) = 50#
    points(4) = 100#: points(5) = 100#
    points(6) = 0#: points(7) = 50#
    Dim objLWPoly As AcadLWPolyline
    Set objLWPoly = ThisDrawing.ModelSpace.AddLightWeightPolyline(points)
    objLWPoly.Closed = True
   
    ' Set Spacing of points for the test
    ' I have set the spacing to 5 just to just to have more false points
    ' results
    Dim XSpacing As Double: XSpacing = 5#
    Dim YSpacing As Double: YSpacing = 5#
   
    ' Create TestPoint
    Dim TestPoint(2) As Double
    TestPoint(0) = 0#: TestPoint(1) = 0#: TestPoint(2) = 0#
   
    ' Update Viewport
    ' This is needed to optimize the SelectByPolygon:
    ' ONLY objects VISIBLE in screen are evaluated
    Application.ZoomExtents
    Application.Update
   
   
    ' Test with PDMode = 66
    ThisDrawing.SetVariable "PDMODE", 66
    ' I get 419 points Inside the closed area
    ' and 44 of these are Outside the closed area
'    ' Test with PDMode = 0
'    ThisDrawing.SetVariable "PDMODE", 0
'    ' I get 375 points Inside the closed area
   
    ' Star Testing points
    Dim objPoint As AcadPoint

    ' I'm intentionaly going outside the closed area
    Do While TestPoint(1) < 150
        Do While TestPoint(0) < 250
            ' Check if element is inside border bounding box
            If TestPoint(1) > 150 Then Exit Do
            If TestPoint(0) > 250 Then GoTo UpdatePto
            ' Insert Points
            Set objPoint = ThisDrawing.ModelSpace.AddPoint(TestPoint)
            Application.Update
            ' Check if point is inside the closed area
            If Not IsInside(objPoint.Coordinates, objLWPoly) Then
                ' Delete point
                objPoint.Delete
            End If
UpdatePto:
            ' Update Insert Point
            TestPoint(0) = TestPoint(0) + XSpacing
        Loop
    ' increment row
    TestPoint(0) = 0#
    TestPoint(1) = TestPoint(1) + YSpacing
    TestPoint(2) = TestPoint(2)
Loop
   
   
End Sub


' Checks if a Point is inside a lwPolyline
Function IsInside(ByVal acPoint As Variant, lwPoly As AcadLWPolyline) As Boolean

    ' Initialize Return value
    IsInside = False

    Dim objSS As AcadSelectionSet       ' temporary SelectionSet
    Dim initCodes(2) As Integer         ' objSS filter codes
    Dim varCodeValues(2) As Variant     ' objSS filter values

    Dim retCoords As Variant            ' lwPoly coordinates
    Dim PointsArray() As Double         ' Array of 3D Points for objSS crossing polygon
    Dim retPto As Variant               ' coordinates of found point
    Dim ent As AcadEntity               ' entity
   
    Dim i As Integer                    ' counter
    Dim j As Integer                    ' counter
   
    ' Create SelectionSet
    Set objSS = PowerSet("myPolygon")
   
    ' DXF Filter
    initCodes(0) = -4
    varCodeValues(0) = "<AND"
    initCodes(1) = 0
    varCodeValues(1) = "POINT"
    initCodes(2) = -4
    varCodeValues(2) = "AND>"

    ' Retrieve lwPolyline Coordiantes and fill 3D Points for Crossing Polygon
    retCoords = lwPoly.Coordinates
    ReDim PointsArray((((UBound(retCoords) + 1) / 2) * 3) - 1)
    ' get the X coordinates
    For i = 0 To UBound(PointsArray)
        For j = 0 To UBound(retCoords) Step 2
            PointsArray(i) = retCoords(j)
            i = i + 3
        Next j
    Next i
    ' get the Y coordiantes
    For i = 1 To UBound(PointsArray)
        For j = 1 To UBound(retCoords) Step 2
            PointsArray(i) = retCoords(j)
            i = i + 3
        Next j
    Next i
    ' fill the Z coordinates with 0, lwPolyline doesn't have Z
    For i = 2 To UBound(PointsArray) Step 3
       PointsArray(i) = 0
    Next i

    ' Fill the objSS
    objSS.SelectByPolygon acSelectionSetCrossingPolygon, PointsArray, _
        initCodes, varCodeValues
    ' get ents in objSS
    If objSS.Count >= 1 Then
        For Each ent In objSS
            retPto = ent.Coordinates
            If retPto(0) = acPoint(0) And retPto(1) = acPoint(1) Then
                IsInside = True
                Exit Function
            Else
                IsInside = False
            End If
        Next ent
    Else
        IsInside = False
    End If
End Function




'Restituisce un 'SelectionSet' evitando i nomi duplicati
' Credit goes to Randal Rath's Code Troute I think, I use this since (?)
Function PowerSet(setName As String) As AcadSelectionSet
    Dim objSS As AcadSelectionSet
    Dim objSSCol As AcadSelectionSets
    On Error GoTo ErrorHandler
    Set objSSCol = ThisDrawing.SelectionSets
    For Each objSS In objSSCol
        If objSS.Name = setName Then
            objSSCol.Item(setName).Delete
            Exit For
        End If
    Next
    Set objSS = objSSCol.Add(setName)
    Set PowerSet = objSS
ExitHere:
    Exit Function
ErrorHandler:
    Select Case Err.Number
        Case Else
            MsgBox Err.Description
            Err.Clear
            Resume ExitHere
        End Select
End Function



I didn't ctry it yet with lisp or .Net, ut guess it will give the same results.
"A clever person solves a problem. A wise person avoids it." - Albert Einstein

Jeff_M

  • King Gator
  • Posts: 4040
  • C3D user & customizer
Re: Wierd discovery, at least for me: Points HAVE dimensions!
« Reply #1 on: June 08, 2009, 10:05:04 AM »
You are "checking" based on a crossing selection set which uses VISIBLE objects. When you change the PDMODE & PDSIZE variables the objects are displayed differently, thereby allowing the selection to be able to select more/less depending on how "big" the point is displayed. This is why one of the other IsInside solutions that use mathematical calculations will give far better results.   

ReneRam

  • Newt
  • Posts: 80
  • The great gig in the sky
Re: Wierd discovery, at least for me: Points HAVE dimensions!
« Reply #2 on: June 08, 2009, 11:37:32 AM »
Quote
You are "checking" based on a crossing selection set which uses VISIBLE objects.
I agree, What I meant was that I thought the point displayed on the screen was just a graphical thing on the screen and not something AutoCAD could "touch" since it changes zooming. I was convinced that when selecting, even crossing, since it's vectorial drawing and not images, the selection was something pure mathematical.
"A clever person solves a problem. A wise person avoids it." - Albert Einstein

sinc

  • Guest
Re: Wierd discovery, at least for me: Points HAVE dimensions!
« Reply #3 on: June 08, 2009, 12:11:54 PM »
I think anything other than the current behavior would be inconsistent.

Take, for example, C3D Points, which may have labels attached to them, too.  If I use a crossing window, I would expect it to select points even if the crossing window only touched part of the label.  If points got ignored unless I specifically put the crossing window AROUND the point node, it would be much more annoying, from a user perspective.

It means you can't use that method you are trying to get the results you want, but I think it is consistent with the way a crossing window should work.

ReneRam

  • Newt
  • Posts: 80
  • The great gig in the sky
Re: Wierd discovery, at least for me: Points HAVE dimensions!
« Reply #4 on: June 08, 2009, 12:26:03 PM »
 :| I guess I'm not explaining what I find strange.
If you replace this line in the IsInside function:

Code: [Select]
    ' Fill the objSS
    objSS.SelectByPolygon acSelectionSetCrossingPolygon, PointsArray, _
        initCodes, varCodeValues

with:

Code: [Select]
    ' Fill the objSS
    objSS.SelectByPolygon acSelectionSetWindowPolygon, PointsArray, _
        initCodes, varCodeValues

you're not "crossing", you're using a "window", but in this case the area is filled with holes.
In any case, the method works enough for my purposes, I was just sharing something I thought wasn't much known.
"A clever person solves a problem. A wise person avoids it." - Albert Einstein