1. using Autodesk.AutoCAD.DatabaseServices;
  2. using Autodesk.AutoCAD.EditorInput;
  3. using Autodesk.AutoCAD.Geometry;
  4. using Autodesk.AutoCAD.Runtime;

  5. /// <summary>
  6. /// 带方向的多重引线绘制交互类
  7. /// 继承自EntityJig,用于通过用户交互动态创建带方向的多重引线(MLeader)
  8. /// 支持实时更新引线终点位置,并根据终点与起点的位置关系自动调整文字方向
  9. /// </summary>
  10. public class DirectionalLeaderJig : EntityJig
  11. {
  12.     #region 私有字段

  13.     /// <summary>
  14.     /// 引线的固定起点坐标(用户初始指定的起点)
  15.     /// </summary>
  16.     private readonly Point3d _start;

  17.     /// <summary>
  18.     /// 引线的实时终点坐标(用户鼠标移动/输入的动态终点)
  19.     /// </summary>
  20.     private Point3d _end;

  21.     /// <summary>
  22.     /// 多重引线中引线簇的索引(用于标识当前操作的引线簇)
  23.     /// </summary>
  24.     private int _index;

  25.     /// <summary>
  26.     /// 引线簇中线段的索引(用于标识当前操作的线段)
  27.     /// </summary>
  28.     private int _lineIndex;

  29.     /// <summary>
  30.     /// 绘制状态标记:true表示已开始绘制(引线已初始化),false表示未开始
  31.     /// 用于避免起点与终点过近时误创建引线
  32.     /// </summary>
  33.     private bool _started;

  34.     /// <summary>
  35.     /// 与引线关联的多行文字对象(存储引线的文字内容及格式)
  36.     /// </summary>
  37.     private readonly MText _mtext;

  38.     #endregion

  39.     #region 构造函数

  40.     /// <summary>
  41.     /// 初始化DirectionalLeaderJig实例
  42.     /// </summary>
  43.     /// <param name="start">引线的固定起点坐标</param>
  44.     /// <param name="ld">需要交互绘制的多重引线对象</param>
  45.     /// <param name="mtext">与引线关联的多行文字对象(包含文字内容和格式)</param>
  46.     public DirectionalLeaderJig(Point3d start, MLeader ld, MText mtext) : base(ld)
  47.     {
  48.         _start = start;          // 初始化起点(固定不变)
  49.         _end = start;            // 初始终点设为起点(避免初始位置异常)
  50.         _started = false;        // 初始标记为未开始绘制
  51.         _mtext = mtext;          // 关联多行文字对象
  52.     }

  53.     #endregion

  54.     #region 重写方法

  55.     /// <summary>
  56.     /// 输入采样处理:获取用户实时输入的引线终点坐标
  57.     /// 继承自EntityJig,用于处理用户交互输入
  58.     /// </summary>
  59.     /// <param name="prompts">交互提示对象,用于获取用户输入</param>
  60.     /// <returns>采样状态:NoChange(坐标未变)、OK(输入有效)、Cancel(用户取消)</returns>
  61.     protected override SamplerStatus Sampler(JigPrompts prompts)
  62.     {
  63.         // 创建点输入提示,指导用户操作
  64.         var pointOptions = new JigPromptPointOptions("\n指定引线终点或[右键取消]: ");
  65.         
  66.         // 配置输入规则:允许3D坐标输入,不接受空响应(避免误操作)
  67.         pointOptions.UserInputControls =
  68.             UserInputControls.Accept3dCoordinates |
  69.             UserInputControls.NoNegativeResponseAccepted;

  70.         // 获取用户输入的点
  71.         PromptPointResult inputResult = prompts.AcquirePoint(pointOptions);

  72.         // 若输入的终点与当前终点相同,返回无变化状态(避免无效更新)
  73.         if (_end == inputResult.Value)
  74.         {
  75.             return SamplerStatus.NoChange;
  76.         }
  77.         // 若用户输入有效,更新终点坐标并返回成功状态
  78.         else if (inputResult.Status == PromptStatus.OK)
  79.         {
  80.             _end = inputResult.Value;
  81.             return SamplerStatus.OK;
  82.         }
  83.         // 其他情况(如用户按ESC取消),返回取消状态
  84.         return SamplerStatus.Cancel;
  85.     }

  86.     /// <summary>
  87.     /// 更新引线几何图形:根据实时终点坐标动态调整引线形状和文字方向
  88.     /// 继承自EntityJig,在用户输入变化时触发
  89.     /// </summary>
  90.     /// <returns>是否更新成功(始终返回true,确保交互流畅)</returns>
  91.     protected override bool Update()
  92.     {
  93.         // 将当前操作的实体转换为多重引线对象(构造函数传入的是MLeader,转换安全)
  94.         MLeader leader = (MLeader)Entity;

  95.         // 首次初始化:当起点与终点距离超过容差时,创建引线基础结构
  96.         if (!_started)
  97.         {
  98.             // 检查起点与终点的距离是否超过全局点容差(避免点击过近时误创建)
  99.             if (_start.DistanceTo(_end) > Tolerance.Global.EqualPoint)
  100.             {
  101.                 // 配置引线内容:关联多行文字(而非块或其他类型)
  102.                 leader.ContentType = ContentType.MTextContent;
  103.                 leader.MText = _mtext;  // 绑定预设的多行文字对象

  104.                 // 创建引线簇和线段结构
  105.                 _index = leader.AddLeader();                  // 添加新的引线簇
  106.                 _lineIndex = leader.AddLeaderLine(_index);    // 在簇中添加线段

  107.                 // 设置线段的起点和初始终点
  108.                 leader.AddFirstVertex(_lineIndex, _start);    // 线段起点固定为初始起点
  109.                 leader.AddLastVertex(_lineIndex, _end);       // 线段终点设为当前输入终点

  110.                 _started = true;  // 标记为已开始绘制(后续进入更新逻辑)
  111.             }
  112.         }
  113.         // 后续更新:已创建引线后,实时调整终点位置
  114.         else
  115.         {
  116.             leader.Visible = true;  // 强制显示引线(避免初始化时的闪烁问题)
  117.             leader.SetLastVertex(_lineIndex, _end);  // 更新线段终点为最新输入坐标
  118.         }

  119.         // 调整文字方向:根据终点与起点的X坐标关系设置狗腿线方向
  120.         if (_started)
  121.         {
  122.             // 狗腿线方向向量:终点在起点右侧则向右(X正方向),左侧则向左(X负方向)
  123.             Vector3d doglegVector = new Vector3d(
  124.                 _end.X >= _start.X ? 1 : -1,  // X方向:右侧为正,左侧为负
  125.                 0, 0                          // Y、Z方向不变
  126.             );
  127.             leader.SetDogleg(_index, doglegVector);  // 应用狗腿线方向,确保文字朝向正确
  128.         }

  129.         return true;  // 确认更新成功
  130.     }

  131.     #endregion
  132. }
  1. using Autodesk.AutoCAD.ApplicationServices;
  2. using Autodesk.AutoCAD.DatabaseServices;
  3. using Autodesk.AutoCAD.EditorInput;
  4. using Autodesk.AutoCAD.Runtime;

  5. /// <summary>
  6. /// 方向性多重引线命令类
  7. /// 包含创建带方向的多重引线(MLeader)的核心命令逻辑
  8. /// 支持用户输入文字内容、指定起点,并通过动态拖动(Jig)实时调整引线终点
  9. /// </summary>
  10. public class DirectionalLeaderCommands
  11. {
  12.     /// <summary>
  13.     /// 创建方向性引线的命令入口(命令名:DL)
  14.     /// 执行流程:获取文字内容 → 获取起点 → 创建引线相关对象 → 启动动态拖动 → 提交数据库操作
  15.     /// </summary>
  16.     [CommandMethod("DL")]
  17.     public void DirectionalLeader()
  18.     {
  19.         // 获取当前活动文档及编辑器(用于用户交互)和数据库(用于对象存储)
  20.         Document doc = Application.DocumentManager.MdiActiveDocument;
  21.         Editor editor = doc.Editor;
  22.         Database db = doc.Database;

  23.         #region 步骤1:获取用户输入的文字内容
  24.         // 创建文字输入选项,允许包含空格(支持多单词内容)
  25.         PromptStringOptions textInputOptions = new PromptStringOptions("\n输入文字内容: ");
  26.         textInputOptions.AllowSpaces = true;

  27.         // 执行文字输入并检查结果
  28.         PromptResult textInputResult = editor.GetString(textInputOptions);
  29.         if (textInputResult.Status != PromptStatus.OK)
  30.         {
  31.             // 用户取消输入或输入失败,直接退出命令
  32.             editor.WriteMessage("\n文字内容输入取消或失败。");
  33.             return;
  34.         }
  35.         #endregion

  36.         #region 步骤2:获取用户指定的引线起点
  37.         // 提示用户指定引线起点
  38.         PromptPointResult startPointResult = editor.GetPoint("\n指定引线起点: ");
  39.         if (startPointResult.Status != PromptStatus.OK)
  40.         {
  41.             // 用户取消选择或选择失败,退出命令
  42.             editor.WriteMessage("\n引线起点选择取消或失败。");
  43.             return;
  44.         }
  45.         Point3d leaderStartPoint = startPointResult.Value; // 保存起点坐标
  46.         #endregion

  47.         #region 步骤3:数据库事务处理(创建并存储引线对象)
  48.         // 使用using语句自动管理事务生命周期(确保异常时自动回滚)
  49.         using (Transaction transaction = db.TransactionManager.StartTransaction())
  50.         {
  51.             try
  52.             {
  53.                 // 打开块表(只读,用于获取当前空间)
  54.                 BlockTable blockTable = (BlockTable)transaction.GetObject(
  55.                     db.BlockTableId,
  56.                     OpenMode.ForRead,
  57.                     false
  58.                 );

  59.                 // 打开当前空间块表记录(可写,用于添加新对象)
  60.                 BlockTableRecord currentSpace = (BlockTableRecord)transaction.GetObject(
  61.                     db.CurrentSpaceId,
  62.                     OpenMode.ForWrite,
  63.                     false
  64.                 );

  65.                 // 确保文字样式已创建并设置(调用外部文字处理逻辑)
  66.                 文字相关.CreateAndSetTextStyle();

  67.                 #region 创建多重引线样式及相关对象
  68.                 // 创建自定义多重引线样式(样式名:XPF_MLeader),返回样式ID
  69.                 ObjectId mLeaderStyleId = 多重引线相关.CreateMleaderStyle("XPF_MLeader");
  70.                 // 打开样式对象(只读,用于配置多行文字)
  71.                 MLeaderStyle mLeaderStyle = (MLeaderStyle)transaction.GetObject(
  72.                     mLeaderStyleId,
  73.                     OpenMode.ForRead
  74.                 );

  75.                 // 创建多重引线对象(初始不可见,避免拖动前闪烁)
  76.                 MLeader multiLeader = new MLeader();
  77.                 multiLeader.MLeaderStyle = mLeaderStyleId; // 应用自定义样式
  78.                 multiLeader.Visible = false; // 初始隐藏,拖动时再显示

  79.                 // 创建多行文字对象(MText):绑定样式、设置内容(带宽度因子0.8)和高度0.75
  80.                 MText leaderText = CreateMtext(
  81.                     mLeaderStyle,
  82.                     $"{{\\W0.8x{textInputResult.StringResult}}}", // 文字内容带宽度因子格式
  83.                     0.75 // 文字高度
  84.                 );
  85.                 #endregion

  86.                 #region 启动动态拖动(Jig)交互
  87.                 // 初始化Jig对象:传入起点、多重引线、多行文字
  88.                 DirectionalLeaderJig leaderJig = new DirectionalLeaderJig(
  89.                     leaderStartPoint,
  90.                     multiLeader,
  91.                     leaderText
  92.                 );

  93.                 // 将多重引线添加到当前空间并注册到事务(确保数据库跟踪)
  94.                 currentSpace.AppendEntity(multiLeader);
  95.                 transaction.AddNewlyCreatedDBObject(multiLeader, true);

  96.                 // 启动动态拖动:用户通过鼠标移动实时调整引线终点
  97.                 PromptResult dragResult = editor.Drag(leaderJig);
  98.                 #endregion

  99.                 #region 提交或回滚事务
  100.                 if (dragResult.Status == PromptStatus.OK)
  101.                 {
  102.                     // 拖动成功,提交事务(永久保存所有对象到数据库)
  103.                     transaction.Commit();
  104.                     editor.WriteMessage("\n方向性引线创建成功。");
  105.                 }
  106.                 else
  107.                 {
  108.                     // 拖动取消或失败,事务自动回滚(不保存任何对象)
  109.                     editor.WriteMessage("\n引线创建已取消。");
  110.                 }
  111.                 #endregion
  112.             }
  113.             catch (System.Exception ex)
  114.             {
  115.                 // 捕获异常并提示错误信息
  116.                 editor.WriteMessage($"\n命令执行出错:{ex.Message}");
  117.                 // 异常时事务自动回滚,无需手动处理
  118.             }
  119.         }
  120.         #endregion
  121.     }

  122.     /// <summary>
  123.     /// 创建并配置与多重引线关联的多行文字对象(MText)
  124.     /// </summary>
  125.     /// <param name="style">关联的多重引线样式(用于继承基础格式)</param>
  126.     /// <param name="content">文字内容(支持格式化代码,如宽度因子)</param>
  127.     /// <param name="height">文字高度</param>
  128.     /// <returns>配置完成的MText对象</returns>
  129.     private MText CreateMtext(MLeaderStyle style, string content, double height)
  130.     {
  131.         MText mtext = new MText();
  132.         mtext.Contents = content; // 设置文字内容(含格式)
  133.         mtext.Height = height;    // 设置文字高度
  134.         // 可根据需要添加更多格式配置(如颜色、字体等,可从style继承)
  135.         return mtext;
  136.     }
  137. }


  • 上一篇:开发图库功能
  • 下一篇:没有了