.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Struggling to add block from external drawing to current drawing

7 REPLIES 7
SOLVED
Reply
Message 1 of 8
asdasdfsd2
698 Views, 7 Replies

Struggling to add block from external drawing to current drawing

Greetings, 

 

This code runs without errors but the block is not showing up? Can't really tell where the error lies here. The block is added to the drawing without problems as i can see in the "current" tab when using the [insert] command and the code to add/append to the blocktable is pieced together from internet but i suspect that this is where the error lies...

Thanks in advance!

 

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;

using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ZkPlaceBlock
{
    public class Commands
    {
        [CommandMethod("ZkPlaceBlock")]

        public void ZkPlaceBlock()
        {
            var doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            var editor = doc.Editor;

            Database sourceDb = new Database(false, true);
            //ObjectId lengteNrId;

            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                try
                {
                    editor.WriteMessage("testing");

                    sourceDb.ReadDwgFile("C:/pathto.dwg", System.IO.FileShare.Read, true, "");
                    ObjectIdCollection blockIds = new ObjectIdCollection();
                    Autodesk.AutoCAD.DatabaseServices.TransactionManager tm = sourceDb.TransactionManager;

                    ObjectId lengteNrId = ObjectId.Null;

                    using (Transaction myT = tm.StartTransaction())
                    {
                        BlockTable bt = (BlockTable)tm.GetObject(sourceDb.BlockTableId, OpenMode.ForRead, false);
                        foreach (ObjectId btrId in bt)
                        {
                            BlockTableRecord btr = (BlockTableRecord)tm.GetObject(btrId, OpenMode.ForRead, false);
                            //editor.WriteMessage("\nBlockNameSource:" + btr.Name); //LENGTENR //Print all blocks in external document
                            if (btr.Name.Equals("LENGTENR"))
                            {
                                blockIds.Add(btrId);
                                IdMapping mapping = new IdMapping();
                                sourceDb.WblockCloneObjects(blockIds,db.BlockTableId,mapping,DuplicateRecordCloning.Replace,false);

                                lengteNrId = btr.ObjectId;

                                btr.Dispose();
                            }
                        }
                        myT.Commit();
                        bt.Dispose();
                    }

                    BlockTable blckTbl;
                    blckTbl = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;

                    PromptSelectionResult acPrompt = doc.Editor.GetSelection();

                    /*
                    foreach(ObjectId blckId in blckTbl)
                    {
                        BlockTableRecord blck = tr.GetObject(blckId, OpenMode.ForRead) as BlockTableRecord;
                        editor.WriteMessage("\nBlockNameDestination:" + blck.Name);
                    }
                    */

                    if (acPrompt.Status == PromptStatus.OK)
                    {
                        SelectionSet acSet = acPrompt.Value;
                        foreach (SelectedObject acObj in acSet)
                        {
                            if (acObj != null)
                            {
                                Entity acEnt = tr.GetObject(acObj.ObjectId, OpenMode.ForRead) as Entity;

                                Extents3d ext3d = acEnt.GeometricExtents;
                                Double tempY = ((ext3d.MaxPoint.Y - ext3d.MinPoint.Y) * 0.5) + ext3d.MinPoint.Y;
                                Point3d basePunt = new Point3d(ext3d.MinPoint.X, tempY, 0);

                                editor.WriteMessage("\nCoordinaten basePunt: " + basePunt.X.ToString() + " " + basePunt.Y.ToString()); 

                                foreach (ObjectId blckId in blckTbl)
                                {
                                    BlockTableRecord blck = tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
                                    
                                    if (blck.Name.Equals("LENGTENR"))
                                    {
                                        BlockReference acBlkRef = new BlockReference(basePunt, blck.ObjectId);
                                        
                                        //editor.WriteMessage("\nBingo");
                                        blck.AppendEntity(acBlkRef);
                                        tr.AddNewlyCreatedDBObject(blck, true);
                                        
                                        //blck.AppendEntity(acBlkRef);
                                        //tr.AddNewlyCreatedDBObject(acBlkRef, true);
                                    }
                                   
                                }
                            }
                        }
                    }

                    tr.Commit();
                }
                catch (Autodesk.AutoCAD.Runtime.Exception Ex)
                {
                    Application.ShowAlertDialog("\n" + Ex.Message);
                    tr.Abort();
                }

            }

        }
    }
}

 

 

 

7 REPLIES 7
Message 2 of 8
_gile
in reply to: asdasdfsd2

Hi,

Try like this. I removed useless statements and made some improvements.

        [CommandMethod("ZkPlaceBlock")]
        public void ZkPlaceBlock()
        {
            var doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
            var db = doc.Database;

            using (Database sourceDb = new Database(false, true))
            {
                sourceDb.ReadDwgFile("C:/pathto.dwg", System.IO.FileShare.Read, true, "");
                ObjectIdCollection blockIds = new ObjectIdCollection();
                ObjectId lengteNrId = ObjectId.Null;

                using (Transaction tr = sourceDb.TransactionManager.StartTransaction())
                {
                    BlockTable bt = (BlockTable)tr.GetObject(sourceDb.BlockTableId, OpenMode.ForRead, false);
                    if (bt.Has("LENGTENR"))
                    {
                        blockIds.Add(bt["LENGTENR"]);
                        IdMapping mapping = new IdMapping();
                        sourceDb.WblockCloneObjects(blockIds, db.BlockTableId, mapping, DuplicateRecordCloning.Replace, false);
                    }
                    tr.Commit();
                }
            }

            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                try
                {
                    BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead, false);
                    if (!bt.Has("LENGTENR"))
                        return;
                    PromptSelectionResult selection = doc.Editor.GetSelection();
                    if (selection.Status == PromptStatus.OK)
                    {
                        BlockTableRecord blck = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
                        foreach (ObjectId id in selection.Value.GetObjectIds())
                        {
                            Entity ent = (Entity)tr.GetObject(id, OpenMode.ForRead);
                            Extents3d ext3d = ent.GeometricExtents;
                            double tempY = (ext3d.MaxPoint.Y - ext3d.MinPoint.Y) * 0.5 + ext3d.MinPoint.Y;
                            Point3d basePunt = new Point3d(ext3d.MinPoint.X, tempY, 0);
                            BlockReference br = new BlockReference(basePunt, bt["LENGTENR"]);
                            blck.AppendEntity(br);
                            tr.AddNewlyCreatedDBObject(br, true);
                        }
                    }
                    tr.Commit();
                }
                catch (Autodesk.AutoCAD.Runtime.Exception Ex)
                {
                    Application.ShowAlertDialog("\n" + Ex.Message);
                    tr.Abort();
                }
            }
        }

 

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 3 of 8
norman.yuan
in reply to: asdasdfsd2

I think there is an error, originally from the OP's code:

 

blck.AppendEntity(br);

tr.AddNewlyCreatedDBObject(blck, true);

 

Should have been:

 

blck.AppendEntity(br);

tr.AddNewlyCreatedDBObject(br, true);

 

 

Norman Yuan

Drive CAD With Code

EESignature

Message 4 of 8
asdasdfsd2
in reply to: _gile

Thank you very much! It's working perfectly now! I see i still have a lot to learn here...

 

While it's working perfectly 3 new issues came to light of which one is resolved:

1 - The block being placed is dynamic and i had to set it's property before placing by using this piece of code:

 

doc.Editor.WriteMessage("\n"+prop.PropertyName);
                                object[] values = prop.GetAllowedValues();

                                if (prop.PropertyName == "Flip state1" && !prop.ReadOnly)
                                {
                                    if (prop.Value.ToString() == values[0].ToString())
                                        prop.Value = values[1];
                                    else
                                        prop.Value = values[0];
                                }

 

I was lucky the property was binary here because i don't understand why it rejected a String as output and needs this trick?

 

2 - The block also contains an attribute and at first it didn't show up but i found that you have to use [attsync] to have it "show". The problem here is that a rotation is applied to the blockreference before placement but the attribute isn't affected. I think due to the fact i call [attsync] after commiting the whole transaction. Would i be able to call [attsync] before adding the block to the current documents blocktable? My guess is no thinking [attsync] will apply to objects in the document and not a virtual one and also because [attsync] will have to be called before applying any transformation but the transformations are done before adding the block to the current doc's database? Am i correct in this assumption and how would you tackle this?

 

3 - And the third is that i want the block to inherit the rotation of the selected object which is Text. So my plan was to just take the max/min-point.x, calculate the angle from there and apply it to the new block. Unfortunately that doesn't work because apparently if you apply a rotation the bounds of the object don't get updated? So regarding the rotation i'm a bit stumped on how to solve it... <Edit:Bounds are updated, just not in the way i would expect them to :)>

 

I made this to test. (the rotation is set to an arbitrary value now)

 

 

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;

using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ZkGeometryTransformTest
{
    public class Commands
    {
        [CommandMethod("ZkGeometryTransform")]

        public void ZkGeometryTransform()
        {
            var doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            var editor = doc.Editor;

            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                try
                {
                    editor.WriteMessage("testing");

                    PromptSelectionResult selection = editor.GetSelection();
                    if (selection.Status == PromptStatus.OK)
                    {
                        BlockTableRecord blck = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
                        foreach (ObjectId id in selection.Value.GetObjectIds())
                        {
                            Entity ent = (Entity)tr.GetObject(id, OpenMode.ForRead);
                            //BlockReference blockRef = tr.GetObject(id, OpenMode.ForWrite) as BlockReference;

                            Extents3d ext3d = ent.GeometricExtents;
                            Point2d lB = new Point2d(ext3d.MinPoint.X, ext3d.MinPoint.Y);
                            Point2d rB = new Point2d(ext3d.MaxPoint.X, ext3d.MinPoint.Y);
                            Point2d rO = new Point2d(ext3d.MaxPoint.X, ext3d.MaxPoint.Y);
                            Point2d lO = new Point2d(ext3d.MinPoint.X, ext3d.MaxPoint.Y);

                            Point3d center = new Point3d(((ext3d.MaxPoint.X - ext3d.MinPoint.X) * 0.5) + ext3d.MinPoint.X, ((ext3d.MaxPoint.Y - ext3d.MinPoint.Y) * 0.5) + ext3d.MinPoint.Y , 0);
                            
                            //Matrix3d translate = Matrix3d.Rotation(blockRef.Rotation, Vector3d.ZAxis, center);
                            //Matrix3d translate = Matrix3d.Rotation(ent.Ecs, Vector3d.ZAxis, center);

                            Polyline p = new Polyline();
                            p.AddVertexAt(0, lB, 0, 0, 0);
                            p.AddVertexAt(1, rB, 0, 0, 0);
                            p.AddVertexAt(2, rO, 0, 0, 0);
                            p.AddVertexAt(3, lO, 0, 0, 0);
                            p.AddVertexAt(4, lB, 0, 0, 0);

                            p.Closed = true;

                            Matrix3d curUCSMatrix = doc.Editor.CurrentUserCoordinateSystem;
                            CoordinateSystem3d curUCS = curUCSMatrix.CoordinateSystem3d;
                            p.TransformBy(Matrix3d.Rotation(0.7854,curUCS.Zaxis, center));

                            //Matrix3d rotationMatrix = ent.CompoundObjectTransform;
                            //p.TransformBy(ent.CompoundObjectTransform);

                            p.SetDatabaseDefaults();
                            blck.AppendEntity(p);
                            tr.AddNewlyCreatedDBObject(p,true);
                        }
                    }


                    tr.Commit();
                }
                catch (Autodesk.AutoCAD.Runtime.Exception Ex)
                {
                    Application.ShowAlertDialog("\n" + Ex.Message);
                    tr.Abort();
                }

            }

        }
    }
}

 

 



 

Message 5 of 8
_gile
in reply to: asdasdfsd2

1. The values of dynamic properties are strongly typed. Assuming you know the dynamic bloc you're inserting, you should also know  the type of the properties (string for visibiliy states, double for distances or angles, ...).

2. When you insert an attributed block reference, you have to also insert the attribute references (see this topic).

3. DBText and MText objects have a Rotation property as the brockReference, so you can simply set the BlockReference.Rotation property with the text rotation.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 6 of 8
asdasdfsd2
in reply to: _gile

Again thanks for the help! I appreciate it!

 

1: Yes, i experienced that earlier with some other code 🙂 It was a double and had to have two decimals after the comma. It was pain to solve... Eventually i just mulitplied by 1.00 and that did the trick. But it's a String in this case ("Flipped","Not flipped")  so i still don't see why it's making an issue of that and needing this trick? (because it rejected prop.Value = "Flipped" for example)

 

2: Thanks! Will check it out!

 

3: And this as well! 


 

Message 7 of 8
_gile
in reply to: asdasdfsd2


@asdasdfsd2  a écrit :

But it's a String in this case ("Flipped","Not flipped")  so i still don't see why it's making an issue of that and needing this trick? (because it rejected prop.Value = "Flipped" for example)


For Inversion parameter, the values have to be 0 or 1 (short).



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 8 of 8
asdasdfsd2
in reply to: _gile

<Edit> Solved original issue with atribute being exposed to dynamic property and being unable to set it correct... (by cheating... i recreated the block and simply removed the dynamic property because it wont be needed if i get this code working)

 

Still standing is the issue with keeping track of the added blocks though. I thought that if i store the ObjectId of the newly created blockreference i could use it later but it only appears temporary? 

 

What puzzles me is that i'm clearly adding it to the current documents database with [blck.AppendEntity(br)] so there has to be some sort of id somewhere. So the question is; How would i get the unique "identifier" for that specific blockreference in the database here?

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

AutoCAD Inside the Factory


Autodesk Design & Make Report