1

Closed

Block.Create don't copy the block AttributeDefinitions in the orginal DxfDocument

description


        /// <summary>
        /// Creates a block from the content of a <see cref="DxfDocument">document</see>.
        /// </summary>
        /// <param name="doc">A <see cref="DxfDocument">DxfDocument</see> instance.</param>
        /// <param name="name">Name of the new block.</param>
        /// <returns>The block build from the <see cref="DxfDocument">document</see> content.</returns>
        /// <remarks>Only the entities contained in ModelSpace will make part of the block.</remarks>
        public static Block Create(DxfDocument doc, string name)
        {
            if (doc == null)
                throw new ArgumentNullException("doc");

            Block block = new Block(name) {Origin = doc.DrawingVariables.InsBase};
            block.Record.Units = doc.DrawingVariables.InsUnits;
            List<DxfObject> entities = doc.Layouts.GetReferences(Layout.ModelSpaceName);
            foreach (DxfObject dxfObject in entities)
            {
                EntityObject entity = dxfObject as EntityObject;
                if (entity == null)
                    continue;
                EntityObject clone = (EntityObject) entity.Clone();
                if (entity.Type == EntityType.AttributeDefinition)
                {
                    AttributeDefinition attdef = clone as AttributeDefinition;
                    block.AttributeDefinitions.Add(attdef);
                    continue;
                }
                // fixed start
                if (entity.Type == EntityType.Insert)
                {
                    Insert insert = clone as Insert;
                    block.Description = insert.Block.Description;
                    block.Flags = insert.Block.flags;
                    foreach (EntityObject e in insert.Block.Entities)
                    {
                        block.Entities.Add((EntityObject)e.Clone());
                    }
                    foreach (AttributeDefinition a in insert.Block.AttributeDefinitions.Values)
                    {
                        block.AttributeDefinitions.Add((AttributeDefinition)a.Clone());
                    }
                    continue;
                }
                // end fixed
                block.Entities.Add(clone);
            }
            return block;
        }
test case:
        DxfDocument dxf = new DxfDocument(DxfVersion.AutoCad2004);
        Block block = new Block("buildingBlock");
        Line line29 = new Line(new Vector3(0, 15, 0), new Vector3(10, 15, 0)) { Color = new AciColor(6), Lineweight = Lineweight.W100 };
        Line line30 = new Line(new Vector3(10, 0, 0), new Vector3(10, 15, 0)) { Color = new AciColor(6), Lineweight = Lineweight.W100 };
        Line line33 = new Line(new Vector3(0, 0, 0), new Vector3(10, 0, 0)) { Color = new AciColor(6), Lineweight = Lineweight.W100 };
        Line line40 = new Line(new Vector3(0, 0, 0), new Vector3(0, 15, 0)) { Color = new AciColor(6), Lineweight = Lineweight.W100 };
        block.Entities.AddRange(new List<EntityObject> { line29, line30, line33, line40 });
        
        block.AttributeDefinitions.Add(new AttributeDefinition("blkWidth") { Prompt = "Width:", Value = 15, Position = new Vector3(1, 13, 0), Lineweight = Lineweight.W20});
        block.AttributeDefinitions.Add(new AttributeDefinition("blkHeight") { Prompt = "Height:", Value = 10, Position = new Vector3(1, 11, 0), Lineweight = Lineweight.W20});
        block.AttributeDefinitions.Add(new AttributeDefinition("blkDirection") { Prompt = "Direction:", Value = 0, Position = new Vector3(1, 9, 0), Lineweight = Lineweight.W20});

        dxf.AddEntity(new Insert(block));
        dxf.Save(@"test.dxf");
Closed May 11 at 6:37 PM by haplokuon

comments

haplokuon wrote Mar 21 at 3:53 PM

I think you are misinterpreting how the Block.Create method actually works, it takes the content in the ModelSpace of a DxfDocument an creates a block from it. So, any Insert entity that might appear will become an insert inside the new block, this is usually known as nested blocks. An Insert is a block reference and a Block is a block definition, this is the nomenclature used in the dxf.

Then in your test case you are not making use of Block.Create method. The code you show would be equivalent, although slower, it involves cloning, to this example using the Block.Create.
DxfDocument docBlock = new DxfDocument(DxfVersion.AutoCad2004);
Line line29 = new Line(new Vector3(0, 15, 0), new Vector3(10, 15, 0)) { Color = new AciColor(6), Lineweight = Lineweight.W100 };
Line line30 = new Line(new Vector3(10, 0, 0), new Vector3(10, 15, 0)) { Color = new AciColor(6), Lineweight = Lineweight.W100 };
Line line33 = new Line(new Vector3(0, 0, 0), new Vector3(10, 0, 0)) { Color = new AciColor(6), Lineweight = Lineweight.W100 };
Line line40 = new Line(new Vector3(0, 0, 0), new Vector3(0, 15, 0)) { Color = new AciColor(6), Lineweight = Lineweight.W100 };
docBlock.AddEntity(new List<EntityObject> { line29, line30, line33, line40 });

docBlock.AddEntity(new AttributeDefinition("blkWidth") { Prompt = "Width:", Value = 15, Position = new Vector3(1, 13, 0), Lineweight = Lineweight.W20 });
docBlock.AddEntity(new AttributeDefinition("blkHeight") { Prompt = "Height:", Value = 10, Position = new Vector3(1, 11, 0), Lineweight = Lineweight.W20 });
docBlock.AddEntity(new AttributeDefinition("blkDirection") { Prompt = "Direction:", Value = 0, Position = new Vector3(1, 9, 0), Lineweight = Lineweight.W20 });

DxfDocument dxf = new DxfDocument(DxfVersion.AutoCad2004);
Block block =Block.Create(docBlock, "buildingBlock");
dxf.AddEntity(new Insert(block));
dxf.Save(@"test2.dxf");
Daniel

Yahasana wrote Mar 29 at 4:09 AM

Sorry I didn't give the full test case.
        DxfDocument dxf = new DxfDocument(DxfVersion.AutoCad2004);
        Block block = new Block("buildingBlock");
        Line line29 = new Line(new Vector3(0, 15, 0), new Vector3(10, 15, 0)) { Color = new AciColor(6), Lineweight = Lineweight.W100 };
        Line line30 = new Line(new Vector3(10, 0, 0), new Vector3(10, 15, 0)) { Color = new AciColor(6), Lineweight = Lineweight.W100 };
        Line line33 = new Line(new Vector3(0, 0, 0), new Vector3(10, 0, 0)) { Color = new AciColor(6), Lineweight = Lineweight.W100 };
        Line line40 = new Line(new Vector3(0, 0, 0), new Vector3(0, 15, 0)) { Color = new AciColor(6), Lineweight = Lineweight.W100 };
        block.Entities.AddRange(new List<EntityObject> { line29, line30, line33, line40 });
        
        block.AttributeDefinitions.Add(new AttributeDefinition("blkWidth") { Prompt = "Width:", Value = 15, Position = new Vector3(1, 13, 0), Lineweight = Lineweight.W20});
        block.AttributeDefinitions.Add(new AttributeDefinition("blkHeight") { Prompt = "Height:", Value = 10, Position = new Vector3(1, 11, 0), Lineweight = Lineweight.W20});
        block.AttributeDefinitions.Add(new AttributeDefinition("blkDirection") { Prompt = "Direction:", Value = 0, Position = new Vector3(1, 9, 0), Lineweight = Lineweight.W20});

        dxf.AddEntity(new Insert(block));
        dxf.Save(@"test.dxf");       // Save the file


       // test for Block.Create to copy Insert elements       
        dxf = DxfDocument.Load(@"test.dxf");
        DxfDocument dxf1 = new DxfDocument(DxfVersion.AutoCad2004);
        block = Block.Create(dxf, "buildingBlock");
        dxf1.AddEntity(new Insert(block));
        dxf1.Save(@"test2.dxf");          // does NOT copy any attributes

haplokuon wrote Apr 3 at 5:37 PM

The result of the example you are showing now should be the same as what I wrote in my previous comment. You are expecting some kind of result that is not correct.

If you look into your propose fix, while iterating through the entities in the document to create the block, you are making copies of some properties of the blocks referenced by inserts contained inside the document. Those inserts might or might not point to the same block, keep in mind that a document might contain multiples inserts and those inserts can be block references of the same or different blocks.

As I said earlier, any Insert entity inside the document will become an insert inside the new block (the one that the "Block.Create" method creates), they are usually known as nested blocks.

Daniel