I can use GetSubentities to get a SelectedSubObject on a simple 3D object but when I use the same code on a 3D object that is "complex" (created by adding and subtracting other 3D objects) I have some trouble. I'm checking the SubentityType and it isn't returning a valid Type (edge, vertex, face) but rather Type {5}. Is there some trick to using GetSubentities() for "complex" solids?
Solved! Go to Solution.
Solved by philippe.leefsma. Go to Solution.
Hi
Could you provide a simple document that contains a sample solid that we can test please? Also be specific about which subentity needs to be selected to reproduce the issue you are describing.
Thank you,
Philippe.
Here is the code I’m using – sorry for the work in progress. I want to select edges and faces of 3D solids that will all be rectangular. When I make a simple box and run the selection for an edge, I get the right result (it’s currently configured just to change the subentity color but I will want to do fillet, etc. as well). When I return to the same object to run again and try a different edge, I get a PromptStatus error. Also, if I union two solid3d boxes and try selecting an edge, I get an “eInvalidInput” error when it calls the sobj.SetSubentityColor method. I commented out the type validation since it also fails. The type returned is type Class {5} instead of edge. I’m relatively new to programming so I’m assuming it’s something obvious. What do you see? I didn’t attach a drawing since it’s simple 3dSolid “box” objects that I’m testing on.
Public Sub BullnoseEdge(ByVal radius As Double)
Dim pso As New PromptSelectionOptions
pso.MessageForAdding = vbLf & "Select an edge to Bullnose: "
pso.SingleOnly = True
pso.SinglePickInSpace = True
pso.ForceSubSelections = True
Dim psr As PromptSelectionResult = ed.GetSelection(pso)
If psr.Status <> PromptStatus.OK Then
MsgBox("Selection Failed.")
Return
End If
Using trans As Transaction = db.TransactionManager.StartTransaction
Dim pickedSolid As ObjectId
Dim subEntID As SubentityId = GetSubentId(ed, trans, psr.Value, SubentityType.Edge, pickedSolid)
Dim edgeIds As SubentityId() = New SubentityId() {subEntID}
Dim rad As New DoubleCollection(radius)
Dim startSetBack As New DoubleCollection(radius)
Dim endSetBack As New DoubleCollection(radius)
sobj = TryCast(trans.GetObject(pickedSolid, OpenMode.ForWrite), Solid3d)
'sobj.FilletEdges(edgeIds, rad, startSetBack, endSetBack)
Dim colorString As acDefaultColors = acDefaultColors.green
Dim myColor As Color = Color.FromColorIndex(ColorMethod.ByColor, colorString)
sobj.SetSubentityColor(subEntID, myColor)
trans.Commit()
End Using
End Sub
Private Function GetSubentId(ByVal ed As Editor, ByVal trans As Transaction, ByVal ss As SelectionSet, ByVal subType As SubentityType, ByRef pickedId As ObjectId) As SubentityId
Dim retId As New SubentityId
'should only be one object in the array
Dim so As SelectedObject = ss(0)
pickedId = so.ObjectId
'access the selected object
Dim pickedSolid As Solid3d = TryCast(trans.GetObject(so.ObjectId, OpenMode.ForRead), Solid3d)
'get the array of subentities for the solid
Dim sso As SelectedSubObject() = so.GetSubentities()
'confirm the type selected matches the desired type
'Dim selectedType As SubentityType = sso(0).FullSubentityPath.SubentId.Type
'If selectedType = subType Then
' retId = sso(0).FullSubentityPath.SubentId
'Else
' ed.WriteMessage(vbLf & "The selected sub entity was of type {0}. Please select a {1}." & vbLf, selectedType, subType)
' Exit Function
'End If
retId = sso(0).FullSubentityPath.SubentId
Dim subEntityPath As New FullSubentityPath(New ObjectId() {solid.ObjectId}, retId)
Using ent As Entity = solid.GetSubentity(subEntityPath)
ed.WriteMessage(vbLf & "Subentity Entity Type: " & ent.ToString)
End Using
Return retId
End Function
End Class
Here is some code that works fine on my side, I am testing that one a single box, then two boxes that have been united. Sorry I don't have the VB.Net version ready to send you:
[CommandMethod("EdgesColor")] public void EdgesColor() { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; PromptEntityOptions peo = new PromptEntityOptions("\nSelect a 3D solid: "); peo.SetRejectMessage("\nInvalid selection..."); peo.AddAllowedClass(typeof(Solid3d), true); PromptEntityResult per = ed.GetEntity(peo); if (per.Status != PromptStatus.OK) return; using (Transaction Tx = db.TransactionManager.StartTransaction()) { Solid3d solid = Tx.GetObject(per.ObjectId, OpenMode.ForWrite)
as Solid3d; ObjectId[] ids = new ObjectId[] { per.ObjectId }; FullSubentityPath path = new FullSubentityPath( ids, new SubentityId(SubentityType.Null, IntPtr.Zero)); List<SubentityId> SubentIds = new List<SubentityId>(); using (Autodesk.AutoCAD.BoundaryRepresentation.Brep brep = new Autodesk.AutoCAD.BoundaryRepresentation.Brep(path)) { foreach (Autodesk.AutoCAD.BoundaryRepresentation.Edge edge in
brep.Edges) { SubentIds.Add(edge.SubentityPath.SubentId); } } short colorIdx = 1; foreach (SubentityId subentId in SubentIds) { Color color = Color.FromColorIndex(
ColorMethod.ByColor,
++colorIdx);
solid.SetSubentityColor(subentId, color); } Tx.Commit(); } }
Here are some blog posts I've been writting as well, they should be useful:
http://adndevblog.typepad.com/autocad/2012/03/selecting-solid3d-sub-entities.html
Regards,
Philippe.
Thanks for the code and the blogs. I had reviewed those blogs (and others) before writing. Your code works fine for selecting all the edges, but my problem comes in trying to select a single subentity with PromptSelectionResult forcing subselections. The GetSubentities method of the SelectedObject doesn't seem to produce a proper result. I can access a useable result with the simple box but I can't return to that box to select a second edge, nor can I get a good result on any edge from the "complex" solids.
Can't find what you're looking for? Ask the community or share your knowledge.