Author Topic: How to create Hatch with islands  (Read 5120 times)

0 Members and 1 Guest are viewing this topic.

hojjat

  • Mosquito
  • Posts: 11
How to create Hatch with islands
« on: September 17, 2023, 03:37:02 PM »
Hi everyone,
I'm using this code to create Hatch after TraceBoundary:

Code - C#: [Select]
  1. Document doc = Application.DocumentManager.MdiActiveDocument;
  2. Editor ed = doc.Editor;
  3.  
  4. //...
  5.  
  6. DBObjectCollection objsAll = ed.TraceBoundary(ppr.Value, true);
  7. ObjectIdCollection ids = new ObjectIdCollection();
  8.  
  9. foreach (DBObject obj in objsAll)
  10. {
  11.     Entity ent = obj as Entity;
  12.     if (ent != null)
  13.     {
  14.         ids.Add(obj.Id);
  15.     }
  16. }
  17.  
  18. Hatch hat = new Hatch();
  19. hat.SetDatabaseDefaults();
  20.  
  21. ObjectId hatId = btr.AppendEntity(hat);
  22.  
  23. tr.AddNewlyCreatedDBObject(hat, true);
  24.  
  25. hat.Associative = true;
  26. hat.HatchStyle = HatchStyle.Normal;
  27.  
  28. hat.AppendLoop(HatchLoopTypes.Default, ids);
  29. hat.EvaluateHatch(true);
  30.  

The Code does not create islands in the hatch. I want to create islands like hatch command. How can I do that?

In the attached image, The code creates the number 1, but I expect the number 2.
« Last Edit: September 20, 2023, 06:33:06 PM by hojjat »

n.yuan

  • Bull Frog
  • Posts: 348
Re: How to create Hatch with islands
« Reply #1 on: September 19, 2023, 08:46:47 AM »
you might want to try to change this portion of code from

Code: [Select]
foreach (DBObject obj in objsAll)
Entity ent = obj as Entity;
if (ent != null)
{
        ids.Add(obj.Id);
}

to

Code: [Select]
foreach (DBObject obj in objsAll)
{
  Entity ent = obj as Entity;
  if (ent != null)
  {
     ids.Add(obj.Id);
  }
}

hojjat

  • Mosquito
  • Posts: 11
Re: How to create Hatch with islands
« Reply #2 on: September 20, 2023, 06:28:57 PM »
Thanks for your answer. Actually My code is like yours, but when I copied this piece of code, the curly braces were omitted. It was my mistake when copying the code here.
The "ids" variable is filled by a polyline, as an entity.

I Edited my code.

kdub_nz

  • Mesozoic keyThumper
  • SuperMod
  • Water Moccasin
  • Posts: 2145
  • class keyThumper<T>:ILazy<T>
Re: How to create Hatch with islands
« Reply #3 on: September 20, 2023, 06:54:36 PM »
@hojjat, hi,

Your revised code in the first post,
 . . does is resolve your issue ??


Called Kerry in my other life
Retired; but they dragged me back in !

I live at UTC + 13.00

---
some people complain about loading the dishwasher.
Sometimes the question is more important than the answer.

hojjat

  • Mosquito
  • Posts: 11
Re: How to create Hatch with islands
« Reply #4 on: September 20, 2023, 09:46:51 PM »
Hi
No, as I said, it was not my answer. It was only my typo when preparing the piece of code to copy here.
I edited my first post.

kdub_nz

  • Mesozoic keyThumper
  • SuperMod
  • Water Moccasin
  • Posts: 2145
  • class keyThumper<T>:ILazy<T>
Re: How to create Hatch with islands
« Reply #5 on: September 21, 2023, 12:21:20 AM »
Just a guess,
Perhaps try with a
Code - C#: [Select]
  1. hat.HatchStyle = HatchStyle.Outer;
in place of normal

and play with
Code - C#: [Select]
  1. hat.AppendLoop(HatchLoopTypes.Outermost, ids);

https://help.autodesk.com/view/OARX/2024/ENU/?guid=GUID-01A47A4F-9FC5-4DB6-8C3E-B72D75688965
« Last Edit: September 21, 2023, 12:24:49 AM by kdub_nz »
Called Kerry in my other life
Retired; but they dragged me back in !

I live at UTC + 13.00

---
some people complain about loading the dishwasher.
Sometimes the question is more important than the answer.

hojjat

  • Mosquito
  • Posts: 11
Re: How to create Hatch with islands
« Reply #6 on: September 21, 2023, 05:03:59 AM »
It doesn't works again. The result as the same

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8746
  • AKA Daniel
Re: How to create Hatch with islands
« Reply #7 on: September 21, 2023, 05:14:08 AM »
with Arx and Python you have to define the outside and the inside

Code - Python: [Select]
  1. import os
  2.  
  3. import PyRx# = Runtime runtime
  4. import PyGe# = Geometry
  5. import PyGi# = Graphics interface
  6. import PyDb# = database
  7. import PyAp# = application, document classes services
  8. import PyEd# = editor
  9.  
  10. def PyRxCmd_pycreate_hatch():
  11.     try:
  12.         db = PyDb.HostApplicationServices().workingDatabase()
  13.        
  14.         hatch = PyDb.Hatch()
  15.         hatch.setDatabaseDefaults()
  16.         normal = PyGe.Vector3d(0,0,1)
  17.         hatch.setNormal(normal)
  18.         hatch.setElevation(0)
  19.        
  20.         hatch.setAssociative(False)
  21.        
  22.         hatch.setPattern(PyDb.HatchPatternType.kPreDefined, "SOLID")
  23.         hatch.setHatchStyle(PyDb.HatchStyle.kNormal)
  24.        
  25.         vertexPts = []
  26.         vertexPts.append(PyGe.Point2d(2.0, 2.0))
  27.         vertexPts.append(PyGe.Point2d(8.0, 2.0))
  28.         vertexPts.append(PyGe.Point2d(8.0, 8.0))
  29.         vertexPts.append(PyGe.Point2d(2.0, 8.0))
  30.         vertexPts.append(PyGe.Point2d(2.0, 2.0))
  31.        
  32.         vertexBulges = []
  33.         for n in range(len(vertexPts)):
  34.             vertexBulges.append(0.0)
  35.            
  36.         hatch.appendLoopBulges(PyDb.HatchLoopType.kExternal, vertexPts, vertexBulges)
  37.            
  38.         cenPt = PyGe.Point2d(5.0, 5.0)
  39.         TWOPI = 2.0 * 3.1415926535897932
  40.         cirArc = PyGe.CircArc2d()
  41.         cirArc.setCenter(cenPt)
  42.         cirArc.setRadius(1.0)
  43.         cirArc.setAngles(0.0, TWOPI)
  44.        
  45.         edgePtrs = []
  46.         edgeTypes = []
  47.  
  48.         edgePtrs.append(cirArc)
  49.         edgeTypes.append(PyDb.HatchEdgeType.kCirArc)
  50.        
  51.         hatch.appendLoopEdges(PyDb.HatchLoopType.kDefault, edgePtrs, edgeTypes)
  52.         hatch.evaluateHatch()
  53.        
  54.         model = PyDb.BlockTableRecord(db.modelSpaceId(), PyDb.OpenMode.kForWrite)
  55.         model.appendAcDbEntity(hatch)      
  56.     except Exception as err:
  57.         print(err)
  58.  

hojjat

  • Mosquito
  • Posts: 11
Re: How to create Hatch with islands
« Reply #8 on: September 21, 2023, 05:55:02 AM »
Hi,
Thanks. I tried to find the equivalent code in C#, but I don't know is it true or not.
By the way, it doesn't work:
Code - C#: [Select]
  1. // hatchMainId: Id of the main Polyline
  2. hat.AppendLoop(HatchLoopTypes.External, hatchMainId);
  3. // hatchIslandIds: Id of the island(s):
  4. hat.AppendLoop(HatchLoopTypes.Default, hatchIslandIds);
  5.  

My entire code is like this:
Code - C#: [Select]
  1. Document doc = Application.DocumentManager.MdiActiveDocument;
  2. Editor ed = doc.Editor;
  3.  
  4. //...
  5.  
  6. DBObjectCollection objsAll = ed.TraceBoundary(ppr.Value, true);
  7. ObjectIdCollection ids = new ObjectIdCollection();
  8.  
  9. foreach (DBObject obj in objsAll)
  10. {
  11.     Entity ent = obj as Entity;
  12.     if (ent != null)
  13.     {
  14.         ids.Add(obj.Id);
  15.     }
  16. }
  17.  
  18. Hatch hat = new Hatch();
  19. hat.SetDatabaseDefaults();
  20.  
  21. ObjectId hatId = btr.AppendEntity(hat);
  22.  
  23. tr.AddNewlyCreatedDBObject(hat, true);
  24.  
  25. hat.Associative = true;
  26. hat.HatchStyle = HatchStyle.Normal;
  27.  
  28. // hatchMainId: Id of the main Polyline
  29. hat.AppendLoop(HatchLoopTypes.External, hatchMainId);
  30. // hatchIslandIds: Id of the island(s):
  31. hat.AppendLoop(HatchLoopTypes.Default, hatchIslandIds);
  32.  
  33. hat.EvaluateHatch(true);
  34.  

The result was the same as my first code.
« Last Edit: September 21, 2023, 05:59:14 AM by hojjat »

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8746
  • AKA Daniel
Re: How to create Hatch with islands
« Reply #9 on: September 21, 2023, 07:36:36 AM »
this works, if I add the islands separately

Code - Python: [Select]
  1. import PyRx as Rx
  2. import PyGe as Ge
  3. import PyGi as Gi
  4. import PyDb as Db
  5. import PyAp as Ap
  6. import PyEd as Ed
  7. import traceback
  8.  
  9.  
  10. def boundryIds(pnt, model):
  11.     plines = Ed.Editor.traceBoundary(pnt, True)
  12.     plines.sort(key=lambda pline: pline.getArea())
  13.     return model.appendAcDbEntities(plines)
  14.  
  15.  
  16. def PyRxCmd_doit():
  17.     try:
  18.         db = Db.curDb()
  19.         model = Db.BlockTableRecord(db.modelSpaceId(), Db.OpenMode.kForWrite)
  20.  
  21.         ptres = Ed.Editor.getPoint("\nGet Point")
  22.         if ptres[0] != Ed.PromptStatus.eNormal:
  23.             return
  24.  
  25.         ids = boundryIds(ptres[1], model)
  26.  
  27.         hatch = Db.Hatch()
  28.         hatch.setDatabaseDefaults()
  29.         hatch.setPattern(Db.HatchPatternType.kPreDefined, "SOLID")
  30.         hatch.setHatchStyle(Db.HatchStyle.kNormal)
  31.         hatch.setAssociative(True)
  32.  
  33.         hatch.appendLoop(Db.HatchLoopType.kExternal, [ids.pop()])
  34.         for id in ids:
  35.             hatch.appendLoop(Db.HatchLoopType.kDefault, [id])
  36.  
  37.         model.appendAcDbEntity(hatch)
  38.         hatch.evaluateHatch()
  39.  
  40.     except Exception as err:
  41.         traceback.print_exception(err)
  42.  
« Last Edit: September 21, 2023, 06:46:02 PM by It's Alive! »

n.yuan

  • Bull Frog
  • Posts: 348
Re: How to create Hatch with islands
« Reply #10 on: September 21, 2023, 10:40:44 AM »
Hi,
Thanks. I tried to find the equivalent code in C#, but I don't know is it true or not.
By the way, it doesn't work:
Code - C#: [Select]
  1. // hatchMainId: Id of the main Polyline
  2. hat.AppendLoop(HatchLoopTypes.External, hatchMainId);
  3. // hatchIslandIds: Id of the island(s):
  4. hat.AppendLoop(HatchLoopTypes.Default, hatchIslandIds);
  5.  

My entire code is like this:
Code - C#: [Select]
  1. Document doc = Application.DocumentManager.MdiActiveDocument;
  2. Editor ed = doc.Editor;
  3.  
  4. //...
  5.  
  6. DBObjectCollection objsAll = ed.TraceBoundary(ppr.Value, true);
  7. ObjectIdCollection ids = new ObjectIdCollection();
  8.  
  9. foreach (DBObject obj in objsAll)
  10. {
  11.     Entity ent = obj as Entity;
  12.     if (ent != null)
  13.     {
  14.         ids.Add(obj.Id);
  15.     }
  16. }
  17.  
  18. Hatch hat = new Hatch();
  19. hat.SetDatabaseDefaults();
  20.  
  21. ObjectId hatId = btr.AppendEntity(hat);
  22.  
  23. tr.AddNewlyCreatedDBObject(hat, true);
  24.  
  25. hat.Associative = true;
  26. hat.HatchStyle = HatchStyle.Normal;
  27.  
  28. // hatchMainId: Id of the main Polyline
  29. hat.AppendLoop(HatchLoopTypes.External, hatchMainId);
  30. // hatchIslandIds: Id of the island(s):
  31. hat.AppendLoop(HatchLoopTypes.Default, hatchIslandIds);
  32.  
  33. hat.EvaluateHatch(true);
  34.  

The result was the same as my first code.

A couple of mistakes I found in your code:

1. since you want to add hatchloop with one of the overloaded AppendLoop() with ObjectIdCollection as second input, it means the entity or entities must be database residing (hence you can have their IDs).
in your original post, you use TraceBoundary() to get a DBObjectCollection back, which are NON-DATABASE-RESIDING objects created by TraceBoundary() call. Thus, the ObjectIdCollections your code created from these DBObjects only contains null ObjectIds, thus the island were not created (but I am not sure how you had the external boundary created).

2. from the method name AppendLoop(), it implies it only appends ONE LOOP AT A TIME. If the input ObjectIdCollection has multiple OBjectIds, these entities should only form a SINGLE LOOP. It means you do not add all the island entities' IDs in one AppendLoop() call. You should add one island at a time:
for (var islandId in islandIds)
{
   theHatch.AppendLoop(xxxxx.Default, new ObjectIdCollection(new[]{ id}));
}

Because you want to use TraceBoundary() to find boundary and islands, after you get the DBObjectCollection, you would do with one the 2 ways:
1. Add all the DBObjects into the database first, then create the hatch and append them as loop one at a time. But this way, you would have duplicated entities of the existing ones;
2. Find matched db-residing, existing entities for each of the DBObjects and use the existing ones as the hatch's boundary/islands, to avoid geometrical duplicates in database.

hojjat

  • Mosquito
  • Posts: 11
Re: How to create Hatch with islands
« Reply #11 on: September 21, 2023, 02:44:05 PM »
Hi
Thank you for your complete explanation.
You are right, actually, in my post, I summarized the code. I previously added all objects obtained from TraceBoundary to the database.
When I trace the code, both ObjectIdCollections are assigned.

Now, I implemented your suggestion for each AppendLoop(). But I have a runtime "eInvalidInput" error at line 69 of the following code.

Here is my complete code:
Code - C#: [Select]
  1. using Autodesk.AutoCAD.ApplicationServices;
  2. using Autodesk.AutoCAD.DatabaseServices;
  3. using Autodesk.AutoCAD.EditorInput;
  4. using Autodesk.AutoCAD.Runtime;
  5. using System.Collections.Generic;
  6. using System.Linq;
  7.  
  8. [assembly: CommandClass(typeof(FCHJ.TestInCad.TraceBoundaryAndHatch))]
  9. namespace FCHJ.TestInCad
  10. {
  11.     public class TraceBoundaryAndHatch
  12.     {
  13.         [CommandMethod("HTB")]
  14.         public void TraceBoundary()
  15.         {
  16.             Document doc = Application.DocumentManager.MdiActiveDocument;
  17.             Editor ed = doc.Editor;
  18.  
  19.             // Select a seed point for our boundary
  20.             PromptPointResult ppr = ed.GetPoint("\nInternal Point: ");
  21.             if (ppr.Status != PromptStatus.OK)
  22.                 return;
  23.            
  24.             DBObjectCollection objsAll = ed.TraceBoundary(ppr.Value, true);
  25.             using (Transaction tr = doc.TransactionManager.StartTransaction())
  26.             {
  27.                 BlockTable bt = (BlockTable)tr.GetObject(doc.Database.BlockTableId, OpenMode.ForRead);
  28.                 BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
  29.                 ObjectIdCollection hatchMainId = new ObjectIdCollection();
  30.                 ObjectIdCollection hatchIslandIds = new ObjectIdCollection();
  31.                 List<Polyline> polylines = new List<Polyline>();
  32.  
  33.                 foreach (DBObject obj in objsAll)
  34.                 {
  35.                     Entity ent = obj as Entity;
  36.                     if (ent != null)
  37.                     {
  38.                         Polyline p = (Polyline)ent;
  39.                         if (p != null)
  40.                             polylines.Add(p);
  41.                     }
  42.                 }
  43.  
  44.                 // Fill MainId
  45.                 Polyline polyline = polylines.OrderByDescending(s => s.Area).First();
  46.                 ObjectId pId = btr.AppendEntity(polyline);
  47.                 hatchMainId.Add(pId);
  48.  
  49.                 // Fill IslandsIds
  50.                 foreach (Polyline pl in polylines)
  51.                 {
  52.                     if (polyline.Equals(pl))
  53.                         continue;
  54.  
  55.                     ObjectId _pId = btr.AppendEntity(pl);
  56.                     hatchIslandIds.Add(_pId);
  57.                 }
  58.  
  59.                 Hatch hat = new Hatch();
  60.                 hat.SetDatabaseDefaults();
  61.  
  62.                 ObjectId hatId = btr.AppendEntity(hat);
  63.  
  64.                 tr.AddNewlyCreatedDBObject(hat, true);
  65.  
  66.                 hat.Associative = true;
  67.                 hat.AppendLoop(HatchLoopTypes.External, hatchMainId);
  68.                 foreach (ObjectId islandId in hatchIslandIds)
  69.                     hat.AppendLoop(HatchLoopTypes.Default, new ObjectIdCollection(new[] { islandId }));
  70.  
  71.                 hat.EvaluateHatch(true);
  72.  
  73.                 tr.Commit();
  74.             }
  75.         }
  76.     }
  77. }
  78.  
« Last Edit: September 21, 2023, 02:49:00 PM by hojjat »

hojjat

  • Mosquito
  • Posts: 11
Re: How to create Hatch with islands
« Reply #12 on: September 21, 2023, 02:46:43 PM »
this works, if I add the islands separately

In my previous post, I tried to use your suggestion. It doesn't work yet.

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8746
  • AKA Daniel
Re: How to create Hatch with islands
« Reply #13 on: September 21, 2023, 05:40:56 PM »
But I have a runtime "eInvalidInput" error at line 69 of the following code.

the objects from traceboundry must be closed or disposed

hojjat

  • Mosquito
  • Posts: 11
Re: How to create Hatch with islands
« Reply #14 on: September 21, 2023, 06:50:01 PM »
I used Transaction to do that.

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8746
  • AKA Daniel
Re: How to create Hatch with islands
« Reply #15 on: September 21, 2023, 07:02:07 PM »
I used Transaction to do that.

It looks to me the hatch and the boundaries are in the same scope. 
the boundaries must be closed before adding their Ids to the hatch  :-)

hojjat

  • Mosquito
  • Posts: 11
Re: How to create Hatch with islands
« Reply #16 on: September 21, 2023, 07:20:13 PM »
Thanks,
That's right. I committed the transaction to close boundary objects, before using AppendLoop method.
Now the error is solved, but the hatch still does not recognize the islands.

gile

  • Gator
  • Posts: 2513
  • Marseille, France
Re: How to create Hatch with islands
« Reply #17 on: September 22, 2023, 03:39:39 AM »
Hi,
I posted a reply on the Autodesk forum.
Speaking English as a French Frog