.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Help needed in slicing solids at given intervals

6 REPLIES 6
SOLVED
Reply
Message 1 of 7
Anonymous
1113 Views, 6 Replies

Help needed in slicing solids at given intervals

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

Slice Solid.png

 

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()

 

6 REPLIES 6
Message 2 of 7
augusto.goncalves
in reply to: Anonymous

From the code, looks like you're trying to slice the same solid twice? I believe that may fail as the solid is not there anymore...
Regards,



Augusto Goncalves
Twitter @augustomaia
Autodesk Developer Network
Message 3 of 7
Anonymous
in reply to: augusto.goncalves

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.

 

 

Message 4 of 7
augusto.goncalves
in reply to: Anonymous

But note the top transaction is not committing, so that can cause the issue. From your error message and code, that can be the issue. Can you try with only 1 transaction that commit on every slice?
Regards,



Augusto Goncalves
Twitter @augustomaia
Autodesk Developer Network
Message 5 of 7
Anonymous
in reply to: augusto.goncalves

Hi!, First I tried with one transaction only. But if I commit the transaction, I couldn't iterate through the lines for further processing. If possible to iterate, please let me know where to commit the transaction.

Regards,
Srikanth.
Message 6 of 7
augusto.goncalves
in reply to: Anonymous

Hi,

So I did a further investigation on this.

The DisposableWrapper will throw this InvalidOperation exception if the object being created is NULL/Nothing (among other problems). But as this is happening inside the API, it's not on your code.

If you look at the C++ documentation, the SLICE method will return OK even if the plane is not crossing the solid, but the sliced solid is null/nothing, and the this pointer is passed on and cause the exception...

So in your case, if the line does not cross the solid, it throw this exception. Sadly

To fix it, put a try/catch around the Solid3D.Slice call, it this InvalidOperationException happens, then you know the solid and the plane (formed by the line points) are not crossing.

Looking at your code, you have no check around this, but you need to. Make sure the LINE and SOLID are crossing. Note that when you slice, you have no testing if the next line will cross the original solid (now sliced) or new piece...
Regards,



Augusto Goncalves
Twitter @augustomaia
Autodesk Developer Network
Message 7 of 7
Anonymous
in reply to: augusto.goncalves

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.

Post to forums  

Forma Design Contest


Autodesk Design & Make Report