AutoCAD C# 二次开发:玩转径向标注(RadialDimension)与防翻转实战
AutoCAD C# 二次开发:玩转径向标注(RadialDimension)与防翻转实战
在 AutoCAD 二次开发中,径向标注(RadialDimension) 是机械、建筑等图纸中经常需要处理的实体。很多初学者在尝试用代码修改径向标注的文字位置时,经常会遇到标注“莫名其妙折了过去”、“引线无限拉长”或者“文字翻转”的诡异现象。
本文将带你彻底理清 RadialDimension 的底层几何逻辑,分享高频常用属性、核心实战案例,并附带完整的属性速查表,帮你完美避坑!
一、 核心概念与常用属性
要搞懂径向标注,首先要明白 CAD 是如何定义它的。径向标注的核心是由圆心、圆弧上的标注点以及文字位置三者决定。
1. 关键几何属性
| 属性名 | 类型 | 说明 |
|---|---|---|
Center |
Point3d |
圆心/弧心坐标。对应 CAD 里的 10 组码。 |
ChordPoint |
Point3d |
弦点/标注点。即落在圆或圆弧边缘、引线箭头所指的那个点。对应 15 组码。 |
TextPosition |
Point3d |
文字位置。在径向标注中,它同时兼任了水平引线(Dog-leg)末端的控制点。对应 11 组码。 |
2. 控制与外观属性
LeaderLength(double):引线长度。Dimtmove(int):文字移动规则(非常关键)。0:文字随尺寸线移动。1:移动文字时,自动添加一条额外的引线(脱离原尺寸线)。2:移动文字时,不添加引线(文字孤立悬空)。
二、 经典实战:解决文字下移“折断翻转”的硬核案例
1. 痛点起因
在业务中,我们经常需要调整标注文字的位置(比如向下平移 60 个单位)以防文字重叠。
如果直接用 dim.TextPosition = new Point3d(oldX, oldY - 60, oldZ);,你会发现整个标注的引线彻底变形或反向折叠。
底层原因: CAD 的水平折线是靠 TextPosition.Y 去跟 Center 到 ChordPoint 的延长线求交点来计算的。你只改 Y 不改 X,交点就会发生横向暴走,导致引线计算出负值而翻转。
2. 解决方案:扩展方法封装
利用相似三角形定理,当 Y 轴发生偏移时,X 轴必须根据径向线的斜率同步进行补偿偏移,让新点依然保持在原有的径向射线方向上。
下面是将该算法封装为 RadialDimension 的扩展方法(Extension Method),您可以直接复制到项目中使用:
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using System;
namespace AutoCAD_CAD_Development
{
public static class RadialDimensionExtensions
{
/// <summary>
/// 智能平移径向标注的末尾引线和文字,完美保持标注原有几何形态
/// </summary>
/// <param name="dim">已以 ForWrite 模式打开的径向标注对象</param>
/// <param name="yOffset">Y轴垂直偏移量(负数向下,正数向上)</param>
public static void MoveTailVertically(this RadialDimension dim, double yOffset)
{
if (dim == null)
throw new ArgumentNullException(nameof(dim), "标注对象不能为空。");
// 1. 获取当前基础几何点
Point3d oldTextPos = dim.TextPosition;
Point3d center = dim.Center;
Point3d chordPoint = dim.ChordPoint;
// 2. 计算径向线的方向向量 (dx, dy)
double dx = chordPoint.X - center.X;
double dy = chordPoint.Y - center.Y;
Point3d newTextPos;
// 3. 规避分母为 0 的情况(即原始标注线接近绝对水平)
if (Math.Abs(dy) > 1e-6)
{
// 相似三角形原理:xOffset / yOffset = dx / dy
double xOffset = yOffset * (dx / dy);
newTextPos = new Point3d(
oldTextPos.X + xOffset,
oldTextPos.Y + yOffset,
oldTextPos.Z
);
}
else
{
// 如果是绝对水平的标注,单纯改变Y会导致CAD无法求交点
// 此时切换为“移动文字并自动生成独立引线”模式 (Dimtmove = 1)
dim.Dimtmove = 1;
newTextPos = new Point3d(
oldTextPos.X,
oldTextPos.Y + yOffset,
oldTextPos.Z
);
}
// 4. 应用计算后的新坐标
dim.TextPosition = newTextPos;
}
}
}
3. 主命令调用示例
在主命令中,直接用 dim.MoveTailVertically(-60); 即可优雅实现下移:
[CommandMethod("SmartMoveRadialDim")]
public void SmartMoveRadialDim()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
PromptEntityOptions peo = new PromptEntityOptions("\n请选择一个径向标注: ");
peo.SetRejectMessage("\n选择实体类型错误,请选择径向标注!");
peo.AddAllowedClass(typeof(RadialDimension), true);
PromptEntityResult per = ed.GetEntity(peo);
if (per.Status != PromptStatus.OK) return;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
try
{
var dim = tr.GetObject(per.ObjectId, OpenMode.ForWrite) as RadialDimension;
if (dim != null)
{
// 直接调用封装好的扩展方法,整体下移 60
dim.MoveTailVertically(-60.0);
tr.Commit();
ed.WriteMessage("\n✓ 标注引线及文字已成功平滑下移。");
}
}
catch (System.Exception ex)
{
tr.Abort();
ed.WriteMessage($"\n操作失败: {ex.Message}");
}
}
}
三、 RadialDimension 常用属性速查表
为了方便大家日常开发时查阅,这里整理了 RadialDimension 最常用的属性与说明表:
| 属性分类 | 属性名称 (Property) | 数据类型 (Type) | 权限 (Access) | 作用与功能说明 |
|---|---|---|---|---|
| 基础几何 | Center |
Point3d |
Read / Write | 对应圆或圆弧的圆心。 |
ChordPoint |
Point3d |
Read / Write | 引线箭头指向的弧面交点(弦点)。 | |
TextPosition |
Point3d |
Read / Write | 文字中心点(在有水平转折引线时,也作为引线终点)。 | |
| 外观样式 | DimensionStyle |
ObjectId |
Read / Write | 该标注绑定的标注样式(DimStyle)。 |
LeaderLength |
double |
Read / Write | 从弦点到文字折点的引线长度。 | |
Dimtmove |
int |
Read / Write | 文字移动规则:0固定, 1加引线, 2不加引线独立移动。 |
|
| 文本内容 | DimensionText |
string |
Read / Write | 自定义文本内容。默认为空字符串 ""(代表系统自动计算实际测量值)。如果要强制改字,直接赋新文本;若恢复自动测量值,改回 "" 或者是 "<>"。 |
TextRotation |
double |
Read / Write | 文字的旋转弧度(相对于当前 UCS)。 | |
| 通用系统 | Measurement |
double |
Read-Only | 标注的实际几何测量值(半径值,只读)。 |
Layer |
string |
Read / Write | 标注所在的图层名称。 |
开发小贴士:
任何时候修改RadialDimension的属性(例如TextPosition或Dimtmove),都要确保在事务(Transaction)中使用OpenMode.ForWrite打开该实体,否则会触发eNotOpenForWrite异常!
项目地址:
更多推荐



所有评论(0)