AutoCAD C# 在编程中使用字段表达式

CAD中有些文字需要随着图纸的当前条件的变化自动变化,例如保存日期、打印日期、打印比例等等。

CAD早期版本只是在扩展工具中提供了动态反应文字(rtext)功能,动态反应文字可以用CAD的Diesel表达式来定义动态文字,也可以动态链接文本文档,文本文档被编辑后,图纸中的文字会自动更新。

由于大多数设计人员对Diesel表达式不了解,因此这个功能会用的人不多,CAD高版本提供了字段(field)功能,这个功能预定义了一系列动态文字,设计人员只需在列表中选用即可,这样使用起来就简单多了。当然也支持高手们用Diesel表达式、LISP变量、系统变量来自定义动态文字。

下面在编程中利用字段表达式达到实时更新内容的效果,手工链接字段也是很费劲的

自己封装的类

 public static class FieldExprEx
 {
     const string exp1 = $"%<\\AcObjProp Object(%<\\_ObjId";//%<\AcObjProp Object(%<\_ObjId
     const string exp2 = ">%)";
     const string expRightEnd = ">%";
     const string expLeftStart = "%<";
     const string DieselExpStart = $"%<\\AcDiesel";
     const string curUnitLength = " \\f \"%lu6\"";
     const string UnitLengthStacked = " \\f \"%lu5\"";
     //%<\AcObjProp Object(%<\_ObjId 1747098246224>%).Area \f "%lu6%qf1">%
     const string curUnitArea = " \\f \"%lu6%qf1\"";
     const string AcExpr = "%<\\AcExpr ";
     /// <summary>
     /// 根据oid创建字段表达式
     /// </summary>
     /// <param name="oid"></param>
     /// <param name="propertyName"></param>
     /// <returns></returns>
     public static string CreateFieldExperssion(this ObjectId oid, string propertyName)
     {
         return $"{exp1} {oid.OldIdPtr.ToInt64()} {exp2}.{propertyName} {expRightEnd}";
     }

     /// <summary>
     /// 提取文字字段表达式
     /// </summary>
     /// <param name="oid"></param>
     /// <returns></returns>
     public static string CreateTextStringFieldExperssion(this ObjectId oid)
     {
         if (!oid.IsOk()) return string.Empty;
         if (!oid.ObjectClass.DxfName.Contains("TEXT")) return string.Empty;
         return $"{exp1} {oid.OldIdPtr.ToInt64()} {exp2}.TextString{expRightEnd}";
     }

     /// <summary>
     /// 提取长度字段表达式
     /// </summary>
     /// <param name="oid"></param>
     /// <param name="小数点位数"></param>
     /// <returns></returns>
     public static string CreateLengthFieldExperssion(this ObjectId oid)
     {
         var cur = RXClass.GetClass(typeof(Curve));
         var rxcls = oid.ObjectClass;
         if (!rxcls.IsDerivedFrom(cur)) return string.Empty;
         var dxfName = rxcls.DxfName.ToLower();
         var pro = "Length";
         //"Line,POLYLINE,LwPolyline,Arc,Circle"
         if (dxfName == "arc") pro = "ArcLength";
         if (dxfName == "circle") pro = "Circumference";
         if (dxfName == "region") pro = "Perimeter";
         return $"{exp1} {oid.OldIdPtr.ToInt64()} {exp2}.{pro} {curUnitLength} {expRightEnd}";
     }

     /// <summary>
     /// 提取半径字段表达式
     /// </summary>
     /// <param name="oid"></param>
     /// <returns></returns>
     public static string CreateRadiusFieldExperssion(this ObjectId oid)
     {
         var cur = RXClass.GetClass(typeof(Curve));
         var rxcls = oid.ObjectClass;
         if (!rxcls.IsDerivedFrom(cur)) return string.Empty;
         var dxfName = rxcls.DxfName.ToLower();
         //"Arc,Circle"
         if (dxfName != "arc" && dxfName != "circle") return string.Empty;
         var pro = "Radius";
         return $"{exp1} {oid.OldIdPtr.ToInt64()} {exp2}.{pro} {curUnitLength} {expRightEnd}";
     }

     /// <summary>
     /// 提取面积的字段表达式
     /// </summary>
     /// <param name="oid"></param>
     /// <param name="小数点位数"></param>
     /// <returns></returns>
     public static string CreateAreaStringFieldExperssion(this ObjectId oid)
     {
         var cur = RXClass.GetClass(typeof(Curve));
         var rxcls = oid.ObjectClass;
         if (!rxcls.IsDerivedFrom(cur)) return string.Empty;
         return $"{exp1} {oid.OldIdPtr.ToInt64()} {exp2}.Area {curUnitArea}{expRightEnd}";
     }

     public static string CreateSubStrDieselExperssion(string exper, int startIndex, int length)
     {
         return $"{DieselExpStart} $(Substr,{exper},{startIndex},{length}){expRightEnd}";
     }

     /// <summary>
     /// 字段表达式数值求和
     /// </summary>
     /// <param name="FieldExps">字段表达式集合</param>
     /// <param name="isArea">是否是面积</param>
     /// <returns></returns>
     public static string ToFieldsExpSum(this IEnumerable<string> FieldExps, bool isArea = false, bool isStacked = false)
     {
         return $"{AcExpr}({string.Join("+", FieldExps)}){(isArea ? curUnitArea : (isStacked ? UnitLengthStacked : curUnitLength))}{expRightEnd}";
     }
     /// <summary>
     /// 提取字段达式的oid
     /// </summary>
     /// <param name="db"></param>
     /// <param name="fieldexpr">字段表达式</param>
     /// <returns></returns>
     public static ObjectId GetObjectId(this Database db, string fieldexpr)
     {
         var oidStr = string.Empty;
         if (fieldexpr.Contains(exp1) && fieldexpr.Contains(exp2))
         {
             var index1 = fieldexpr.IndexOf(exp1) + exp1.Length;
             var index2 = fieldexpr.IndexOf(exp2);
             oidStr = fieldexpr.Substring(index1 + 1, index2 - index1 - 1);
             return oidStr.StrOid2ObjectId();
         }
         else
             return ObjectId.Null;
     }

     /// <summary>
     /// 提取动态块的动态属性的字段表达式
     /// </summary>
     /// <param name="oid">动态块参照的objectid</param>
     /// <param name="Parameter">序号</param>
     /// <param name="description">描述,长度:UpdatedDistance,用户字符串:UserVariable,块表:BlockPropertiesTable,查询,lookupString</param>
     /// <returns></returns>
     public static string GetDynamicBlkDynPropertyFieldExpStr(this ObjectId oid, int Parameter, string description = "UpdatedDistance")
     {
         if (!oid.IsOk()) return string.Empty;
         if (!oid.IsDynamicBlockref()) return string.Empty;
         //%<\AcObjProp Object(%<\_ObjId 2458306484880>%).Parameter(1038).UpdatedDistance \f "%lu6">%
         return $"{exp1} {oid.OldIdPtr.ToInt64()}" +
      $">%).Parameter({Parameter}).{description}{(description == "UpdatedDistance" ? curUnitLength : string.Empty)} {expRightEnd}";
     }

     /// <summary>
     /// id转句柄
     /// </summary>
     /// <param name="oid"></param>
     /// <returns></returns>
     public static string ObjectId2Handle(this ObjectId oid) => oid.Handle.ToString();


     /// <summary>
     /// id字符串转id
     /// </summary>
     /// <param name="strOid"></param>
     /// <returns></returns>
     public static ObjectId StrOid2ObjectId(this string strOid) => new ObjectId(new IntPtr(Convert.ToInt64(strOid)));

     /// <summary>
     /// id有效未被删除
     /// </summary>
     /// <param name="oid"></param>
     /// <returns></returns>
     public static bool IsOk(this ObjectId id) =>
         !id.IsNull && id.IsValid && !id.IsErased && !id.IsEffectivelyErased && id.IsResident;

     /// <summary>
     /// 判断为动态块
     /// </summary>
     /// <param name="oid"></param>
     /// <returns></returns>
     public static bool IsDynamicBlockref(this ObjectId oid)
     {
         bool rtn = false;
         if (oid.ObjectClass.IsDerivedFrom(RXClass.GetClass(typeof(BlockReference))))
         {
             var blkref = (BlockReference)oid.Open(OpenMode.ForRead);
             rtn = blkref.IsDynamicBlock;
             blkref.Cancel();
         }
         return rtn;
     }
 }
测试代码
[CommandMethod("myss4")]
  public static void 曲线长度字段表达式()
  {
      using var doclock = AcApp.DocumentManager.MdiActiveDocument.LockDocument();
      var msg = "\n select a curve:";
      var peo = new PromptEntityOptions(msg)
      {
          AllowNone = true,
          AllowObjectOnLockedLayer = false
      };
      var per = AcApp.DocumentManager.MdiActiveDocument.Editor.GetEntity(peo);
      if (per.Status != PromptStatus.OK) return;
      if (!per.ObjectId.ObjectClass.IsDerivedFrom(RXClass.GetClass(typeof(Curve))))return;
      var cur = (Curve)per.ObjectId.Open(Autodesk.AutoCAD.DatabaseServices.OpenMode.ForRead);
      var ang = cur.GetFirstDerivative(cur.StartPoint);
      var txt = new DBText()
      {
          TextString = FieldExprEx.CreateLengthFieldExperssion(per.ObjectId),
          Rotation = Math.Atan(ang.Y / ang.X),
          Height = 20,
          Position = cur.StartPoint
      };
      cur.Cancel();
      AcApp.DocumentManager.MdiActiveDocument.Database.AppendEntities(txt);
      Editor ed = AcApp.DocumentManager.MdiActiveDocument.Editor;
      ed.Regen();
  }

  [CommandMethod("myss5")]
  public static void 曲线长度汇总字段表达式()
  {
      using var doclock = AcApp.DocumentManager.MdiActiveDocument.LockDocument();
      var msg = "\n select a curve:";
      var peo = new PromptSelectionOptions()
      {
          MessageForAdding = msg,
          AllowDuplicates = false,
          RejectObjectsOnLockedLayers = true,
          RejectObjectsFromNonCurrentSpace = true,
      };
      var sf = new SelectionFilter(new TypedValue[]
      {
          new TypedValue(0,"Circle,*Line,Arc")
      });
      var per = AcApp.DocumentManager.MdiActiveDocument.Editor.GetSelection(peo, sf);
      if (per.Status != PromptStatus.OK) return;
      List<string> length = new List<string>();
      per.Value.GetObjectIds().ForEach(c => length.Add(c.CreateLengthFieldExperssion()));

      var ppr = AcApp.DocumentManager.MdiActiveDocument.Editor.GetPoint("\npick an point to put totalLength:");

      var txt = new DBText()
      {
          TextString = "totalLength: " + length.ToFieldsExpSum(),
          Height = 20,
          Position = ppr.Status == PromptStatus.OK ? ppr.Value : Point3d.Origin
      };
      AcApp.DocumentManager.MdiActiveDocument.Database.AppendEntities(txt);
      Editor ed = AcApp.DocumentManager.MdiActiveDocument.Editor;
      ed.Regen();
  }

 

将实体加入当前布局
public static ObjectIdCollection AppendEntities(this Database acdb, params Entity[] ents)
   {
       ObjectIdCollection oids = new ObjectIdCollection();
       var btr = (BlockTableRecord)acdb.CurrentSpaceId.Open(OpenMode.ForWrite);
       foreach (var item in ents)
       {
           if (item.IsNewObject)
           {
                   oids.Add(btr.AppendEntity(item));
               item.CloseAndPage(true);
           }    
       }
       btr.Close();
       return oids;
   }

自己一个一个链接字段表达式很麻烦,有编程手段就简单多了

posted @ 2024-04-20 15:36  南胜NanSheng  阅读(225)  评论(0编辑  收藏  举报