【发布时间】:2015-11-04 07:50:33
【问题描述】:
我正在尝试编写一种可以在 AutoCAD 中正确绘制块的方法。现在这是我所拥有的最好的:
public static BlockReference DrawBlock(string name, Point3d position, string layerToInsertOn, List<string> attributeValues = null, Distance xScale = null, Distance yScale = null, Distance zScale = null)
{
LastPositionPoint = position;
LastDirectionPoint = position;
//Creating default distances if null is passed for the scales
if (xScale == null)
{
xScale = new Distance(DistanceType.Inch, 1);
}
if (yScale == null)
{
yScale = new Distance(DistanceType.Inch, 1);
}
if (zScale == null)
{
zScale = new Distance(DistanceType.Inch, 1);
}
ObjectId blkRecId = _generateBlockRecordId(name); //Generating ID for the block
BlockReference blkRef = null; //Reference of the block that will be inserted
using (Transaction tr = _database.TransactionManager.StartTransaction()) //Starting the transaction to insert the block into the drawing
using (DocumentLock docLock = _activeDocument.LockDocument())
{
blkRef = new BlockReference(position, blkRecId); //Creating the block reference
blkRef.SetDatabaseDefaults();
blkRef.ScaleFactors = new Scale3d(xScale.Inches, yScale.Inches, zScale.Inches); //Changing the scales to what the programmer specifies
blkRef.Layer = layerToInsertOn; //Assigning layer to draw the block on
Point start = Point.MakePointWithInches(position.X, position.Y, position.Z);
Angle a = new Angle(AngleType.Radian, 0); //Angle to rotate the block by
BlockTableRecord blkTblRec = tr.GetObject(_database.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
blkTblRec.AppendEntity(blkRef); //Adding block referece to the block table of the drawing
tr.AddNewlyCreatedDBObject(blkRef, true); //Adding block to the drawing
//Assigning attributes of the block
BlockTableRecord btr = (BlockTableRecord)tr.GetObject(blkRef.BlockTableRecord, OpenMode.ForRead);
int attCounter = 0; //Counter to iterate through attributes
foreach (ObjectId objId in btr) //Checking each item in the BlockReference's records
{
DBObject obj = objId.GetObject(OpenMode.ForRead);
if (obj is AttributeDefinition) //If the object is an attribute, update it.
{
AttributeDefinition ad = obj as AttributeDefinition;
AttributeReference ar = new AttributeReference();
ar.SetAttributeFromBlock(ad, blkRef.BlockTransform);
ar.Position = ad.Position.TransformBy(blkRef.BlockTransform);
try
{
ar.TextString = attributeValues.ElementAt(attCounter);
}
catch (System.ArgumentOutOfRangeException)
{
ar.TextString = "";
}
catch (System.ArgumentNullException)
{
ar.TextString = "";
}
attCounter++;
blkRef.AttributeCollection.AppendAttribute(ar);
tr.AddNewlyCreatedDBObject(ar, true);
}
}
tr.Commit();
return blkRef;
}
}
/// <summary>
/// Method to generate a block record id for a block to be inserted
/// </summary>
private static ObjectId _generateBlockRecordId(string passedBlockName)
{
Transaction tr = _database.TransactionManager.StartTransaction();
DocumentLock docLock = _activeDocument.LockDocument();
using (tr)
using (docLock)
{
BlockTable blkTbl = tr.GetObject(_database.BlockTableId, OpenMode.ForRead) as BlockTable;
ObjectId blkRecId = ObjectId.Null;
if (blkTbl.Has(passedBlockName)) //Checking if the block exists
{
blkRecId = blkTbl[passedBlockName]; //If it does, getting the current id
}
else //If it doesn't exist create one
{
Database blkDb = new Database(false, true);
blkDb.ReadDwgFile(passedBlockName + ".dwg", System.IO.FileShare.Read, true, ""); //Reading block source file
_database.Insert(passedBlockName, blkDb, true);
blkRecId = blkTbl[passedBlockName];
}
return blkRecId;
}
}
有几个问题。
首先:假设我有一个代表一扇门的方块。块自然是一尺一尺。如果我想画一扇 3' 长的门,我会为 xScale 传入 3,以便它正确地代表一个 3' 的门。结果如下所示:
这是我想要的(蓝线代表门进入的墙)。但是,如果墙壁是垂直的,效果就不那么好了..
如何更改 DrawBlock 方法,以使墙是水平、垂直还是介于两者之间的任何位置都无关紧要?我知道我可以将长度作为垂直墙壁的 yScale 传递,但我需要一个更通用的倾斜墙壁解决方案。
另外,如果有人知道我如何消除对辅助方法的需求,那也很棒。谢谢!
【问题讨论】:
-
这很棘手,因为 AutoCAD 不将这些线条理解为“墙”,而只是一些线条。所以给你一个问题:这里的用户输入是什么?点击墙线?如果是这样,在点击的点,调用GetFirstDerivative(),也就是线的方向角度,然后旋转“门”块。
-
提示用户选择一个点来插入块,并用我的drawblock方法将它绘制在那里
-
这个点是否越过墙线?或者可以在任何地方?据我了解,没有墙线我们无法计算角度。
-
我将墙的前线作为变量存储在我的墙类中
-
嗨,您的代码中 BlockRef 集的旋转在哪里?我没有看到任何线路。 BlockReference 对象本身有一个属性旋转,它是一个 Double(以弧度为单位的角度),因此不需要转换...您可以考虑使用 Dinamyc 块(具有可变长度参数)然后您不必处理 Scales ...您也可以尝试Entityjig 放置块。
标签: c# autocad autocad-plugin