Hi!
I need to iterate through the user selected cut lines and for every cutline, identify the solids crossing and slice them to that line. Below the code is working for single line selection. But for multiple lines selection, in the second iteration, getting the error.
Any help would be greatly appreciated.
Image: User Selecting Lines & Solids to Identify
Code:
Public Sub SliceSolid() Dim Doc As Document = Application.DocumentManager.MdiActiveDocument Dim DB As Database = Doc.Database Dim Ed As Editor = Doc.Editor Try Using Tr As Transaction = DB.TransactionManager.StartTransaction Dim BT As BlockTable = Tr.GetObject(DB.BlockTableId, OpenMode.ForRead) Dim BTR As BlockTableRecord = Tr.GetObject(BT(BlockTableRecord.ModelSpace), OpenMode.ForWrite) Dim SObjPrRes As PromptSelectionResult = Ed.GetSelection If SObjPrRes.Status = PromptStatus.OK Then Dim SSet As SelectionSet = SObjPrRes.Value For Each Obj As SelectedObject In SSet Dim Ent As Entity = Tr.GetObject(Obj.ObjectId, OpenMode.ForRead) If Obj.ObjectId.ObjectClass.DxfName = "LINE" Then Dim L As Line : L = Ent Dim PT1 As Point3d = L.StartPoint : Dim PT2 As Point3d = L.EndPoint Ed.WriteMessage(vbLf & "Line Start : " & L.StartPoint.ToString & " - Line End :" & L.EndPoint.ToString) Dim CrossSelection As SelectionSet = SelectObjectsByCrossingWindow(L.StartPoint, L.EndPoint) 'PrintSelectionSetObjectIds(CrossSelection) 'SliceSolidsByPoints(CrossSelection, L.StartPoint, L.EndPoint) Using Tr2 As Transaction = DB.TransactionManager.StartTransaction For Each Obj2 As SelectedObject In CrossSelection If Obj2.ObjectId.ObjectClass.DxfName = "3DSOLID" Then Dim Sol3D As Solid3d = Tr2.GetObject(Obj2.ObjectId, OpenMode.ForWrite) Dim Pt3 As Point3d = New Point3d(PT1.X, PT1.Y, PT1.Z) Dim Pt4 As Point3d = New Point3d(PT1.X, PT1.Y, PT1.Z + 10) Dim Pt5 As Point3d = New Point3d(PT2.X, PT2.Y, PT1.Z + 10) Dim acPlane As Plane = New Plane(Pt3, Pt4, Pt5) Dim Sol3DSlice As Solid3d = Sol3D.Slice(acPlane, True) BTR.AppendEntity(Sol3DSlice) Tr2.AddNewlyCreatedDBObject(Sol3DSlice, True) Ed.WriteMessage(vbLf & "New Solid Created: " & Sol3DSlice.ObjectId.ToString()) End If Next Tr2.Commit() End Using End If Next End If Tr.Commit() End Using Catch ex As Exception MsgBox(ex.ToString, , "Sub - " & System.Reflection.MethodBase.GetCurrentMethod.Name) Clipboard.SetText(ex.ToString) End Try End Sub
Error:
System.InvalidOperationException: Operation is not valid due to the current state of the object.
at Autodesk.AutoCAD.Runtime.DisposableWrapper.Attach(IntPtr unmanagedPointer, Boolean autoDelete)
at Autodesk.AutoCAD.DatabaseServices.Solid3d.Slice(Plane plane, Boolean negativeHalfToo)
at ClassLibrary1.SliceSolids.SliceSolid()
Solved! Go to Solution.
Hi Augusto,
Thanks for your response.
You are correct, if we cut the same solid twice without updating database. But in current case after slicing the solid, committed the transaction to update the database. After that program returns to next Cut line and identifies crossing solids (including newly cut solid) to process further.
Could you please confirm whether slicing is an asynchronous process and causing error? If so, what is the easiest way to overcome?
Regards,
Srikanth.
Hi Augusto!
Thank you for your kind help and suggestion on try catch.
Coming to the point, First identified objects crossing the line, then checked whether identified object is Solid, then tried to slice the solid. So in this scenario, no chance of slicing null object. So no exception.
Then as you suggested I tried the way committing first transaction. Finally concluded it as below.
I have stored and reused the points in very raw manner. Suggest me some better options.
Start Transaction
Get Lines from User
Collect Points from User Selected Lines
Commit Transaction
For Each Item in Collection Points
Identify Crossing Objects
For Each Object in Crossing Objects
If Object is Solid then
Start Transaction
Slice Object to Point Collection
Commit Transaction
End if
Next
Next
Code:
Dim SlicePoints As New List(Of String) <CommandMethod("SliceSolidsByLines")> Public Sub SliceSolid() Dim Doc As Document = Application.DocumentManager.MdiActiveDocument Dim DB As Database = Doc.Database Dim Ed As Editor = Doc.Editor Try Using Tr As Transaction = DB.TransactionManager.StartTransaction Dim BT As BlockTable = Tr.GetObject(DB.BlockTableId, OpenMode.ForRead) Dim BTR As BlockTableRecord = Tr.GetObject(BT(BlockTableRecord.ModelSpace), OpenMode.ForRead) Dim SObjPrRes As PromptSelectionResult = Ed.GetSelection If SObjPrRes.Status = PromptStatus.OK Then Dim SSet As SelectionSet = SObjPrRes.Value For Each Obj As SelectedObject In SSet Dim Ent As Entity = Tr.GetObject(Obj.ObjectId, OpenMode.ForRead) If Obj.ObjectId.ObjectClass.DxfName = "LINE" Then Dim L As Line : L = Ent Dim PT1 As Point3d = L.StartPoint : Dim PT2 As Point3d = L.EndPoint Dim SStr As String = L.StartPoint.X & "|" & L.StartPoint.Y & "|" & L.StartPoint.Z & "|" & L.EndPoint.X & "|" & L.EndPoint.Y & "|" & L.EndPoint.Z SlicePoints.Add(SStr) End If Next End If Tr.Commit() End Using For Each AStr As String In SlicePoints Dim PTS() As String = AStr.Split("|") Dim PT1 As Point3d = New Point3d(PTS(0), PTS(1), PTS(2)) Dim PT2 As Point3d = New Point3d(PTS(3), PTS(4), PTS(5)) Dim CrossSelection As SelectionSet = SelectObjectsByCrossingWindow(PT1, PT2) For Each Obj2 As SelectedObject In CrossSelection If Obj2.ObjectId.ObjectClass.DxfName = "3DSOLID" Then SliceSolidByPoints(Obj2.ObjectId, PT1, PT2) End If Next Next Catch ex As Exception MsgBox(ex.ToString, , "Sub - " & System.Reflection.MethodBase.GetCurrentMethod.Name) Clipboard.SetText(ex.ToString) End Try End Sub
Regards,
Srikanth.
Can't find what you're looking for? Ask the community or share your knowledge.