SolidWorks API SelectByID2 method

Viewed 1809

There is a more efficient method using the GetSelectedObjectCount() and GetSelectionPoint2() methods to obtain the points that can be used with SelectByID2 method. The issue of the method below is that creation of each point is not time efficient nor tidy in the feature tree. Will update this thread once I have time.

Thank you for understanding.


I recently started some programming in VBA in SolidWorks and I am looking to write a macro. The goal for now is to create a reference plane from selected face and point(deriving it from edge). As a reminder, method to create the reference plane is InsertRefPlane, which requires the selection to be done by SelectByID2 method.

So far I've managed to save the handle for the face and point objects, but I haven't managed to successfully use the SelectByID2 method. Objects that were selected become deselected.

value = instance.SelectByID2(Name, Type, X, Y, Z, Append, Mark, Callout, SelectOption)

I have tried select just a face, but I couldn't manage to do it. Also, I have renamed the face property using the SetEntityName method, and supplied it as well, but it did not manage to select it.

Could you please share the ideas how to do create a reference plane? It doesn't have to be necessary a face and an edge/mid-point.

Thank you in advance.

Edit 1: For further clarification, I have added two objects (face and edge) to selection and I would like to use those to properly select objects with SelectByID2 to use for InsertRefPlane. I have added the code below.

Ideas that I have are:

  • I have handles to the face and the edge, but can I use those for proper selection with SelectByID2?

  • Can I create a reference points on the selected face and edge to identify the face somehow?

  • SelectByRay seems feasible, but it would require some calculations with face normals so, I would try some other "simpler" methods if available. Edit 2: I have non-planar face so I can't request Normal property of the face.

  • Edit 3: It seems that it all comes down to identifying an object name and type is the way to solve the problem. This is probably a solution, but I'm open for another one, easier if possible. We can create a reference points when using one of appropriate Selection methods, because their names are known, we can use those for SelectbyID2 method. Will post the solution once I am done.

  • Regarding the GetFaces/GetFirstFace/GetNextFace methods, InsertRefPlane requires objects to be selected by SelectByID2

Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Dim swPart As SldWorks.PartDoc
Dim swSelMgr As SldWorks.SelectionMgr
Dim swModelDocExt As SldWorks.ModelDocExtension
Dim swFeatMgr As SldWorks.FeatureManager

Dim selBool As Boolean
Dim longstatus As Long, longwarnings As Long

Sub main()

Set swApp = Application.SldWorks
Set swModel = swApp.ActiveDoc
Set swModelDocExt = swModel.Extension
Set swPart = swModel
Set swSelMgr = swModel.SelectionManager
Set swFeatMgr = swModel.FeatureManager

' Check which file is opened
Dim filePath As String: filePath = swModel.GetPathName()
Debug.Print "File path is:" & filePath

'   User has to select the face and the edge of the body to create plane and
'   sketch to convert face entities
' Gets selection from SelectionManager
Dim numSelectedObjs As Long
Dim selectionMark As Long: selectionMark = -1

numSelectedObjs = swSelMgr.GetSelectedObjectCount2(selectionMark)
Debug.Print "Number of selected objects:" & numSelectedObjs

Dim faceObj As SldWorks.Face2
Dim edgeObj As SldWorks.Edge
Dim midpointObj As Object

If (numSelectedObjs > 0) Then
    ' Get and validate selection
    Dim selObj As Object
    Dim selObjIndex As Long
    Dim selObjType As Long
    For selObjIndex = 1 To numSelectedObjs ' This method uses 1 as first index
        selObjType = swSelMgr.GetSelectedObjectType3(selObjIndex, selectionMark)
        ' Check selected object type and assign it to appropriate variable
        If (selObjType = SwConst.swSelFACES) Then
            Set faceObj = swSelMgr.GetSelectedObject6(selObjIndex, selectionMark)
            Dim faceFeat As Object
            Set faceFeat = faceObj.GetFeature()
        ElseIf (selObjType = SwConst.swSelEDGES) Then
            Set edgeObj = swSelMgr.GetSelectedObject6(selObjIndex, selectionMark)
            swModel.SelectMidpoint ' With this line, we add point to selection, increasing the count to 3
            Dim deselVal As Long
            deselVal = swSelMgr.DeSelect2(selObjIndex, selectionMark) ' Deselect the edge
            Set midpointObj = swSelMgr.GetSelectedObject6(selObjIndex, selectionMark) ' Set the object to the point
        Else
            MsgBox "Wrong objects selected, select only face and edge"
            Exit For
        End If
    Next
End If

' Create reference plane using face and a point
' InsertRefPlane method requires selection using SelectByID2 Method

Dim objName, objType As String: objName = "": objType = SwConst.swSelectType_e.swSelFACES
Dim X, Y, Z As Double: X = 0: Y = 0: Z = 0
Dim selAppend As Boolean: selAppend = True
Dim objMark As Long: objMark = 0
Dim objCallout As Callout
Dim selOption As swSelectOption_e: selOption = 0

selBool = swModel.Extension.SelectByID2(objName, objType, X, Y, Z, selAppend, objMark, objCallout, selOption)
Debug.Print selBool
3 Answers

The most of the details are in my question and the last edit is the how I solved it. The way to do it is to:

  1. Obtain a handle to the object (such as face or edge) from the SelectionManager
  2. Create an Entity object of the selected object, this allows you to use Select4 methods
  3. Now you can create reference geometry, and you obtain the Name property which you can use with SelectByID2 method

I tried it out on another model, but can't guarantee it will work for you as well.

' PREREQUISITES:
'   User has to select the face and the edge of the body to create plane and
'   sketch to convert face entities to it

Sub main()

Set swApp = Application.SldWorks
Set swModel = swApp.ActiveDoc
Set swModelDocExt = swModel.Extension
Set swPart = swModel
Set swSelMgr = swModel.SelectionManager
Set swFeatMgr = swModel.FeatureManager
Set swSelData = swSelMgr.CreateSelectData
' Check which file is opened
Dim filePath As String: filePath = swModel.GetPathName()
Debug.Print "File path is:" & filePath


' Gets selection from SelectionManager
Dim numSelectedObjs As Long
Dim selectionMark As Long: selectionMark = -1

numSelectedObjs = swSelMgr.GetSelectedObjectCount2(selectionMark)
Debug.Print "Number of selected objects:" & numSelectedObjs

Dim faceObj As SldWorks.Face2

Dim edgeObj As SldWorks.Edge
Dim vEdges, vEdge As Variant
Dim nEdges As Long
Dim edgeEntityPairs(999), tempEdgeEntity(99, 99) As Variant

Dim loopObj As SldWorks.Loop2
Dim vLoops, vLoop As Variant
Dim nLoops, nLoop As Long

Dim counter(99) As Long

If (numSelectedObjs = 2) Then
    ' Get and validate selection
    Dim selObj As Object
    Dim selObjIndex As Long
    Dim selObjType As Long
    For selObjIndex = 1 To numSelectedObjs ' This method uses 1 as first index
        selObjType = swSelMgr.GetSelectedObjectType3(selObjIndex, selectionMark)
        Debug.Print "Selected obj type:" & selObjType
        ' Check selected object type and assign it to appropriate variable
        If (selObjType = SwConst.swSelFACES) Then ' Face
            Set faceObj = swSelMgr.GetSelectedObject6(selObjIndex, selectionMark)
            Set faceEntity = faceObj
            vLoops = faceObj.GetLoops()
            nLoops = faceObj.GetLoopCount()
            ' This loop gets the each loop(SW) object and its edges
            For Each vLoop In vLoops
                ' To do: Check if there's only single loop on the face
                Set loopObj = vLoop
                nEdges = loopObj.GetEdgeCount()
                vEdges = loopObj.GetEdges()
                For Each vEdge In vEdges
                    Set edgeObj = vEdge
                    Set tempEdgeEntity(nLoop, counter(nLoop)) = edgeObj
                    counter(nLoop) = counter(nLoop) + 1
                Next
                nLoop = nLoop + 1
            Next
        ElseIf (selObjType = SwConst.swSelEDGES) Then ' Edge
            Set edgeObj = swSelMgr.GetSelectedObject6(selObjIndex, selectionMark)
            Set edgeEntity = edgeObj
        Else
            MsgBox "Wrong type of objects selected, select only face and edge"
            Exit For
        End If
    Next
Else
MsgBox "Wrong number of objects selected"
   Stop
End If

'
swModel.ClearSelection2 (True)
Debug.Print "Selection cleared"
selBool = edgeEntity.Select4(True, swSelData)
'Debug.Print "Edge selected - " & selBool

Dim surfaceMidpoint, edgeMidpoint As Variant
Dim surfaceMidpointString, edgeMidpointString As String

edgeMidpoint = swFeatMgr.InsertReferencePoint(2, 1, 50, 1) ' Edge midpoint
edgeMidpointString = edgeMidpoint(0).Name

'''''' To create a reference plane from face and its midpoint
'''''swModel.ClearSelection2 (True)
'''''selBool = faceEntity.Select4(True, swSelData)
'''''Debug.Print "Face selected - " & selBool
'''''
'''''surfaceMidpoint = swModel.FeatureManager.InsertReferencePoint(4, 1, 50, 1) ' Surface midpoint
'''''surfaceMidpointString = surfaceMidpoint(0).Name

'' Create 3 points from 6 edges by intersection for a reference plane
' Get an edge and the one adjacent to it to create a point by InsertReferencePoint method

' Loop that traverses through lists of loop objs, edge entities to
' filter out empty elements
' To do: handle cases where the first loop is the outer one and it has odd number
'        of edges, if there are inner loops such as holes that have 2 edges each
'        it is not possible to find an intersection point on those edges

kk = 0 ' kk is the number of found edges
For i = 0 To nLoops
    For k = 0 To 99
        If (Not IsEmpty(tempEdgeEntity(i, k))) Then
            Set edgeEntityPairs(kk) = tempEdgeEntity(i, k)
            kk = kk + 1
        End If
    Next
Next


Dim intersectPoint(2) As Variant
Dim intersectPointString(2) As String

' This If statement needs to be more robust, haven't encountered issues
' but there might be some. It is possible to find the outer loop and
' obtain enough points for reference plane just from it
If (kk = 4) Then
    ' Case where there's only a face that contains 1 loop with 4 edges
    swModel.ClearSelection2 (True)
    selBool = edgeEntityPairs(0).Select4(True, swSelData)
    selBool = edgeEntityPairs(1).Select4(True, swSelData)
    intersectPoint(0) = swFeatMgr.InsertReferencePoint(6, 1, 50, 1) ' Edges intersection
    swModel.ClearSelection2 (True)
    selBool = edgeEntityPairs(1).Select4(True, swSelData)
    selBool = edgeEntityPairs(2).Select4(True, swSelData)
    intersectPoint(1) = swFeatMgr.InsertReferencePoint(6, 1, 50, 1) ' Edges intersection
    swModel.ClearSelection2 (True)
    selBool = edgeEntityPairs(2).Select4(True, swSelData)
    selBool = edgeEntityPairs(3).Select4(True, swSelData)
    intersectPoint(2) = swFeatMgr.InsertReferencePoint(6, 1, 50, 1) ' Edges intersection
    swModel.ClearSelection2 (True)
Else
    ' Case when there are multiple loops and when the first loop is a
    ' a hole that contains two edges
    swModel.ClearSelection2 (True)
    selBool = edgeEntityPairs(0).Select4(True, swSelData)
    selBool = edgeEntityPairs(1).Select4(True, swSelData)
    intersectPoint(0) = swFeatMgr.InsertReferencePoint(6, 1, 50, 1) ' Edges intersection
    swModel.ClearSelection2 (True)
    selBool = edgeEntityPairs(2).Select4(True, swSelData)
    selBool = edgeEntityPairs(3).Select4(True, swSelData)
    intersectPoint(1) = swFeatMgr.InsertReferencePoint(6, 1, 50, 1) ' Edges intersection
    swModel.ClearSelection2 (True)
    selBool = edgeEntityPairs(4).Select4(True, swSelData)
    selBool = edgeEntityPairs(5).Select4(True, swSelData)
    intersectPoint(2) = swFeatMgr.InsertReferencePoint(6, 1, 50, 1) ' Edges intersection
    swModel.ClearSelection2 (True)
End If

' Create reference plane using 3 points
intersectPointString(0) = intersectPoint(0)(0).Name
intersectPointString(1) = intersectPoint(1)(0).Name
intersectPointString(2) = intersectPoint(2)(0).Name

' Selecting the points
For p = 0 To 2
    If (p = 0) Then
        selBool = swModel.Extension.SelectByID2(intersectPointString(p), "DATUMPOINT", 0, 0, 0, False, 0, Nothing, 0)
    Else
        selBool = swModel.Extension.SelectByID2(intersectPointString(p), "DATUMPOINT", 0, 0, 0, True, p, Nothing, 0)
    End If
Next

' Creating the reference plane
Dim refPlaneObj As Object
Dim firstCon As Long: firstCon = SwConst.swRefPlaneReferenceConstraint_Coincident
Dim firstConVal As Long: firstConVal = 0
Dim secondCon As Long: secondCon = SwConst.swRefPlaneReferenceConstraint_Coincident
Dim secondConVal As Long: secondConVal = 0
Dim thirdCon As Long: thirdCon = SwConst.swRefPlaneReferenceConstraint_Coincident
Dim thirdConVal As Long: thirdConVal = 0
Set refPlaneObj = swModel.FeatureManager.InsertRefPlane(firstCon, firstConVal, _
                                                        secondCon, secondConVal, _
                                                        thirdCon, thirdConVal)

' Convert face entity to the sketch on the new plane
Dim refPlaneEntity As SldWorks.Entity
Set refPlaneEntity = refPlaneObj
swModel.ClearSelection2 (True)
selBool = refPlaneEntity.Select4(True, swSelData)
swModel.SketchManager.InsertSketch (True)
selVal = faceEntity.Select4(True, swSelData)
boolstatus = swModel.SketchManager.SketchUseEdge3(False, False)
swModel.SketchManager.InsertSketch True
End Sub

Actually it looks like there might be issues because the CAD model is imported and faces are faces are non-planar.

Hi Mario,

You can check if the selected face is planar by using:

Face.IGetSurface().IsPlane()

Eddy

There could be many reasons why I doesn't work for you. Without your complete code, it would be difficult to help you.

If your selection get deselected, it might be because you set "Attempt" to False. Also "Mark" needs to be "0" for the first selection, and "1" for the second. Look at the remarks and examples in InsertRefPlane

The best way to get a base for your code is to start recording a macro, manually insert a plane then stop and edit the code.

Also SelectByID2 is not the only method to select a face, there is also SelectByRay, or cycle through all the entities with GetFirstFace / GetNextFace or GetFaces to find the one you want.

Related