将预先存在的AutoCAD图形插入当前图形中

时间:2014-11-11 15:24:10

标签: c# .net autocad-plugin

我正在尝试以编程方式将预先存在的绘图中的块插入到运行插件的当前绘图中。为此,我在C#.NET表单上有一个按钮,调用以下方法

public void MakeAndInsertObject() //Method to add all windows and doors templates to drawing database for use later
{
    Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument; //Stores the active document
    Editor ed = doc.Editor; //Stores the document's editor
    Database dtb = ed.Document.Database; //Stores the database from the editor

    Transaction tr = dtb.TransactionManager.StartTransaction(); //Start a transaction with the document's database
    DocumentLock docLock = doc.LockDocument();

    using (tr)    
    using (docLock)
    {
        BlockTableRecord btr = (BlockTableRecord)tr.GetObject(dtb.CurrentSpaceId, OpenMode.ForWrite); //Opens the block table record so you can write to it
        BlockTableRecord newBlockDef = new BlockTableRecord(); //Creates a new record in the block table
        BlockTable blockTable = (BlockTable)tr.GetObject(dtb.BlockTableId, OpenMode.ForWrite); //Opens the block table so it can be written to
        //Pointing new block to correct drawing file
        newBlockDef.Name = "Door";
        newBlockDef.PathName = "C:/Users/Administrator/Documents/All Code/clearspan-autocad-tools-development/Templates/locks/DOOR.dwg";
        blockTable.Add(newBlockDef); //Adds the block table record to the block table
        BlockReference newBlock = new BlockReference(new Point3d(0, 0, 0), newBlockDef.ObjectId); //Insert a block reference with the newly created block
        btr.AppendEntity(newBlock); //Inserts the block into the current space (Model or Paper) via the block table record
        //Updates the Transaction with all new database objects
        tr.AddNewlyCreatedDBObject(newBlockDef, true);
        tr.AddNewlyCreatedDBObject(newBlock, true);
        tr.Commit(); //Applies all changes made as part of the current transaction
        tr.Dispose();
    }
}

代码完全执行但是我的DOOR.dwg文件中的块没有出现在位置(0,0,0),我不知道它为什么没有

3 个答案:

答案 0 :(得分:3)

我从Keen Walmsley获取了一个片段,并将其编辑为不那么繁琐且更易读。这是非常基本的。你应该阅读一些Keen的东西,这是非常好的,他的笔记非常具有描述性。请参阅下面的代码以了解用法。

public void ImportBlocks()
{
    DocumentCollection dm =
    Application.DocumentManager;
    Editor ed = dm.MdiActiveDocument.Editor;
    Database destDb = dm.MdiActiveDocument.Database;
    Database sourceDb = new Database(false, true);
    try
    {
        // Get name of DWG from which to copy blocks
        var sourceFileName = ed.GetString("\nEnter the path of the source drawing: ");

        // Read the DWG into a side database
        sourceDb.ReadDwgFile(sourceFileName.StringResult, System.IO.FileShare.Read, true, "");

        // Create a variable to store the list of block identifiers
        ObjectIdCollection blockIds = new ObjectIdCollection();

        var tm = sourceDb.TransactionManager;

        using (var myT = tm.StartOpenCloseTransaction())
        {
            // Open the block table
            BlockTable bt = (BlockTable)myT.GetObject(sourceDb.BlockTableId, OpenMode.ForRead, false);

            // Check each block in the block table
            foreach (ObjectId btrId in bt)
            {
                BlockTableRecord btr =
                (BlockTableRecord)myT.GetObject(btrId, OpenMode.ForRead, false);

                // Only add named & non-layout blocks to the copy list
                if (!btr.IsAnonymous && !btr.IsLayout)
                    blockIds.Add(btrId);
                btr.Dispose();
            }
        }
        // Copy blocks from source to destination database
        var mapping = new IdMapping();
        sourceDb.WblockCloneObjects(blockIds,
            destDb.BlockTableId,
            mapping,
            DuplicateRecordCloning.Replace,
            false);
    }
    catch(Autodesk.AutoCAD.Runtime.Exception ex)
    {
        ed.WriteMessage("\nError during copy: " + ex.Message);
    }
    sourceDb.Dispose();
}

出于好奇,如果有人开发了用于AutoCAD的python API,你会使用它吗?还是试一试?

答案 1 :(得分:0)

您需要使用wblockcloneObjects方法从源dwg到目标dwg blocktable获取块。然后你可以插入它。

在vb代码中:

Dim doc As Document = Application.DocumentManager.MdiActiveDocument
        Using lock = doc.LockDocument

            Using OpenDb As New Database(False, False)
                OpenDb.ReadDwgFile(PathDwg, System.IO.FileShare.ReadWrite, True, "")
                Dim ids As New ObjectIdCollection()
                Dim bt As BlockTable
                Dim sourceBlockId As ObjectId = ObjectId.Null
                Using tr As Transaction = OpenDb.TransactionManager.StartTransaction()

                    bt = DirectCast(tr.GetObject(OpenDb.BlockTableId, OpenMode.ForRead), BlockTable)
                    If bt.Has(NaamBlok) Then
                        ids.Add(bt(NaamBlok))
                        sourceBlockId = bt(NaamBlok)
                    End If

                    If ids.Count <> 0 Then
                        Dim destdb As Database = doc.Database
                        Dim iMap As New IdMapping()
                        OpenDb.WblockCloneObjects(ids, destdb.BlockTableId, iMap, DuplicateRecordCloning.Replace, False)

                    End If

                    tr.Commit()

                End Using
            End Using
        End Using

答案 2 :(得分:0)

        /// <summary>
        /// the source drawig should be drawn as number of
        /// separate entites with or without attributes.
        /// Throws NotImplementedException if invoked with .dxf file
        /// </summary>
        /// <param name="sourceDrawing"></param>
        /// <param name="insertionPoint"></param>
        /// <returns>ObjectID of the Block Def that was imported.</returns>
        public void ImportDwgAsBlock(string sourceDrawing, Point3d insertionPoint)
        {
            Matrix3d ucs = _ed.CurrentUserCoordinateSystem;

            string blockname = sourceDrawing.Remove(0, sourceDrawing.LastIndexOf("\\", StringComparison.Ordinal) + 1);
            blockname = blockname.Substring(0, blockname.Length - 4); // remove the extension

            try
            {
                using (_doc.LockDocument())
                {
                    using (var inMemoryDb = new Database(false, true))
                    {
                        #region Load the drawing into temporary inmemory database
                        if (sourceDrawing.LastIndexOf(".dwg", StringComparison.Ordinal) > 0)
                        {
                            inMemoryDb.ReadDwgFile(sourceDrawing, System.IO.FileShare.Read, true, "");
                        }
                        else if (sourceDrawing.LastIndexOf(".dxf", StringComparison.Ordinal) > 0)
                        {
                            _logger.Error(MethodBase.GetCurrentMethod().DeclaringType.FullName + "." + MethodBase.GetCurrentMethod().Name + " : Tried to invoke the method with .dxf file.");
                            throw new NotImplementedException("Importing .dxf is not supported in this version.");
                            //inMemoryDb.DxfIn("@" + sourceDrawing, System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase) + "\\log\\import_block_dxf_log.txt");
                        }
                        else
                        {
                            throw new ArgumentException("This is not a valid drawing.");
                        }
                        #endregion

                        using (var transaction =  _db.TransactionManager.StartTransaction())
                        {
                            BlockTable destDbBlockTable = (BlockTable)transaction.GetObject(_db.BlockTableId, OpenMode.ForRead);
                            BlockTableRecord destDbCurrentSpace = (BlockTableRecord)_db.CurrentSpaceId.GetObject(OpenMode.ForWrite);

                            // If the destination DWG already contains this block definition
                            // we will create a block reference and not a copy of the same definition
                            ObjectId sourceBlockId;
                            if (destDbBlockTable.Has(blockname))
                            {

                                //BlockTableRecord destDbBlockDefinition = (BlockTableRecord)transaction.GetObject(destDbBlockTable[blockname], OpenMode.ForRead);
                                //sourceBlockId = destDbBlockDefinition.ObjectId;

                                sourceBlockId = transaction.GetObject(destDbBlockTable[blockname], OpenMode.ForRead).ObjectId;

                                // Create a block reference to the existing block definition
                                using (var blockReference = new BlockReference(insertionPoint, sourceBlockId))
                                {
                                    _ed.CurrentUserCoordinateSystem = Matrix3d.Identity;
                                    blockReference.TransformBy(ucs);
                                    _ed.CurrentUserCoordinateSystem = ucs;
                                    var converter = new MeasurementUnitsConverter();
                                    var scaleFactor = converter.GetScaleRatio(inMemoryDb.Insunits, _db.Insunits);
                                    blockReference.ScaleFactors = new Scale3d(scaleFactor);
                                    destDbCurrentSpace.AppendEntity(blockReference);
                                    transaction.AddNewlyCreatedDBObject(blockReference, true);
                                    _ed.Regen();
                                    transaction.Commit();
                                    // At this point the Bref has become a DBObject and (can be disposed) and will be disposed by the transaction
                                }
                                return;
                            }

                            //else // There is not such block definition, so we are inserting/creating new one

                            sourceBlockId = _db.Insert(blockname, inMemoryDb, true);
                            BlockTableRecord sourceBlock = (BlockTableRecord)sourceBlockId.GetObject(OpenMode.ForRead);
                            sourceBlock.UpgradeOpen();
                            sourceBlock.Name = blockname;
                            destDbCurrentSpace.DowngradeOpen();
                            var sourceBlockMeasurementUnits = inMemoryDb.Insunits;
                            try
                            {
                                CreateBlockReference(sourceBlock.Name, sourceBlockMeasurementUnits,
                                                     insertionPoint,
                                                     destDbCurrentSpace,
                                                     destDbBlockTable);
                            }
                            catch (ArgumentException argumentException)
                            {
                                _logger.Error("Error. Check inner exception.", argumentException);
                            }

                            _ed.Regen();
                            transaction.Commit();
                        }
                    }
                }
            }
            catch (Autodesk.AutoCAD.Runtime.Exception exception)
            {
                _logger.Error("Error in ImportDrawingAsBlock().", exception);

            }
        }

更新以下是我错过的转换器:

#if !bcad
using Autodesk.AutoCAD.DatabaseServices;
#else
using Teigha.DatabaseServices;
#endif
using Castle.Core.Logging;
using System.Collections.Generic;

namespace KojtoCAD.Utilities
{
    public class MeasurementUnitsConverter
    {
        private ILogger _logger = NullLogger.Instance;

    private readonly Dictionary<UnitsValue, double> _linkBetweenDrawingUnitsAndMilimeters;

    public MeasurementUnitsConverter()
    {
        _linkBetweenDrawingUnitsAndMilimeters = new Dictionary<UnitsValue, double>
                                                    {
                                                        {
                                                            UnitsValue.Angstroms,
                                                            0.0000001
                                                        },
                                                        {
                                                            UnitsValue.Astronomical,
                                                            149600000000000
                                                        },
                                                        {
                                                            UnitsValue.Centimeters, 10
                                                        },
                                                        {
                                                            UnitsValue.Decimeters, 100
                                                        },
                                                        {
                                                            UnitsValue.Dekameters,
                                                            10000
                                                        },
                                                        { UnitsValue.Feet, 304.8 },
                                                        {
                                                            UnitsValue.Gigameters,
                                                            1000000000000
                                                        },
                                                        {
                                                            UnitsValue.Hectometers,
                                                            100000
                                                        },
                                                        { UnitsValue.Inches, 25.4 },
                                                        {
                                                            UnitsValue.Kilometers,
                                                            1000000
                                                        },
                                                        {
                                                            UnitsValue.LightYears,
                                                            9460700000000000000
                                                        },
                                                        { UnitsValue.Meters, 1000 },
                                                        {
                                                            UnitsValue.MicroInches,
                                                            0.0000254
                                                        },
                                                        { UnitsValue.Microns, 0.001 },
                                                        {
                                                            UnitsValue.Miles, 1609344.0
                                                        },
                                                        { UnitsValue.Millimeters, 1 },
                                                        { UnitsValue.Mils, 25400 },
                                                        {
                                                            UnitsValue.Nanometers,
                                                            0.000001
                                                        },
                                                        { UnitsValue.Undefined, 1.0 },
                                                        { UnitsValue.Yards, 914.4 }
                                                    };
        //_linkBetweenDrawingUnitsAndMilimeters.Add(UnitsValue.Parsecs, 30857000000000000000);
    }

    public double GetScaleRatio(UnitsValue sourceUnits, UnitsValue targetUnits)
    {
        if (sourceUnits == UnitsValue.Undefined || targetUnits == UnitsValue.Undefined
            || !_linkBetweenDrawingUnitsAndMilimeters.ContainsKey(sourceUnits)
            || !_linkBetweenDrawingUnitsAndMilimeters.ContainsKey(targetUnits))
        {
            return 1;
        }
        return _linkBetweenDrawingUnitsAndMilimeters[sourceUnits]
               / _linkBetweenDrawingUnitsAndMilimeters[targetUnits];
    }
}
}