How to hatch newly created objects in block using C#

How to hatch newly created objects in block using C#

Anonymous
Not applicable
3,108 Views
8 Replies
Message 1 of 9

How to hatch newly created objects in block using C#

Anonymous
Not applicable

Hello!

I am new in .net customization of Autocad and I'm apologize if there is some similar post like mine, but so far I didn't found any solution for the problem. Here is the situation:

 

I am trying to create block using c# , inside the block I create few Entities (closed polyline with circle inside) and I want to hatch the circle. For hatching I use trace boundary, but there I met my first problem - the Entity is not in database, so returned object ID collection is 0. I try different ways to get traced obj. ID's, but without success. I try to zoom to object ID, which i get before committing the transaction and trace it after zooming, but I get same result. Does anyone can help me with this? Thanks!

0 Likes
3,109 Views
8 Replies
Replies (8)
Message 2 of 9

_gile
Consultant
Consultant

Hi,

 

Assuming you want to hatch a known entity (the circle) you do not need to use the TraceBoundary, you directly use the circle ObjectId to define the Hatch loop.

 

        private static ObjectId CreateBlockWithHatch(Database db, string blockName)
        {
            using (var tr = db.TransactionManager.StartTransaction())
            {
                var bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                BlockTableRecord block;
                if (bt.Has(blockName)) return bt[blockName];

                tr.GetObject(db.BlockTableId, OpenMode.ForWrite);
                block = new BlockTableRecord();
                block.Name = blockName;
                var blockId = bt.Add(block);
                tr.AddNewlyCreatedDBObject(block, true);

                var pline = new Polyline(4) { Closed = true, Layer = "0" };
                pline.Layer = "0";
                pline.AddVertexAt(0, new Point2d(-12.0, -12.0), 0.0, 0.0, 0.0);
                pline.AddVertexAt(0, new Point2d(12.0, -12.0), 0.0, 0.0, 0.0);
                pline.AddVertexAt(0, new Point2d(12.0, 12.0), 0.0, 0.0, 0.0);
                pline.AddVertexAt(0, new Point2d(-12.0, 12.0), 0.0, 0.0, 0.0);
                block.AppendEntity(pline);
                tr.AddNewlyCreatedDBObject(pline, true);

                var circle = new Circle() { Center = Point3d.Origin, Radius = 8.0, Layer = "0" };
                block.AppendEntity(circle);
                tr.AddNewlyCreatedDBObject(circle, true);
                var ids = new ObjectIdCollection(new[] { circle.ObjectId });

                var hatch = new Hatch() { Layer = "0", PatternScale = 0.5, ColorIndex = 1 };
                hatch.SetHatchPattern(HatchPatternType.PreDefined, "ANSI31");
                block.AppendEntity(hatch);
                tr.AddNewlyCreatedDBObject(hatch, true);
                hatch.Associative = true;
                hatch.AppendLoop(HatchLoopTypes.Default, ids);
                hatch.EvaluateHatch(true);

                tr.Commit();
                return blockId;
            }
        }


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 3 of 9

Anonymous
Not applicable

Thanks for your answer _gilie,

but that's not exactly the case, which I met. That will work, because in the code above we know object ID(i mean we can get it), but If we didn't  know which object are in use for hatch definition , we won't be able to get them ID's, so I found that the method, which should work for me, will be TraceBoundaty , and it will, but the problem, is to get those object ID's to use them.  In 

 hatch.AppendLoop(HatchLoopTypes.Default, ids);

where in your code you use  

var ids = new ObjectIdCollection(new[] { circle.ObjectId });

to get circle ID. Let say it otherwise I want to select an objects from the drawing and a point inside the objects to hatch. Then the program should create a block using the selected entities from the user and also the hatch based on the selected point , this is why I need to use TraceBoudary  . Where am I go wrong here, i am thinking that i miss something about editor details, any ideas how to solve this?

 

0 Likes
Message 4 of 9

_gile
Consultant
Consultant

This is not what you said in the original post:


@Anonymous wrote:
I am trying to create block using c# , inside the block I create few Entities (closed polyline with circle inside) and I want to hatch the circle.

 


 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 5 of 9

Anonymous
Not applicable

Apologize, my mistake. I forgot that, if I need some information in programming I should be precise to receive best fit solution. Can you give some advice where to look for potential solution, that's became very hard task. Thanks

0 Likes
Message 6 of 9

norman.yuan
Mentor
Mentor

Regardless what your use case is, be it hatching newly created entity in block, or whatever, the actual issue is that if you want to create a hatch, you CAN ONLY append HtachLoops with one or more entities (typically curves) that is database-residing, as ObjectIdCollection. 

 

If you use Editor.TraceBoundary() method to detect a boundary, this method, if successful, return a one or more DBObjects (Entities) in DBObjectCollection. They ARE NOT db-residing objects, thus their ObjectId is ObjectId.Null. It is up to the calling process to decide what to do with the returned non-db-residing objects. You can add then into the database first, and then use them to create HatchLopp.

 

However, if you have some entities created already (a circle, in your case), but for some very odd reasons you know know it is there created by your code, and you know you want to use it to hatch it, but you have no way to get its ObjectId, therefore you have to use TraceBoundary() to find out the possible loop as boundary. 

 

If you do have a known point and want to find if it is inside a single closed curve (so you can use that closed curve to hatch), it might be much easier to test each curve in the drawing to see if the point is inside. If the curve is circle, it is even simple: you simply loop through all circles to see if the distance form the point to circle's center is equal or less than the radius.

 

But for whatever reasons if you must or can only use TraceBoundary() to find the boundary, but only want to do hatch with existing entity, then you need to compare the returned non-db-residing entities with existing entities in drawing geometrically to find the exact corresponding existing entities for creating hatch (and you will dispose all the DBObjects returned by TraceBoundary() after the comparison is done). IMO, it only makes sense to use TraceBoundary() to get outmost loop for hatch WHEN the area to be hatched is formed by multiple entities.

 

In your particular case, if the test point used in TraceBoundary() is inside a circle, the returned DBCollection would only have one DBObject, which should be a circle with exact same center/radius as the existing circle. So, you can use the non-db-residing circle's center/radius to search the drawing for the "real circle", and then do the hatch.

 

The real issue here is, you must know that 1). TraceBoundary() returns a set of non-database-residing objects, and you decide how to use them (adding to DB, or using their geometric info then disposing them); 2). curve(s) for hatchloop must be db-residing objects.

 

Norman Yuan

Drive CAD With Code

EESignature

0 Likes
Message 7 of 9

Anonymous
Not applicable

0 Likes
Message 8 of 9

ehsan_bahrani
Enthusiast
Enthusiast

hi
that's not work for me!

i want to create block with hatch, i can create entities but when i want to hatch the created entity error happens in this line:

hatch.AppendLoop(HatchLoopTypes.Default, ids);

the error message is "eInvalidInput"

0 Likes
Message 9 of 9

ehsan_bahrani
Enthusiast
Enthusiast
i found the reason& i have to use 'AddNewlyCreatedDBObject' first and then do hatch stuff.
0 Likes