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;
}
自己一个一个链接字段表达式很麻烦,有编程手段就简单多了
标签:oid,AutoCAD,string,C#,编程,static,var,return,public From: https://www.cnblogs.com/NanShengBlogs/p/18147766