CAD获取外部参照内部图元
通过当前文件的块表记录递归获取图中所有所需的图元(如文字,直线等),如果当前文件的外部参照过多,通过本文件中外部参照的块表记录`BlockTableRecord`读取参照内部的图元速度极慢。这种情况下可以通过`XrefGraph`类获取所有的参照节点,通过`XrefGraph`获取每个外部参照中的图元,同时记录下每个外部参照的位置信息,最后将获取到的图元与外部参照对应,计算出正确的位置信息。代码如下,以获取文字为例。


public class Test
{
[CommandMethod("TextExtract")]
public void Start()
{
Document doc = AcadApp.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
List<EntityInfo> ebs = new List<EntityInfo>();
List<EntityInfo> texts = new List<EntityInfo>();
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = db.BlockTableId.GetObject(OpenMode.ForRead) as BlockTable;
BlockTableRecord btr = bt[BlockTableRecord.ModelSpace].GetObject(OpenMode.ForRead) as BlockTableRecord;
LayerTable lt = db.LayerTableId.GetObject(OpenMode.ForRead) as LayerTable;
GetXrefsInfo(tr, ebs, btr, Point3d.Origin, new Scale3d(1), 0);
tr.Abort();
}
#region 通过XrefGraph获取每个外部参照中的文字信息
XrefGraph xg = db.GetHostDwgXrefGraph(false);
for (int i = 0; i < xg.NumNodes; i++)
{
XrefGraphNode xNode = xg.GetXrefNode(i) as XrefGraphNode;
var temp = ebs.FirstOrDefault(x => x.XrefFullPath.ToLower() == xNode.Database.Filename.ToLower());
if (temp != null || xNode.Database.Filename.ToLower() == doc.Name.ToLower())
{
using (Transaction tr = xNode.Database.TransactionManager.StartTransaction())
{
BlockTable bt = xNode.Database.BlockTableId.GetObject(OpenMode.ForRead) as BlockTable;
BlockTableRecord btr = bt[BlockTableRecord.ModelSpace].GetObject(OpenMode.ForRead) as BlockTableRecord;
List<EntityInfo> texts_temp = new List<EntityInfo>();
GetTextsInfo(tr, texts_temp, btr, Point3d.Origin, new Scale3d(1), 0);
texts_temp.ForEach(p => p.XrefFullPath = xNode.Database.Filename);//获取的文字图元是属于哪个外部参照
texts.AddRange(texts_temp);
tr.Abort();
}
}
}
#endregion
List<Entity> result = new List<Entity>();
using (Transaction tr = db.TransactionManager.StartTransaction())
{
foreach (var item in texts)
{
var xrefs = ebs.Where(x => x.XrefFullPath.ToLower() == item.XrefFullPath.ToLower()).ToList();//使用where是同一文件可能参照了多次
if (xrefs.Count == 0)//不在参照中
{
Entity entClone = item.Entity.Clone() as Entity;
Vector3d vec = item.Position - Point3d.Origin;
Matrix3d matrix3D = Matrix3d.Displacement(vec);
entClone.TransformBy(matrix3D);
if (item.Rotation != 0)//块参照旋转
{
Matrix3d rmatrix = Matrix3d.Rotation(item.Rotation, Vector3d.ZAxis, item.Position);
entClone.TransformBy(rmatrix);
}
entClone.ColorIndex = 1;
result.Add(entClone);
}
else
{
foreach (var xref in xrefs)
{
Vector3d vec = TransPoint3d(item.Position, xref.Position, xref.Scale, xref.Rotation) - Point3d.Origin;
Matrix3d matrix3D = Matrix3d.Displacement(vec);
Entity entClone = item.Entity.Clone() as Entity;
entClone.TransformBy(matrix3D);
if (xref.Scale.X * item.Scale.X == -1)//外部参照X轴镜像
{
Point3d pte = xref.Position + new Vector3d(0, 1, 0);
Line3d templ = new Line3d(xref.Position, pte);
Matrix3d mmatrix = Matrix3d.Mirroring(templ);
entClone.TransformBy(mmatrix);
}
if (xref.Scale.Y * item.Scale.Y == -1)//外部参照Y轴镜像
{
Point3d pte = xref.Position + new Vector3d(100, 0, 0);
Line3d templ = new Line3d(xref.Position, pte);
Matrix3d mmatrix = Matrix3d.Mirroring(templ);
entClone.TransformBy(mmatrix);
}
if (xref.Rotation + item.Rotation != 0)//外部参照旋转
{
Matrix3d rmatrix = Matrix3d.Rotation(xref.Rotation + item.Rotation, Vector3d.ZAxis, TransPoint3d(item.Position, xref.Position, xref.Scale, xref.Rotation));
entClone.TransformBy(rmatrix);
}
entClone.ColorIndex = 1;
result.Add(entClone);
}
}
}
foreach (var item in result)
{
AddToModelSpace(db, item);
}
tr.Commit();
}
}
/// <summary>
/// 获取所有外部参照的位置,缩放,旋转信息
/// </summary>
/// <param name="trans"></param>
/// <param name="blocks"></param>
/// <param name="btr"></param>
/// <param name="position"></param>
/// <param name="scale"></param>
/// <param name="rotate"></param>
public void GetXrefsInfo(Transaction trans, List<EntityInfo> blocks, BlockTableRecord btr, Point3d position, Scale3d scale, double rotate)
{
foreach (var item in btr)
{
Entity ent = item.GetObject(OpenMode.ForRead) as Entity;
if (ent is BlockReference)
{
BlockReference block = ent as BlockReference;
if (block.BlockTableRecord != ObjectId.Null && block.Visible)//如果块隐藏了,就不取该块及其子参照信息
{
BlockTableRecord blockrecord = block.BlockTableRecord.GetObject(OpenMode.ForRead) as BlockTableRecord;
if (blockrecord.IsFromExternalReference || blockrecord.IsFromOverlayReference)
{
string temppath = blockrecord.PathName;
if (temppath.StartsWith(@".\"))
temppath = Path.GetFullPath(temppath);
EntityInfo eb = new EntityInfo()
{
Entity = block,
Position = TransPoint3d(block.Position, position, scale, rotate),//外部参照在当前文件中的实际位置
Scale = block.ScaleFactors * scale,//外部参照在当前文件中的实际缩放
Rotation = block.Rotation + rotate,//外部参照在当前文件中的实际旋转角度
XrefFullPath = temppath //外部参照的文件路径
};
blocks.Add(eb);
}
GetXrefsInfo(trans, blocks, blockrecord, TransPoint3d(block.Position, position, scale, rotate), block.ScaleFactors * scale, block.Rotation + rotate);
}
}
}
}
/// <summary>
/// 获取文字的信息
/// </summary>
/// <param name="trans"></param>
/// <param name="texts"></param>
/// <param name="btr"></param>
/// <param name="position"></param>
/// <param name="scale"></param>
/// <param name="rotate"></param>
public void GetTextsInfo(Transaction trans, List<EntityInfo> texts, BlockTableRecord btr, Point3d position, Scale3d scale, double rotate)
{
foreach (var item in btr)
{
Entity ent = item.GetObject(OpenMode.ForRead) as Entity;
if (ent is BlockReference)
{
BlockReference block = ent as BlockReference;
if (block.BlockTableRecord != ObjectId.Null)
{
BlockTableRecord blockrecord = block.BlockTableRecord.GetObject(OpenMode.ForRead) as BlockTableRecord;
if (!blockrecord.IsFromExternalReference && !blockrecord.IsFromOverlayReference && block.Visible)//非外部参照并且可见
{
GetTextsInfo(trans, texts, blockrecord, TransPoint3d(block.Position, position, scale, rotate), scale * block.ScaleFactors, rotate + block.Rotation);
}
}
}
else if (ent is DBText)
{
EntityInfo eb = new EntityInfo()
{
Entity = ent,
Position = position,//在块中的相对位置
Rotation = rotate,//在块中的旋转角度
Scale = scale //在块中的缩放比例
};
texts.Add(eb);
}
}
}
public Point3d TransPoint3d(Point3d before, Point3d origin, Scale3d scale, double rotation)
{
double X = origin.X + scale.X * before.X;
double Y = origin.Y + scale.Y * before.Y;
Point3d pt = new Point3d(X, Y, 0.0);
double angle = GetAngle(origin, pt) + rotation;
Point3d pt3d = Polar(origin, angle, pt.DistanceTo(origin));
return pt3d;
}
public double GetAngle(Point3d pt1, Point3d pt2)
{
//构建一个从第一点到第二点所确定的矢量
Vector2d vector = new Vector2d(pt2.X - pt1.X, pt2.Y - pt1.Y);
//返回该矢量和X轴正半轴的角度(弧度)
return vector.Angle;
}
public Point3d Polar(Point3d point, double angle, double dist)
{
return new Point3d(point.X + dist * Math.Cos(angle), point.Y + dist * Math.Sin(angle), point.Z);
}
public ObjectId AddToModelSpace(Database db, Entity ent)
{
ObjectId result;
using (Transaction transaction = db.TransactionManager.StartTransaction())
{
BlockTable blockTable = (BlockTable)transaction.GetObject(db.BlockTableId, 0);
BlockTableRecord blockTableRecord = (BlockTableRecord)transaction.GetObject(blockTable[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
result = blockTableRecord.AppendEntity(ent);
transaction.AddNewlyCreatedDBObject(ent, true);
transaction.Commit();
}
return result;
}
}
public class EntityInfo
{
public Entity Entity { get; set; }
public double Rotation { get; set; }
public Point3d Position { get; set; }
public Scale3d Scale { get; set; }
public string XrefFullPath { get; set; }
}

浙公网安备 33010602011771号