Announcements
Attention for Customers without Multi-Factor Authentication or Single Sign-On - OTP Verification rolls out April 2025. Read all about it here.

Erase specific block in drawing

Anonymous

Erase specific block in drawing

Anonymous
Not applicable

Hello,

 

I'm currenty facing to an issue, I'm able to create a block, more precisely the user can select the type of tree, and insert into the drawing (it is a cercle with a specific label inside). To do that, I use the code below :

  • I get the tree type, the current layout
  • Then I initialise my tree class which contains some properties.
  • I check if the block already exist in the drawing, if it not the case I create a new block.
  • Finaly I create a block reference base on the previous step and I add it to the model space.

 

I would like offer the possibily to the user to change the type of tree if he clics on a specific block in drawing. To do that the easy way I think,  should be to erase the current block reference and re-create another one with the new parameters but I could not find a way to do that.

 

 

 

 

public static void DrawTreeInsert(LA_Layout la_layout, TypeLOD1 treeType)
{
	// Get the current document and database
	Document doc = AcAp.DocumentManager.MdiActiveDocument;
	Database db = doc.Database;
	Editor ed = doc.Editor;

	//Change le focus Palette vers Viewport
	doc.Window.Focus();    
	
	using (Transaction tr = db.TransactionManager.StartTransaction())
	{
		using (doc.LockDocument())
		{
			#region Initialization 
			//Create tree
			S_Tree tree = new S_Tree(treeType.Type, la_layout);

			//Parameters
			tree.typeLOD1         = treeType;
			double treeRadius     = 5;
			string blkName        = treeType.Type + "_Arbre";
			Matrix3d matrixLayout = Matrix_Helper.MatrixAcad_BuilderFromS_Matrix(la_layout.Matrix);

			//Create or get layer
			S_Layer layer = Layers_Helper.CreateLayer(db,
													  la_layout.Name + ".Arbre", 
													  Autodesk.AutoCAD.Colors.Color.FromRgb(23, 54, 232), 
													  ObjectId.Null
													  );
			#endregion

			#region coordinate
			// Prompt the user for 1 point
			PromptPointResult  pPtRes;
			PromptPointOptions pPtOpts = new PromptPointOptions("\nInsertion d'arbre en ");

			pPtRes = doc.Editor.GetPoint(pPtOpts);

			if (pPtRes == null) return;

			Point3d pointInsert = new Point3d(pPtRes.Value.X, pPtRes.Value.Y, pPtRes.Value.Z);
			S_Point3D s_pointInsert = new S_Point3D(pointInsert.X, pointInsert.Y, pointInsert.Z);


			// Exit if the user presses ESC or cancels the command
			if (pPtRes.Status == PromptStatus.Cancel) return;
			#endregion

			#region Block
			//---------------------- Get or create custum Block ----------------------//
			//
			BlockTable bt    = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;


			bool blkExist = Blocks_Helper.BlockExistsInDrawing(blkName, db, out ObjectId blockId);
			// Retourn True if the block exist,
			// ObjectId out : if block exist return block's id, else return ObjectId.Null

			if (blkExist == false)
			{
				// Create new block and set properties
				using (BlockTableRecord btr = new BlockTableRecord())
				{
					btr.Name = blkName;

					// Add the new block to the block table
					bt.UpgradeOpen();
					bt.Add(btr);
					blockId = btr.Id;
					tr.AddNewlyCreatedDBObject(btr, true);

					// Add the entities belong directly to the block 
					DBObjectCollection ents = DrawBlockTree(treeRadius, tree.Type, Point3d.Origin);
					foreach (Entity ent in ents)
					{
						btr.UpgradeOpen();
						btr.AppendEntity(ent);
						tr.AddNewlyCreatedDBObject(ent, true);
						tree.BlckEntitiesHandle.Add(ent.Handle.ToString());
					}             
					  
					// Report
					ed.WriteMessage("\nCreated block named \"{0}\" containing {1} entities.", blkName, ents.Count);
				}
					
			}

			//---------------------- Add block reference to the model space ----------------------//                    
			if (blockId != ObjectId.Null)
			{
				using (BlockReference BlkRef = new BlockReference(pointInsert, blockId))
				{
					
					BlockTableRecord curentSpaceBTR = tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;

					// Edit block reference
					BlkRef.LayerId = layer.LayerId.Value;
					BlkRef.TransformBy(matrixLayout);

					// Add block reference to model space
					curentSpaceBTR.AppendEntity(BlkRef);
					tr.AddNewlyCreatedDBObject(BlkRef, true);


					#region Data Management
					//Update tree data
					ObjectId objId = BlkRef.Id;
					tree.BlkRefHandle = objId.Handle.ToString();

					//Associate element's Id to AutoCAD block thanks to Xdata
					LA_Data_Helper.WriteLADataXML_to_AcadObject(doc, objId, tree);
					#endregion

					#region EventHandler
					BlkRef.Erased += (s, e) => EventHandler_Actions.EraseTree(la_layout, tree);
					#endregion
				}
			}
		  

			#endregion


			//Add the new tree to the database
			tree.Point = s_pointInsert;
			la_layout.Trees.Add(tree);
		}
		tr.Commit();
	}
}

 

 

 

Here is my try to erase the bock selected by the user but it does not work, I did many try but I think I miss an important point :

 

 

        public static void DrawTreeChange(LA_Layout la_layout, TypeLOD1 newTreeType)
        {
            // Get the current document and database
            Document doc = AcAp.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;

            doc.Window.Focus();

            var options = new PromptEntityOptions("\nSelectionner le block définissant l'objet : ");

            var result = ed.GetEntity(options);
            if (result.Status == PromptStatus.OK)
            {

                FindTree(result.ObjectId.Handle.ToString(), out LA_Layout layoutTree, out S_Tree drewTree);
                // Get from the prompt result the layout and the tree
                
                if (drewTree != null)
                {
                    using (doc.LockDocument())
                    {
                        using (Transaction tr = db.TransactionManager.StartTransaction())
                        {
                            // open the block table which contains all the BlockTableRecords (block definitions and spaces)
                            var blockTable = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);

                            // open the model space BlockTableRecord
                            var modelSpace = (BlockTableRecord)tr.GetObject(blockTable[BlockTableRecord.ModelSpace], OpenMode.ForRead);

                            
                            // try to erase the entities wich belong to the old tree block
                            BlockTableRecord btRecord = (BlockTableRecord)tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead);
                            foreach (ObjectId id in btRecord)

                            {
                                Entity entity = (Entity)tr.GetObject(id, OpenMode.ForRead);

                                foreach (string entHdl in drewTree.BlckEntitiesHandle)
                                {
                                    if (entity.Handle.ToString() == entHdl)
                                    {
                                        entity.Erase();
                                    }
                                }        
                            }

                            // iterate through the model space to erase the block referense to 
                            foreach (ObjectId id in modelSpace)
                            {
                                // check if the current ObjectId is a block reference wich belong to the old tree block
                                if (id.ObjectClass.DxfName == "INSERT")
                                {
                                    // open the block reference
                                    var blckRef = (BlockReference)tr.GetObject(id, OpenMode.ForRead);

                                    if (blckRef.Handle.ToString() == drewTree.BlkRefHandle)
                                    {
                                        // print the block name to the command line
                                        ed.WriteMessage("\n" + blckRef.Name);
                                        blckRef.UpgradeOpen();

                                        blckRef.Erase();

                                    }
                                }
                            }
                        }          
                    }
                }
            }
        }

 

 

Thanks for your help,

Alexis

0 Likes
Reply
Accepted solutions (2)
945 Views
5 Replies
Replies (5)

_gile
Mentor
Mentor
Accepted solution

@Anonymous  a écrit :

I would like offer the possibily to the user to change the type of tree if he clics on a specific block in drawing. To do that the easy way I think,  should be to erase the current block reference and re-create another one with the new parameters but I could not find a way to do that.


The easiest way is to set the BlockTableRecord property of the block reference with the ObjectId of the new block definition.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes

Anonymous
Not applicable
Accepted solution

Hi,

 

After having combining different part of code I finally succed to erase a specific block. I think it can be improved so any comment would be appreciated 🙂

 

Here is my code :

        public static void DrawTreeChange(LA_Layout la_layout, TypeLOD1 newTreeType)
        {
            // Get the current document and database
            Document doc = AcAp.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;

            doc.Window.Focus();

            var options = new PromptEntityOptions("\nSelectionner le block définissant l'objet : ");

            var result = ed.GetEntity(options);
            if (result.Status == PromptStatus.OK)
            {

                FindTree(result.ObjectId.Handle.ToString(), out LA_Layout layoutTree, out S_Tree drewTree);
                // Get from the prompt result the layout and the tree
                
                if (drewTree != null)
                {
                    using (doc.LockDocument())
                    {
                        using (Transaction tr = db.TransactionManager.StartTransaction())
                        {
                            // open the block table which contains all the BlockTableRecords (block definitions and spaces)
                            var blockTable = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);

                            // open the model space BlockTableRecord
                            var modelSpace = (BlockTableRecord)tr.GetObject(blockTable[BlockTableRecord.ModelSpace], OpenMode.ForRead);

                            // iterate through the model space to erase the block referense to 
                            foreach (ObjectId id in modelSpace)
                            {
                                // check if the current ObjectId is a block reference wich belong to the old tree block
                                if (id.ObjectClass.DxfName == "INSERT")
                                {
                                    // open the block reference
                                    var blckRef = (BlockReference)tr.GetObject(id, OpenMode.ForRead);

                                    if (blckRef.Handle.ToString() == drewTree.BlkRefHandle)
                                    {
                                        BlockTableRecord btrec = tr.GetObject(blckRef.BlockTableRecord, OpenMode.ForRead) as BlockTableRecord;

                                        if (btrec.HasAttributeDefinitions)
                                        {
                                            AttributeCollection atcoll = blckRef.AttributeCollection;

                                            foreach (ObjectId subid in btrec)
                                            {
                                                Entity ent = (Entity)subid.GetObject(OpenMode.ForRead);
                                                ent.Erase();
                                            }
                                        }                                                
                                                
                                        blckRef.UpgradeOpen();

                                        blckRef.Erase();

                                    }
                                }
                            }

                            tr.Commit();
                        }
                        
                    }
                }
            }
        }

 

Thanks,
Alexis

0 Likes

Anonymous
Not applicable

Indeed it is much cleaner to do this, but I did not figure out how to do that 😅. Because I have to change the block name (currently the block name is defined with the tree 's type so if the user choose another type I should change accordly), and maybe some entities that make up the block (the block is made up with two entities : a circle with the type of tree inside).

 

Thanks for your answer.

0 Likes

_gile
Mentor
Mentor

@Anonymous  a écrit :

Indeed it is much cleaner to do this, but I did not figure out how to do that 😅. Because I have to change the block name (currently the block name is defined with the tree 's type so if the user choose another type I should change accordly), and maybe some entities that make up the block (the block is made up with two entities : a circle with the type of tree inside).

 

Thanks for your answer.


if I do not misunderstand, you create (if not already exists) the block definition (BlockTableRecord) form the "tree's type". So, just setting the BlockTableRecord property of the BlockReference with the one choosen by the user will change the BlockReference name and entites (it's only a reference to the block definition).



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes

Anonymous
Not applicable
Okay I see the idea.

Thanks for your help,
Alexis
0 Likes