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

Can in-memory xref objects be cloned to current db?

6 REPLIES 6
Reply
Message 1 of 7
elliottpd11
913 Views, 6 Replies

Can in-memory xref objects be cloned to current db?

I have a successful Copy Layer program that copies all entities on an xref layer to the current (non-Xref) layer.  I'm doing this by creating a new database, and using the db.ReadDwgFile() function.  My question is: is it possible to use db.WblockCloneObjects to copy objects by accessing the in-memory xref database?  I can get the database using XrefGraphNode.Database, but all efforts to use WblockCloneObjects have failed. Can anyone provide direction?  Thanks in advance for your efforts.  Pete Elliott

6 REPLIES 6
Message 2 of 7
khoa.ho
in reply to: elliottpd11

Yes, we can. But instead of using WblockCloneObjects which may cause eWrongDatabase error, we can use Clone() method of entities from Xref database. This is a different way to copy entities between AutoCAD databases. The following code is an example to copy all entities (except BlockReference) from xrefs to the host drawing:

 

[CommandMethod("CopyEntitiesFromXrefs")]
public static void CopyEntitiesFromXrefs()
{
    Document doc = Application.DocumentManager.MdiActiveDocument;
    Database db = doc.Database;
    using (Transaction trans = db.TransactionManager.StartTransaction())
    {
        try
        {
            var list = new List<Entity>();
            var bt = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForRead);
            var modelSpace = (BlockTableRecord)trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);

            XrefGraph xrefGraph = db.GetHostDwgXrefGraph(true);
            int xrefCount = xrefGraph.NumNodes;
            for (int i = 0; i < xrefCount; i++)
            {
                XrefGraphNode xrefNode = xrefGraph.GetXrefNode(i);
                Database xrefDb = xrefNode.Database;
                using (var xrefBt = (BlockTable)trans.GetObject(xrefDb.BlockTableId, OpenMode.ForRead, false))
                {
                    using (var xrefModelSpace = (BlockTableRecord)trans.GetObject(xrefBt[BlockTableRecord.ModelSpace], OpenMode.ForRead, false))
                    {
                        foreach (ObjectId id in xrefModelSpace)
                        {
                            DBObject obj = trans.GetObject(id, OpenMode.ForRead);
                            Entity clonedEntity = (Entity)obj.Clone();
                            list.Add(clonedEntity);
                        }
                    }
                }
            }
            if (list.Count > 0)
            {
                foreach (Entity entity in list)
                {
                    modelSpace.AppendEntity(entity);
                    trans.AddNewlyCreatedDBObject(entity, true);
                }
            }
            modelSpace.DowngradeOpen();
            modelSpace.Dispose();
            bt.Dispose();
            trans.Commit();
        }
        catch (System.Exception ex)
        {
        }
    }
}

 

This code does not copy BlockReference as it requires BlockTableRecord to import from source to destination database. In-memory xref database is much faster than db.ReadDwgFile() as all external databases were loaded inside AutoCAD memory.

 

You can extend the code with predicate delegate to filter out entities of specified properties (layer, entity type…).

 

Message 3 of 7
elliottpd11
in reply to: khoa.ho

Thanks so much for this. It led me to further testing. However, the bulk of the objects to be copied are usually Block References, so cloning the BlockTableRecords is critical to success.
Message 4 of 7
khoa.ho
in reply to: elliottpd11

Have a look at Hallex solution for copying BlockTableRecord between two AutoCAD databases at the post: http://forums.autodesk.com/t5/NET/Copy-of-BlockTableRecord-save-as/td-p/3602444

 

I have a feeling that we can use either WblockCloneObjects() or Clone() from my code to replicate entities. But we have to do some twists (Deep Cloning) to avoid eWrongDatabase error. I will go back later today as I have a hard time to maintain my daily job while playing with this forum.

 

Message 5 of 7
khoa.ho
in reply to: elliottpd11

If you use db.ReadDwgFile to open xref and db.WblockCloneObjects to clone xref entities (including BlockReference), it should not be a problem for your task. I tested it works.

 

The problem is in-memory xrefs deny all cloning process either to use db.WblockCloneObjects or db.DeepCloneObjects, AutoCAD returns errors of eWrongDatabase or eInvalidOwnerObject. I have no luck with it now. I will go back this pain problem later when I have more time.

 

Message 6 of 7
elliottpd11
in reply to: khoa.ho

Yes, I agree, these are my results also.
Message 7 of 7
FRFR1426
in reply to: khoa.ho

You can use DBObject.DeepClone instead of RXObject.Clone to copy the BlockReference objects.

Maxence DELANNOY
Manager
Add-ins development for Autodesk software products
http://wiip.fr

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

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report

”Boost