我正在尝试以编程方式将预先存在的绘图中的块插入到运行插件的当前绘图中。为此,我在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),我不知道它为什么没有
答案 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];
}
}
}