Author Topic: Passing points as an array to a function... this shouldn't be hard....  (Read 2400 times)

0 Members and 1 Guest are viewing this topic.

michael_h

  • Guest
Hi all,

I'm working on a VBA program that will provide the user with a list of layers, allow the user to choose a layer, automatically select the first (and only) object on that layer, and then select all items within that object using the acselectionsetWindowPolygon method.

Right now, I can get Autocad to select the object that I want, but I'm having a hard time trying to get it to pass the points to the selection function.

I'm getting the points of the object using the following code:

Code: [Select]
Dim varPoints As Variant
varPoints = myRegionObj.Coordinates

Then, as I understand it, I need to convert this 2 dimensional set of points into 3d points. I wrote a function to do that:

Code: [Select]
Function ConvertPoints(ByRef PointsArray() As Double) As Double
'function creates a new array to hold three dimensional points and converts 2D points into 3D with z=0

Dim PreviousBound As Integer, NewBound As Integer

PreviousBound = (UBound(PointsArray) + 1) / 2
NewBound = PreviousBound * 3

ReDim ConvertPoints(NewBound) As Double

Dim i As Integer
For i = 0 To UBound(PointsArray)
    If i Mod 3 = 0 Then ConvertPoints(i) = 0
    Else: ConvertPoints(i) = PointsArray(i)
Next i

End Function

and then of course, I would want to do the actual selection, using something like this:

Code: [Select]
dim mode as integer
mode = acselectionsetWindowPolygon
mySelectionSet.SelectByPolygon mode, ConvertPoints(varPoints())

However, I can't seem to figure out how to pass an array to the function. Can someone tell me if I'm going about this anywhere even near the right way?

Many thanks for the help.

Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16897
  • Superior Stupidity at its best
What you might need to do is change the return value of ConvertPoints to a variant.
Another option would be to create a global variable in the function and not return a value from the function, but set the value within the function. Does that make sense?
Proud provider of opinion and arrogance since November 22, 2003 at 09:35:31 am
CadJockey Militia Field Marshal

Find me on https://parler.com @kblackie

michael_h

  • Guest
Keith,

Thanks for the quick reply.

I've made the change you suggested:

Code: [Select]
Function ConvertPoints(ByRef PointsArray() As Double) As Variant


However, when I try to make the selection using this command:

Code: [Select]
mySelectionSet.SelectByPolygon mode, ConvertPoints(varPoints())

I get the message: "Type mismatch, array or user-defined type expected"

I get the same message if I try the following (e.g. using the name of the array without the parentheses).

Code: [Select]
ConvertPoints(varPoints)

I feel like I'm doing something wrong with the syntax. Anyway, I'll try to create a global function and see if that will work.
To do that, I'd ass Public NewArray() as double in the general portion of the code  and then redim it in the function, correct?

michael_h

  • Guest
Alas, I just tried to make a public variable:

Code: [Select]
Public NewArray() As Double

and the compiler told me that "... arrays ... are not allowed as Public members of object modules"


Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16897
  • Superior Stupidity at its best
In a module (not a form)
Code: [Select]
Dim MyArray() As Double
Public Function MyFunction(ByVal PointsArray As Variant)
'do stuff here to fill in MyArray
End Function
Proud provider of opinion and arrogance since November 22, 2003 at 09:35:31 am
CadJockey Militia Field Marshal

Find me on https://parler.com @kblackie

Atook

  • Swamp Rat
  • Posts: 996
  • AKA Tim
Keith is right, when passing arrays, you need to dim them as variants.

Jeff_M

  • King Gator
  • Posts: 4040
  • C3D user & customizer
Michael,
Your function is flawed, in that it isn't creating the proper size new array and it isn't filling it in correctly either.
Try this:
Code: [Select]
Function ConvertPoints(ByRef PointsArray() As Double) As Variant
'function creates a new array to hold three dimensional points and converts 2D points into 3D with z=0

Dim PreviousBound As Integer, NewBound As Integer, NewPoints() As Variant

PreviousBound = (UBound(PointsArray) + 1) / 2
NewBound = (PreviousBound * 3) - 1

ReDim NewPoints(NewBound)

Dim i As Integer
Dim j As Integer

For i = 0 To UBound(PointsArray) Step 2
    NewPoints(j) = PointsArray(i)
    NewPoints(j + 1) = PointsArray(i + 1)
    NewPoints(j + 2) = 0#
    j = j + 3
Next i
ConvertPoints = NewPoints
End Function

rogue

  • Guest
Seems too much like work, to me. I dont see the need to convert anything; and Im not sure why your routine isnt working - are you selecting a single line as an object? Because a single line, or a polyline with only one subentity, will only have 2 points (coordinates), which isnt enough points to describe the polygon you wish to select by.

Also, you realize that in a lot of cases, the polygon you wish to use to select by WONT also select, say, the polyline with the coordinates you used to describe the polygon? because the polygon would be ON, not IN, the selectionset polygonal window.

Try the code below. ts beasically whipped up from copy/paste from the help files; it creates a triangular polyline, and a circle inside it, then creates the selectionset boundary from the polyline coordinates. Note that the circle is selected, and not the polyline....


' -------- snip -------- snip -------- snip -------- snip --------

Sub Main()
    ' Create a polyline. Then use the Coordinates
    ' property to return all the coordinates in the polyline.
   
    Dim plineObj As AcadPolyline
    ' Create Polyline resembling a triangle
    Dim points(8) As Double
    points(0) = -10: points(1) = 0: points(2) = 0
    points(3) = 10: points(4) = 0: points(5) = 0
    points(6) = 0: points(7) = 7: points(8) = 0
    Set plineObj = ThisDrawing.ModelSpace.AddPolyline(points)

    ' Return all the coordinates of the polyline
    Dim retCoord As Variant
    retCoord = plineObj.Coordinates
   
    ' Draw a circle in the middle of the triangle
    Dim MyCircle As AcadCircle
    Dim CenterPoint(2) As Double
    CenterPoint(0) = 0: CenterPoint(1) = 3: CenterPoint(2) = 0
    Set MyCircle = ThisDrawing.ModelSpace.AddCircle(CenterPoint, 1)
    ThisDrawing.Regen acActiveViewport
   
    ' create a selection set
    Dim mode As Integer
    mode = acSelectionSetWindowPolygon
    Dim mySelectionSet As AcadSelectionSet
    Set mySelectionSet = ThisDrawing.SelectionSets.Add("TEST_SSET")
   

    ' use our points from the polyline to select entities
    mySelectionSet.SelectByPolygon mode, retCoord

    If mySelectionSet.Count > -1 Then
        Dim acEnt As AcadObject
        For i = 0 To mySelectionSet.Count - 1
            Set acEnt = mySelectionSet.Item(i)
            MsgBox "Item " & i & "  " & acEnt.ObjectName
        Next i
    Else
        MsgBox "Nothing in selection set"
    End If


    mySelectionSet.Delete
    Set mySelectionSet = Nothing
   
End Sub

Jeff_M

  • King Gator
  • Posts: 4040
  • C3D user & customizer
Rogue,
If the object obtained for the Polygon is a LightWeightPolyLine, the Coordinates property returns a 2D point list which must be converted to a 3D point list. Based on Michael's first post, he knows what the first entity on a layer is and what the Coordinates returns, which is a 2D point list.