07-图元操作与几何处理教程
第七章:图元操作与几何处理教程
7.1 图元基础操作
7.1.1 创建基本图元
AutoCAD中的图元(Entity)是数据库中的图形对象。IFoxCAD简化了图元的创建和操作。
创建点
using var tr = new DBTrans();
// 创建点(DBPoint)
var point = new DBPoint(new Point3d(50, 50, 0));
point.Layer = "点图层";
tr.CurrentSpace.AddEntity(point);
创建直线
using var tr = new DBTrans();
// 创建直线
var line = new Line(
new Point3d(0, 0, 0), // 起点
new Point3d(100, 100, 0) // 终点
);
line.Color = Color.FromColorIndex(ColorMethod.ByAci, 1);
tr.CurrentSpace.AddEntity(line);
创建圆
using var tr = new DBTrans();
// 创建圆
var circle = new Circle(
new Point3d(50, 50, 0), // 圆心
Vector3d.ZAxis, // 法向量
25 // 半径
);
tr.CurrentSpace.AddEntity(circle);
创建圆弧
using var tr = new DBTrans();
// 通过圆心、半径和角度创建圆弧
var arc = new Arc(
new Point3d(50, 50, 0), // 圆心
25, // 半径
0, // 起始角度(弧度)
Math.PI // 终止角度(弧度)
);
tr.CurrentSpace.AddEntity(arc);
// 三点圆弧
Point3d pt1 = new Point3d(0, 0, 0);
Point3d pt2 = new Point3d(50, 50, 0);
Point3d pt3 = new Point3d(100, 0, 0);
var circArc = new CircularArc3d(pt1, pt2, pt3);
var arc2 = new Arc(
circArc.Center,
circArc.Normal,
circArc.Radius,
circArc.StartAngle,
circArc.EndAngle
);
tr.CurrentSpace.AddEntity(arc2);
创建椭圆
using var tr = new DBTrans();
// 创建椭圆
var ellipse = new Ellipse(
new Point3d(50, 50, 0), // 中心点
Vector3d.ZAxis, // 法向量
new Vector3d(50, 0, 0), // 主轴向量
0.5, // 长短轴比
0, // 起始角度
Math.PI * 2 // 终止角度
);
tr.CurrentSpace.AddEntity(ellipse);
7.1.2 创建多段线
轻量多段线(Polyline)
using var tr = new DBTrans();
// 创建矩形
var pline = new Polyline();
pline.AddVertexAt(0, new Point2d(0, 0), 0, 0, 0);
pline.AddVertexAt(1, new Point2d(100, 0), 0, 0, 0);
pline.AddVertexAt(2, new Point2d(100, 50), 0, 0, 0);
pline.AddVertexAt(3, new Point2d(0, 50), 0, 0, 0);
pline.Closed = true;
tr.CurrentSpace.AddEntity(pline);
带圆弧的多段线
using var tr = new DBTrans();
// 创建带圆角的矩形
var pline = new Polyline();
// 凸度(bulge)计算:bulge = tan(角度/4)
// 90度圆弧的凸度约为 0.414
double bulge = Math.Tan(Math.PI / 8); // 45度/4
pline.AddVertexAt(0, new Point2d(10, 0), 0, 0, 0);
pline.AddVertexAt(1, new Point2d(90, 0), bulge, 0, 0);
pline.AddVertexAt(2, new Point2d(100, 10), 0, 0, 0);
pline.AddVertexAt(3, new Point2d(100, 40), bulge, 0, 0);
pline.AddVertexAt(4, new Point2d(90, 50), 0, 0, 0);
pline.AddVertexAt(5, new Point2d(10, 50), bulge, 0, 0);
pline.AddVertexAt(6, new Point2d(0, 40), 0, 0, 0);
pline.AddVertexAt(7, new Point2d(0, 10), bulge, 0, 0);
pline.Closed = true;
tr.CurrentSpace.AddEntity(pline);
变宽度多段线
using var tr = new DBTrans();
// 创建箭头形状
var pline = new Polyline();
pline.AddVertexAt(0, new Point2d(0, 5), 0, 5, 5); // 尾部
pline.AddVertexAt(1, new Point2d(70, 5), 0, 5, 15); // 中段
pline.AddVertexAt(2, new Point2d(70, 15), 0, 15, 0); // 箭头底
pline.AddVertexAt(3, new Point2d(100, 0), 0, 0, 0); // 箭尖
tr.CurrentSpace.AddEntity(pline);
7.1.3 创建样条曲线
using var tr = new DBTrans();
// 通过控制点创建样条曲线
var points = new Point3dCollection
{
new Point3d(0, 0, 0),
new Point3d(25, 50, 0),
new Point3d(50, 0, 0),
new Point3d(75, 50, 0),
new Point3d(100, 0, 0)
};
var spline = new Spline(
points,
3, // 阶数
0 // 拟合公差
);
tr.CurrentSpace.AddEntity(spline);
7.1.4 创建填充
using var tr = new DBTrans();
// 创建边界多段线
var boundary = new Polyline();
boundary.AddVertexAt(0, new Point2d(0, 0), 0, 0, 0);
boundary.AddVertexAt(1, new Point2d(100, 0), 0, 0, 0);
boundary.AddVertexAt(2, new Point2d(100, 100), 0, 0, 0);
boundary.AddVertexAt(3, new Point2d(0, 100), 0, 0, 0);
boundary.Closed = true;
ObjectId boundaryId = tr.CurrentSpace.AddEntity(boundary);
// 创建填充
var hatch = new Hatch();
hatch.SetHatchPattern(HatchPatternType.PreDefined, "ANSI31");
hatch.Associative = true;
hatch.AppendLoop(HatchLoopTypes.Default, new ObjectIdCollection { boundaryId });
hatch.EvaluateHatch(true);
tr.CurrentSpace.AddEntity(hatch);
7.2 文字与标注
7.2.1 创建单行文字
using var tr = new DBTrans();
// 创建单行文字
var text = new DBText();
text.Position = new Point3d(0, 0, 0);
text.TextString = "Hello IFoxCAD";
text.Height = 5;
text.WidthFactor = 0.8;
text.Rotation = 0; // 弧度
tr.CurrentSpace.AddEntity(text);
// 居中对齐的文字
var centerText = new DBText();
centerText.TextString = "居中文字";
centerText.Height = 10;
centerText.HorizontalMode = TextHorizontalMode.TextCenter;
centerText.VerticalMode = TextVerticalMode.TextVerticalMid;
centerText.AlignmentPoint = new Point3d(50, 50, 0);
tr.CurrentSpace.AddEntity(centerText);
7.2.2 创建多行文字
using var tr = new DBTrans();
// 创建多行文字
var mtext = new MText();
mtext.Location = new Point3d(0, 100, 0);
mtext.TextHeight = 5;
mtext.Width = 100;
mtext.Contents = "这是多行文字\\P第二行\\P第三行";
mtext.Attachment = AttachmentPoint.TopLeft;
tr.CurrentSpace.AddEntity(mtext);
// 带格式的多行文字
var formattedMtext = new MText();
formattedMtext.Location = new Point3d(0, 50, 0);
formattedMtext.TextHeight = 5;
formattedMtext.Width = 200;
formattedMtext.Contents = @"{\C1;红色文字}\\P{\C3;绿色文字}\\P{\fSimHei|b1;粗体黑体}";
tr.CurrentSpace.AddEntity(formattedMtext);
7.2.3 创建标注
线性标注
using var tr = new DBTrans();
// 创建线性标注
var dim = new AlignedDimension(
new Point3d(0, 0, 0), // 第一点
new Point3d(100, 0, 0), // 第二点
new Point3d(50, 20, 0), // 标注线位置
"", // 标注文字(空表示自动)
tr.Database.DimStyleTableId
);
tr.CurrentSpace.AddEntity(dim);
// 水平标注
var hDim = new RotatedDimension(
0, // 旋转角度
new Point3d(0, 0, 0),
new Point3d(100, 50, 0),
new Point3d(50, 70, 0),
"",
tr.Database.DimStyleTableId
);
tr.CurrentSpace.AddEntity(hDim);
角度标注
using var tr = new DBTrans();
// 创建角度标注
var angDim = new Point3AngularDimension(
new Point3d(50, 50, 0), // 圆心/顶点
new Point3d(100, 50, 0), // 第一条线上的点
new Point3d(50, 100, 0), // 第二条线上的点
new Point3d(80, 80, 0), // 标注弧位置
"",
tr.Database.DimStyleTableId
);
tr.CurrentSpace.AddEntity(angDim);
半径和直径标注
using var tr = new DBTrans();
// 创建圆
var circle = new Circle(new Point3d(50, 50, 0), Vector3d.ZAxis, 30);
ObjectId circleId = tr.CurrentSpace.AddEntity(circle);
// 半径标注
var radDim = new RadialDimension(
new Point3d(50, 50, 0), // 圆心
new Point3d(80, 50, 0), // 圆上点
15, // 引线长度
"",
tr.Database.DimStyleTableId
);
tr.CurrentSpace.AddEntity(radDim);
// 直径标注
var diaDim = new DiametricDimension(
new Point3d(20, 50, 0), // 弦点1
new Point3d(80, 50, 0), // 弦点2
20, // 引线长度
"",
tr.Database.DimStyleTableId
);
tr.CurrentSpace.AddEntity(diaDim);
7.3 块操作
7.3.1 创建块定义
using var tr = new DBTrans();
// 创建块定义
tr.BlockTable.Add("MySymbol", btr =>
{
// 创建块内容
var circle = new Circle(Point3d.Origin, Vector3d.ZAxis, 10);
var line1 = new Line(new Point3d(-10, 0, 0), new Point3d(10, 0, 0));
var line2 = new Line(new Point3d(0, -10, 0), new Point3d(0, 10, 0));
// 添加图元到块定义
btr.AppendEntity(circle);
tr.Transaction.AddNewlyCreatedDBObject(circle, true);
btr.AppendEntity(line1);
tr.Transaction.AddNewlyCreatedDBObject(line1, true);
btr.AppendEntity(line2);
tr.Transaction.AddNewlyCreatedDBObject(line2, true);
});
tr.Editor?.WriteMessage("\n块定义创建完成!");
7.3.2 创建带属性的块
using var tr = new DBTrans();
// 创建带属性的块
tr.BlockTable.Add("LabelBlock", btr =>
{
// 创建块图形
var rect = new Polyline();
rect.AddVertexAt(0, new Point2d(-50, -10), 0, 0, 0);
rect.AddVertexAt(1, new Point2d(50, -10), 0, 0, 0);
rect.AddVertexAt(2, new Point2d(50, 10), 0, 0, 0);
rect.AddVertexAt(3, new Point2d(-50, 10), 0, 0, 0);
rect.Closed = true;
btr.AppendEntity(rect);
tr.Transaction.AddNewlyCreatedDBObject(rect, true);
// 创建属性定义
var attDef = new AttributeDefinition();
attDef.Position = new Point3d(0, 0, 0);
attDef.Tag = "NAME";
attDef.Prompt = "输入名称";
attDef.TextString = "默认名称";
attDef.Height = 5;
attDef.HorizontalMode = TextHorizontalMode.TextCenter;
attDef.VerticalMode = TextVerticalMode.TextVerticalMid;
attDef.AlignmentPoint = new Point3d(0, 0, 0);
btr.AppendEntity(attDef);
tr.Transaction.AddNewlyCreatedDBObject(attDef, true);
});
7.3.3 插入块参照
using var tr = new DBTrans();
// 插入简单块参照
ObjectId blockId = tr.BlockTable["MySymbol"];
if (!blockId.IsNull)
{
var blockRef = new BlockReference(new Point3d(100, 100, 0), blockId);
blockRef.ScaleFactors = new Scale3d(2, 2, 2);
blockRef.Rotation = Math.PI / 4; // 45度
tr.CurrentSpace.AddEntity(blockRef);
}
7.3.4 插入带属性的块参照
using var tr = new DBTrans();
ObjectId blockId = tr.BlockTable["LabelBlock"];
if (!blockId.IsNull)
{
// 创建块参照
var blockRef = new BlockReference(new Point3d(200, 100, 0), blockId);
ObjectId blockRefId = tr.CurrentSpace.AddEntity(blockRef);
// 获取块定义以添加属性
var btr = tr.BlockTable.GetRecord(blockId);
if (btr != null && btr.HasAttributeDefinitions)
{
foreach (ObjectId id in btr)
{
var attDef = tr.GetObject<AttributeDefinition>(id);
if (attDef != null && !attDef.Constant)
{
// 创建属性参照
var attRef = new AttributeReference();
attRef.SetAttributeFromBlock(attDef, blockRef.BlockTransform);
attRef.TextString = "设备名称"; // 设置属性值
using (blockRef.ForWrite())
{
blockRef.AttributeCollection.AppendAttribute(attRef);
}
tr.Transaction.AddNewlyCreatedDBObject(attRef, true);
}
}
}
}
7.3.5 修改块参照属性
using var tr = new DBTrans();
// 选择块参照
var filter = OpFilter.Build(e => e.Dxf(0) == "INSERT" & e.Dxf(2) == "LabelBlock");
var result = tr.Editor?.GetSelection(filter);
if (result?.Status == PromptStatus.OK)
{
foreach (SelectedObject obj in result.Value)
{
if (obj == null) continue;
var blockRef = tr.GetObject<BlockReference>(obj.ObjectId, OpenMode.ForWrite);
if (blockRef == null) continue;
// 遍历属性
foreach (ObjectId attId in blockRef.AttributeCollection)
{
var attRef = tr.GetObject<AttributeReference>(attId, OpenMode.ForWrite);
if (attRef != null && attRef.Tag == "NAME")
{
attRef.TextString = "新的名称";
}
}
}
}
7.4 图元变换
7.4.1 变换矩阵基础
变换矩阵是进行图元几何变换的核心工具。
// 平移矩阵
Matrix3d moveMatrix = Matrix3d.Displacement(new Vector3d(100, 50, 0));
// 旋转矩阵(绕Z轴)
Matrix3d rotateMatrix = Matrix3d.Rotation(
Math.PI / 4, // 角度(弧度)
Vector3d.ZAxis, // 旋转轴
Point3d.Origin // 旋转中心
);
// 缩放矩阵
Matrix3d scaleMatrix = Matrix3d.Scaling(
2.0, // 缩放比例
Point3d.Origin // 缩放中心
);
// 镜像矩阵
Matrix3d mirrorMatrix = Matrix3d.Mirroring(
new Line3d(Point3d.Origin, new Point3d(0, 100, 0))
);
// 组合变换
Matrix3d combinedMatrix = scaleMatrix * rotateMatrix * moveMatrix;
7.4.2 应用变换
using var tr = new DBTrans();
// 选择图元
var result = tr.Editor?.GetSelection();
if (result?.Status != PromptStatus.OK) return;
// 获取变换参数
var baseResult = tr.Editor?.GetPoint("\n指定基点:");
if (baseResult?.Status != PromptStatus.OK) return;
Point3d basePoint = baseResult.Value;
var targetResult = tr.Editor?.GetPoint("\n指定目标点:", basePoint);
if (targetResult?.Status != PromptStatus.OK) return;
Point3d targetPoint = targetResult.Value;
// 创建变换矩阵
Vector3d displacement = targetPoint - basePoint;
Matrix3d matrix = Matrix3d.Displacement(displacement);
// 应用变换
foreach (SelectedObject obj in result.Value)
{
if (obj == null) continue;
var ent = tr.GetObject<Entity>(obj.ObjectId, OpenMode.ForWrite);
if (ent != null)
{
ent.TransformBy(matrix);
}
}
tr.Editor?.WriteMessage($"\n已移动 {result.Value.Count} 个图元");
7.4.3 复制与变换
using var tr = new DBTrans();
// 选择图元
var result = tr.Editor?.GetEntity("\n选择要阵列的图元:");
if (result?.Status != PromptStatus.OK) return;
var ent = tr.GetObject<Entity>(result.ObjectId);
if (ent == null) return;
// 矩形阵列
int rows = 3;
int cols = 4;
double rowSpacing = 50;
double colSpacing = 80;
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
if (i == 0 && j == 0) continue; // 跳过原始位置
var clone = ent.Clone() as Entity;
if (clone != null)
{
Matrix3d matrix = Matrix3d.Displacement(
new Vector3d(j * colSpacing, i * rowSpacing, 0));
clone.TransformBy(matrix);
tr.CurrentSpace.AddEntity(clone);
}
}
}
tr.Editor?.WriteMessage($"\n已创建 {rows * cols - 1} 个副本");
7.4.4 环形阵列
using var tr = new DBTrans();
var result = tr.Editor?.GetEntity("\n选择要阵列的图元:");
if (result?.Status != PromptStatus.OK) return;
var ent = tr.GetObject<Entity>(result.ObjectId);
if (ent == null) return;
// 获取圆心
var centerResult = tr.Editor?.GetPoint("\n指定圆心:");
if (centerResult?.Status != PromptStatus.OK) return;
Point3d center = centerResult.Value;
// 阵列参数
int count = 8;
double totalAngle = Math.PI * 2; // 360度
double angleStep = totalAngle / count;
for (int i = 1; i < count; i++)
{
var clone = ent.Clone() as Entity;
if (clone != null)
{
Matrix3d matrix = Matrix3d.Rotation(
angleStep * i,
Vector3d.ZAxis,
center);
clone.TransformBy(matrix);
tr.CurrentSpace.AddEntity(clone);
}
}
tr.Editor?.WriteMessage($"\n已创建 {count - 1} 个副本");
7.5 几何计算
7.5.1 点与曲线
using var tr = new DBTrans();
// 创建曲线
var pline = new Polyline();
pline.AddVertexAt(0, new Point2d(0, 0), 0, 0, 0);
pline.AddVertexAt(1, new Point2d(100, 0), 0, 0, 0);
pline.AddVertexAt(2, new Point2d(100, 100), 0, 0, 0);
tr.CurrentSpace.AddEntity(pline);
// 曲线长度
double length = pline.Length;
tr.Editor?.WriteMessage($"\n曲线长度:{length:F2}");
// 获取曲线上的点
Point3d midPoint = pline.GetPointAtDist(length / 2);
tr.Editor?.WriteMessage($"\n中点:{midPoint}");
// 获取点到曲线的最近点
Point3d testPoint = new Point3d(50, 50, 0);
Point3d closestPoint = pline.GetClosestPointTo(testPoint, false);
tr.Editor?.WriteMessage($"\n最近点:{closestPoint}");
// 获取曲线上某点的切线方向
Vector3d tangent = pline.GetFirstDerivative(closestPoint);
tr.Editor?.WriteMessage($"\n切线方向:{tangent.GetNormal()}");
7.5.2 曲线求交
using var tr = new DBTrans();
// 创建两条曲线
var line1 = new Line(new Point3d(0, 0, 0), new Point3d(100, 100, 0));
var line2 = new Line(new Point3d(0, 100, 0), new Point3d(100, 0, 0));
tr.CurrentSpace.AddEntity(line1);
tr.CurrentSpace.AddEntity(line2);
// 计算交点
Point3dCollection intersections = new Point3dCollection();
line1.IntersectWith(line2, Intersect.OnBothOperands, intersections, IntPtr.Zero, IntPtr.Zero);
tr.Editor?.WriteMessage($"\n找到 {intersections.Count} 个交点");
foreach (Point3d pt in intersections)
{
tr.Editor?.WriteMessage($"\n 交点:{pt}");
// 在交点处创建标记
var point = new DBPoint(pt);
tr.CurrentSpace.AddEntity(point);
}
7.5.3 区域计算
using var tr = new DBTrans();
// 创建闭合多段线
var pline = new Polyline();
pline.AddVertexAt(0, new Point2d(0, 0), 0, 0, 0);
pline.AddVertexAt(1, new Point2d(100, 0), 0, 0, 0);
pline.AddVertexAt(2, new Point2d(100, 50), 0, 0, 0);
pline.AddVertexAt(3, new Point2d(0, 50), 0, 0, 0);
pline.Closed = true;
tr.CurrentSpace.AddEntity(pline);
// 计算面积
double area = pline.Area;
tr.Editor?.WriteMessage($"\n面积:{area:F2}");
// 使用区域计算更复杂的形状
DBObjectCollection curves = new DBObjectCollection { pline };
var regions = Region.CreateFromCurves(curves);
if (regions.Count > 0)
{
var region = regions[0] as Region;
if (region != null)
{
// 获取区域属性
var props = region.AreaProperties;
tr.Editor?.WriteMessage($"\n区域面积:{region.Area:F2}");
tr.Editor?.WriteMessage($"\n周长:{region.Perimeter:F2}");
}
}
7.5.4 边界计算
using var tr = new DBTrans();
// 选择多个图元
var result = tr.Editor?.GetSelection();
if (result?.Status != PromptStatus.OK) return;
// 计算边界框
Extents3d? totalExtents = null;
foreach (SelectedObject obj in result.Value)
{
if (obj == null) continue;
var ent = tr.GetObject<Entity>(obj.ObjectId);
if (ent == null) continue;
try
{
var entExtents = ent.GeometricExtents;
if (totalExtents == null)
{
totalExtents = entExtents;
}
else
{
totalExtents?.AddExtents(entExtents);
}
}
catch
{
// 某些图元可能没有几何范围
}
}
if (totalExtents != null)
{
tr.Editor?.WriteMessage($"\n边界框:");
tr.Editor?.WriteMessage($"\n 最小点:{totalExtents?.MinPoint}");
tr.Editor?.WriteMessage($"\n 最大点:{totalExtents?.MaxPoint}");
// 创建边界框多段线
var min = totalExtents!.Value.MinPoint;
var max = totalExtents!.Value.MaxPoint;
var boundingBox = new Polyline();
boundingBox.AddVertexAt(0, new Point2d(min.X, min.Y), 0, 0, 0);
boundingBox.AddVertexAt(1, new Point2d(max.X, min.Y), 0, 0, 0);
boundingBox.AddVertexAt(2, new Point2d(max.X, max.Y), 0, 0, 0);
boundingBox.AddVertexAt(3, new Point2d(min.X, max.Y), 0, 0, 0);
boundingBox.Closed = true;
boundingBox.Color = Color.FromColorIndex(ColorMethod.ByAci, 1);
tr.CurrentSpace.AddEntity(boundingBox);
}
7.6 本章小结
本章我们深入学习了图元操作与几何处理:
- 基本图元创建:掌握了点、线、圆、弧、椭圆等基本图元的创建
- 多段线操作:学习了创建各种类型的多段线,包括带圆弧和变宽度的
- 文字与标注:掌握了单行文字、多行文字和各种标注的创建
- 块操作:学习了块定义创建、块参照插入和属性操作
- 图元变换:掌握了变换矩阵的使用和各种变换操作
- 几何计算:学习了曲线计算、求交、区域计算和边界计算
这些是CAD二次开发中最常用的图元操作技术。下一章我们将通过实战案例来综合应用所学知识。

浙公网安备 33010602011771号