Author Topic: Creating an associative hatch in C# causes access violation  (Read 7880 times)

0 Members and 1 Guest are viewing this topic.

akaranta

  • Guest
Creating an associative hatch in C# causes access violation
« on: September 30, 2015, 06:54:34 AM »
I wrote code to programmatically (in C#) create a hatch that I first created interactively, i.e. the properties of the bounding polyline, the hatch and the hatch loop are taken from that real case. The problem is that I get access violation when calling AppendLoop method.
 
Here's the code - it is easy to copy-paste into a class and run using the command NSASSOCHATCH
 
Code - C#: [Select]
  1. [CommandMethod( "NSASSOCHATCH" )]
  2. public static void AssocHatch() {
  3.     var doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
  4.     using ( var tx = doc.TransactionManager.StartTransaction() ) {
  5.         var polyline = CreatePolyline();
  6.         AddEntity( tx, doc.Database, polyline );
  7.         polyline.Layer = "0";
  8.  
  9.         CreateHatch( doc, tx, polyline );
  10.  
  11.         tx.Commit();
  12.     }
  13. }
  14.  
  15. private static readonly EntityColor __color = new EntityColor( ColorMethod.ByLayer, 256 );
  16.  
  17.  
  18. private static Hatch CreateHatch( Autodesk.AutoCAD.ApplicationServices.Document doc, Transaction tx, Polyline boundary ) {
  19.     var h = new Hatch();
  20.  
  21.     h.SetHatchPattern( HatchPatternType.PreDefined, "ANGLE" );
  22.     h.HatchObjectType = HatchObjectType.HatchObject;
  23.  
  24.     //using ( var c = Color.FromEntityColor( __bgColor ) ) {
  25.     //    h.BackgroundColor = c;
  26.     //}
  27.  
  28.     h.SetGradient( GradientPatternType.PreDefinedGradient, "LINEAR" );
  29.     h.GradientAngle = 0;
  30.     h.GradientOneColorMode = false;
  31.     h.GradientShift = 0;
  32.  
  33.     h.HatchStyle = HatchStyle.Outer;
  34.  
  35.     h.Normal = new Vector3d( 0, 0, 1 );
  36.     h.Origin = new Point2d( 0, 0 );
  37.  
  38.     h.PatternAngle = 0;
  39.     h.PatternDouble = false;
  40.     h.PatternScale = 1.0;
  41.     h.PatternSpace = 1.0;
  42.  
  43.     var gradientColors = new GradientColor[] { new GradientColor( Color.FromColorIndex( ColorMethod.ByAci, 5 ) , 0),
  44.                                                new GradientColor( Color.FromColorIndex( ColorMethod.ByAci, 2 ), 1)};
  45.  
  46.     h.SetGradientColors( gradientColors );
  47.     // according to http://adndevblog.typepad.com/autocad/2012/07/hatch-using-the-autocad-net-api.html
  48.     // the pattern needs to be "reaffirmed"
  49.     h.SetHatchPattern( HatchPatternType.PreDefined, "ANGLE" );
  50.  
  51.     // add to db before making hatch associative
  52.     AddEntity( tx, doc.Database, h );
  53.  
  54.     h.Associative = true;
  55.  
  56.     var boundaryColl = new ObjectIdCollection( new [] { boundary.ObjectId } );
  57.     // this call causes access violation
  58.     h.AppendLoop( HatchLoopTypes.Derived | HatchLoopTypes.Polyline | HatchLoopTypes.External, boundaryColl );
  59.  
  60.     h.EvaluateHatch( true );
  61.  
  62.     return h;
  63. }
  64.  
  65. private static Polyline CreatePolyline() {
  66.     var polyline = new Polyline( 5 );
  67.     polyline.Normal = new Vector3d( 0.0, 0.0, 1.0 );
  68.     // changing this to true does not help to the access violation
  69.     polyline.Closed = false;
  70.     using ( var c = Color.FromEntityColor( __color ) ) {
  71.         polyline.Color = c;
  72.     }
  73.  
  74.     var startPoint = new Point2d( -1689.42165011024, 992.835483259347 );
  75.  
  76.     polyline.AddVertexAt( 0, startPoint, 0, 0, 0 );
  77.     polyline.AddVertexAt( 1, new Point2d( -551.330950840098, 109.713933732506 ), 0, 0, 0 );
  78.     polyline.AddVertexAt( 2, new Point2d( 29.8217540440291, 1216.64025798278 ), 0, 0, 0 );
  79.     polyline.AddVertexAt( 3, new Point2d( 1052.89265151563, 1313.42070640714 ), 0, 0, 0 );
  80.     polyline.AddVertexAt( 4, startPoint, 0, 0, 0 );
  81.  
  82.     polyline.MinimizeMemory();
  83.  
  84.     return polyline;
  85. }
  86.  
  87. private static ObjectId AddEntity( Transaction tx, Database db, Entity e ) {
  88.     var btr = (BlockTableRecord)tx.GetObject( SymbolUtilityServices.GetBlockModelSpaceId( db ), OpenMode.ForWrite );
  89.     var oid = btr.AppendEntity( e );
  90.     e.SetDatabaseDefaults( db );
  91.     tx.AddNewlyCreatedDBObject( e, true );
  92.     return oid;
  93. }
  94.  

 
Environment: windows 7 on x64 (also occurs at least on windows 8), AutoCAD 2015

Ps. I have also posted this question to the AutoCAD forum at http://forums.autodesk.com/t5/autocad-2013-2014-2015-2016/creating-an-associative-hatch-in-c-causes-access-violation/td-p/5836968

Jeff H

  • Needs a day job
  • Posts: 6142
Re: Creating an associative hatch in C# causes access violation
« Reply #1 on: September 30, 2015, 03:41:33 PM »
Welcome to the Swamp!

Seems like hatches are like mleaders sometimes where the order you set properties can cause problems.
Will have a little more time later to look at it but if seems right could just be order the properties are set.

Bryco

  • Water Moccasin
  • Posts: 1882
Re: Creating an associative hatch in C# causes access violation
« Reply #2 on: October 02, 2015, 07:59:57 PM »
Closing the pline help?

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Creating an associative hatch in C# causes access violation
« Reply #3 on: October 02, 2015, 09:32:35 PM »
I believe the problem is associated with adding the Pattern as well as the Gradient.

I also committed the pline before adding the hatch.
I left the pline not closed.

tested in AutoCAD 2016 on Win10
Hope that helps.

Code - C#: [Select]
  1. using System;
  2. using Autodesk.AutoCAD.Runtime;
  3. using Autodesk.AutoCAD.ApplicationServices;
  4. using Autodesk.AutoCAD.Colors;
  5. using Autodesk.AutoCAD.DatabaseServices;
  6. using Autodesk.AutoCAD.Geometry;
  7. using Autodesk.AutoCAD.EditorInput;
  8.  
  9. [assembly: CommandClass(typeof(NSASSOCHATCH.MyCommands))]
  10.  
  11. namespace NSASSOCHATCH {
  12.     public class MyCommands {
  13.         [CommandMethod("NSASSOCHATCH")]
  14.         public static void AssocHatch() {
  15.             var doc =
  16.                 Autodesk.AutoCAD.ApplicationServices.Core.Application.DocumentManager
  17.                         .MdiActiveDocument;
  18.             var polyline = new Polyline();
  19.  
  20.             using(var tx = doc.TransactionManager.StartTransaction()) {
  21.                 polyline = CreatePolyline();
  22.                 AddEntity(tx, doc.Database, polyline);
  23.                 polyline.Layer = "0";
  24.                 tx.Commit();
  25.             }
  26.             using(var tx = doc.TransactionManager.StartTransaction()) {
  27.                 CreateHatch(doc, tx, polyline);
  28.                 tx.Commit();
  29.             }
  30.         }
  31.  
  32.         private static readonly EntityColor __color = new EntityColor(ColorMethod.ByLayer, 256);
  33.  
  34.         private static Hatch CreateHatch(Document doc, Transaction tx, Polyline boundary) {
  35.             var h = new Hatch();
  36.  
  37.             // // ***revised
  38.             // h.SetHatchPattern(HatchPatternType.PreDefined, "ANGLE");
  39.  
  40.             // h.HatchObjectType = HatchObjectType.HatchObject;
  41.             h.HatchObjectType = HatchObjectType.GradientObject;
  42.  
  43.             //using ( var c = Color.FromEntityColor( __bgColor ) ) {
  44.             //    h.BackgroundColor = c;
  45.             //}
  46.  
  47.             h.SetGradient(GradientPatternType.PreDefinedGradient, "LINEAR");
  48.             // h.GradientAngle = 0;
  49.             h.GradientAngle = 0.0;
  50.             h.GradientOneColorMode = false;
  51.             h.GradientShift = 0;
  52.  
  53.             h.HatchStyle = HatchStyle.Outer;
  54.  
  55.             h.Normal = new Vector3d(0, 0, 1);
  56.             h.Origin = new Point2d(0, 0);
  57.  
  58.             // h.PatternAngle = 0;          // ***revised
  59.             // h.PatternAngle = 0.0;        // ***revised
  60.             // h.PatternDouble = false;     // ***revised
  61.             // h.PatternScale = 1.0;        // ***revised
  62.             // h.PatternSpace = 1.0;        // ***revised
  63.  
  64.             var gradientColors = new GradientColor[] {
  65.                                                          new GradientColor(
  66.                                                              Color.FromColorIndex(ColorMethod.ByAci,5),0),
  67.                                                          new GradientColor(
  68.                                                              Color.FromColorIndex(ColorMethod.ByAci,2),1)
  69.                                                      };
  70.             h.SetGradientColors(gradientColors);
  71.             // according to http://adndevblog.typepad.com/autocad/2012/07/hatch-using-the-autocad-net-api.html
  72.             // the pattern needs to be "reaffirmed"
  73.  
  74.             // ***revised
  75.             // h.SetHatchPattern(HatchPatternType.PreDefined, "ANGLE");
  76.  
  77.             // add to db before making hatch associative
  78.             AddEntity(tx, doc.Database, h);
  79.  
  80.             h.Associative = true;
  81.  
  82.             var boundaryColl = new ObjectIdCollection(new[] { boundary.ObjectId });
  83.             // this call causes access violation
  84.             h.AppendLoop(
  85.                          // ***revised HatchLoopTypes.Derived | HatchLoopTypes.Polyline |
  86.                          // ***revised HatchLoopTypes.External,
  87.                          HatchLoopTypes.Default,
  88.                          boundaryColl);
  89.  
  90.             h.EvaluateHatch(true);
  91.  
  92.             return h;
  93.         }
  94.  
  95.         private static Polyline CreatePolyline() {
  96.             var polyline = new Polyline(5);
  97.             polyline.Normal = new Vector3d(0.0, 0.0, 1.0);
  98.             // changing this to true does not help to the access violation
  99.             polyline.Closed = false;
  100.  
  101.             using(var c = Color.FromEntityColor(__color)) {
  102.                 polyline.Color = c;
  103.             }
  104.  
  105.             var startPoint = new Point2d(-1689.42165011024, 992.835483259347);
  106.  
  107.             polyline.AddVertexAt(0, startPoint, 0, 0, 0);
  108.             polyline.AddVertexAt(1,
  109.                                  new Point2d(-551.330950840098, 109.713933732506),
  110.                                  0, 0, 0);
  111.             polyline.AddVertexAt(2,
  112.                                  new Point2d(29.8217540440291, 1216.64025798278),
  113.                                  0, 0, 0);
  114.             polyline.AddVertexAt(3,
  115.                                  new Point2d(1052.89265151563, 1313.42070640714),
  116.                                  0, 0, 0);
  117.  
  118.             polyline.AddVertexAt(4, startPoint, 0, 0, 0);
  119.  
  120.             polyline.MinimizeMemory();
  121.  
  122.             return polyline;
  123.         }
  124.  
  125.         private static ObjectId AddEntity(Transaction tx, Database db, Entity e) {
  126.             var btr =
  127.                 (BlockTableRecord)
  128.                 tx.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db),
  129.                              OpenMode.ForWrite);
  130.             var oid = btr.AppendEntity(e);
  131.             e.SetDatabaseDefaults(db);
  132.             tx.AddNewlyCreatedDBObject(e, true);
  133.             return oid;
  134.         }
  135.  
  136.     }
  137. }
  138.  
  139.  
« Last Edit: October 02, 2015, 10:01:07 PM by Kerry »
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.

akaranta

  • Guest
Re: Creating an associative hatch in C# causes access violation
« Reply #4 on: October 06, 2015, 06:30:19 AM »
Thank you Kerry!

This is a huge step forward for me in this issue. Unoftunately it is not quite yet resolved - I still get an access violation when trying to create a hatch, not a gradient.

A bit of background - I need to programmatically extract the properties of an AutoCAD object and recreate / modify a corresponding object in another AutoCAD instance.

If I understood you right, some of the Hatch class' properties are only applicable when HatchObjectType == HatchObjectType.HatchObject and others only when HatchObjectType == HatchObjectType.GradientObject?
All the properties I set in the code were read from a real live Hatch object. In order to reproduce this object I only need to take care of the relevant subset of the hatch properties?

With that in mind I revised the original code like so (note that the original object was a hatch, not a gradient):

Code - C#: [Select]
  1.         private static Hatch CreateHatch( Autodesk.AutoCAD.ApplicationServices.Document doc, Transaction tx, Polyline boundary, HatchObjectType htype = HatchObjectType.HatchObject ) {
  2.             var h = new Hatch();
  3.  
  4.             h.HatchObjectType = htype;
  5.             if ( h.HatchObjectType == HatchObjectType.HatchObject ) {
  6.                 h.SetHatchPattern( HatchPatternType.PreDefined, "ANGLE" );
  7.             }
  8.  
  9.             if ( h.HatchObjectType == HatchObjectType.GradientObject ) {
  10.                 h.SetGradient( GradientPatternType.PreDefinedGradient, "LINEAR" );
  11.                 h.GradientAngle = 0;
  12.                 h.GradientOneColorMode = false;
  13.                 h.GradientShift = 0;
  14.                 var gradientColors = new GradientColor[] { new GradientColor( Color.FromColorIndex( ColorMethod.ByAci, 5 ) , 0),
  15.                                                        new GradientColor( Color.FromColorIndex( ColorMethod.ByAci, 2 ), 1)};
  16.  
  17.                 h.SetGradientColors( gradientColors );
  18.             }
  19.  
  20.             if ( h.HatchObjectType == HatchObjectType.HatchObject ) {
  21.                 h.HatchStyle = HatchStyle.Outer;
  22.  
  23.                 h.Normal = new Vector3d( 0, 0, 1 );
  24.                 h.Origin = new Point2d( 0, 0 );
  25.  
  26.                 h.PatternAngle = 0;
  27.                 h.PatternDouble = false;
  28.                 h.PatternScale = 1.0;
  29.                 h.PatternSpace = 1.0;
  30.             }
  31.  
  32.             // according to http://adndevblog.typepad.com/autocad/2012/07/hatch-using-the-autocad-net-api.html
  33.             // the pattern needs to be "reaffirmed"
  34.             if ( h.HatchObjectType == HatchObjectType.HatchObject ) {
  35.                 h.SetHatchPattern( HatchPatternType.PreDefined, "ANGLE" );
  36.             }
  37.  
  38.             // add to db before making hatch associative
  39.             AddEntity( tx, doc.Database, h );
  40.  
  41.             h.Associative = true;
  42.  
  43.             var boundaryColl = new ObjectIdCollection( new [] { boundary.ObjectId } );
  44.             // this call causes access violation
  45.             h.AppendLoop( HatchLoopTypes.Derived | HatchLoopTypes.Polyline | HatchLoopTypes.External, boundaryColl );
  46.  
  47.             h.EvaluateHatch( true );
  48.  
  49.             return h;
  50.         }
  51.  

I still get an access violation from the AppendLoop method. :( Am I still setting some properties I should not or missing properties I should set?

Ps. A secondary question - do I need to Dispose of the ObjectIdCollection myself or will the hatch object attain its "ownership" (and Dispose of it when needed) when I give the loop to the hatch object via AppendLoop? This is not really clean in the docs IMO. Or maybe I missed it?

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Creating an associative hatch in C# causes access violation
« Reply #5 on: October 06, 2015, 07:02:29 AM »
I don't use hatches very much ...

I thought we could fill existing objects or enclosed areas with either hatch patterns, solid color fills, or gradients.

I wasn't aware that they could be combined into ONE object.

Can you post the drawing with the hatch object you used as a template ??

ADDED:
Re-reading your last post.
It appears you ARE trying to only apply ONE type.

Personally, I'd make one function for each option rather than jump through hoops in the builder.

I'm off to bed now, so could you please post (at your leisure ) the complete class source.
I'll have a look tomorrow.


ADDED:

Your post at the AutoDesk Discussion Group may have been better located in the .NET forum.
http://forums.autodesk.com/t5/net/bd-p/152

« Last Edit: October 06, 2015, 08:03:19 AM by Kerry »
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.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Creating an associative hatch in C# causes access violation
« Reply #6 on: October 07, 2015, 09:35:31 AM »
See if this suits you ...

First, the result then the code layout.
The next post will have the code commands and methods.

This is the way I'd do it ... subject to the result spec's and the work flow requirements.
Note the nested using statements.
... and the parameters passed to the Polyline and Hatch generators.

Note that the vector calculations are base on X,Y pairs for each leg, not the absolute location.
This is easy to modify, it just suited my sample using the same shape for the examples.
It may suit you to generate a collection of vertex points in the main module  and pass that collection to the generator.

The code has not been reviewed, it'sjust proof of concept code
... due care and no responsibility :)


« Last Edit: October 07, 2015, 10:01:59 AM by Kerry »
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.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Creating an associative hatch in C# causes access violation
« Reply #7 on: October 07, 2015, 09:45:24 AM »
The code ... just add each to the class
The Source Zip is attached at the bottom of the post.

Code - C#: [Select]
  1. // codehimbelonga kdub@theSwamp  
  2. // Oct 2015 // for http://www.theswamp.org/index.php?topic=50188.msg553449#msg553449
  3. using System;
  4. using Autodesk.AutoCAD.Runtime;
  5. using Autodesk.AutoCAD.ApplicationServices;
  6. using Autodesk.AutoCAD.Colors;
  7. using Autodesk.AutoCAD.DatabaseServices;
  8. using Autodesk.AutoCAD.Geometry;
  9. using AcadApp = Autodesk.AutoCAD.ApplicationServices.Core.Application;
  10.  
  11. [assembly: CommandClass(typeof(NSASSOCHATCH.MyHatchTestingCommands))]
  12.  
  13. namespace NSASSOCHATCH {
  14.     public class MyHatchTestingCommands {
  15.  
  16. }
  17.  

Code - C#: [Select]
  1.         [CommandMethod("AH01")]
  2.         public static void AddHatch01() {
  3.             var doc = AcadApp.DocumentManager.MdiActiveDocument;
  4.             var db = doc.Database;
  5.             using(var tr = doc.TransactionManager.StartTransaction()) {
  6.                 var bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead)
  7.                          as BlockTable;
  8.                 var br = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite)
  9.                          as BlockTableRecord;
  10.  
  11.                 using(Circle circ = new Circle()) {
  12.                     circ.Center = new Point3d(5, 5, 0);
  13.                     circ.Radius = 50;
  14.  
  15.                     br.AppendEntity(circ);
  16.                     tr.AddNewlyCreatedDBObject(circ, true);
  17.  
  18.                     var objIdColl = new ObjectIdCollection();
  19.                     objIdColl.Add(circ.ObjectId);
  20.  
  21.  
  22.                     using(Hatch hatch = new Hatch()) {
  23.                         br.AppendEntity(hatch);
  24.                         tr.AddNewlyCreatedDBObject(hatch, true);
  25.                         CreateHatchPattern(hatch, "ANGLE", objIdColl);
  26.                     }
  27.                 }
  28.                 tr.Commit();
  29.             }
  30.         }
  31.  

Code - C#: [Select]
  1.         [CommandMethod("AH02")]
  2.         public static void AddHatch02() {
  3.             var doc = AcadApp.DocumentManager.MdiActiveDocument;
  4.             var db = doc.Database;
  5.             using(var tr = doc.TransactionManager.StartTransaction()) {
  6.                 var bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead)
  7.                          as BlockTable;
  8.                 var br = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite)
  9.                          as BlockTableRecord;
  10.  
  11.                 using(Circle circ = new Circle()) {
  12.                     circ.Center = new Point3d(100, 5, 0);
  13.                     circ.Radius = 50;
  14.  
  15.                     br.AppendEntity(circ);
  16.                     tr.AddNewlyCreatedDBObject(circ, true);
  17.  
  18.                     var objIdColl = new ObjectIdCollection();
  19.                     objIdColl.Add(circ.ObjectId);
  20.  
  21.                     using(Hatch hatch = new Hatch()) {
  22.                         br.AppendEntity(hatch);
  23.                         tr.AddNewlyCreatedDBObject(hatch, true);
  24.                         CreateHatchGradient(hatch, "LINEAR", objIdColl, 2, 5);
  25.                     }
  26.                 }
  27.                 tr.Commit();
  28.             }
  29.         }
  30.  

Code - C#: [Select]
  1.         [CommandMethod("AH03")]
  2.         public static void AddHatch03() {
  3.             var doc = AcadApp.DocumentManager.MdiActiveDocument;
  4.             var db = doc.Database;
  5.             using(var tr = doc.TransactionManager.StartTransaction()) {
  6.                 var bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead)
  7.                          as BlockTable;
  8.                 var br = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite)
  9.                          as BlockTableRecord;
  10.  
  11.                 using(Polyline pline = new Polyline()) {
  12.                     CreatePolyShape(pline, new Point2d(150, 10));
  13.                     br.AppendEntity(pline);
  14.                     tr.AddNewlyCreatedDBObject(pline, true);
  15.  
  16.                     var objIdColl = new ObjectIdCollection();
  17.                     objIdColl.Add(pline.ObjectId);
  18.  
  19.                     using(Hatch hatch = new Hatch()) {
  20.                         br.AppendEntity(hatch);
  21.                         tr.AddNewlyCreatedDBObject(hatch, true);
  22.                         CreateHatchPattern(hatch, "ANGLE", objIdColl);
  23.                     }
  24.                 }
  25.                 tr.Commit();
  26.             }
  27.         }
  28.  

Code - C#: [Select]
  1.         [CommandMethod("AH04")]
  2.         public static void AddHatch04() {
  3.             var doc = AcadApp.DocumentManager.MdiActiveDocument;
  4.             var db = doc.Database;
  5.             using(var tr = doc.TransactionManager.StartTransaction()) {
  6.                 var bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead)
  7.                          as BlockTable;
  8.                 var br = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite)
  9.                          as BlockTableRecord;
  10.  
  11.                 using(Polyline pline = new Polyline()) {
  12.                     CreatePolyShape(pline, new Point2d(130, 75));
  13.                     br.AppendEntity(pline);
  14.                     tr.AddNewlyCreatedDBObject(pline, true);
  15.  
  16.                     var objIdColl = new ObjectIdCollection();
  17.                     objIdColl.Add(pline.ObjectId);
  18.  
  19.                     using(Hatch hatch = new Hatch()) {
  20.                         br.AppendEntity(hatch);
  21.                         tr.AddNewlyCreatedDBObject(hatch, true);
  22.                         CreateHatchGradient(hatch, "LINEAR", objIdColl, 5, 2);
  23.                     }
  24.                 }
  25.                 tr.Commit();
  26.             }
  27.         }
  28.  

Code - C#: [Select]
  1.         private static readonly EntityColor __color = new EntityColor(ColorMethod.ByLayer, 256);
  2.         //===========================================
  3.         private static void CreatePolyShape(Polyline pline, Point2d startPoint) {
  4.             pline.Normal = new Vector3d(0.0, 0.0, 1.0);
  5.             pline.Color = Color.FromEntityColor(__color);
  6.             pline.Closed = true;
  7.  
  8.             pline.AddVertexAt(0, startPoint, 0, 0, 0);
  9.             pline.AddVertexAt(1, startPoint.Add(new Vector2d(200, 10)), 0, 0, 0);
  10.             pline.AddVertexAt(2, startPoint.Add(new Vector2d(70, 20)), 0, 0, 0);
  11.             pline.AddVertexAt(3, startPoint.Add(new Vector2d(80, -50)), 0, 0, 0);
  12.             pline.AddVertexAt(4, startPoint.Add(new Vector2d(50, -40)), 0, 0, 0);
  13.             pline.MinimizeMemory();
  14.         }
  15.  

Code - C#: [Select]
  1.         private static void CreateHatchPattern(Hatch hatch,
  2.                                                 String patternName,
  3.                                                 ObjectIdCollection boundaryCollection) {
  4.             // Set associative after appending and before AppendLoop
  5.             hatch.SetHatchPattern(HatchPatternType.PreDefined, patternName);
  6.             hatch.Associative = true;
  7.             hatch.AppendLoop(HatchLoopTypes.Outermost, boundaryCollection);
  8.             hatch.EvaluateHatch(true);
  9.         }
  10.         //===========================================
  11.         private static void CreateHatchGradient(Hatch hatch,
  12.                                                 String gradientName,
  13.                                                 ObjectIdCollection boundaryCollection,
  14.                                                 short colorIndex0,
  15.                                                 short colorIndex1) {
  16.             // Set associative after appending and before AppendLoop
  17.             hatch.HatchObjectType = HatchObjectType.GradientObject;
  18.             hatch.SetGradient(GradientPatternType.PreDefinedGradient, gradientName);
  19.             hatch.GradientOneColorMode = false;
  20.             hatch.GradientShift = 0;
  21.             var gradientColors = new GradientColor[] {
  22.                                                          new GradientColor(
  23.                                                              Color.FromColorIndex(ColorMethod.ByAci,
  24.                                                                                   colorIndex0), 0),
  25.                                                          new GradientColor(
  26.                                                              Color.FromColorIndex(ColorMethod.ByAci,
  27.                                                                                   colorIndex1), 1)
  28.                                                      };
  29.             hatch.SetGradientColors(gradientColors);
  30.             hatch.Associative = true;
  31.             hatch.AppendLoop(HatchLoopTypes.Outermost, boundaryCollection);
  32.             hatch.EvaluateHatch(true);
  33.         }
  34.  
« Last Edit: October 07, 2015, 07:28:00 PM by Kerry »
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.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Creating an associative hatch in C# causes access violation
« Reply #8 on: October 08, 2015, 08:24:22 AM »

I'd recommend that you start with this working example and progressively add code  ( to match the properties in your code).
You may be able to discover the cause of the error in your code.

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.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Creating an associative hatch in C# causes access violation
« Reply #9 on: October 15, 2015, 10:09:34 AM »

Was this ever followed up ??

Any issues ?

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.

akaranta

  • Guest
Re: Creating an associative hatch in C# causes access violation
« Reply #10 on: October 18, 2015, 06:53:14 AM »
Sorry, I got a more urgent matter to take care of and had to postpone resolving this a little bit. I'll likely return to it in a week.

Thank you very much for your advice and code, I will certainly use it as the basis for further experiments. I will post a reply to this topic to let you know how it goes and of any further findings / solutions.

akaranta

  • Guest
Re: Creating an associative hatch in C# causes access violation
« Reply #11 on: November 04, 2015, 03:42:24 AM »
I have now been investigating the issue some more and the access violation is clearly connected to the HatchLoopTypes enum values used in calls to AppendLoop.

At least these work ok:

HatchLoopTypes.External
HatchLoopTypes.Derived | HatchLoopTypes.External

At least these crash:

HatchLoopTypes.Derived | HatchLoopTypes.Polyline | HatchLoopTypes.External // my original case
HatchLoopTypes.Polyline | HatchLoopTypes.External

Looking at the documentation of the HatchLoopTypes enumeration it seems a little strange that HatchLoopTypes.Polyline should be combined with HatchLoopTypes.External as the former implies there are specific defining objects e.g. AutoCAD.Geometry.CircularArc2d. However, in this case the hatch is associative and this particular loop is (logically) External as it used a database resident polyline entity as a boundary.
And, like I stated before, this is the state I read from a hatch object I created.

At least to me it is not clear from the documentation which combinations of this enum's values are legal and which are not. And it is not at all clear how I can reproduce a hatch entity like the one I took this state from.

I will continue investigating, any hints highly appreciated...

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Creating an associative hatch in C# causes access violation
« Reply #12 on: November 04, 2015, 03:54:21 AM »

How about you produce a drawing that contains samples of what works and what doesn't with the LoopTypes nominated on the drawing.

Or generate code samples that demonstrate the issue.
Are you attempting to apply a generic LoopType to all your polylines ??

We'll need more information to resolve the issue.
And you will need reproducible failures if you expect AutoDesk to look at the situation.

I'll need a better indicator of the situation that causes the errors and I'd need to see code.

Regards,
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.

akaranta

  • Guest
Re: Creating an associative hatch in C# causes access violation
« Reply #13 on: November 04, 2015, 06:44:27 AM »
Here are instructions on how to reproduce the access violation with real data in a real drawing.

I attached hatch_access_violation_sample.dwg that you can use to reproduce the problem. However, you can easily make your own:

  * create a new drawing (I used acadiso.dwt template but I don't think that has any effect)
  * create a rectangle
  * press H and <enter> (the hatch command)
  * click inside the rectangle and press <enter>

Here's the source code (can be copy-pasted to any class you have your custom AutoCAD commands in):

Code - C#: [Select]
  1. [CommandMethod( "NSCOPYASSOCHATCH", CommandFlags.UsePickSet )]
  2.         public static void CopyHatch() {
  3.             var doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
  4.             var ed = doc.Editor;
  5.             var selPrompt = ed.SelectImplied();
  6.             var selSet = selPrompt.Value;
  7.             if ( selPrompt.Status != PromptStatus.OK || selSet.Count != 1 || typeof( Hatch ) != selSet.GetObjectIds()[ 0 ].ObjectClass.GetRuntimeType() ) {
  8.                 Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog( "please select a single hatch before running this command" );
  9.                 return;
  10.             }
  11.  
  12.             using ( var tr = doc.TransactionManager.StartTransaction() ) {
  13.                 var originalHatch = (Hatch)tr.GetObject( selSet.GetObjectIds()[0], OpenMode.ForRead );
  14.                 if ( !originalHatch.Associative || originalHatch.HatchObjectType != HatchObjectType.HatchObject ||
  15.                      originalHatch.NumberOfLoops == 0 || HasLoopsWithNoAssociatedObjects( originalHatch ) ) {
  16.                     Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog( "please select an associative hatch (with only loops defined by db resident objects)" );
  17.                     return;
  18.                 }
  19.                 CopyAssociativeHatch( ed, doc.Database, tr, originalHatch );
  20.                 tr.Commit();
  21.             }
  22.         }
  23.  
  24.         private static bool HasLoopsWithNoAssociatedObjects( Hatch h ) {
  25.             for ( int i = 0 ; i < h.NumberOfLoops ; i++ ) {
  26.                 var associatedObjectIds = h.GetAssociatedObjectIdsAt( i );
  27.                 if ( associatedObjectIds == null || associatedObjectIds.Count == 0 ) return true;
  28.             }
  29.             return false;
  30.         }
  31.  
  32.         private static Hatch CopyAssociativeHatch( Editor ed, Database db, Transaction tx, Hatch originalHatch ) {
  33.             var h = new Hatch();
  34.  
  35.             AddEntity( tx, db, h );
  36.  
  37.             h.Normal = originalHatch.Normal;
  38.             h.Origin = originalHatch.Origin;
  39.  
  40.             h.Associative = true;
  41.             h.SetHatchPattern( originalHatch.PatternType, originalHatch.PatternName );
  42.             h.PatternAngle = originalHatch.PatternAngle;
  43.             h.PatternScale = originalHatch.PatternScale;
  44.             h.PatternDouble = originalHatch.PatternDouble;
  45.             h.PatternSpace = originalHatch.PatternSpace;
  46.  
  47.             for ( int i = 0 ; i < originalHatch.NumberOfLoops ; i++ ) {
  48.                 var loop = originalHatch.GetLoopAt( i );
  49.                 var associatedObjectIds = originalHatch.GetAssociatedObjectIdsAt( i );
  50.                 ed.WriteMessage( "copying loop of type " + loop.LoopType + "\n" );
  51.                 using ( var boundaryColl = new ObjectIdCollection( associatedObjectIds.Cast<ObjectId>().ToArray() ) ) {
  52.                     // this call causes access violation
  53.                     h.AppendLoop( loop.LoopType, boundaryColl );
  54.                 }
  55.             }
  56.  
  57.             h.HatchStyle = originalHatch.HatchStyle;
  58.             h.EvaluateHatch( true );
  59.  
  60.             return h;
  61.         }
  62.  
  63.         private static ObjectId AddEntity( Transaction tx, Database db, Entity e ) {
  64.             var btr = (BlockTableRecord)tx.GetObject( SymbolUtilityServices.GetBlockModelSpaceId( db ), OpenMode.ForWrite );
  65.             var oid = btr.AppendEntity( e );
  66.             e.SetDatabaseDefaults( db );
  67.             tx.AddNewlyCreatedDBObject( e, true );
  68.             return oid;
  69.         }
  70.  

This is a simplified version of what I am trying to accomplish - read state from an existing hatch object and create a new one exactly like the original. In reality the copy will be created in another process (on another computer) so I can't use Clone, autocad copy commands, clipboard etc.

To reproduce the access violation:

  * select the hatch in the drawing
  * type in command NSCOPYASSOCHATCH <enter>
  => access violation (in AppendLoop method)

  Note that you can see in the debugger that loop.LoopType = External | Polyline | Derived

  If you have problems reproducing the access violation, need more information or I have mistakenly left out something please ask.

code tags added kdub : [code = csharp]
« Last Edit: November 04, 2015, 07:00:39 AM by Kerry »

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Creating an associative hatch in C# causes access violation
« Reply #14 on: November 04, 2015, 07:11:17 AM »

I haven't had a good look at the code , I'll do that tomorrow, I'm brain dead at the moment.
but .. are you trying to copy the id's of the associated entity(s)?? .. or perhaps does the definition of the associated hatch refer to the bounding objects ??
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.

akaranta

  • Guest
Re: Creating an associative hatch in C# causes access violation
« Reply #15 on: November 04, 2015, 07:30:14 AM »
I am not quite sure what you mean by "are you trying to copy the id's of the associated entity(s)?? .. or perhaps does the definition of the associated hatch refer to the bounding objects ??".
I am assuming that Hatch.GetAssociatedObjectIdsAt( int index ) returns the objects associated with the loop with the given index (in this case I assume the id of the rectangle is returned). In the code I just posted I am making a new ObjectIdCollection with the same object ids as in the original loop in order to create an identical hatch loop (i.e. in this case it is associated with the same object(s) as the original one).
If I haven't misunderstood completely, by definition an associative hatch refers to the bounding objects.

akaranta

  • Guest
Re: Creating an associative hatch in C# causes access violation
« Reply #16 on: November 11, 2015, 02:26:43 AM »
As a workaround I changed my code so that I "strip" away the Polyline flag from the hatch loop type like so:

Code: [Select]
var ltype = ( loopType.HasFlag( HatchLoopTypes.Polyline ) && loopType != HatchLoopTypes.Polyline ) ? loopType & ~HatchLoopTypes.Polyline : loopType;

This seems to be working at least with the hatches I have tried this far and visually they look the same. I am not sure if removing the Polyline flag from the loop type like this causes any differences that are significant to a user using the drawing.