Author Topic: Fatal Error on Explode  (Read 3930 times)

0 Members and 1 Guest are viewing this topic.

gabep

  • Guest
Fatal Error on Explode
« on: June 05, 2008, 06:35:40 PM »
Hello,

Can somebody please tell me why I am getting a "FATAL ERROR" in Autocad 2008 at the
"curve.Explode(xobjs)" line? If I leave the explode section out it works fine.

Thanks!


 
Code: [Select]
Public Sub Test()

        Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor
        Dim db As Database = Application.DocumentManager.MdiActiveDocument.Database
        Dim trans As Transaction = db.TransactionManager.StartTransaction()

        Dim curves_p As DBObjectCollection = Nothing
        Dim curves_n As DBObjectCollection = Nothing
        Dim xents As DBObjectCollection = Nothing
        Dim xobjs As DBObjectCollection = Nothing

        Try
            Dim selOptions As PromptSelectionOptions = New PromptSelectionOptions
            selOptions.MessageForAdding = "Select polyline(s) to offset:"
            selOptions.AllowDuplicates = False
            selOptions.SingleOnly = False
            Dim result As PromptSelectionResult = ed.GetSelection(selOptions)

            If result.Status <> PromptStatus.OK Then Return

            Dim selSet As SelectionSet = result.Value

            Dim dblOptions As New PromptDoubleOptions(ControlChars.Lf & "Enter offset: ")
            dblOptions.AllowNegative = False
            dblOptions.AllowNone = False
            dblOptions.AllowZero = False
            Dim dblOptionsResult As PromptDoubleResult = ed.GetDouble(dblOptions)

            If dblOptionsResult.Status <> PromptStatus.OK Then Return

            Dim offset As Double = dblOptionsResult.Value

            Dim objIdArray As ObjectId() = selSet.GetObjectIds()
            Dim btr As BlockTableRecord = trans.GetObject(db.CurrentSpaceId, OpenMode.ForWrite)

            Dim ent As Entity
            Dim pl As Polyline
            Dim xent As Entity

            Dim id As ObjectId
            For Each id In objIdArray

                ent = DirectCast(trans.GetObject(id, OpenMode.ForRead), Entity)
                pl = DirectCast(ent, Polyline)

                curves_p = pl.GetOffsetCurves(offset)   'positive offset
                curves_n = pl.GetOffsetCurves(-offset)  'negative offset

                If curves_n IsNot Nothing Then
                    For Each curve As Entity In curves_n
                        curve.ColorIndex = 1

                        btr.AppendEntity(curve)
                        trans.AddNewlyCreatedDBObject(curve, True)
                    Next
                End If

                If curves_p IsNot Nothing Then
                    For Each curve As Entity In curves_p
                        curve.ColorIndex = 1

                        'Explode/

                        curve.Explode(xobjs)
                        For Each xobj As DBObject In xobjs
                            xent = DirectCast(xobj, Entity)
                            btr.AppendEntity(xent)
                            trans.AddNewlyCreatedDBObject(xent, True)
                        Next

                        '/Explode

                        'btr.AppendEntity(curve)
                        'trans.AddNewlyCreatedDBObject(curve, True)
                    Next
                End If


            Next id

            trans.Commit()
            curves_p.Dispose()
            curves_n.Dispose()

        Catch ex As Exception

            trans.Abort()
            MsgBox(ex.Message)

        Finally

            trans.Dispose()

        End Try

    End Sub

EDIT: by Dan ... added code tags
« Last Edit: June 05, 2008, 08:59:24 PM by Daniel »

Bryco

  • Water Moccasin
  • Posts: 1883
Re: Fatal Error on Explode
« Reply #1 on: June 05, 2008, 06:48:07 PM »
Are the ents that you are exploding always plines?

gabep

  • Guest
Re: Fatal Error on Explode
« Reply #2 on: June 05, 2008, 06:53:09 PM »
Yes.

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8706
  • AKA Daniel
Re: Fatal Error on Explode
« Reply #3 on: June 05, 2008, 08:50:07 PM »
try removing these two lines

Code: [Select]
curves_p.Dispose()
curves_n.Dispose()

gabep

  • Guest
Re: Fatal Error on Explode
« Reply #4 on: June 05, 2008, 09:28:12 PM »
try removing these two lines

Code: [Select]
curves_p.Dispose()
curves_n.Dispose()

Thanks, but it did not help...

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8706
  • AKA Daniel
Re: Fatal Error on Explode
« Reply #5 on: June 05, 2008, 09:34:50 PM »
This works on my machine, Sorry it’s in C# , I hope you can see the changes I made

Code: [Select]
[CommandMethod("doit")]
    public void Test()
    {
      Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
      Database db = Application.DocumentManager.MdiActiveDocument.Database;
      Transaction trans = db.TransactionManager.StartTransaction();
      DBObjectCollection curves_p = new DBObjectCollection(); //<<<-----
      DBObjectCollection curves_n = new DBObjectCollection();//<<<-----
      DBObjectCollection xobjs = new DBObjectCollection();//<<<-----
      try
      {
        PromptSelectionOptions selOptions = new PromptSelectionOptions();
        selOptions.MessageForAdding = "Select polyline(s) to offset:";
        selOptions.AllowDuplicates = false;
        selOptions.SingleOnly = false;
        PromptSelectionResult result = ed.GetSelection(selOptions);
        if (result.Status == PromptStatus.OK)
        {
          SelectionSet selSet = result.Value;
          PromptDoubleOptions dblOptions = new PromptDoubleOptions('\n' + "Enter offset: ");
          dblOptions.AllowNegative = false;
          dblOptions.AllowNone = false;
          dblOptions.AllowZero = false;
          PromptDoubleResult dblOptionsResult = ed.GetDouble(dblOptions);
          if (dblOptionsResult.Status == PromptStatus.OK)
          {
            double offset = dblOptionsResult.Value;
            ObjectId[] objIdArray = selSet.GetObjectIds();
            BlockTableRecord btr = trans.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
            Entity ent = null;
            Polyline pl = null;
            Entity xent = null;
            foreach (ObjectId id in objIdArray)
            {
              ent = (Entity)trans.GetObject(id, OpenMode.ForRead);
              pl = (Polyline)ent;
              curves_p = pl.GetOffsetCurves(offset);
              curves_n = pl.GetOffsetCurves(-offset);
              if (curves_n != null)
              {
                foreach (Entity curve in curves_n)
                {
                  curve.ColorIndex = 1;
                  btr.AppendEntity(curve);
                  trans.AddNewlyCreatedDBObject(curve, true);
                }
              }
              if (curves_p != null)
              {
                foreach (Entity curve in curves_p)
                {
                  curve.ColorIndex = 1;
                  curve.Explode(xobjs);

                  foreach (DBObject xobj in xobjs)
                  {
                    xent = (Entity)xobj;
                    if (xent.IsNewObject)//<<<-----
                    {
                      btr.AppendEntity(xent);
                      trans.AddNewlyCreatedDBObject(xent, true);
                    }
                  }
                  btr.AppendEntity(curve);
                  trans.AddNewlyCreatedDBObject(curve, true);
                }
              }
            }
            trans.Commit();
          }
        }
      }
      catch (SystemException ex)
      {
        trans.Abort();
        ed.WriteMessage(ex.Message);
        ed.WriteMessage(ex.StackTrace);
      }
      finally
      {
        trans.Dispose();
      }
    }


Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Fatal Error on Explode
« Reply #6 on: June 05, 2008, 10:19:53 PM »
This works on my machine, Sorry it’s in C# , I hope you can see the changes I made

Code: [Select]
[CommandMethod("doit")]
//............

gEEZE, don't be sorry :-)


I initially was going to comment on the Dispose for the curves as well, but the crash seemed to be happening at the explode.
Didn't take the time to have a good look otherwise ..
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8706
  • AKA Daniel
Re: Fatal Error on Explode
« Reply #7 on: June 05, 2008, 10:39:11 PM »
A couple of notes,

you don’t need to add the object(s) produced by GetOffsetCurves() to the database before exploding them.

Explode appends the objects to a collection so I assume the collection cannot be null.

Since the objects are appended to the collection, you only need one collection. Also since the collection may contain more than pointer to the same object you probably need to check to see if the object is already in the database.


Code: [Select]
[CommandMethod("doit")]
    public void Test()
    {
      Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
      Database db = Application.DocumentManager.MdiActiveDocument.Database;
      Transaction trans = db.TransactionManager.StartTransaction();
      DBObjectCollection curves = new DBObjectCollection(); //<<<-----
      try
      {

        PromptSelectionOptions selOptions = new PromptSelectionOptions();
        selOptions.MessageForAdding = "Select polyline(s) to offset:";
        selOptions.AllowDuplicates = false;
        selOptions.SingleOnly = false;
        PromptSelectionResult result = ed.GetSelection(selOptions);

        if (result.Status == PromptStatus.OK)
        {

          SelectionSet selSet = result.Value;
          PromptDoubleOptions dblOptions = new PromptDoubleOptions('\n' + "Enter offset: ");
          dblOptions.AllowNegative = false;
          dblOptions.AllowNone = false;
          dblOptions.AllowZero = false;
          PromptDoubleResult dblOptionsResult = ed.GetDouble(dblOptions);

          if (dblOptionsResult.Status == PromptStatus.OK)
          {

            double offset = dblOptionsResult.Value;
            ObjectId[] objIdArray = selSet.GetObjectIds();
            BlockTableRecord btr = trans.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;

            foreach (ObjectId id in objIdArray)
            {
              Entity ent = (Entity)trans.GetObject(id, OpenMode.ForRead);
              Polyline pl = (Polyline)ent;

              foreach (Entity curve in pl.GetOffsetCurves(offset))
              {
                curve.Explode(curves);
              }
              foreach (Entity curve in pl.GetOffsetCurves(-offset))
              {
                curve.Explode(curves);
              }

              foreach (DBObject xobj in curves)
              {
                Entity xent = (Entity)xobj;
                if (xent.IsNewObject)//<<<-----
                {
                  xent.ColorIndex = 1;
                  btr.AppendEntity(xent);
                  trans.AddNewlyCreatedDBObject(xent, true);
                }
              }

            }
            trans.Commit();
          }
        }
      }
      catch (SystemException ex)
      {
        trans.Abort();
        ed.WriteMessage(ex.Message);
        ed.WriteMessage(ex.StackTrace);
      }
      finally
      {
        trans.Dispose();
      }
    }

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Fatal Error on Explode
« Reply #8 on: June 05, 2008, 10:48:35 PM »


...
you may also want to filter and validate for pline selection

Have a look at PromptEntityResult.AddAllowedClass(...)  for Get entity options or selection filters for SelectionSets
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8706
  • AKA Daniel
Re: Fatal Error on Explode
« Reply #9 on: June 05, 2008, 10:55:09 PM »


...
you may also want to filter and validate for pline selection

Have a look at PromptEntityResult.AddAllowedClass(...)  for Get entity options or selection filters for SelectionSets

Good call Kerry

new code

Code: [Select]
[CommandMethod("doit")]
    public void Test()
    {
      Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;

      TypedValue[] values = new TypedValue[]
                     {
                        new TypedValue((short)DxfCode.Start, "LWPOLYLINE")
                     };

      SelectionFilter filter = new SelectionFilter(values);

      Database db = Application.DocumentManager.MdiActiveDocument.Database;
      Transaction trans = db.TransactionManager.StartTransaction();
      DBObjectCollection curves = new DBObjectCollection();
      try
      {
        PromptSelectionOptions selOptions = new PromptSelectionOptions();
        selOptions.MessageForAdding = "Select polyline(s) to offset:";
        selOptions.AllowDuplicates = false;
        selOptions.SingleOnly = false;
        PromptSelectionResult result = ed.GetSelection(selOptions,filter);
        if (result.Status == PromptStatus.OK)
        {
          SelectionSet selSet = result.Value;
          PromptDoubleOptions dblOptions = new PromptDoubleOptions('\n' + "Enter offset: ");
          dblOptions.AllowNegative = false;
          dblOptions.AllowNone = false;
          dblOptions.AllowZero = false;
          PromptDoubleResult dblOptionsResult = ed.GetDouble(dblOptions);
          if (dblOptionsResult.Status == PromptStatus.OK)
          {
            double offset = dblOptionsResult.Value;
            ObjectId[] objIdArray = selSet.GetObjectIds();
            BlockTableRecord btr = trans.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
            foreach (ObjectId id in objIdArray)
            {
              Entity ent = (Entity)trans.GetObject(id, OpenMode.ForRead);
              Polyline pl = (Polyline)ent;
              foreach (Entity curve in pl.GetOffsetCurves(offset))
              {
                using (curve)
                {
                  curve.Explode(curves);
                  continue;
                }
              }
              foreach (Entity curve in pl.GetOffsetCurves(-offset))
              {
                using (curve)
                {
                  curve.Explode(curves);
                  continue;
                }
              }
              foreach (DBObject xobj in curves)
              {
                Entity xent = (Entity)xobj;
                if (xent.IsNewObject)
                {
                  xent.ColorIndex = 1;
                  btr.AppendEntity(xent);
                  trans.AddNewlyCreatedDBObject(xent, true);
                }
              }
            }
            trans.Commit();
          }
        }
      }
      catch (SystemException ex)
      {
        trans.Abort();
        ed.WriteMessage(ex.Message);
        ed.WriteMessage(ex.StackTrace);
      }
      finally
      {
        trans.Dispose();
      }
    }

tjr

  • Guest
Re: Fatal Error on Explode
« Reply #10 on: June 05, 2008, 11:40:18 PM »
Also note if you are a VB.NET developer SharpDevelop's online code converter can be a very good friend of yours when it comes to C# samples.

Here are the results of the conversion from Dan's latest code:
Code: [Select]
<CommandMethod("doit")> _
Public Sub Test()
Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor

Dim values As TypedValue() = New TypedValue() {New TypedValue(CShort(DxfCode.Start), "LWPOLYLINE")}

Dim filter As New SelectionFilter(values)

Dim db As Database = Application.DocumentManager.MdiActiveDocument.Database
Dim trans As Transaction = db.TransactionManager.StartTransaction()
Dim curves As New DBObjectCollection()
Try
Dim selOptions As New PromptSelectionOptions()
selOptions.MessageForAdding = "Select polyline(s) to offset:"
selOptions.AllowDuplicates = False
selOptions.SingleOnly = False
Dim result As PromptSelectionResult = ed.GetSelection(selOptions, filter)
If result.Status = PromptStatus.OK Then
Dim selSet As SelectionSet = result.Value
Dim dblOptions As New PromptDoubleOptions(ControlChars.Lf & "Enter offset: ")
dblOptions.AllowNegative = False
dblOptions.AllowNone = False
dblOptions.AllowZero = False
Dim dblOptionsResult As PromptDoubleResult = ed.GetDouble(dblOptions)
If dblOptionsResult.Status = PromptStatus.OK Then
Dim offset As Double = dblOptionsResult.Value
Dim objIdArray As ObjectId() = selSet.GetObjectIds()
Dim btr As BlockTableRecord = TryCast(trans.GetObject(db.CurrentSpaceId, OpenMode.ForWrite), BlockTableRecord)
For Each id As ObjectId In objIdArray
Dim ent As Entity = DirectCast(trans.GetObject(id, OpenMode.ForRead), Entity)
Dim pl As Polyline = DirectCast(ent, Polyline)
For Each curve As Entity In pl.GetOffsetCurves(offset)
Using curve
curve.Explode(curves)
Continue For
End Using
Next
For Each curve As Entity In pl.GetOffsetCurves(-offset)
Using curve
curve.Explode(curves)
Continue For
End Using
Next
For Each xobj As DBObject In curves
Dim xent As Entity = DirectCast(xobj, Entity)
If xent.IsNewObject Then
xent.ColorIndex = 1
btr.AppendEntity(xent)
trans.AddNewlyCreatedDBObject(xent, True)
End If
Next
Next
trans.Commit()
End If
End If
Catch ex As SystemException
trans.Abort()
ed.WriteMessage(ex.Message)
ed.WriteMessage(ex.StackTrace)
Finally
trans.Dispose()
End Try
End Sub

gabep

  • Guest
Re: Fatal Error on Explode
« Reply #11 on: June 06, 2008, 01:05:25 AM »
Thanks a lot for the great examples guys!

After making the suggested changes, it now works!

 :-)


It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8706
  • AKA Daniel
Re: Fatal Error on Explode
« Reply #12 on: June 06, 2008, 01:10:47 AM »
My pleasure, and Welcome to TheSwamp.Org  :-)