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

Copy Problems

13 REPLIES 13
SOLVED
Reply
Message 1 of 14
HelloWorlddd
870 Views, 13 Replies

Copy Problems

I want to create a command, it could copy the contents of another drawing to the current drawing directly, not XERF, Is there anyone can give me a simple example?
Thanks very much

13 REPLIES 13
Message 2 of 14
_gile
in reply to: HelloWorlddd

Have a look at the Database.WblockCloneObjects() method.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 3 of 14
_gile
in reply to: _gile

Here's a little sample

 

        public static ObjectIdCollection ImportModelSpace(string filename)
        {
            if (!File.Exists(filename))
                throw new FileNotFoundException("File not found", filename);

            Database targetDb = HostApplicationServices.WorkingDatabase;
            ObjectId owner = SymbolUtilityServices.GetBlockModelSpaceId(targetDb);
            IdMapping idMap = new IdMapping();

            using (Database sourceDb = new Database())
            {
                sourceDb.ReadDwgFile(filename, FileShare.Read, false, "");
                using (Transaction tr = sourceDb.TransactionManager.StartTransaction())
                {
                    BlockTableRecord mSpace = (BlockTableRecord)tr.GetObject(
                        SymbolUtilityServices.GetBlockModelSpaceId(sourceDb), OpenMode.ForRead);
                    ObjectIdCollection ids = new ObjectIdCollection(mSpace.Cast<ObjectId>().ToArray());
                    sourceDb.WblockCloneObjects(ids, owner, idMap, DuplicateRecordCloning.Ignore, false);
                    tr.Commit();
                }
            }
            return new ObjectIdCollection(
                idMap
                .Cast<IdPair>()
                .Where(p => p.IsCloned)
                .Select(p => p.Value)
                .ToArray());
        }

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 4 of 14
HelloWorlddd
in reply to: _gile

I think the code is still a little complicated for me,


Can you help me achieve the following process?  It will be a better way.

 

For example, there is a source drawing which contains a BlockReference called tstrm in the D drive,
Then execute custom command in the new drawing, this target block above will be copied to the new drawings.

Attachment has the source drawings


Extremely grateful

demo.PNG

Message 5 of 14
_gile
in reply to: HelloWorlddd

Do you want to add the block reference to the target model space or only import the block definition in the target block table ?



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 6 of 14
HelloWorlddd
in reply to: _gile

I do not quite understand the difference between these two
But the result I want is equivalent to using Autocad COPY command , just like copy the graphics to a new drawing, the graphics is same with the old one.

 

The new command that I want to get will work as below:

1,Exceute the command,

2,Automatic drawing that graphics at my specified position, in fact this step the program will access the source drawing and then copy that graphics

 

This small command will save some time during copy, just like select target object and so on

Message 7 of 14
_gile
in reply to: HelloWorlddd

First, IMO, if you want to make autoCAD customization, especially with a as sophisticated technology as .NET, you must, above all, master the autoCAD basics as the difference between a block definition (BlockTableRecord) and an insertion of this definition (BlockReference).

 

The AutoCAD COPY command do not allow to copy a graphic object between different drawing (either between two spaces). This can be done with the Windows clipboard technology (Copy/Paste commands) which is tolerate by AutoCAD.

The "AutoCAD way" to do what you describe is using the DesignCenter to import the block definition from another drawing and insert a reference of this block in the model space or elsewhere. This can be done programmatically using the WblockCloneObjects() method as shown upper.

 

You can find a method to import a block definition from an external drawing in this recent thread (reply #7):

http://forums.autodesk.com/t5/NET/How-to-include-extension-dictionary-in-block-inserted-using/td-p/4...



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 8 of 14
HelloWorlddd
in reply to: _gile

Thank you very much, I have a learn about WBlockCloneObjects() method in the AutoCAD Developer Guide, it works well.

but I am not very unstudand about your ImportBlock() method, this one has some problem.
Can you fix my code? Just let it work,

 

For example:
filePath=@"D:\SourceDwg\sourceDrawing.dwg"
BlockName="tstrm"
The Block will be import at origin

 

The above attachment has the drawing.

Blow is code,

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

[assembly: CommandClass(typeof(AutocadCommandCollection.test6))]


namespace AutocadCommandCollection
{

    class test6
    {

        [CommandMethod("test6")]


        public static void CopyFrom()
        {
            Document acDoc = Application.DocumentManager.MdiActiveDocument;
            Database acCurDb = acDoc.Database;

            using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
            {
                BlockTable acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId, OpenMode.ForRead) as BlockTable;
                ObjectId Id = ImportBlock(@"D:\SourceDwg\sourceDrawing.dwg", "tstrm");
                BlockTableRecord btr = (BlockTableRecord)acTrans.GetObject(Id, OpenMode.ForRead);
                acBlkTbl.Add(btr);
                acTrans.AddNewlyCreatedDBObject(btr, true);

                acTrans.Commit();
            }
        }




        private static ObjectId ImportBlock(string fileName, string blockName)
        {
            if (!File.Exists(fileName))
                throw new FileNotFoundException("File not found", fileName);

            Document acDoc = Application.DocumentManager.MdiActiveDocument;
            Database targetDb = acDoc.Database;
            ObjectId owner = targetDb.BlockTableId;

            using (Database sourceDb = new Database())
            {
                sourceDb.ReadDwgFile(fileName, System.IO.FileShare.Read, false, "");
                using (Transaction tr = sourceDb.TransactionManager.StartOpenCloseTransaction())
                {
                    BlockTable bt = (BlockTable)tr.GetObject(sourceDb.BlockTableId, OpenMode.ForRead);
                    if (!bt.Has(blockName))
                        return ObjectId.Null;

                    ObjectId id = bt[blockName];
                    ObjectIdCollection ids = new ObjectIdCollection();
                    ids.Add(id);
                    IdMapping idMap = new IdMapping();
                    sourceDb.WblockCloneObjects(ids, owner, idMap, DuplicateRecordCloning.Ignore, false);
                    return idMap[id].IsCloned ? idMap[id].Value : ObjectId.Null;
                }
            }
        }

    }

}

 

 

Message 9 of 14
HelloWorlddd
in reply to: HelloWorlddd

I think I finally find the new block after run the code above, the block is existing int the BlockTable or maybe, I can find it throuht the Insert Block drop down list of the Insert Menu.

But It doesn't show as same as the old one after insert manully, I just want Insert the Block in the new drawing, It will be same with the old one.

Can you help me? Very thanks

Picture.PNG

Message 10 of 14
_gile
in reply to: HelloWorlddd

        private void ImportBlockReference(string blockName, string filenName)
        {
            if (!File.Exists(filenName))
                throw new FileNotFoundException("File not found", filenName);

            Database targetDb = HostApplicationServices.WorkingDatabase;
            ObjectId owner = SymbolUtilityServices.GetBlockModelSpaceId(targetDb);

            using (Database sourceDb = new Database(false, true))
            {
                sourceDb.ReadDwgFile(filenName, FileShare.ReadWrite, false, "");
                using (Transaction tr = sourceDb.TransactionManager.StartTransaction())
                {
                    BlockTable bt = (BlockTable)tr.GetObject(sourceDb.BlockTableId, OpenMode.ForRead);
                    if (!bt.Has(blockName))
                        throw new ArgumentException("Block definition not found", blockName);

                    ObjectIdCollection ids = new ObjectIdCollection();

                    BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt[blockName], OpenMode.ForRead);
                    ObjectId mSpaceId = SymbolUtilityServices.GetBlockModelSpaceId(sourceDb);
                    foreach (ObjectId id in btr.GetBlockReferenceIds(true, false))
                    {
                        BlockReference br = (BlockReference)tr.GetObject(id, OpenMode.ForRead);
                        if (br.OwnerId == mSpaceId)
                        {
                            ids.Add(id);
                            break;
                        }
                    }

                    if (ids.Count == 0)
                        throw new ArgumentException("Block reference not found", blockName);

                    IdMapping idMap = new IdMapping();
                    sourceDb.WblockCloneObjects(ids, owner, idMap, DuplicateRecordCloning.Ignore, false);
                }
            }
        }

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 11 of 14
HelloWorlddd
in reply to: _gile

Thank you very much for your help, the above code have finished the above function I seted, a celebration~

 

At before, I thought if I can achieve the above code, then I can make changes, and then complete the final function, but I can’t -_-

 

The above code is still need one step, in fact, I want to control the position copied into the new graphics ,
For example, I want the block which in the original drawing coordinates is ( 0,0,0 )  will be copied to a new position specfied by cursor in the new drawing, I think this needs to move an object , the method may be used is similar with:

     acCirc.TransformBy (Matrix3d.Displacement (acVec3d));

But I can not find something equivalent to the acCirc object form your code.  
Can you finish it?

 

The problem is I am not familiar with WblockCloneObjects () method, and IdMapping class, I do not know how to use.

 

Let me think about my mastery of AtuoCAD, now I'm not too familiar with AutoCAD 's API, The basic API I know all learn from AutoCAD Developer Guide, I just basically modify the sample code.
I very much hope to further study, but there is no sample code in ObjectARX_2010_Win_64_and_32Bit, it seems not easy to understand, do you have any good way?

 

Sincere wishes!

Message 12 of 14
HelloWorlddd
in reply to: HelloWorlddd

Smiley SurprisedYes, I think I need the new ObjectId of this block in the new drawing, then I can get the new BlockReference in the new drawing, then move and so on.
How can I get it, maybe I can get it though the idMap?

Message 13 of 14
HelloWorlddd
in reply to: HelloWorlddd

I have solve this move problem, thank you very much and a celebration : )

May be you can tell me how to learn AutoCAD's API~~~

 

below is code

using System;
using System.IO;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;

[assembly: CommandClass(typeof(AutocadCommandCollection.test9))]


namespace AutocadCommandCollection
{

    class test9
    {

        [CommandMethod("test9")]
        public static void CopyFrom()
        {
            Document acDoc = Application.DocumentManager.MdiActiveDocument;
            Database acCurDb = acDoc.Database;

            using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
            {
                ImportBlockReference("tstrm",@"D:\SourceDwg\sourceDrawing.dwg");
            
                acTrans.Commit();
            }
        }

        private static void ImportBlockReference(string blockName, string filenName)
        {
            if (!File.Exists(filenName))
                throw new FileNotFoundException("File not found", filenName);

            Database targetDb = HostApplicationServices.WorkingDatabase;
            ObjectId owner = SymbolUtilityServices.GetBlockModelSpaceId(targetDb);

            using (Database sourceDb = new Database(false, true))
            {
                sourceDb.ReadDwgFile(filenName, FileShare.ReadWrite, false, "");
                using (Transaction tr = sourceDb.TransactionManager.StartTransaction())
                {
                    BlockTable bt = (BlockTable)tr.GetObject(sourceDb.BlockTableId, OpenMode.ForRead);
                    if (!bt.Has(blockName))
                        throw new ArgumentException("Block definition not found", blockName);

                    ObjectIdCollection ids = new ObjectIdCollection();

                    BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt[blockName], OpenMode.ForRead);
                    ObjectId mSpaceId = SymbolUtilityServices.GetBlockModelSpaceId(sourceDb);
                    ObjectId brefId = new ObjectId();
                    foreach (ObjectId id in btr.GetBlockReferenceIds(true, false))
                    {
                        BlockReference br = (BlockReference)tr.GetObject(id, OpenMode.ForRead);

                        if (br.OwnerId == mSpaceId)
                        {
                            ids.Add(id);
                            brefId = id;
                            break;
                        }
                    }

                    if (ids.Count == 0)
                        throw new ArgumentException("Block reference not found", blockName);

                    IdMapping idMap = new IdMapping();
                    sourceDb.WblockCloneObjects(ids, owner, idMap, DuplicateRecordCloning.Ignore, false);
                    Document acDoc = Application.DocumentManager.MdiActiveDocument;
                    Database acCurDb = acDoc.Database;

                    using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
                    {
                        BlockReference bref = acTrans.GetObject(idMap[brefId].Value, OpenMode.ForWrite) as BlockReference;
                        if (bref != null)
                        {
                            Application.ShowAlertDialog(bref.Position.ToString());

                            Point3d newPoint = new Point3d(100,100,0);
                            Point3d oldPoint = new Point3d(0,0,0);

                            Vector3d acVec3d = oldPoint.GetVectorTo(newPoint);
                            bref.TransformBy(Matrix3d.Displacement(acVec3d));
                            Application.ShowAlertDialog(bref.Position.ToString());
                        }
                        acTrans.Commit();
                    }
                }
            }
        }
    }
}

 

Message 14 of 14
_gile
in reply to: HelloWorlddd

Hi,

 

You can make the importBlockReference() method return the newly created ObjectId to the calling function from where you move the newly created block reference.

 

        [CommandMethod("TEST")]
        public void Tet()
        {
            ObjectId id = ImportBlockReference("tstrm", @"D:\SourceDwg\sourceDrawing.dwg");
            if (id != ObjectId.Null)
            {
                Database db = HostApplicationServices.WorkingDatabase;
                using (Transaction tr = db.TransactionManager.StartTransaction())
                {
                    BlockReference br = (BlockReference)tr.GetObject(id, OpenMode.ForWrite);
                    br.TransformBy(Matrix3d.Displacement(new Vector3d(10, 20, 0)));
                    tr.Commit();
                }
            }
        }

        private ObjectId ImportBlockReference(string blockName, string filenName)
        {
            if (!File.Exists(filenName))
                throw new FileNotFoundException("File not found", filenName);

            Database targetDb = HostApplicationServices.WorkingDatabase;
            ObjectId owner = SymbolUtilityServices.GetBlockModelSpaceId(targetDb);

            using (Database sourceDb = new Database(false, true))
            {
                sourceDb.ReadDwgFile(filenName, FileShare.ReadWrite, false, "");
                using (Transaction tr = sourceDb.TransactionManager.StartTransaction())
                {
                    BlockTable bt = (BlockTable)tr.GetObject(sourceDb.BlockTableId, OpenMode.ForRead);
                    if (!bt.Has(blockName))
                        throw new ArgumentException("Block definition not found", blockName);

                    ObjectIdCollection ids = new ObjectIdCollection();

                    BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt[blockName], OpenMode.ForRead);
                    ObjectId mSpaceId = SymbolUtilityServices.GetBlockModelSpaceId(sourceDb);
                    foreach (ObjectId id in btr.GetBlockReferenceIds(true, false))
                    {
                        BlockReference br = (BlockReference)tr.GetObject(id, OpenMode.ForRead);
                        if (br.OwnerId == mSpaceId)
                        {
                            ids.Add(id);
                            break;
                        }
                    }

                    if (ids.Count == 0)
                        throw new ArgumentException("Block reference not found", blockName);

                    IdMapping idMap = new IdMapping();
                    sourceDb.WblockCloneObjects(ids, owner, idMap, DuplicateRecordCloning.Ignore, false);

                    return idMap[ids[0]].Value;
                }
            }
        }

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

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