From 6b71b97a3092b52d6e7d32a935a38e9f80f61756 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Wed, 15 Feb 2023 00:28:20 +0800 Subject: [PATCH 001/453] =?UTF-8?q?dbtans=E7=B1=BB=E5=A2=9E=E5=8A=A0gettop?= =?UTF-8?q?transation=E5=87=BD=E6=95=B0=EF=BC=8C=E5=B9=B6=E5=B0=86?= =?UTF-8?q?=E6=89=80=E6=9C=89dbtans.top=E7=9A=84=E8=B0=83=E7=94=A8?= =?UTF-8?q?=E6=9B=BF=E6=8D=A2=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/DBDictionaryEx.cs | 38 +++++++------- .../Entity/BlockReferenceEx.cs | 18 +++---- .../ExtensionMethod/Entity/PolylineEx.cs | 12 ++--- .../ExtensionMethod/ObjectIdEx.cs | 13 +++-- .../ExtensionMethod/SelectionSetEx.cs | 10 ++-- .../ExtensionMethod/SymbolTableEx.cs | 2 +- .../ExtensionMethod/SymbolTableRecordEx.cs | 49 +++++++++---------- .../HatchConverter.cs" | 7 ++- src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs | 18 +++++++ src/CAD/IFox.CAD.Shared/Runtime/RedrawEx.cs | 11 ++--- ...53\345\205\205\344\272\213\344\273\266.cs" | 9 ++-- 11 files changed, 98 insertions(+), 89 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBDictionaryEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBDictionaryEx.cs index e099a93..e5bd8e3 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBDictionaryEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBDictionaryEx.cs @@ -13,12 +13,12 @@ public static class DBDictionaryEx /// 事务 /// 对象迭代器 [System.Diagnostics.DebuggerStepThrough] - public static IEnumerable GetAllObjects(this DBDictionary dict, DBTrans? trans = null) where T : DBObject + public static IEnumerable GetAllObjects(this DBDictionary dict) where T : DBObject { - trans ??= DBTrans.Top; + var tr = DBTrans.GetTopTransaction(dict.Database); foreach (DBDictionaryEntry e in dict) { - var ent = trans.GetObject(e.Value); + var ent = tr.GetObject(e.Value, OpenMode.ForRead) as T; if (ent is not null) yield return ent; } @@ -32,14 +32,14 @@ public static IEnumerable GetAllObjects(this DBDictionary dict, DBTrans? t /// 事务 /// 指定的键值 /// T 类型的对象 - public static T? GetAt(this DBDictionary dict, string key, DBTrans? trans = null) where T : DBObject + public static T? GetAt(this DBDictionary dict, string key) where T : DBObject { - trans ??= DBTrans.Top; + var tr = DBTrans.GetTopTransaction(dict.Database); if (dict.Contains(key)) { ObjectId id = dict.GetAt(key); if (!id.IsNull) - return trans.GetObject(id); + return tr.GetObject(id, OpenMode.ForRead) as T; } return null; } @@ -52,13 +52,14 @@ public static IEnumerable GetAllObjects(this DBDictionary dict, DBTrans? t /// 事务 /// 键 /// 值 - public static void SetAt(this DBDictionary dict, string key, T newValue, Transaction? trans = null) where T : DBObject + public static void SetAt(this DBDictionary dict, string key, T newValue) where T : DBObject { - trans ??= DBTrans.Top.Transaction; + var tr = DBTrans.GetTopTransaction(dict.Database); + using (dict.ForWrite()) { dict.SetAt(key, newValue); - trans.AddNewlyCreatedDBObject(newValue, true); + tr.AddNewlyCreatedDBObject(newValue, true); } } @@ -101,7 +102,8 @@ public static void SetXRecord(this DBDictionary dict, string key, XRecordDataLis /// 扩展字典对象 public static DBDictionary? GetXDictionary(this DBObject obj, DBTrans? trans = null) { - trans ??= DBTrans.Top; + var tr = DBTrans.GetTopTransaction(obj.Database); + ObjectId id = obj.ExtensionDictionary; if (id.IsNull) { @@ -110,7 +112,7 @@ public static void SetXRecord(this DBDictionary dict, string key, XRecordDataLis id = obj.ExtensionDictionary; } - return id.GetObject(trans: trans); + return id.GetObject(); } #region 数据表 @@ -214,11 +216,10 @@ public static void SetValue(this DataCell cell, CellType type, object value) /// 字典 public static DBDictionary? GetSubDictionary(this DBDictionary dict, bool createSubDictionary, - IEnumerable dictNames, - DBTrans? trans = null) + IEnumerable dictNames) { DBDictionary? newdict = null; - trans ??= DBTrans.Top; + if (createSubDictionary) { using (dict.ForWrite()) @@ -228,12 +229,12 @@ public static void SetValue(this DataCell cell, CellType type, object value) { if (dict.Contains(name)) { - newdict = dict.GetAt(name, trans); + newdict = dict.GetAt(name); } else { DBDictionary subDict = new(); - dict.SetAt(name, subDict, trans); + dict.SetAt(name, subDict); newdict = subDict; newdict.TreatElementsAsHard = true; } @@ -244,7 +245,7 @@ public static void SetValue(this DataCell cell, CellType type, object value) foreach (string name in dictNames) { if (dict.Contains(name)) - newdict = dict.GetAt(name, trans); + newdict = dict.GetAt(name); else return null; } @@ -285,7 +286,8 @@ public static ObjectId AddGroup(this DBDictionary dict, string name, ObjectIdCol Group g = new(); g.Append(ids); dict.SetAt(name, g); - DBTrans.Top.Transaction.AddNewlyCreatedDBObject(g, true); + var tr = DBTrans.GetTopTransaction(dict.Database); + tr.AddNewlyCreatedDBObject(g, true); return g.ObjectId; } } diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs index 203bc54..65cf35e 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs @@ -93,13 +93,13 @@ public static void ChangeBlockProperty(this BlockReference blockReference, /// /// [System.Diagnostics.DebuggerStepThrough] - public static void ForEach(this BlockReference brf, Action action, DBTrans? tr = null) + public static void ForEach(this BlockReference brf, Action action) { //if (action == null) // throw new ArgumentNullException(nameof(action)); action.NotNull(nameof(action)); - tr ??= DBTrans.Top; - var btr = tr.GetObject(brf.BlockTableRecord); + var tr = DBTrans.GetTopTransaction(brf.Database); + var btr = tr.GetObject(brf.BlockTableRecord, OpenMode.ForRead) as BlockTableRecord; if (btr == null) return; btr.ForEach(action); @@ -112,13 +112,13 @@ public static void ForEach(this BlockReference brf, Action action, DBT /// /// [System.Diagnostics.DebuggerStepThrough] - public static void ForEach(this BlockReference brf, Action action, DBTrans? tr = null) + public static void ForEach(this BlockReference brf, Action action) { //if (action == null) // throw new ArgumentNullException(nameof(action)); action.NotNull(nameof(action)); - tr ??= DBTrans.Top; - var btr = tr.GetObject(brf.BlockTableRecord); + var tr = DBTrans.GetTopTransaction(brf.Database); + var btr = tr.GetObject(brf.BlockTableRecord, OpenMode.ForRead) as BlockTableRecord; if (btr == null) return; btr.ForEach(action); @@ -131,11 +131,11 @@ public static void ForEach(this BlockReference brf, Action /// /// [System.Diagnostics.DebuggerStepThrough] - public static void ForEach(this BlockReference brf, Action action, DBTrans? tr = null) + public static void ForEach(this BlockReference brf, Action action) { action.NotNull(nameof(action)); - tr ??= DBTrans.Top; - var btr = tr.GetObject(brf.BlockTableRecord); + var tr = DBTrans.GetTopTransaction(brf.Database); + var btr = tr.GetObject(brf.BlockTableRecord, OpenMode.ForRead) as BlockTableRecord; if (btr == null) return; btr.ForEach(action); diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/PolylineEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/PolylineEx.cs index 02681b4..b0a91ca 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/PolylineEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/PolylineEx.cs @@ -11,12 +11,12 @@ public static class PolylineEx /// 二维多段线 /// 事务 /// 端点坐标集合 - public static IEnumerable GetPoints(this Polyline2d pl2d, DBTrans? trans = null) + public static IEnumerable GetPoints(this Polyline2d pl2d) { - trans ??= DBTrans.Top; + var tr = DBTrans.GetTopTransaction(pl2d.Database); foreach (ObjectId id in pl2d) { - var vertex = trans.GetObject(id); + var vertex = tr.GetObject(id, OpenMode.ForRead) as Vertex2d; if (vertex != null) yield return vertex.Position; } @@ -29,12 +29,12 @@ public static IEnumerable GetPoints(this Polyline2d pl2d, DBTrans? tran /// 三维多段线 /// 事务 /// 端点坐标集合 - public static IEnumerable GetPoints(this Polyline3d pl3d, DBTrans? trans = null) + public static IEnumerable GetPoints(this Polyline3d pl3d) { - trans ??= DBTrans.Top; + var tr = DBTrans.GetTopTransaction(pl3d.Database); foreach (ObjectId id in pl3d) { - var vertex = trans.GetObject(id); + var vertex = tr.GetObject(id, OpenMode.ForRead) as PolylineVertex3d; if (vertex != null) yield return vertex.Position; } diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs index a329da5..aba6375 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs @@ -1,4 +1,6 @@ -namespace IFoxCAD.Cad; +using System.Data.Common; + +namespace IFoxCAD.Cad; /// /// 对象id扩展类 @@ -18,12 +20,11 @@ public static class ObjectIdEx /// 指定类型对象 public static T? GetObject(this ObjectId id, OpenMode openMode = OpenMode.ForRead, - Transaction? trans = null, bool openErased = false, bool openLockedLayer = false) where T : DBObject { - trans ??= DBTrans.Top.Transaction; - return trans.GetObject(id, openMode, openErased, openLockedLayer) as T; + var tr = DBTrans.GetTopTransaction(id.Database); + return tr.GetObject(id, openMode, openErased, openLockedLayer) as T; } /// @@ -39,12 +40,10 @@ public static class ObjectIdEx [System.Diagnostics.DebuggerStepThrough] public static IEnumerable GetObject(this IEnumerable ids, OpenMode openMode = OpenMode.ForRead, - Transaction? trans = null, bool openErased = false, bool openLockedLayer = false) where T : DBObject { - trans ??= DBTrans.Top.Transaction; - return ids.Select(id => id.GetObject(openMode, trans, openErased, openLockedLayer)); + return ids.Select(id => id.GetObject(openMode, openErased, openLockedLayer)); } /// diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SelectionSetEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SelectionSetEx.cs index 2223554..d8aed4c 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SelectionSetEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SelectionSetEx.cs @@ -77,16 +77,14 @@ public static IEnumerable> GetObjectIdGroup(this Sel [System.Diagnostics.DebuggerStepThrough] public static IEnumerable GetEntities(this SelectionSet ss, OpenMode openMode = OpenMode.ForRead, - DBTrans? trans = null, bool openErased = false, bool openLockedLayer = false) where T : Entity { //if (ss is null) // throw new ArgumentNullException(nameof(ss)); ss.NotNull(nameof(ss)); - trans ??= DBTrans.Top; return ss.GetObjectIds() - .Select(id => trans.GetObject(id, openMode, openErased, openLockedLayer)) + .Select(id => id.GetObject(openMode, openErased, openLockedLayer)) .Where(ent => ent != null) .OfType(); } @@ -113,7 +111,7 @@ public static void ForEach(this SelectionSet ss, { ForEach(ss, (ent, state) => { action.Invoke(ent); - }, openMode, tr, openErased, openLockedLayer); + }, openMode, openErased, openLockedLayer); } /// @@ -131,15 +129,13 @@ public static void ForEach(this SelectionSet ss, public static void ForEach(this SelectionSet ss, Action action, OpenMode openMode = OpenMode.ForRead, - DBTrans? trans = null, bool openErased = false, bool openLockedLayer = false) where T : Entity { action.NotNull(nameof(action)); - trans ??= DBTrans.Top; LoopState state = new(); - var ents = ss.GetEntities(openMode, trans, openErased, openLockedLayer); + var ents = ss.GetEntities(openMode, openErased, openLockedLayer); foreach (var ent in ents) { action.Invoke(ent, state); diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableEx.cs index 4c13159..fc811de 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableEx.cs @@ -54,7 +54,7 @@ public static ObjectId Rename(this SymbolTable tab /// 成功返回 ,失败返回 public static bool Delete(this SymbolTable table, string name) { - if (name == "0" || name == "Defpoints" || !table.Has(name) || table[name] == DBTrans.Top.Database.Clayer) + if (name == "0" || name == "Defpoints" || !table.Has(name) || table[name] == table.Database.Clayer) return false; table.CurrentSymbolTable.GenerateUsageData(); diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs index 1bd99a8..9e72794 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs @@ -71,18 +71,17 @@ public static void DeepCloneEx(this BlockTableRecord btr, ObjectIdCollection obj /// 实体 /// 事务管理器 /// 对象 id - public static ObjectId AddEntity(this BlockTableRecord btr, Entity entity, - Transaction? trans = null) + public static ObjectId AddEntity(this BlockTableRecord btr, Entity entity) { // if (entity is null) // throw new ArgumentNullException(nameof(entity), "对象为 null"); ObjectId id; - trans ??= DBTrans.Top.Transaction; + var tr = DBTrans.GetTopTransaction(btr.Database); using (btr.ForWrite()) { id = btr.AppendEntity(entity); - trans.AddNewlyCreatedDBObject(entity, true); + tr.AddNewlyCreatedDBObject(entity, true); } return id; } @@ -95,18 +94,17 @@ public static ObjectId AddEntity(this BlockTableRecord btr, Entity entity, /// 实体集合 /// 事务 /// 对象 id 列表 - public static IEnumerable AddEntity(this BlockTableRecord btr, IEnumerable ents, - Transaction? trans = null) where T : Entity + public static IEnumerable AddEntity(this BlockTableRecord btr, IEnumerable ents) where T : Entity { // if (ents.Any(ent => ent is null)) // throw new ArgumentNullException(nameof(ents), "实体集合内存在 null 对象"); - trans ??= DBTrans.Top.Transaction; + var tr = DBTrans.GetTopTransaction(btr.Database); using (btr.ForWrite()) { return ents.Select(ent => { ObjectId id = btr.AppendEntity(ent); - trans.AddNewlyCreatedDBObject(ent, true); + tr.AddNewlyCreatedDBObject(ent, true); return id; }).ToList(); } @@ -120,7 +118,7 @@ public static IEnumerable AddEntity(this BlockTableRecord btr, IEnu /// 对象 id 列表 public static IEnumerable AddEntity(this BlockTableRecord btr, params Entity[] ents) { - return btr.AddEntity(ents, null); + return btr.AddEntity(ents); } #endregion @@ -135,10 +133,10 @@ public static IEnumerable AddEntity(this BlockTableRecord btr, params /// 事务管理器 /// 图元id private static ObjectId AddEnt(this BlockTableRecord btr, T ent, - Action? action, Transaction? trans = null) where T : Entity + Action? action) where T : Entity { action?.Invoke(ent); - return btr.AddEntity(ent, trans); + return btr.AddEntity(ent); } /// /// 委托式的添加图元 @@ -153,7 +151,7 @@ public static ObjectId AddEnt(this BlockTableRecord btr, Func action, Tr if (ent is null) return ObjectId.Null; - return btr.AddEntity(ent, trans); + return btr.AddEntity(ent); } /// @@ -166,10 +164,10 @@ public static ObjectId AddEnt(this BlockTableRecord btr, Func action, Tr /// 直线属性设置委托 /// 直线的id public static ObjectId AddLine(this BlockTableRecord btr, Point3d start, Point3d end, - Action? action = null, Transaction? trans = null) + Action? action = null) { var line = new Line(start, end); - return btr.AddEnt(line, action, trans); + return btr.AddEnt(line, action); } /// /// 在指定绘图空间X-Y平面添加圆 @@ -184,7 +182,7 @@ public static ObjectId AddCircle(this BlockTableRecord btr, Point3d center, doub Action? action = null, Transaction? trans = null) { var circle = new Circle(center, Vector3d.ZAxis, radius); - return btr.AddEnt(circle, action, trans); + return btr.AddEnt(circle, action); } /// @@ -198,14 +196,14 @@ public static ObjectId AddCircle(this BlockTableRecord btr, Point3d center, doub /// 事务管理器 /// 三点有外接圆则返回圆的id,否则返回ObjectId.Null public static ObjectId AddCircle(this BlockTableRecord btr, Point3d p0, Point3d p1, Point3d p2, - Action? action = null, Transaction? trans = null) + Action? action = null) { var circle = CircleEx.CreateCircle(p0, p1, p2); // return circle is not null ? btr.AddEnt(circle, action, trans) : throw new ArgumentNullException(nameof(circle), "对象为 null"); //if (circle is null) // throw new ArgumentNullException(nameof(circle), "对象为 null"); circle.NotNull(nameof(circle)); - return btr.AddEnt(circle, action, trans); + return btr.AddEnt(circle, action); } /// /// 在指定的绘图空间添加轻多段线 @@ -236,7 +234,7 @@ public static ObjectId AddPline(this BlockTableRecord btr, pl.AddVertexAt(i, bvws[i].Vertex, bvws[i].Bulge, bvws[i].StartWidth, bvws[i].EndWidth); } pl.Closed = isClosed;// 闭合 - return btr.AddEnt(pl, action, trans); + return btr.AddEnt(pl, action); } /// /// 在指定的绘图空间添加轻多段线 @@ -266,7 +264,7 @@ public static ObjectId AddPline(this BlockTableRecord btr, for (int i = 0; i < pts.Count; i++) pl.AddVertexAt(i, pts[i].Point2d(), bulges[i], startWidths[i], endWidths[i]); - return btr.AddEnt(pl, action, trans); + return btr.AddEnt(pl, action); } /// @@ -289,7 +287,7 @@ public static ObjectId AddPline(this BlockTableRecord btr, pl.AddVertexAt(index, vertex.pt.Point2d(), vertex.bulge, vertex.startWidth, vertex.endWidth); }); - return btr.AddEnt(pl, action, trans); + return btr.AddEnt(pl, action); } /// @@ -307,7 +305,7 @@ public static ObjectId AddArc(this BlockTableRecord btr, Action? action = null, Transaction? trans = null) { var arc = ArcEx.CreateArc(startPoint, pointOnArc, endPoint); - return btr.AddEnt(arc, action, trans); + return btr.AddEnt(arc, action); } #endregion @@ -325,15 +323,13 @@ public static ObjectId AddArc(this BlockTableRecord btr, /// 实体集合 public static IEnumerable GetEntities(this BlockTableRecord btr, OpenMode openMode = OpenMode.ForRead, - Transaction? trans = null, bool openErased = false, bool openLockedLayer = false) where T : Entity { - trans ??= DBTrans.Top.Transaction; return btr .Cast() - .Select(id => trans.GetObject(id, openMode, openErased, openLockedLayer)) + .Select(id => id.GetObject(openMode, openErased, openLockedLayer)) .OfType(); } @@ -375,9 +371,8 @@ public static IEnumerable> GetObjectIds(this BlockTa bool openErased = false, bool openLockedLayer = false) { - trans ??= DBTrans.Top.Transaction; - return trans.GetObject(btr.DrawOrderTableId, OpenMode.ForRead, - openErased, openLockedLayer) as DrawOrderTable; + var tr = DBTrans.GetTopTransaction(btr.Database); + return tr.GetObject(btr.DrawOrderTableId, OpenMode.ForRead, openErased, openLockedLayer) as DrawOrderTable; } #endregion diff --git "a/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchConverter.cs" "b/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchConverter.cs" index 9f549df..b1d56ff 100644 --- "a/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchConverter.cs" +++ "b/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchConverter.cs" @@ -321,8 +321,7 @@ public void CreateBoundary(List outEnts) /// 新填充id,边界在获取 public ObjectId CreateBoundarysAndHatchToMsPs(BlockTableRecord btrOfAddEntitySpace, bool boundaryAssociative = true, - bool createHatchFlag = true, - Transaction? trans = null) + bool createHatchFlag = true) { List boEnts = new(); CreateBoundary(boEnts); @@ -345,11 +344,11 @@ public ObjectId CreateBoundarysAndHatchToMsPs(BlockTableRecord btrOfAddEntitySpa using IdMapping map = new(); btrOfAddEntitySpace.DeepCloneEx(idc, map); var newHatchId = map.GetValues()[0]; - trans ??= DBTrans.Top.Transaction; + var tr = DBTrans.GetTopTransaction(btrOfAddEntitySpace.Database); bool openErased = false; bool openLockedLayer = false; - var hatchEnt = trans.GetObject(newHatchId, OpenMode.ForWrite, + var hatchEnt = tr.GetObject(newHatchId, OpenMode.ForWrite, openErased, openLockedLayer) as Hatch; if (hatchEnt != null) { diff --git a/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs b/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs index 1bd5c74..3dcb5d9 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs @@ -17,6 +17,21 @@ public class DBTrans : IDisposable [DebuggerBrowsable(DebuggerBrowsableState.Never)] string DebuggerDisplay => ToString(" | "); + #region 静态函数 + /// + /// 获取顶层事务 + /// + /// 数据库 + /// 事务对象 + public static Transaction GetTopTransaction(Database database) + { + database.NotNull(nameof(database)); + var trans = database.TransactionManager.TopTransaction; + trans.NotNull(nameof(trans)); + return trans; + } + #endregion + #region 私有字段 /// /// 事务栈 @@ -70,6 +85,9 @@ public static DBTrans Top return trans; } } + + + /// /// 文档 /// diff --git a/src/CAD/IFox.CAD.Shared/Runtime/RedrawEx.cs b/src/CAD/IFox.CAD.Shared/Runtime/RedrawEx.cs index 3799eed..a24bcaf 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/RedrawEx.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/RedrawEx.cs @@ -172,12 +172,12 @@ public static void Redraw(this Entity ent, BrightEntity bright) /// /// 实体对象 [Obsolete("此处已经被RedrawEx代替")] - public static void Flush(this Entity entity, DBTrans? trans = null) + public static void Flush(this Entity entity) { - trans ??= DBTrans.Top; + var tr = DBTrans.GetTopTransaction(entity.Database); entity.RecordGraphicsModified(true); - trans.Transaction.TransactionManager.QueueForGraphicsFlush(); - trans.Document?.TransactionManager.FlushGraphics(); + tr.TransactionManager.QueueForGraphicsFlush(); + } /// @@ -185,7 +185,6 @@ public static void Flush(this Entity entity, DBTrans? trans = null) /// /// 实体id [Obsolete("此处已经被RedrawEx代替")] - public static void Flush(this ObjectId id) - => Flush(DBTrans.Top.GetObject(id)!); + public static void Flush(this ObjectId id) => Flush(id.GetObject()!); #endregion } \ No newline at end of file diff --git "a/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/02.\346\213\211\344\274\270\345\241\253\345\205\205\344\272\213\344\273\266.cs" "b/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/02.\346\213\211\344\274\270\345\241\253\345\205\205\344\272\213\344\273\266.cs" index f08eea8..5d41635 100644 --- "a/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/02.\346\213\211\344\274\270\345\241\253\345\205\205\344\272\213\344\273\266.cs" +++ "b/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/02.\346\213\211\344\274\270\345\241\253\345\205\205\344\272\213\344\273\266.cs" @@ -498,10 +498,10 @@ void Md_ImpliedSelectionChanged(object sender, EventArgs e) /// /// /// - void CreatHatchConverter(Hatch hatch, HashSet outSsgetIds, DBTrans? tr = null) + void CreatHatchConverter(Hatch hatch, HashSet outSsgetIds) { - tr ??= DBTrans.Top; - + //tr ??= DBTrans.Top; + var tr = DBTrans.GetTopTransaction(hatch.Database); var hc = new HatchConverter(hatch); ObjectId newid; @@ -523,7 +523,8 @@ void CreatHatchConverter(Hatch hatch, HashSet outSsgetIds, DBTrans? tr // 创建新填充和边界 hc.GetBoundarysData(); - newid = hc.CreateBoundarysAndHatchToMsPs(tr.CurrentSpace, trans: tr); + + newid = hc.CreateBoundarysAndHatchToMsPs((BlockTableRecord)tr.GetObject(hatch.Database.CurrentSpaceId,OpenMode.ForWrite)); HatchPickEnv.SetMeXData(newid, hc.BoundaryIds); // 清理上次,删除边界和填充 -- Gitee From a4ef9d1188eb1c1c5161e8616d17cfe8a9ab99e7 Mon Sep 17 00:00:00 2001 From: vicwjb <403009819@qq.com> Date: Wed, 15 Mar 2023 13:24:41 +0800 Subject: [PATCH 002/453] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/TestShared/TestBlock.cs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/tests/TestShared/TestBlock.cs b/tests/TestShared/TestBlock.cs index 75403c3..20761a6 100644 --- a/tests/TestShared/TestBlock.cs +++ b/tests/TestShared/TestBlock.cs @@ -27,7 +27,7 @@ public void Test_Refedit() public void Test_GetBoundingBoxEx() { using DBTrans tr = new(); - var ents = Env.Editor.SSGet()?.Value?.GetEntities(); + var ents = Env.Editor.SSGet().Value?.GetEntities(); if (ents == null) return; foreach (var item in ents) @@ -50,9 +50,7 @@ public void Test_BlockDef() btr.Origin = new Point3d(0, 0, 0); }, () => // 图元 - { - return new List { new Line(new Point3d(0, 0, 0), new Point3d(1, 1, 0)) }; - }, + new List { new Line(new Point3d(0, 0, 0), new Point3d(1, 1, 0)) }, () => // 属性定义 { var id1 = new AttributeDefinition() { Position = new Point3d(0, 0, 0), Tag = "start", Height = 0.2 }; @@ -137,13 +135,16 @@ public void Test_BlockDefChange() var ent = tr.GetObject(id); using (ent!.ForWrite()) { - if (ent is Dimension dBText) + switch (ent) { - dBText.DimensionText = "234"; - dBText.RecomputeDimensionBlock(true); + case Dimension dBText: + dBText.DimensionText = "234"; + dBText.RecomputeDimensionBlock(true); + break; + case Hatch hatch: + hatch.ColorIndex = 0; + break; } - if (ent is Hatch hatch) - hatch.ColorIndex = 0; } } }); -- Gitee From f44091c6d77f90d735c7f708777aab6650ee16bf Mon Sep 17 00:00:00 2001 From: vicwjb Date: Fri, 17 Feb 2023 00:01:08 +0800 Subject: [PATCH 003/453] =?UTF-8?q?=E4=BC=98=E5=8C=96GetTopTransaction?= =?UTF-8?q?=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/DBDictionaryEx.cs | 8 ++--- .../Entity/BlockReferenceEx.cs | 6 ++-- .../ExtensionMethod/Entity/PolylineEx.cs | 4 +-- .../ExtensionMethod/ObjectIdEx.cs | 2 +- .../ExtensionMethod/SymbolTableRecordEx.cs | 35 ++++++++++--------- .../HatchConverter.cs" | 3 +- src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs | 13 +++++-- src/CAD/IFox.CAD.Shared/Runtime/RedrawEx.cs | 4 +-- ...53\345\205\205\344\272\213\344\273\266.cs" | 2 +- tests/TestShared/TestBlock.cs | 26 +++++++++++++- 10 files changed, 69 insertions(+), 34 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBDictionaryEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBDictionaryEx.cs index e5bd8e3..3942b6c 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBDictionaryEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBDictionaryEx.cs @@ -18,7 +18,7 @@ public static IEnumerable GetAllObjects(this DBDictionary dict) where T : var tr = DBTrans.GetTopTransaction(dict.Database); foreach (DBDictionaryEntry e in dict) { - var ent = tr.GetObject(e.Value, OpenMode.ForRead) as T; + var ent = tr.GetObject(e.Value, OpenMode.ForRead); if (ent is not null) yield return ent; } @@ -39,7 +39,7 @@ public static IEnumerable GetAllObjects(this DBDictionary dict) where T : { ObjectId id = dict.GetAt(key); if (!id.IsNull) - return tr.GetObject(id, OpenMode.ForRead) as T; + return tr.GetObject(id); } return null; } @@ -59,7 +59,7 @@ public static void SetAt(this DBDictionary dict, string key, T newValue) wher using (dict.ForWrite()) { dict.SetAt(key, newValue); - tr.AddNewlyCreatedDBObject(newValue, true); + tr.Transaction.AddNewlyCreatedDBObject(newValue, true); } } @@ -287,7 +287,7 @@ public static ObjectId AddGroup(this DBDictionary dict, string name, ObjectIdCol g.Append(ids); dict.SetAt(name, g); var tr = DBTrans.GetTopTransaction(dict.Database); - tr.AddNewlyCreatedDBObject(g, true); + tr.Transaction.AddNewlyCreatedDBObject(g, true); return g.ObjectId; } } diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs index 65cf35e..218697b 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs @@ -99,7 +99,7 @@ public static void ForEach(this BlockReference brf, Action action) // throw new ArgumentNullException(nameof(action)); action.NotNull(nameof(action)); var tr = DBTrans.GetTopTransaction(brf.Database); - var btr = tr.GetObject(brf.BlockTableRecord, OpenMode.ForRead) as BlockTableRecord; + var btr = tr.GetObject(brf.BlockTableRecord); if (btr == null) return; btr.ForEach(action); @@ -118,7 +118,7 @@ public static void ForEach(this BlockReference brf, Action // throw new ArgumentNullException(nameof(action)); action.NotNull(nameof(action)); var tr = DBTrans.GetTopTransaction(brf.Database); - var btr = tr.GetObject(brf.BlockTableRecord, OpenMode.ForRead) as BlockTableRecord; + var btr = tr.GetObject(brf.BlockTableRecord); if (btr == null) return; btr.ForEach(action); @@ -135,7 +135,7 @@ public static void ForEach(this BlockReference brf, Action(brf.BlockTableRecord); if (btr == null) return; btr.ForEach(action); diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/PolylineEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/PolylineEx.cs index b0a91ca..41aa787 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/PolylineEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/PolylineEx.cs @@ -16,7 +16,7 @@ public static IEnumerable GetPoints(this Polyline2d pl2d) var tr = DBTrans.GetTopTransaction(pl2d.Database); foreach (ObjectId id in pl2d) { - var vertex = tr.GetObject(id, OpenMode.ForRead) as Vertex2d; + var vertex = tr.GetObject(id, OpenMode.ForRead); if (vertex != null) yield return vertex.Position; } @@ -34,7 +34,7 @@ public static IEnumerable GetPoints(this Polyline3d pl3d) var tr = DBTrans.GetTopTransaction(pl3d.Database); foreach (ObjectId id in pl3d) { - var vertex = tr.GetObject(id, OpenMode.ForRead) as PolylineVertex3d; + var vertex = tr.GetObject(id); if (vertex != null) yield return vertex.Position; } diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs index aba6375..63050c3 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs @@ -24,7 +24,7 @@ public static class ObjectIdEx bool openLockedLayer = false) where T : DBObject { var tr = DBTrans.GetTopTransaction(id.Database); - return tr.GetObject(id, openMode, openErased, openLockedLayer) as T; + return tr.GetObject(id, openMode, openErased, openLockedLayer); } /// diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs index 9e72794..26281a9 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs @@ -81,8 +81,9 @@ public static ObjectId AddEntity(this BlockTableRecord btr, Entity entity) using (btr.ForWrite()) { id = btr.AppendEntity(entity); - tr.AddNewlyCreatedDBObject(entity, true); + tr.Transaction.AddNewlyCreatedDBObject(entity, true); } + return id; } @@ -104,7 +105,7 @@ public static IEnumerable AddEntity(this BlockTableRecord btr, IEnu { return ents.Select(ent => { ObjectId id = btr.AppendEntity(ent); - tr.AddNewlyCreatedDBObject(ent, true); + tr.Transaction.AddNewlyCreatedDBObject(ent, true); return id; }).ToList(); } @@ -372,7 +373,7 @@ public static IEnumerable> GetObjectIds(this BlockTa bool openLockedLayer = false) { var tr = DBTrans.GetTopTransaction(btr.Database); - return tr.GetObject(btr.DrawOrderTableId, OpenMode.ForRead, openErased, openLockedLayer) as DrawOrderTable; + return tr.GetObject(btr.DrawOrderTableId, OpenMode.ForRead, openErased, openLockedLayer); } #endregion @@ -392,16 +393,15 @@ public static ObjectId InsertBlock(this BlockTableRecord blockTableRecord, Point string blockName, Scale3d scale = default, double rotation = default, - Dictionary? atts = null, - Transaction? trans = null) + Dictionary? atts = null) { - trans ??= DBTrans.Top.Transaction; - if (!DBTrans.Top.BlockTable.Has(blockName)) + var tr = DBTrans.GetTopTransaction(blockTableRecord.Database); + if (!tr.BlockTable.Has(blockName)) { - DBTrans.Top.Editor?.WriteMessage($"\n不存在名字为{blockName}的块定义。"); + tr.Editor?.WriteMessage($"\n不存在名字为{blockName}的块定义。"); return ObjectId.Null; } - return blockTableRecord.InsertBlock(position, DBTrans.Top.BlockTable[blockName], scale, rotation, atts, trans); + return blockTableRecord.InsertBlock(position, tr.BlockTable[blockName], scale, rotation, atts); } /// /// 插入块参照 @@ -417,15 +417,18 @@ public static ObjectId InsertBlock(this BlockTableRecord blockTableRecord, ObjectId blockId, Scale3d scale = default, double rotation = default, - Dictionary? atts = null, - Transaction? trans = null) + Dictionary? atts = null) { - trans ??= DBTrans.Top.Transaction; - if (!DBTrans.Top.BlockTable.Has(blockId)) + //trans ??= DBTrans.Top.Transaction; + var tr = DBTrans.GetTopTransaction(blockTableRecord.Database); + + if (!tr.BlockTable.Has(blockId)) { - DBTrans.Top.Editor?.WriteMessage($"\n不存在块定义。"); + tr.Editor?.WriteMessage($"\n不存在块定义。"); return ObjectId.Null; } + + using var blockref = new BlockReference(position, blockId) { ScaleFactors = scale, @@ -435,7 +438,7 @@ public static ObjectId InsertBlock(this BlockTableRecord blockTableRecord, if (atts != null) { - var btr = DBTrans.Top.GetObject(blockref.BlockTableRecord)!; + var btr = tr.GetObject(blockref.BlockTableRecord)!; if (btr.HasAttributeDefinitions) { var attdefs = btr.GetEntities(); @@ -451,7 +454,7 @@ public static ObjectId InsertBlock(this BlockTableRecord blockTableRecord, attref.TextString = atts[attdef.Tag]; blockref.AttributeCollection.AppendAttribute(attref); - trans.AddNewlyCreatedDBObject(attref, true); + tr.Transaction.AddNewlyCreatedDBObject(attref, true); } } } diff --git "a/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchConverter.cs" "b/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchConverter.cs" index b1d56ff..34a1604 100644 --- "a/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchConverter.cs" +++ "b/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchConverter.cs" @@ -348,8 +348,7 @@ public ObjectId CreateBoundarysAndHatchToMsPs(BlockTableRecord btrOfAddEntitySpa bool openErased = false; bool openLockedLayer = false; - var hatchEnt = tr.GetObject(newHatchId, OpenMode.ForWrite, - openErased, openLockedLayer) as Hatch; + var hatchEnt = tr.GetObject(newHatchId, OpenMode.ForWrite, openErased, openLockedLayer); if (hatchEnt != null) { ResetBoundary(hatchEnt, boundaryAssociative); diff --git a/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs b/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs index 3dcb5d9..e760b1d 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs @@ -23,12 +23,21 @@ public class DBTrans : IDisposable /// /// 数据库 /// 事务对象 - public static Transaction GetTopTransaction(Database database) + public static DBTrans GetTopTransaction(Database database) { database.NotNull(nameof(database)); var trans = database.TransactionManager.TopTransaction; trans.NotNull(nameof(trans)); - return trans; + + foreach (var item in _dBTrans) + { + if (item.Transaction.UnmanagedObject == trans.UnmanagedObject) + { + return item; + } + } // 匹配事务栈内dbtrans的transaction的指针与数据库的顶层事务的指针 + + return Top; } #endregion diff --git a/src/CAD/IFox.CAD.Shared/Runtime/RedrawEx.cs b/src/CAD/IFox.CAD.Shared/Runtime/RedrawEx.cs index a24bcaf..b0cb47b 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/RedrawEx.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/RedrawEx.cs @@ -176,8 +176,8 @@ public static void Flush(this Entity entity) { var tr = DBTrans.GetTopTransaction(entity.Database); entity.RecordGraphicsModified(true); - tr.TransactionManager.QueueForGraphicsFlush(); - + tr.Transaction.TransactionManager.QueueForGraphicsFlush(); + tr.Document?.TransactionManager.FlushGraphics(); } /// diff --git "a/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/02.\346\213\211\344\274\270\345\241\253\345\205\205\344\272\213\344\273\266.cs" "b/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/02.\346\213\211\344\274\270\345\241\253\345\205\205\344\272\213\344\273\266.cs" index 5d41635..b4535b1 100644 --- "a/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/02.\346\213\211\344\274\270\345\241\253\345\205\205\344\272\213\344\273\266.cs" +++ "b/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/02.\346\213\211\344\274\270\345\241\253\345\205\205\344\272\213\344\273\266.cs" @@ -524,7 +524,7 @@ void CreatHatchConverter(Hatch hatch, HashSet outSsgetIds) // 创建新填充和边界 hc.GetBoundarysData(); - newid = hc.CreateBoundarysAndHatchToMsPs((BlockTableRecord)tr.GetObject(hatch.Database.CurrentSpaceId,OpenMode.ForWrite)); + newid = hc.CreateBoundarysAndHatchToMsPs(tr.CurrentSpace); HatchPickEnv.SetMeXData(newid, hc.BoundaryIds); // 清理上次,删除边界和填充 diff --git a/tests/TestShared/TestBlock.cs b/tests/TestShared/TestBlock.cs index 20761a6..9459304 100644 --- a/tests/TestShared/TestBlock.cs +++ b/tests/TestShared/TestBlock.cs @@ -1,4 +1,7 @@ -namespace Test; +using IFoxCAD.Cad; +using System.Data.Common; + +namespace Test; public class TestBlock { @@ -195,6 +198,27 @@ public void Test_InsertBlockDef() tr.CurrentSpace.InsertBlock(new Point3d(10, 10, 0), "test2", atts: def2); tr.CurrentSpace.InsertBlock(new Point3d(-10, 0, 0), "test44"); } + [CommandMethod(nameof(Test_InsertBlockWithDoubleDatabase))] + public void Test_InsertBlockWithDoubleDatabase() + { + using var tr = new DBTrans(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "test.dwg")); + using var trans = new DBTrans(); + + tr.BlockTable.Add("test456", + btr => { + btr.Origin = new(0, 0, 0); + }, + () => { + var line = new Line(new(0, 0, 0), new(1, 1, 0)); + var actext = new TextInfo("123", Point3d.Origin, AttachmentPoint.BaseLeft, database: tr.Database).AddDBTextToEntity(); + return new List { line,actext }; + + }); + tr.CurrentSpace.InsertBlock(Point3d.Origin, "test456"); + tr.SaveDwgFile(); + } + + [CommandMethod(nameof(Test_AddAttsDef))] public void Test_AddAttsDef() -- Gitee From 57a474a3616ed5f7abe583a9035939c07e2e7595 Mon Sep 17 00:00:00 2001 From: utopio Date: Thu, 9 Mar 2023 10:40:56 +0000 Subject: [PATCH 004/453] =?UTF-8?q?update=20src/CAD/IFox.CAD.Shared/Extens?= =?UTF-8?q?ionMethod/EditorEx.cs.=20=E4=BF=AE=E6=94=B9RunLisp=E6=B3=A8?= =?UTF-8?q?=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: utopio --- src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs index d432bf3..9a00d99 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs @@ -1,4 +1,4 @@ -using IFoxCAD.Com; +using IFoxCAD.Com; namespace IFoxCAD.Cad; @@ -1067,7 +1067,7 @@ public enum RunLispFlag : byte if ((flag & RunLispFlag.AdsQueueexpr) == RunLispFlag.AdsQueueexpr) { // 这个在08/12发送lisp不会出错,但是发送bo命令出错了. - // 0x01 设置 CommandFlags.Session 可以同步, + // 0x01 设置RunLispFlag特性为RunLispFlag.AcedEvaluateLisp即可同步执行 // 0x02 自执行发送lisp都是异步,用来发送 含有(command)的lisp的 _ = Ads_queueexpr(lispCode + "\n"); } -- Gitee From 3b6c46ce00f8b446674e5dffe284e3db2ebe1aa9 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Thu, 9 Mar 2023 21:48:59 +0800 Subject: [PATCH 005/453] =?UTF-8?q?=E6=9B=BF=E6=8D=A2=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E4=B8=AD=E7=9A=84dbtrans.top?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs | 2 +- tests/TestShared/TestAddEntity.cs | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs index 26281a9..5a9cdf7 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs @@ -448,7 +448,7 @@ public static ObjectId InsertBlock(this BlockTableRecord blockTableRecord, attref.SetDatabaseDefaults(); attref.SetAttributeFromBlock(attdef, blockref.BlockTransform); attref.Position = attdef.Position.TransformBy(blockref.BlockTransform); - attref.AdjustAlignment(DBTrans.Top.Database); + attref.AdjustAlignment(tr.Database); if (atts.ContainsKey(attdef.Tag)) attref.TextString = atts[attdef.Tag]; diff --git a/tests/TestShared/TestAddEntity.cs b/tests/TestShared/TestAddEntity.cs index 9b1dcd8..3db0db8 100644 --- a/tests/TestShared/TestAddEntity.cs +++ b/tests/TestShared/TestAddEntity.cs @@ -41,11 +41,11 @@ public void Test_DBTrans() public void Test_Addent() { using DBTrans tr = new(); - Line line = new(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); + Line line = new(new(0, 0, 0), new(1, 1, 0)); tr.CurrentSpace.AddEntity(line); - Line line1 = new(new Point3d(10, 10, 0), new Point3d(41, 1, 0)); + Line line1 = new(new(10, 10, 0), new(41, 1, 0)); tr.ModelSpace.AddEntity(line1); - Line line2 = new(new Point3d(-10, 10, 0), new Point3d(41, 1, 0)); + Line line2 = new(new(-10, 10, 0), new(41, 1, 0)); tr.PaperSpace.AddEntity(line2); } @@ -58,6 +58,7 @@ public void Test_Drawarc() Arc arc3 = ArcEx.CreateArc(new Point3d(1, 0, 0), new Point3d(0, 0, 0), new Point3d(0, 1, 0)); // 起点,圆上一点,终点 tr.CurrentSpace.AddEntity(arc1, arc2, arc3); tr.CurrentSpace.AddArc(new Point3d(0, 0, 0), new Point3d(1, 1, 0), new Point3d(2, 0, 0));// 起点,圆上一点,终点 + } [CommandMethod(nameof(Test_DrawCircle))] -- Gitee From 348c4655e61d5b532e287e3f1673fd33f11cef7a Mon Sep 17 00:00:00 2001 From: vicwjb Date: Thu, 9 Mar 2023 21:59:16 +0800 Subject: [PATCH 006/453] =?UTF-8?q?=E6=B8=85=E7=90=86=E6=97=A0=E7=94=A8?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.ACAD/GlobalUsings.cs | 1 + src/CAD/IFox.CAD.GCAD/GlobalUsings.cs | 1 + .../ExtensionMethod/EditorEx.cs | 2 - .../IFox.CAD.Shared/IFox.CAD.Shared.projitems | 1 - src/CAD/IFox.CAD.Shared/Runtime/AOP.cs | 99 ------------------- src/CAD/IFox.CAD.ZCAD/GlobalUsings.cs | 1 + 6 files changed, 3 insertions(+), 102 deletions(-) delete mode 100644 src/CAD/IFox.CAD.Shared/Runtime/AOP.cs diff --git a/src/CAD/IFox.CAD.ACAD/GlobalUsings.cs b/src/CAD/IFox.CAD.ACAD/GlobalUsings.cs index dadfe53..51a43ac 100644 --- a/src/CAD/IFox.CAD.ACAD/GlobalUsings.cs +++ b/src/CAD/IFox.CAD.ACAD/GlobalUsings.cs @@ -43,6 +43,7 @@ // ifoxcad.basal 引用 global using IFoxCAD.Basal; +global using IFoxCAD.Com; #if !NewtonsoftJson global using System.Web.Script.Serialization; diff --git a/src/CAD/IFox.CAD.GCAD/GlobalUsings.cs b/src/CAD/IFox.CAD.GCAD/GlobalUsings.cs index 08de9aa..c04963d 100644 --- a/src/CAD/IFox.CAD.GCAD/GlobalUsings.cs +++ b/src/CAD/IFox.CAD.GCAD/GlobalUsings.cs @@ -45,6 +45,7 @@ /// ifoxcad.basal 引用 global using IFoxCAD.Basal; +global using IFoxCAD.Com; #if !NewtonsoftJson global using System.Web.Script.Serialization; diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs index 9a00d99..14ca11c 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs @@ -1,5 +1,3 @@ -using IFoxCAD.Com; - namespace IFoxCAD.Cad; /// diff --git a/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems b/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems index 9983528..648af96 100644 --- a/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems +++ b/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems @@ -66,7 +66,6 @@ - diff --git a/src/CAD/IFox.CAD.Shared/Runtime/AOP.cs b/src/CAD/IFox.CAD.Shared/Runtime/AOP.cs deleted file mode 100644 index 4bb5cb3..0000000 --- a/src/CAD/IFox.CAD.Shared/Runtime/AOP.cs +++ /dev/null @@ -1,99 +0,0 @@ -// namespace IFoxCAD.Cad; -// using HarmonyLib; - -// public class IFoxRefuseInjectionTransaction : Attribute -// { -// /// -// /// 拒绝注入事务 -// /// -// public IFoxRefuseInjectionTransaction() -// { -// } -// } - -// public class AOP -// { -// /// -// /// 在此命名空间下的命令末尾注入清空事务栈函数 -// /// -// public static void Run(string nameSpace) -// { -// Dictionary cmdDic = new(); -// AutoClass.AppDomainGetTypes(type => { -// if (type.Namespace != nameSpace) -// return; -// // 类上面特性 -// if (type.IsClass) -// { -// var attr = type.GetCustomAttributes(true); -// if (RefuseInjectionTransaction(attr)) -// return; -// } - -// // 函数上面特性 -// var mets = type.GetMethods();// 获得它的成员函数 -// for (int ii = 0; ii < mets.Length; ii++) -// { -// var method = mets[ii]; -// // 找到特性,特性下面的方法要是Public,否则就被编译器优化掉了. -// var attr = method.GetCustomAttributes(true); -// for (int jj = 0; jj < attr.Length; jj++) -// if (attr[jj] is CommandMethodAttribute cmdAtt) -// { -// if (!RefuseInjectionTransaction(attr)) -// cmdDic.Add(cmdAtt.GlobalName, (cmdAtt, type, method)); -// } -// } -// }); - -// // 运行的命令写在了Test.dll,当然不是ifox.cad类库内了.... -// if (cmdDic.Count == 0) -// return; - -// var harmony = new Harmony(nameSpace); -// var mPrefix = SymbolExtensions.GetMethodInfo(() => IFoxCmdAddFirst());// 进入函数前 -// var mPostfix = SymbolExtensions.GetMethodInfo(() => IFoxCmdAddLast());// 进入函数后 -// var mp1 = new HarmonyMethod(mPrefix); -// var mp2 = new HarmonyMethod(mPostfix); - -// foreach (var item in cmdDic) -// { -// // 原函数执行(空间type,函数名) -// var mOriginal = AccessTools.Method(item.Value.MetType, item.Value.MetInfo.Name); -// // mOriginal.Invoke(); -// // 新函数执行:创造两个函数加入里面 -// var newMet = harmony.Patch(mOriginal, mp1, mp2); -// // newMet.Invoke(); -// } -// } - -// /// -// /// 拒绝注入事务 -// /// -// /// 属性 -// /// -// private static bool RefuseInjectionTransaction(object[] attr) -// { -// bool refuseInjectionTransaction = false; -// for (int kk = 0; kk < attr.Length; kk++) -// { -// if (attr[kk] is IFoxRefuseInjectionTransaction) -// { -// refuseInjectionTransaction = true; -// break; -// } -// } -// return refuseInjectionTransaction; -// } - -// public static void IFoxCmdAddFirst() -// { -// // 此生命周期会在静态事务栈上面,被无限延长 -// var _ = DBTrans.Top; -// } - -// public static void IFoxCmdAddLast() -// { -// DBTrans.FinishDatabase(); -// } -// } \ No newline at end of file diff --git a/src/CAD/IFox.CAD.ZCAD/GlobalUsings.cs b/src/CAD/IFox.CAD.ZCAD/GlobalUsings.cs index add1774..85aac4c 100644 --- a/src/CAD/IFox.CAD.ZCAD/GlobalUsings.cs +++ b/src/CAD/IFox.CAD.ZCAD/GlobalUsings.cs @@ -42,6 +42,7 @@ /// ifoxcad.basal 引用 global using IFoxCAD.Basal; +global using IFoxCAD.Com; #if !NewtonsoftJson global using System.Web.Script.Serialization; -- Gitee From 7cc920d021f4989fe8c53934e1da19e4cf5e7b1d Mon Sep 17 00:00:00 2001 From: vicwjb Date: Tue, 14 Mar 2023 23:42:51 +0800 Subject: [PATCH 007/453] =?UTF-8?q?=E8=B0=83=E6=95=B4=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Basal/Directory.Build.props | 4 +- .../IFox.Basal.Shared/General}/LateBinding.cs | 2 +- .../IFox.Basal.Shared.projitems | 1 + .../IFox.Basal.Shared/WindowsAPI/MouseHook.cs | 5 +- src/Basal/IFox.Basal/GlobalUsings.cs | 2 - src/CAD/Directory.Build.props | 4 +- src/CAD/IFox.CAD.ACAD/GlobalUsings.cs | 1 - src/CAD/IFox.CAD.GCAD/GlobalUsings.cs | 1 - .../{Runtime => AutoReg}/AcadEMR.cs | 0 .../{Runtime => AutoReg}/AssemInfo.cs | 0 .../{Runtime => AutoReg}/AutoLoad.cs | 7 +- .../{Runtime => AutoReg}/AutoRegAssem.cs | 0 .../{Runtime => AutoReg}/IAutoGo.cs | 0 .../{Runtime => AutoReg}/MethodInfoHelper.cs | 0 .../{Runtime => CadVersion}/AcadVersion.cs | 0 .../{Runtime => CadVersion}/CadVersion.cs | 3 + .../CadInternalUtils.cs} | 55 ---- .../IdleAction.cs | 0 .../ExtensionMethod/LogEx/DBLogger.cs | 108 +++++++ .../ExtensionMethod/LogEx/EventLogger.cs | 147 ++++++++++ .../ExtensionMethod/LogEx/FileLogger.cs | 118 ++++++++ .../ExtensionMethod/LogEx/LogBase.cs | 94 ++++++ .../LogEx/LogHelper.cs} | 272 ------------------ .../ExtensionMethod/LogEx/LogTarget.cs | 110 +++++++ .../ExtensionMethod/LogEx/LogTxt.cs | 60 ++++ .../{Runtime => ExtensionMethod}/RedrawEx.cs | 0 .../IFox.CAD.Shared/IFox.CAD.Shared.projitems | 45 +-- .../{Runtime => }/PE/AcadPeInfo.cs | 0 .../IFox.CAD.Shared/{Runtime => }/PE/DBmod.cs | 0 .../{Runtime => }/PE/PostCmd.cs | 0 .../{Runtime => }/PE/ProgramPE.cs | 0 src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs | 4 - .../Runtime/{Utils.cs => DBTransHelper.cs} | 19 +- src/CAD/IFox.CAD.ZCAD/GlobalUsings.cs | 1 - 34 files changed, 687 insertions(+), 376 deletions(-) rename src/{CAD/IFox.CAD.Shared/Runtime => Basal/IFox.Basal.Shared/General}/LateBinding.cs (98%) rename src/CAD/IFox.CAD.Shared/{Runtime => AutoReg}/AcadEMR.cs (100%) rename src/CAD/IFox.CAD.Shared/{Runtime => AutoReg}/AssemInfo.cs (100%) rename src/CAD/IFox.CAD.Shared/{Runtime => AutoReg}/AutoLoad.cs (95%) rename src/CAD/IFox.CAD.Shared/{Runtime => AutoReg}/AutoRegAssem.cs (100%) rename src/CAD/IFox.CAD.Shared/{Runtime => AutoReg}/IAutoGo.cs (100%) rename src/CAD/IFox.CAD.Shared/{Runtime => AutoReg}/MethodInfoHelper.cs (100%) rename src/CAD/IFox.CAD.Shared/{Runtime => CadVersion}/AcadVersion.cs (100%) rename src/CAD/IFox.CAD.Shared/{Runtime => CadVersion}/CadVersion.cs (97%) rename src/CAD/IFox.CAD.Shared/{Runtime/FileOpenMode.cs => ExtensionMethod/CadInternalUtils.cs} (33%) rename src/CAD/IFox.CAD.Shared/{Runtime => ExtensionMethod}/IdleAction.cs (100%) create mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/DBLogger.cs create mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/EventLogger.cs create mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/FileLogger.cs create mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/LogBase.cs rename src/CAD/IFox.CAD.Shared/{Runtime/Log.cs => ExtensionMethod/LogEx/LogHelper.cs} (41%) create mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/LogTarget.cs create mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/LogTxt.cs rename src/CAD/IFox.CAD.Shared/{Runtime => ExtensionMethod}/RedrawEx.cs (100%) rename src/CAD/IFox.CAD.Shared/{Runtime => }/PE/AcadPeInfo.cs (100%) rename src/CAD/IFox.CAD.Shared/{Runtime => }/PE/DBmod.cs (100%) rename src/CAD/IFox.CAD.Shared/{Runtime => }/PE/PostCmd.cs (100%) rename src/CAD/IFox.CAD.Shared/{Runtime => }/PE/ProgramPE.cs (100%) rename src/CAD/IFox.CAD.Shared/Runtime/{Utils.cs => DBTransHelper.cs} (90%) diff --git a/src/Basal/Directory.Build.props b/src/Basal/Directory.Build.props index 77a2d37..98c0b4e 100644 --- a/src/Basal/Directory.Build.props +++ b/src/Basal/Directory.Build.props @@ -1,8 +1,8 @@  - 0.5.2.4 - 完善源码包,源码包映射原始目录 + 0.6.0.0 + 调整目录结构 diff --git a/src/CAD/IFox.CAD.Shared/Runtime/LateBinding.cs b/src/Basal/IFox.Basal.Shared/General/LateBinding.cs similarity index 98% rename from src/CAD/IFox.CAD.Shared/Runtime/LateBinding.cs rename to src/Basal/IFox.Basal.Shared/General/LateBinding.cs index 45cafa9..c72d4b4 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/LateBinding.cs +++ b/src/Basal/IFox.Basal.Shared/General/LateBinding.cs @@ -1,4 +1,4 @@ -namespace IFoxCAD.Com; +namespace IFoxCAD.Basal; /// /// 后绑代码工具 diff --git a/src/Basal/IFox.Basal.Shared/IFox.Basal.Shared.projitems b/src/Basal/IFox.Basal.Shared/IFox.Basal.Shared.projitems index 814c381..64a78d7 100644 --- a/src/Basal/IFox.Basal.Shared/IFox.Basal.Shared.projitems +++ b/src/Basal/IFox.Basal.Shared/IFox.Basal.Shared.projitems @@ -22,6 +22,7 @@ + diff --git a/src/Basal/IFox.Basal.Shared/WindowsAPI/MouseHook.cs b/src/Basal/IFox.Basal.Shared/WindowsAPI/MouseHook.cs index 400e4a7..d0f939a 100644 --- a/src/Basal/IFox.Basal.Shared/WindowsAPI/MouseHook.cs +++ b/src/Basal/IFox.Basal.Shared/WindowsAPI/MouseHook.cs @@ -1,4 +1,7 @@ -namespace IFoxCAD.Basal; +using System.Drawing; +using System.Windows.Forms; + +namespace IFoxCAD.Basal; public class MouseHook { diff --git a/src/Basal/IFox.Basal/GlobalUsings.cs b/src/Basal/IFox.Basal/GlobalUsings.cs index 35cc1cd..cb820d5 100644 --- a/src/Basal/IFox.Basal/GlobalUsings.cs +++ b/src/Basal/IFox.Basal/GlobalUsings.cs @@ -9,8 +9,6 @@ global using System.ComponentModel; global using System.Runtime.InteropServices; global using System.Diagnostics; -global using System.Drawing; -global using System.Windows.Forms; global using Microsoft.Win32; global using System.Runtime.CompilerServices; global using System.Threading; diff --git a/src/CAD/Directory.Build.props b/src/CAD/Directory.Build.props index 84265c2..4aed4b2 100644 --- a/src/CAD/Directory.Build.props +++ b/src/CAD/Directory.Build.props @@ -1,8 +1,8 @@  - 0.5.2.4 - 补充2023的信息 + 0.6.0.0 + 修复TextInfo.AddDBTextToEntity()报错的问题 diff --git a/src/CAD/IFox.CAD.ACAD/GlobalUsings.cs b/src/CAD/IFox.CAD.ACAD/GlobalUsings.cs index 51a43ac..dadfe53 100644 --- a/src/CAD/IFox.CAD.ACAD/GlobalUsings.cs +++ b/src/CAD/IFox.CAD.ACAD/GlobalUsings.cs @@ -43,7 +43,6 @@ // ifoxcad.basal 引用 global using IFoxCAD.Basal; -global using IFoxCAD.Com; #if !NewtonsoftJson global using System.Web.Script.Serialization; diff --git a/src/CAD/IFox.CAD.GCAD/GlobalUsings.cs b/src/CAD/IFox.CAD.GCAD/GlobalUsings.cs index c04963d..08de9aa 100644 --- a/src/CAD/IFox.CAD.GCAD/GlobalUsings.cs +++ b/src/CAD/IFox.CAD.GCAD/GlobalUsings.cs @@ -45,7 +45,6 @@ /// ifoxcad.basal 引用 global using IFoxCAD.Basal; -global using IFoxCAD.Com; #if !NewtonsoftJson global using System.Web.Script.Serialization; diff --git a/src/CAD/IFox.CAD.Shared/Runtime/AcadEMR.cs b/src/CAD/IFox.CAD.Shared/AutoReg/AcadEMR.cs similarity index 100% rename from src/CAD/IFox.CAD.Shared/Runtime/AcadEMR.cs rename to src/CAD/IFox.CAD.Shared/AutoReg/AcadEMR.cs diff --git a/src/CAD/IFox.CAD.Shared/Runtime/AssemInfo.cs b/src/CAD/IFox.CAD.Shared/AutoReg/AssemInfo.cs similarity index 100% rename from src/CAD/IFox.CAD.Shared/Runtime/AssemInfo.cs rename to src/CAD/IFox.CAD.Shared/AutoReg/AssemInfo.cs diff --git a/src/CAD/IFox.CAD.Shared/Runtime/AutoLoad.cs b/src/CAD/IFox.CAD.Shared/AutoReg/AutoLoad.cs similarity index 95% rename from src/CAD/IFox.CAD.Shared/Runtime/AutoLoad.cs rename to src/CAD/IFox.CAD.Shared/AutoReg/AutoLoad.cs index 004ae50..b2e65d2 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/AutoLoad.cs +++ b/src/CAD/IFox.CAD.Shared/AutoReg/AutoLoad.cs @@ -61,8 +61,11 @@ private static RegistryKey GetAcAppKey() RegistryKey ackey = Registry.CurrentUser.OpenSubKey(key, true); return ackey.CreateSubKey("Applications"); } - - protected void AppendSupportPath(string path) + /// + /// 添加 path 到 acad环境变量 + /// + /// 目录 + protected static void AppendSupportPath(string path) { #if NET35 string key = HostApplicationServices.Current.RegistryProductRootKey; diff --git a/src/CAD/IFox.CAD.Shared/Runtime/AutoRegAssem.cs b/src/CAD/IFox.CAD.Shared/AutoReg/AutoRegAssem.cs similarity index 100% rename from src/CAD/IFox.CAD.Shared/Runtime/AutoRegAssem.cs rename to src/CAD/IFox.CAD.Shared/AutoReg/AutoRegAssem.cs diff --git a/src/CAD/IFox.CAD.Shared/Runtime/IAutoGo.cs b/src/CAD/IFox.CAD.Shared/AutoReg/IAutoGo.cs similarity index 100% rename from src/CAD/IFox.CAD.Shared/Runtime/IAutoGo.cs rename to src/CAD/IFox.CAD.Shared/AutoReg/IAutoGo.cs diff --git a/src/CAD/IFox.CAD.Shared/Runtime/MethodInfoHelper.cs b/src/CAD/IFox.CAD.Shared/AutoReg/MethodInfoHelper.cs similarity index 100% rename from src/CAD/IFox.CAD.Shared/Runtime/MethodInfoHelper.cs rename to src/CAD/IFox.CAD.Shared/AutoReg/MethodInfoHelper.cs diff --git a/src/CAD/IFox.CAD.Shared/Runtime/AcadVersion.cs b/src/CAD/IFox.CAD.Shared/CadVersion/AcadVersion.cs similarity index 100% rename from src/CAD/IFox.CAD.Shared/Runtime/AcadVersion.cs rename to src/CAD/IFox.CAD.Shared/CadVersion/AcadVersion.cs diff --git a/src/CAD/IFox.CAD.Shared/Runtime/CadVersion.cs b/src/CAD/IFox.CAD.Shared/CadVersion/CadVersion.cs similarity index 97% rename from src/CAD/IFox.CAD.Shared/Runtime/CadVersion.cs rename to src/CAD/IFox.CAD.Shared/CadVersion/CadVersion.cs index d9614bf..cffbf71 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/CadVersion.cs +++ b/src/CAD/IFox.CAD.Shared/CadVersion/CadVersion.cs @@ -53,6 +53,9 @@ public override string ToString() // // } } #else +/// +/// CAD版本 +/// public record CadVersion { /// diff --git a/src/CAD/IFox.CAD.Shared/Runtime/FileOpenMode.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/CadInternalUtils.cs similarity index 33% rename from src/CAD/IFox.CAD.Shared/Runtime/FileOpenMode.cs rename to src/CAD/IFox.CAD.Shared/ExtensionMethod/CadInternalUtils.cs index b75d403..d56e0dc 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/FileOpenMode.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/CadInternalUtils.cs @@ -1,58 +1,3 @@ -#if ac2008 // NET35 -namespace Autodesk.AutoCAD.DatabaseServices -{ - [Wrapper("AcDbDatabase::OpenMode")] - public enum FileOpenMode - { - /// - /// 只读模式打开 - /// - OpenForReadAndReadShare = 1, - OpenForReadAndWriteNoShare = 2, - OpenForReadAndAllShare = 3, - OpenTryForReadShare = 4, - } - - public static class FileOpenModeHelper - { - /* - * 这个开图方式会致命错误,不清楚怎么用的文件句柄开图 - * using FileStream fileStream = new(_fileName, FileMode.Open, fileAccess, GetFileShare(fileOpenMode)); - * Database.ReadDwgFile(fileStream.SafeFileHandle.DangerousGetHandle(), true, password); - */ - public static FileShare GetFileShare(FileOpenMode fileOpenMode) - { - // FileAccess fileAccess = FileAccess.Read; - FileShare fileShare = FileShare.Read; - switch (fileOpenMode) - { - // 不完美匹配 - case FileOpenMode.OpenTryForReadShare: - // fileAccess = FileAccess.ReadWrite; - fileShare = FileShare.ReadWrite; - break; - // 完美匹配 - case FileOpenMode.OpenForReadAndAllShare: - // fileAccess = FileAccess.ReadWrite; - fileShare = FileShare.ReadWrite; - break; - // 完美匹配 - case FileOpenMode.OpenForReadAndWriteNoShare: - // fileAccess = FileAccess.ReadWrite; - fileShare = FileShare.None; - break; - // 完美匹配 - case FileOpenMode.OpenForReadAndReadShare: - // fileAccess = FileAccess.Read; - fileShare = FileShare.Read; - break; - } - return fileShare; - } - } -} -#endif - #if NET35 namespace Autodesk.AutoCAD.Internal { diff --git a/src/CAD/IFox.CAD.Shared/Runtime/IdleAction.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/IdleAction.cs similarity index 100% rename from src/CAD/IFox.CAD.Shared/Runtime/IdleAction.cs rename to src/CAD/IFox.CAD.Shared/ExtensionMethod/IdleAction.cs diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/DBLogger.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/DBLogger.cs new file mode 100644 index 0000000..0724412 --- /dev/null +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/DBLogger.cs @@ -0,0 +1,108 @@ +namespace IFoxCAD.Cad; + +using System; +#region 写入日志到不同的环境中 + +/// +/// 写入到数据库(暂时不支持) +/// +public class DBLogger : LogBase +{ + public override void DeleteLog() + { + throw new NotImplementedException(); + } + public override string[] ReadLog() + { + throw new NotImplementedException(); + } + public override void WriteLog(string? message) + { + throw new NotImplementedException(); + } +} +#endregion + + +#if false // 最简单的实现 +public static class Log +{ + /// + /// 读写锁 + /// 当资源处于写入模式时,其他线程写入需要等待本次写入结束之后才能继续写入 + /// + static readonly ReaderWriterLockSlim _logWriteLock = new(); + + /// + /// 日志文件完整路径 + /// + static readonly string _logAddress; + + static Log() + { + // 微软回复:静态构造函数只会被调用一次, + // 并且在它执行完成之前,任何其它线程都不能创建这个类的实例或使用这个类的静态成员 + // https://blog.csdn.net/weixin_34204722/article/details/90095812 + var sb = new StringBuilder(); + sb.Append(Environment.CurrentDirectory); + sb.Append("\\ErrorLog"); + + // 新建文件夹 + var path = sb.ToString(); + if (!Directory.Exists(path)) + { + Directory.CreateDirectory(path) + .Attributes = FileAttributes.Normal; // 设置文件夹属性为普通 + } + + sb.Append('\\'); + sb.Append(DateTime.Now.ToString("yy-MM-dd")); + sb.Append(".log"); + _logAddress = sb.ToString(); + } + + + /// + /// 将异常打印到日志文件 + /// + /// 异常 + /// 备注 + /// DEBUG模式打印到vs输出窗口 + public static string? WriteLog(this Exception? ex, + string? remarks = null, + bool printDebugWindow = true) + { + try + { + _logWriteLock.EnterWriteLock();// 写模式锁定 读写锁 + + var logtxt = new LogTxt(ex, remarks); + // var logtxtJson = Newtonsoft.Json.JsonConvert.SerializeObject(logtxt, Formatting.Indented); + var logtxtJson = logtxt.ToString(); + + if (logtxtJson == null) + return string.Empty; + + // 把异常信息输出到文件 + var sw = new StreamWriter(_logAddress, true/*当天日志文件存在就追加,否则就创建*/); + sw.Write(logtxtJson); + sw.Flush(); + sw.Close(); + sw.Dispose(); + + if (printDebugWindow) + { + Debugx.Printl("错误日志: " + _logAddress); + Debug.Write(logtxtJson); + // Debugger.Break(); + // Debug.Assert(false, "终止进程"); + } + return logtxtJson; + } + finally + { + _logWriteLock.ExitWriteLock();// 解锁 读写锁 + } + } +} +#endif \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/EventLogger.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/EventLogger.cs new file mode 100644 index 0000000..4e011e4 --- /dev/null +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/EventLogger.cs @@ -0,0 +1,147 @@ +namespace IFoxCAD.Cad; + +using System.Diagnostics; +using Exception = Exception; +#region 写入日志到不同的环境中 + +/// +/// 写入到win日志 +/// +public class EventLogger : LogBase +{ + // 需要win权限 + // https://blog.csdn.net/weixin_38208401/article/details/77870909 + // NET50要加 + // https://docs.microsoft.com/en-us/answers/questions/526018/windows-event-log-with-net-5.html + + public string LogName = "IFoxCadLog"; + public override void DeleteLog() + { +#if !NET5_0 && !NET6_0 + if (EventLog.Exists(LogName)) + EventLog.Delete(LogName); +#endif + } + public override string[] ReadLog() + { + List lines = new(); +#if !NET5_0 && !NET6_0 + try + { + EventLog eventLog = new() + { + Log = LogName + }; + foreach (EventLogEntry entry in eventLog.Entries) + lines.Add(entry.Message); + } + catch (System.Security.SecurityException e) + { + throw new Exception("您没有权限读取win日志::" + e.Message); + } +#endif + return lines.ToArray(); + } + public override void WriteLog(string? message) + { +#if !NET5_0 && !NET6_0 + try + { + EventLog eventLog = new() + { + Source = LogName + }; + eventLog.WriteEntry(message, EventLogEntryType.Information); + } + catch (System.Security.SecurityException e) + { + throw new Exception("您没有权限写入win日志::" + e.Message); + } +#endif + } +} +#endregion + + +#if false // 最简单的实现 +public static class Log +{ + /// + /// 读写锁 + /// 当资源处于写入模式时,其他线程写入需要等待本次写入结束之后才能继续写入 + /// + static readonly ReaderWriterLockSlim _logWriteLock = new(); + + /// + /// 日志文件完整路径 + /// + static readonly string _logAddress; + + static Log() + { + // 微软回复:静态构造函数只会被调用一次, + // 并且在它执行完成之前,任何其它线程都不能创建这个类的实例或使用这个类的静态成员 + // https://blog.csdn.net/weixin_34204722/article/details/90095812 + var sb = new StringBuilder(); + sb.Append(Environment.CurrentDirectory); + sb.Append("\\ErrorLog"); + + // 新建文件夹 + var path = sb.ToString(); + if (!Directory.Exists(path)) + { + Directory.CreateDirectory(path) + .Attributes = FileAttributes.Normal; // 设置文件夹属性为普通 + } + + sb.Append('\\'); + sb.Append(DateTime.Now.ToString("yy-MM-dd")); + sb.Append(".log"); + _logAddress = sb.ToString(); + } + + + /// + /// 将异常打印到日志文件 + /// + /// 异常 + /// 备注 + /// DEBUG模式打印到vs输出窗口 + public static string? WriteLog(this Exception? ex, + string? remarks = null, + bool printDebugWindow = true) + { + try + { + _logWriteLock.EnterWriteLock();// 写模式锁定 读写锁 + + var logtxt = new LogTxt(ex, remarks); + // var logtxtJson = Newtonsoft.Json.JsonConvert.SerializeObject(logtxt, Formatting.Indented); + var logtxtJson = logtxt.ToString(); + + if (logtxtJson == null) + return string.Empty; + + // 把异常信息输出到文件 + var sw = new StreamWriter(_logAddress, true/*当天日志文件存在就追加,否则就创建*/); + sw.Write(logtxtJson); + sw.Flush(); + sw.Close(); + sw.Dispose(); + + if (printDebugWindow) + { + Debugx.Printl("错误日志: " + _logAddress); + Debug.Write(logtxtJson); + // Debugger.Break(); + // Debug.Assert(false, "终止进程"); + } + return logtxtJson; + } + finally + { + _logWriteLock.ExitWriteLock();// 解锁 读写锁 + } + } +} +#endif \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/FileLogger.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/FileLogger.cs new file mode 100644 index 0000000..de84385 --- /dev/null +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/FileLogger.cs @@ -0,0 +1,118 @@ +namespace IFoxCAD.Cad; +#region 写入日志到不同的环境中 + +/// +/// 写入到文件中 +/// +public class FileLogger : LogBase +{ + public override void DeleteLog() + { + File.Delete(LogHelper.LogAddress); + } + public override string[] ReadLog() + { + List lines = new(); + using (var sr = new StreamReader(LogHelper.LogAddress, true/*自动识别文件头*/)) + { + string line; + while ((line = sr.ReadLine()) != null) + lines.Add(line); + } + return lines.ToArray(); + } + public override void WriteLog(string? message) + { + // 把异常信息输出到文件 + var sw = new StreamWriter(LogHelper.LogAddress, true/*当天日志文件存在就追加,否则就创建*/); + sw.Write(message); + sw.Flush(); + sw.Close(); + sw.Dispose(); + } +} +#endregion + + +#if false // 最简单的实现 +public static class Log +{ + /// + /// 读写锁 + /// 当资源处于写入模式时,其他线程写入需要等待本次写入结束之后才能继续写入 + /// + static readonly ReaderWriterLockSlim _logWriteLock = new(); + + /// + /// 日志文件完整路径 + /// + static readonly string _logAddress; + + static Log() + { + // 微软回复:静态构造函数只会被调用一次, + // 并且在它执行完成之前,任何其它线程都不能创建这个类的实例或使用这个类的静态成员 + // https://blog.csdn.net/weixin_34204722/article/details/90095812 + var sb = new StringBuilder(); + sb.Append(Environment.CurrentDirectory); + sb.Append("\\ErrorLog"); + + // 新建文件夹 + var path = sb.ToString(); + if (!Directory.Exists(path)) + { + Directory.CreateDirectory(path) + .Attributes = FileAttributes.Normal; // 设置文件夹属性为普通 + } + + sb.Append('\\'); + sb.Append(DateTime.Now.ToString("yy-MM-dd")); + sb.Append(".log"); + _logAddress = sb.ToString(); + } + + + /// + /// 将异常打印到日志文件 + /// + /// 异常 + /// 备注 + /// DEBUG模式打印到vs输出窗口 + public static string? WriteLog(this Exception? ex, + string? remarks = null, + bool printDebugWindow = true) + { + try + { + _logWriteLock.EnterWriteLock();// 写模式锁定 读写锁 + + var logtxt = new LogTxt(ex, remarks); + // var logtxtJson = Newtonsoft.Json.JsonConvert.SerializeObject(logtxt, Formatting.Indented); + var logtxtJson = logtxt.ToString(); + + if (logtxtJson == null) + return string.Empty; + + // 把异常信息输出到文件 + var sw = new StreamWriter(_logAddress, true/*当天日志文件存在就追加,否则就创建*/); + sw.Write(logtxtJson); + sw.Flush(); + sw.Close(); + sw.Dispose(); + + if (printDebugWindow) + { + Debugx.Printl("错误日志: " + _logAddress); + Debug.Write(logtxtJson); + // Debugger.Break(); + // Debug.Assert(false, "终止进程"); + } + return logtxtJson; + } + finally + { + _logWriteLock.ExitWriteLock();// 解锁 读写锁 + } + } +} +#endif \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/LogBase.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/LogBase.cs new file mode 100644 index 0000000..73ff44e --- /dev/null +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/LogBase.cs @@ -0,0 +1,94 @@ +namespace IFoxCAD.Cad; +#region 写入日志到不同的环境中 +// https://zhuanlan.zhihu.com/p/338492989 +public abstract class LogBase +{ + public abstract void DeleteLog(); + public abstract string[] ReadLog(); + public abstract void WriteLog(string message); +} +#endregion + + +#if false // 最简单的实现 +public static class Log +{ + /// + /// 读写锁 + /// 当资源处于写入模式时,其他线程写入需要等待本次写入结束之后才能继续写入 + /// + static readonly ReaderWriterLockSlim _logWriteLock = new(); + + /// + /// 日志文件完整路径 + /// + static readonly string _logAddress; + + static Log() + { + // 微软回复:静态构造函数只会被调用一次, + // 并且在它执行完成之前,任何其它线程都不能创建这个类的实例或使用这个类的静态成员 + // https://blog.csdn.net/weixin_34204722/article/details/90095812 + var sb = new StringBuilder(); + sb.Append(Environment.CurrentDirectory); + sb.Append("\\ErrorLog"); + + // 新建文件夹 + var path = sb.ToString(); + if (!Directory.Exists(path)) + { + Directory.CreateDirectory(path) + .Attributes = FileAttributes.Normal; // 设置文件夹属性为普通 + } + + sb.Append('\\'); + sb.Append(DateTime.Now.ToString("yy-MM-dd")); + sb.Append(".log"); + _logAddress = sb.ToString(); + } + + + /// + /// 将异常打印到日志文件 + /// + /// 异常 + /// 备注 + /// DEBUG模式打印到vs输出窗口 + public static string? WriteLog(this Exception? ex, + string? remarks = null, + bool printDebugWindow = true) + { + try + { + _logWriteLock.EnterWriteLock();// 写模式锁定 读写锁 + + var logtxt = new LogTxt(ex, remarks); + // var logtxtJson = Newtonsoft.Json.JsonConvert.SerializeObject(logtxt, Formatting.Indented); + var logtxtJson = logtxt.ToString(); + + if (logtxtJson == null) + return string.Empty; + + // 把异常信息输出到文件 + var sw = new StreamWriter(_logAddress, true/*当天日志文件存在就追加,否则就创建*/); + sw.Write(logtxtJson); + sw.Flush(); + sw.Close(); + sw.Dispose(); + + if (printDebugWindow) + { + Debugx.Printl("错误日志: " + _logAddress); + Debug.Write(logtxtJson); + // Debugger.Break(); + // Debug.Assert(false, "终止进程"); + } + return logtxtJson; + } + finally + { + _logWriteLock.ExitWriteLock();// 解锁 读写锁 + } + } +} +#endif \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/Runtime/Log.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/LogHelper.cs similarity index 41% rename from src/CAD/IFox.CAD.Shared/Runtime/Log.cs rename to src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/LogHelper.cs index 812d694..e1e6b0b 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/Log.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/LogHelper.cs @@ -5,148 +5,9 @@ using System.Threading; using Exception = Exception; -#region 写入日志到不同的环境中 -// https://zhuanlan.zhihu.com/p/338492989 -public abstract class LogBase -{ - public abstract void DeleteLog(); - public abstract string[] ReadLog(); - public abstract void WriteLog(string message); -} - -/// -/// 日志输出环境 -/// -public enum LogTarget -{ - /// - /// 文件(包含错误和备注) - /// - File = 1, - /// - /// 文件(不包含错误,也就是只写备注信息) - /// - FileNotException = 2, - /// - /// 数据库 - /// - Database = 4, - /// - /// windows日志 - /// - EventLog = 8, -} - -/// -/// 写入到文件中 -/// -public class FileLogger : LogBase -{ - public override void DeleteLog() - { - File.Delete(LogHelper.LogAddress); - } - public override string[] ReadLog() - { - List lines = new(); - using (var sr = new StreamReader(LogHelper.LogAddress, true/*自动识别文件头*/)) - { - string line; - while ((line = sr.ReadLine()) != null) - lines.Add(line); - } - return lines.ToArray(); - } - public override void WriteLog(string? message) - { - // 把异常信息输出到文件 - var sw = new StreamWriter(LogHelper.LogAddress, true/*当天日志文件存在就追加,否则就创建*/); - sw.Write(message); - sw.Flush(); - sw.Close(); - sw.Dispose(); - } -} - -/// -/// 写入到数据库(暂时不支持) -/// -public class DBLogger : LogBase -{ - public override void DeleteLog() - { - throw new NotImplementedException(); - } - public override string[] ReadLog() - { - throw new NotImplementedException(); - } - public override void WriteLog(string? message) - { - throw new NotImplementedException(); - } -} - -/// -/// 写入到win日志 -/// -public class EventLogger : LogBase -{ - // 需要win权限 - // https://blog.csdn.net/weixin_38208401/article/details/77870909 - // NET50要加 - // https://docs.microsoft.com/en-us/answers/questions/526018/windows-event-log-with-net-5.html - public string LogName = "IFoxCadLog"; - public override void DeleteLog() - { -#if !NET5_0 && !NET6_0 - if (EventLog.Exists(LogName)) - EventLog.Delete(LogName); -#endif - } - public override string[] ReadLog() - { - List lines = new(); -#if !NET5_0 && !NET6_0 - try - { - EventLog eventLog = new() - { - Log = LogName - }; - foreach (EventLogEntry entry in eventLog.Entries) - lines.Add(entry.Message); - } - catch (System.Security.SecurityException e) - { - throw new Exception("您没有权限读取win日志::" + e.Message); - } -#endif - return lines.ToArray(); - } - public override void WriteLog(string? message) - { -#if !NET5_0 && !NET6_0 - try - { - EventLog eventLog = new() - { - Source = LogName - }; - eventLog.WriteEntry(message, EventLogEntryType.Information); - } - catch (System.Security.SecurityException e) - { - throw new Exception("您没有权限写入win日志::" + e.Message); - } -#endif - } -} -#endregion -#region 静态方法 public static class LogHelper { #pragma warning disable CA2211 // 非常量字段应当不可见 @@ -313,141 +174,8 @@ static string LogAction(Exception? ex, } } } -#endregion -#region 序列化 -[Serializable] -public class LogTxt -{ - public string? 当前时间; - public string? 备注信息; - public string? 异常信息; - public string? 异常对象; - public string? 触发方法; - public string? 调用堆栈; - public LogTxt() { } - public LogTxt(Exception? ex, string? message) : this() - { - if (ex == null && message == null) - throw new ArgumentNullException(nameof(ex)); - // 以不同语言显示日期 - // DateTime.Now.ToString("f", new System.Globalization.CultureInfo("es-ES")) - // DateTime.Now.ToString("f", new System.Globalization.CultureInfo("zh-cn")) - // 为了最小信息熵,所以用这样的格式,并且我喜欢补0 - 当前时间 = DateTime.Now.ToString("yy-MM-dd hh:mm:ss"); - if (ex != null) - { - 异常信息 = ex.Message; - 异常对象 = ex.Source; - 触发方法 = ex.TargetSite == null ? string.Empty : ex.TargetSite.ToString(); - 调用堆栈 = ex.StackTrace == null ? string.Empty : ex.StackTrace.Trim(); - } - if (message != null) - 备注信息 = message; - } - - /// 为了不引入json的dll,所以这里自己构造 - public override string? ToString() - { - var sb = new StringBuilder(); - sb.Append('{'); - sb.Append(Environment.NewLine); - sb.AppendLine($" \"{nameof(当前时间)}\": \"{当前时间}\""); - sb.AppendLine($" \"{nameof(备注信息)}\": \"{备注信息}\""); - sb.AppendLine($" \"{nameof(异常信息)}\": \"{异常信息}\""); - sb.AppendLine($" \"{nameof(异常对象)}\": \"{异常对象}\""); - sb.AppendLine($" \"{nameof(触发方法)}\": \"{触发方法}\""); - sb.AppendLine($" \"{nameof(调用堆栈)}\": \"{调用堆栈}\""); - sb.Append('}'); - return sb.ToString(); - } -} -#endregion - - -#if false // 最简单的实现 -public static class Log -{ - /// - /// 读写锁 - /// 当资源处于写入模式时,其他线程写入需要等待本次写入结束之后才能继续写入 - /// - static readonly ReaderWriterLockSlim _logWriteLock = new(); - - /// - /// 日志文件完整路径 - /// - static readonly string _logAddress; - - static Log() - { - // 微软回复:静态构造函数只会被调用一次, - // 并且在它执行完成之前,任何其它线程都不能创建这个类的实例或使用这个类的静态成员 - // https://blog.csdn.net/weixin_34204722/article/details/90095812 - var sb = new StringBuilder(); - sb.Append(Environment.CurrentDirectory); - sb.Append("\\ErrorLog"); - - // 新建文件夹 - var path = sb.ToString(); - if (!Directory.Exists(path)) - { - Directory.CreateDirectory(path) - .Attributes = FileAttributes.Normal; // 设置文件夹属性为普通 - } - - sb.Append('\\'); - sb.Append(DateTime.Now.ToString("yy-MM-dd")); - sb.Append(".log"); - _logAddress = sb.ToString(); - } - - - /// - /// 将异常打印到日志文件 - /// - /// 异常 - /// 备注 - /// DEBUG模式打印到vs输出窗口 - public static string? WriteLog(this Exception? ex, - string? remarks = null, - bool printDebugWindow = true) - { - try - { - _logWriteLock.EnterWriteLock();// 写模式锁定 读写锁 - - var logtxt = new LogTxt(ex, remarks); - // var logtxtJson = Newtonsoft.Json.JsonConvert.SerializeObject(logtxt, Formatting.Indented); - var logtxtJson = logtxt.ToString(); - - if (logtxtJson == null) - return string.Empty; - - // 把异常信息输出到文件 - var sw = new StreamWriter(_logAddress, true/*当天日志文件存在就追加,否则就创建*/); - sw.Write(logtxtJson); - sw.Flush(); - sw.Close(); - sw.Dispose(); - - if (printDebugWindow) - { - Debugx.Printl("错误日志: " + _logAddress); - Debug.Write(logtxtJson); - // Debugger.Break(); - // Debug.Assert(false, "终止进程"); - } - return logtxtJson; - } - finally - { - _logWriteLock.ExitWriteLock();// 解锁 读写锁 - } - } -} -#endif \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/LogTarget.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/LogTarget.cs new file mode 100644 index 0000000..1ac2277 --- /dev/null +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/LogTarget.cs @@ -0,0 +1,110 @@ +namespace IFoxCAD.Cad; +#region 写入日志到不同的环境中 + +/// +/// 日志输出环境 +/// +public enum LogTarget +{ + /// + /// 文件(包含错误和备注) + /// + File = 1, + /// + /// 文件(不包含错误,也就是只写备注信息) + /// + FileNotException = 2, + /// + /// 数据库 + /// + Database = 4, + /// + /// windows日志 + /// + EventLog = 8, +} +#endregion + + +#if false // 最简单的实现 +public static class Log +{ + /// + /// 读写锁 + /// 当资源处于写入模式时,其他线程写入需要等待本次写入结束之后才能继续写入 + /// + static readonly ReaderWriterLockSlim _logWriteLock = new(); + + /// + /// 日志文件完整路径 + /// + static readonly string _logAddress; + + static Log() + { + // 微软回复:静态构造函数只会被调用一次, + // 并且在它执行完成之前,任何其它线程都不能创建这个类的实例或使用这个类的静态成员 + // https://blog.csdn.net/weixin_34204722/article/details/90095812 + var sb = new StringBuilder(); + sb.Append(Environment.CurrentDirectory); + sb.Append("\\ErrorLog"); + + // 新建文件夹 + var path = sb.ToString(); + if (!Directory.Exists(path)) + { + Directory.CreateDirectory(path) + .Attributes = FileAttributes.Normal; // 设置文件夹属性为普通 + } + + sb.Append('\\'); + sb.Append(DateTime.Now.ToString("yy-MM-dd")); + sb.Append(".log"); + _logAddress = sb.ToString(); + } + + + /// + /// 将异常打印到日志文件 + /// + /// 异常 + /// 备注 + /// DEBUG模式打印到vs输出窗口 + public static string? WriteLog(this Exception? ex, + string? remarks = null, + bool printDebugWindow = true) + { + try + { + _logWriteLock.EnterWriteLock();// 写模式锁定 读写锁 + + var logtxt = new LogTxt(ex, remarks); + // var logtxtJson = Newtonsoft.Json.JsonConvert.SerializeObject(logtxt, Formatting.Indented); + var logtxtJson = logtxt.ToString(); + + if (logtxtJson == null) + return string.Empty; + + // 把异常信息输出到文件 + var sw = new StreamWriter(_logAddress, true/*当天日志文件存在就追加,否则就创建*/); + sw.Write(logtxtJson); + sw.Flush(); + sw.Close(); + sw.Dispose(); + + if (printDebugWindow) + { + Debugx.Printl("错误日志: " + _logAddress); + Debug.Write(logtxtJson); + // Debugger.Break(); + // Debug.Assert(false, "终止进程"); + } + return logtxtJson; + } + finally + { + _logWriteLock.ExitWriteLock();// 解锁 读写锁 + } + } +} +#endif \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/LogTxt.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/LogTxt.cs new file mode 100644 index 0000000..fb98424 --- /dev/null +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/LogTxt.cs @@ -0,0 +1,60 @@ +namespace IFoxCAD.Cad; + +using System; +using Exception = Exception; + + +#region 序列化 +[Serializable] +public class LogTxt +{ + public string? 当前时间; + public string? 备注信息; + public string? 异常信息; + public string? 异常对象; + public string? 触发方法; + public string? 调用堆栈; + + public LogTxt() { } + + public LogTxt(Exception? ex, string? message) : this() + { + if (ex == null && message == null) + throw new ArgumentNullException(nameof(ex)); + + // 以不同语言显示日期 + // DateTime.Now.ToString("f", new System.Globalization.CultureInfo("es-ES")) + // DateTime.Now.ToString("f", new System.Globalization.CultureInfo("zh-cn")) + // 为了最小信息熵,所以用这样的格式,并且我喜欢补0 + 当前时间 = DateTime.Now.ToString("yy-MM-dd hh:mm:ss"); + + if (ex != null) + { + 异常信息 = ex.Message; + 异常对象 = ex.Source; + 触发方法 = ex.TargetSite == null ? string.Empty : ex.TargetSite.ToString(); + 调用堆栈 = ex.StackTrace == null ? string.Empty : ex.StackTrace.Trim(); + } + if (message != null) + 备注信息 = message; + } + + /// 为了不引入json的dll,所以这里自己构造 + public override string? ToString() + { + var sb = new StringBuilder(); + sb.Append('{'); + sb.Append(Environment.NewLine); + sb.AppendLine($" \"{nameof(当前时间)}\": \"{当前时间}\""); + sb.AppendLine($" \"{nameof(备注信息)}\": \"{备注信息}\""); + sb.AppendLine($" \"{nameof(异常信息)}\": \"{异常信息}\""); + sb.AppendLine($" \"{nameof(异常对象)}\": \"{异常对象}\""); + sb.AppendLine($" \"{nameof(触发方法)}\": \"{触发方法}\""); + sb.AppendLine($" \"{nameof(调用堆栈)}\": \"{调用堆栈}\""); + sb.Append('}'); + return sb.ToString(); + } +} +#endregion + + diff --git a/src/CAD/IFox.CAD.Shared/Runtime/RedrawEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/RedrawEx.cs similarity index 100% rename from src/CAD/IFox.CAD.Shared/Runtime/RedrawEx.cs rename to src/CAD/IFox.CAD.Shared/ExtensionMethod/RedrawEx.cs diff --git a/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems b/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems index 648af96..f76f248 100644 --- a/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems +++ b/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems @@ -45,6 +45,12 @@ + + + + + + @@ -64,31 +70,34 @@ - - - - - - + + + + + + - - - - - - - - - - - + + + + + + + + + + - + + + + + \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/Runtime/PE/AcadPeInfo.cs b/src/CAD/IFox.CAD.Shared/PE/AcadPeInfo.cs similarity index 100% rename from src/CAD/IFox.CAD.Shared/Runtime/PE/AcadPeInfo.cs rename to src/CAD/IFox.CAD.Shared/PE/AcadPeInfo.cs diff --git a/src/CAD/IFox.CAD.Shared/Runtime/PE/DBmod.cs b/src/CAD/IFox.CAD.Shared/PE/DBmod.cs similarity index 100% rename from src/CAD/IFox.CAD.Shared/Runtime/PE/DBmod.cs rename to src/CAD/IFox.CAD.Shared/PE/DBmod.cs diff --git a/src/CAD/IFox.CAD.Shared/Runtime/PE/PostCmd.cs b/src/CAD/IFox.CAD.Shared/PE/PostCmd.cs similarity index 100% rename from src/CAD/IFox.CAD.Shared/Runtime/PE/PostCmd.cs rename to src/CAD/IFox.CAD.Shared/PE/PostCmd.cs diff --git a/src/CAD/IFox.CAD.Shared/Runtime/PE/ProgramPE.cs b/src/CAD/IFox.CAD.Shared/PE/ProgramPE.cs similarity index 100% rename from src/CAD/IFox.CAD.Shared/Runtime/PE/ProgramPE.cs rename to src/CAD/IFox.CAD.Shared/PE/ProgramPE.cs diff --git a/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs b/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs index e760b1d..1de7299 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs @@ -231,11 +231,7 @@ public DBTrans(string fileName, } else { -#if ac2008 - Database.ReadDwgFile(_fileName, FileOpenModeHelper.GetFileShare(fileOpenMode), true, password); -#else Database.ReadDwgFile(_fileName, fileOpenMode, true, password); -#endif } Database.CloseInput(true); } diff --git a/src/CAD/IFox.CAD.Shared/Runtime/Utils.cs b/src/CAD/IFox.CAD.Shared/Runtime/DBTransHelper.cs similarity index 90% rename from src/CAD/IFox.CAD.Shared/Runtime/Utils.cs rename to src/CAD/IFox.CAD.Shared/Runtime/DBTransHelper.cs index 28c47c2..ebc1a90 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/Utils.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/DBTransHelper.cs @@ -1,9 +1,11 @@ namespace IFoxCAD.Cad; -using System; - +/// +/// dbtrans辅助类 +/// public class DBTransHelper { +#if NET35 /* * id = db.GetObjectId(false, handle, 0); * 参数意义: db.GetObjectId(如果没有找到就创建,句柄号,标记..将来备用) @@ -64,7 +66,7 @@ static int GetAcDbObjectId(IntPtr db, Handle handle, out ObjectId id, bool creat } return -1; } - +#endif /// /// 句柄转id /// @@ -84,15 +86,4 @@ public static ObjectId TryGetObjectId(Database db, Handle handle) return id; } - // public static int GetCadFileVersion(string filename) - // { - // var bytes = File.ReadAllBytes(filename); - // var headstr = Encoding.Default.GetString(bytes)[0..6]; - // if (!headstr.StartsWith("AC")) return 0; - // var vernum = int.Parse(headstr.Replace("AC", "")); - // var a = Enum.Parse(typeof(DwgVersion), "AC1800"); - // Enum.TryParse() - // return vernum + 986; - - // } } \ No newline at end of file diff --git a/src/CAD/IFox.CAD.ZCAD/GlobalUsings.cs b/src/CAD/IFox.CAD.ZCAD/GlobalUsings.cs index 85aac4c..add1774 100644 --- a/src/CAD/IFox.CAD.ZCAD/GlobalUsings.cs +++ b/src/CAD/IFox.CAD.ZCAD/GlobalUsings.cs @@ -42,7 +42,6 @@ /// ifoxcad.basal 引用 global using IFoxCAD.Basal; -global using IFoxCAD.Com; #if !NewtonsoftJson global using System.Web.Script.Serialization; -- Gitee From fadad23d0222df1a54046ab873a29a45b37c26b9 Mon Sep 17 00:00:00 2001 From: Music_Die Date: Fri, 10 Mar 2023 09:47:48 +0000 Subject: [PATCH 008/453] =?UTF-8?q?update=20src/Basal/IFox.Basal.Shared/Wi?= =?UTF-8?q?ndowsAPI/MouseHook.cs.=20=E8=A1=A5=E5=85=85=E4=B8=AD=E9=94=AE?= =?UTF-8?q?=E5=8F=8C=E5=87=BB=E5=92=8C=E5=BC=B9=E8=B5=B7=E5=8A=A8=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Music_Die --- src/Basal/IFox.Basal.Shared/WindowsAPI/MouseHook.cs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/Basal/IFox.Basal.Shared/WindowsAPI/MouseHook.cs b/src/Basal/IFox.Basal.Shared/WindowsAPI/MouseHook.cs index d0f939a..822c4b5 100644 --- a/src/Basal/IFox.Basal.Shared/WindowsAPI/MouseHook.cs +++ b/src/Basal/IFox.Basal.Shared/WindowsAPI/MouseHook.cs @@ -1,4 +1,4 @@ -using System.Drawing; +using System.Drawing; using System.Windows.Forms; namespace IFoxCAD.Basal; @@ -175,6 +175,16 @@ bool HookTask(int nCode, int wParam, IntPtr lParam) _clickCount = 1; _ck = true; break; + case WM.WM_MBUTTONUP: + _button = MouseButtons.Middle; + _clickCount = 1; + _up = true; + break; + case WM.WM_MBUTTONDBLCLK: + _button = MouseButtons.Middle; + _clickCount = 2; + _ck = true; + break; case WM.WM_MOUSEWHEEL: // 滚轮 break; -- Gitee From 486f9ff605b8ebe20c6df554b84f8f086712d4d8 Mon Sep 17 00:00:00 2001 From: Music_Die Date: Mon, 13 Mar 2023 07:58:42 +0000 Subject: [PATCH 009/453] =?UTF-8?q?update=20src/Basal/IFox.Basal.Shared/Wi?= =?UTF-8?q?ndowsAPI/MouseHook.cs.=20=E8=A1=A5=E5=85=85wheel=E5=92=8Cmove?= =?UTF-8?q?=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Music_Die --- .../IFox.Basal.Shared/WindowsAPI/MouseHook.cs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/Basal/IFox.Basal.Shared/WindowsAPI/MouseHook.cs b/src/Basal/IFox.Basal.Shared/WindowsAPI/MouseHook.cs index 822c4b5..89f96fa 100644 --- a/src/Basal/IFox.Basal.Shared/WindowsAPI/MouseHook.cs +++ b/src/Basal/IFox.Basal.Shared/WindowsAPI/MouseHook.cs @@ -112,6 +112,8 @@ public void SetHook(bool processHook = false) bool _down = false; bool _up = false; bool _ck = false; + bool _wheel = false; + bool _move = false; /// /// 钩子的消息处理 @@ -135,6 +137,8 @@ bool HookTask(int nCode, int wParam, IntPtr lParam) _down = false; _up = false; _ck = false; + _wheel = false; + _move = false; switch ((WM)wParam) { @@ -186,9 +190,11 @@ bool HookTask(int nCode, int wParam, IntPtr lParam) _ck = true; break; case WM.WM_MOUSEWHEEL: + _wheel = true; // 滚轮 break; case WM.WM_MOUSEMOVE: + _move = true; // 移动 // 假设想要限制鼠标在屏幕中的移动区域能够在此处设置 // 后期须要考虑实际的x y的容差 @@ -223,8 +229,14 @@ bool HookTask(int nCode, int wParam, IntPtr lParam) _watch.Start(); } } - MouseMove?.Invoke(this, e); - MouseWheel?.Invoke(this, e); + if (_move) + { + MouseMove?.Invoke(this, e); + } + if (_wheel) + { + MouseWheel?.Invoke(this, e); + } // 屏蔽此输入 if (_isHookBreak) -- Gitee From ebca215ba7643d7541fe3701591a7ae7dea2883f Mon Sep 17 00:00:00 2001 From: vicwjb <403009819@qq.com> Date: Wed, 15 Mar 2023 15:32:32 +0800 Subject: [PATCH 010/453] =?UTF-8?q?=E5=8F=96=E6=B6=88GetObject=E8=BF=94?= =?UTF-8?q?=E5=9B=9E=E7=B1=BB=E5=9E=8B=E5=8F=AF=E7=A9=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs b/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs index 1de7299..b185b76 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs @@ -398,12 +398,13 @@ public static implicit operator Transaction(DBTrans tr) /// 是否打开已删除对象,默认为不打开 /// 是否打开锁定图层对象,默认为不打开 /// 图元对象,类型不匹配时返回 - public T? GetObject(ObjectId id, + public T GetObject(ObjectId id, OpenMode openMode = OpenMode.ForRead, bool openErased = false, bool openLockedLayer = false) where T : DBObject { - return Transaction.GetObject(id, openMode, openErased, openLockedLayer) as T; + return Transaction.GetObject(id, openMode, openErased, openLockedLayer) as T + ?? throw new ArgumentNullException(nameof(T), $"你传入的 id 不能转换为 {nameof(T)} 类型"); } /// @@ -536,7 +537,6 @@ public void SaveFile(DwgVersion version = DwgVersion.AC1800, Database.SaveAs(saveAsFile, version); } - /// /// 获取文件名,无效的话就制造 /// -- Gitee From e4ac0e6eeef2ec109df52e2e5776d053e09f4bd6 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 16 Mar 2023 20:57:22 +0800 Subject: [PATCH 011/453] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dprojitems=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E9=94=99=E8=AF=AF=E5=AF=BC=E8=87=B4=E6=89=BE=E4=B8=8D?= =?UTF-8?q?=E5=88=B0.cs=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems b/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems index f76f248..87d4520 100644 --- a/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems +++ b/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems @@ -51,6 +51,7 @@ + @@ -81,7 +82,6 @@ - @@ -89,7 +89,7 @@ - + -- Gitee From 8de1f9a3febf8cb6037b100e2e089479041120de Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 16 Mar 2023 21:05:33 +0800 Subject: [PATCH 012/453] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=BF=94=E5=9B=9E?= =?UTF-8?q?=E6=9C=AC=E8=BA=AB=E7=B1=BB=E5=9E=8B=E7=9A=84=E5=85=8B=E9=9A=86?= =?UTF-8?q?=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../IFox.CAD.Shared/ExtensionMethod/DBObjectEx.cs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBObjectEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBObjectEx.cs index 9733d94..711c270 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBObjectEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBObjectEx.cs @@ -50,7 +50,17 @@ public static void RemoveXData(this DBObject obj, string appName) obj.XData = rb; } } - + /// + /// 克隆对象 + /// + /// 对象类型 + /// 对象 + /// 克隆后的对象 + /// + public static T CloneEx(this T ent) where T : RXObject + { + return ent.Clone() is T tEnt ? tEnt : throw new ArgumentException(nameof(CloneEx) + "克隆出错"); + } /// /// 修改扩展数据 /// -- Gitee From 039eb249c4a950f59ab23a060ca2c96eedf3428f Mon Sep 17 00:00:00 2001 From: vicwjb Date: Fri, 17 Mar 2023 22:01:32 +0800 Subject: [PATCH 013/453] =?UTF-8?q?=E5=88=A9=E7=94=A8CreateDBText=E5=92=8C?= =?UTF-8?q?AddDBText=EF=BC=8CCreateMText=E5=92=8CAddMText=EF=BC=8C?= =?UTF-8?q?=E6=9B=BF=E4=BB=A3TextInfo=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/Entity/DBTextEx.cs | 49 +++++ .../ExtensionMethod/Entity/MTextEx.cs | 47 +++++ .../TextEntityAdd.cs" | 62 ------ .../TextInfo.cs" | 179 ------------------ .../IFox.CAD.Shared/IFox.CAD.Shared.projitems | 2 - tests/TestShared/TestBlock.cs | 10 +- tests/TestShared/TestJig.cs | 8 +- tests/TestShared/TestShared.projitems | 1 + tests/TestShared/TestText.cs | 32 ++++ 9 files changed, 135 insertions(+), 255 deletions(-) delete mode 100644 "src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\346\226\207\345\255\227/TextEntityAdd.cs" delete mode 100644 "src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\346\226\207\345\255\227/TextInfo.cs" create mode 100644 tests/TestShared/TestText.cs diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/DBTextEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/DBTextEx.cs index 5e01e58..ddc9ac9 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/DBTextEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/DBTextEx.cs @@ -5,6 +5,55 @@ /// public static class DBTextEx { + /// + /// 创建单行文字 + /// + /// 插入点 + /// 文本内容 + /// 文字高度 + /// 文字所在的数据库 + /// 文字属性设置委托 + /// 文字对象 + /// + public static DBText CreateDBText(Point3d position, string text, double height, Database? database = null,Action? action = null) + { + if (string.IsNullOrEmpty(text)) + throw new ArgumentNullException(nameof(text), "创建文字无内容"); + + var acText = new DBText(); + + acText.SetDatabaseDefaults(database ?? DBTrans.Top.Database); + + acText.Height = height; + acText.TextString = text; + acText.Position = position; // 插入点(一定要先设置) + + acText.Justify = AttachmentPoint.BaseLeft; // 使他们对齐 + + action?.Invoke(acText); + + if (acText.Justify != AttachmentPoint.BaseLeft) + acText.AlignmentPoint = position; + + acText.AdjustAlignment(database ?? DBTrans.Top.Database); + return acText; + } + + /// + /// 添加单行文字到块表记录 + /// + /// 块表记录 + /// 插入点 + /// 文本内容 + /// 文字高度 + /// 文字属性设置委托 + /// 文字对象id + /// + public static ObjectId AddDBText(this BlockTableRecord btr, Point3d position, string text, double height, Action? action = null) + { + var acText = CreateDBText(position, text, height, btr.Database, action); + return btr.AddEntity(acText); + } /// /// 更正单行文字的镜像属性 diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/MTextEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/MTextEx.cs index fd39bac..1a27abd 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/MTextEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/MTextEx.cs @@ -6,6 +6,53 @@ public static class MTextEx { + /// + /// 创建多行文字 + /// + /// 插入点 + /// 文本内容 + /// 文字高度 + /// 文字所在的数据库 + /// 文字属性设置委托 + /// 文字对象id + /// + public static MText CreateMText(Point3d position, string text, double height, Database? database = null, Action? action = null) + { + if (string.IsNullOrEmpty(text)) + throw new ArgumentNullException(nameof(text), "创建文字无内容"); + + var mText = new MText(); + + mText.SetDatabaseDefaults(database ?? DBTrans.Top.Database); + + mText.TextHeight = height; // 高度 + mText.Contents = text; // 内容 + mText.Location = position; // 插入点 + + action?.Invoke(mText); + + return mText; + } + + + /// + /// 添加多行文字到块表记录 + /// + /// 块表记录 + /// 插入点 + /// 文本内容 + /// 文字高度 + /// 文字属性设置委托 + /// 文字对象id + /// + public static ObjectId AddMText(this BlockTableRecord btr, Point3d position, string text, double height, Action? action = null) + { + var mText = CreateMText(position, text, height, btr.Database, action); + + return btr.AddEntity(mText); + } + + /// /// 炸散多行文字 /// diff --git "a/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\346\226\207\345\255\227/TextEntityAdd.cs" "b/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\346\226\207\345\255\227/TextEntityAdd.cs" deleted file mode 100644 index f9ba03d..0000000 --- "a/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\346\226\207\345\255\227/TextEntityAdd.cs" +++ /dev/null @@ -1,62 +0,0 @@ -namespace IFoxCAD.Cad; -#if false -public static partial class EntityAdd -{ - /// - /// 创建单行文字 - /// - /// 数据库 - /// 内容 - /// 插入点 - /// 字体高度 - /// 文字样式 - /// 对齐方式 - /// 对齐点,因样式 可能无效 - /// - public static Entity AddDBTextToEntity(this Database db, - string textContents, - Point3d position, - double textHigh = 2.5, - ObjectId? textStyleId = null, - AttachmentPoint justify = AttachmentPoint.BaseLeft, - Point3d? justifyPoint = null) - { - var TextInfo = new TextInfo( - textContents, - position, - justify, - justifyPoint, - textStyleId, - textHigh); - return TextInfo.AddDBTextToEntity(); - } - - /// - /// 新建多行文字 - /// - /// 数据库 - /// 内容 - /// 插入点 - /// 字体高度 - /// 文字样式 - /// 对齐方式 - /// - public static Entity AddMTextToEntity(this Database db, - string textContents, - Point3d position, - double textHigh = 2.5, - ObjectId? textStyleId = null, - AttachmentPoint justify = AttachmentPoint.BaseLeft) - { - var TextInfo = new TextInfo( - textContents, - position, - justify, - null, - textStyleId, - textHigh); - return TextInfo.AddMTextToEntity(); - } -} - -#endif \ No newline at end of file diff --git "a/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\346\226\207\345\255\227/TextInfo.cs" "b/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\346\226\207\345\255\227/TextInfo.cs" deleted file mode 100644 index cf010d4..0000000 --- "a/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\346\226\207\345\255\227/TextInfo.cs" +++ /dev/null @@ -1,179 +0,0 @@ -namespace IFoxCAD.Cad; - -/// -/// 文字信息类 -/// -public class TextInfo -{ - readonly Database? Database; - readonly string? Contents; - readonly Point3d Position; - /// - /// 文字对齐方式的中文说明 - /// - public string TextJustifyCn => AttachmentPointHelper.Get(TextJustify); - readonly AttachmentPoint TextJustify; - readonly Point3d? AlignmentPoint; - - readonly double TextHeight; - readonly ObjectId? TextStyleId; - - /// - /// 文字信息类 - /// - /// 内容 - /// 基点 - /// 对齐方式 - /// 对齐点(对齐方式是左,此参数无效,为null不为左就报错) - /// 文字样式id - /// 文字高度 - /// 数据库 - public TextInfo(string? contents, - Point3d position, - AttachmentPoint justify, - Point3d? justifyPoint = null, - ObjectId? textStyleId = null, - double textHeight = 2.5, - Database? database = null) - { - Contents = contents; - Position = position; - TextJustify = justify; - - if (justifyPoint is null && TextJustify != AttachmentPoint.BaseLeft) - throw new ArgumentNullException(nameof(justifyPoint)); - - AlignmentPoint = justifyPoint; - TextHeight = textHeight; - TextStyleId = textStyleId; - Database = database; - } - - /// - /// 创建单行文字 - /// - public DBText AddDBTextToEntity() - { - if (string.IsNullOrEmpty(Contents)) - throw new ArgumentNullException(nameof(Contents) + "创建文字无内容"); - - var acText = new DBText(); - - acText.SetDatabaseDefaults(Database ?? DBTrans.Top.Database); - - if (TextStyleId is not null) - acText.SetTextStyleId(TextStyleId.Value); - - acText.Height = TextHeight; // 高度 - acText.TextString = Contents; // 内容 - acText.Position = Position; // 插入点(一定要先设置) - acText.Justify = TextJustify; // 使他们对齐 - // acText.HorizontalMode - - if (AlignmentPoint is not null) - acText.AlignmentPoint = AlignmentPoint.Value; - else if (acText.Justify != AttachmentPoint.BaseLeft) - acText.AlignmentPoint = Position; - - - acText.AdjustAlignment(Database ?? DBTrans.Top.Database); - return acText; - } - - /// - /// 创建多行文字 - /// - /// - public MText AddMTextToEntity() - { - if (string.IsNullOrEmpty(Contents)) - throw new ArgumentNullException(nameof(Contents) + "创建文字无内容"); - - var mText = new MText(); - - mText.SetDatabaseDefaults(Database ?? DBTrans.Top.Database); - - if (TextStyleId is not null) - mText.SetTextStyleId(TextStyleId.Value); - - mText.TextHeight = TextHeight; // 高度 - mText.Contents = Contents; // 内容 - mText.Location = Position; // 插入点(一定要先设置) - - // mText.SetAttachmentMovingLocation(TextJustify); - mText.Attachment = TextJustify;// 使他们对齐 - - return mText; - } -} - - -/// -/// 反射设定对象的文字样式id -/// -public static partial class TextInfoHelper -{ - /// - /// 设置文字样式id - /// - /// 单行文字 - /// 文字样式表记录id - public static void SetTextStyleId(this DBText acText, ObjectId ltrObjectId) - { - SetEntityTxtStyleId(acText, ltrObjectId); - } - - /// - /// 设置文字样式id - /// - /// 多行文字 - /// 文字样式表记录id - public static void SetTextStyleId(this MText acText, ObjectId ltrObjectId) - { - SetEntityTxtStyleId(acText, ltrObjectId); - } - - static void SetEntityTxtStyleId(Entity acText, ObjectId ltrObjectId) - { - GetTextStyleIdType(acText)?.SetValue(acText, ltrObjectId, null); - } - - /// - /// 获取文字样式id - /// - public static ObjectId GetTextStyleId(this DBText acText) - { - return GetEntityTxtStyleId(acText); - } - - /// - /// 获取文字样式id - /// - public static ObjectId GetTextStyleId(this MText acText) - { - return GetEntityTxtStyleId(acText); - } - - static ObjectId GetEntityTxtStyleId(Entity acText) - { - var result = ObjectId.Null; - var id = GetTextStyleIdType(acText)?.GetValue(acText, null); - if (id != null) - result = (ObjectId)id; - return result; - } - - static PropertyInfo? _textStyleId = null; - static PropertyInfo GetTextStyleIdType(Entity acText) - { - if (_textStyleId == null) - { - var entType = acText.GetType(); - var prs = entType.GetProperties(); - _textStyleId = prs.FirstOrDefault(a => a.Name == "TextStyle");// 反射获取属性 - if (_textStyleId == null) - _textStyleId = prs.FirstOrDefault(a => a.Name == "TextStyleId");// 反射获取属性 - } - return _textStyleId; - } -} diff --git a/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems b/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems index 87d4520..fa2fe30 100644 --- a/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems +++ b/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems @@ -64,8 +64,6 @@ - - diff --git a/tests/TestShared/TestBlock.cs b/tests/TestShared/TestBlock.cs index 9459304..88dcdee 100644 --- a/tests/TestShared/TestBlock.cs +++ b/tests/TestShared/TestBlock.cs @@ -69,9 +69,7 @@ public void Test_BlockDef() }, () => { var line = new Line(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); - var acText = new TextInfo("123", Point3d.Origin, AttachmentPoint.BaseLeft) - .AddDBTextToEntity(); - + var acText = DBTextEx.CreateDBText(Point3d.Origin, "123", 2.5); return new List { line, acText }; }); } @@ -105,8 +103,7 @@ public void Test_BlockDefbehind() }, () => { var line = new Line(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); - var acText = new TextInfo("12345", Point3d.Origin, AttachmentPoint.BaseLeft) - .AddDBTextToEntity(); + var acText = DBTextEx.CreateDBText(Point3d.Origin, "12345", 2.5); return new List { line, acText }; }); @@ -210,7 +207,8 @@ public void Test_InsertBlockWithDoubleDatabase() }, () => { var line = new Line(new(0, 0, 0), new(1, 1, 0)); - var actext = new TextInfo("123", Point3d.Origin, AttachmentPoint.BaseLeft, database: tr.Database).AddDBTextToEntity(); + var actext = DBTextEx.CreateDBText(Point3d.Origin, "123", 2.5, tr.Database); + return new List { line,actext }; }); diff --git a/tests/TestShared/TestJig.cs b/tests/TestShared/TestJig.cs index 6db1f38..c0bf411 100644 --- a/tests/TestShared/TestJig.cs +++ b/tests/TestShared/TestJig.cs @@ -75,8 +75,7 @@ public void Test_Jig44() // 生成文字 var dictString = (pl.GetDistAtPoint(closestPt) * 0.001).ToString("0.00"); - var acText = new TextInfo(dictString, closestPt, AttachmentPoint.BaseLeft, textHeight: 200) - .AddDBTextToEntity(); + var acText = DBTextEx.CreateDBText(closestPt, dictString, 200); // 加入刷新队列 drawEntitys.Enqueue(acText); @@ -186,10 +185,7 @@ static public void Test_QuickText() var btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite); // Create the text object, set its normal and contents - var acText = new TextInfo(pr.StringResult, - Point3d.Origin, - AttachmentPoint.BaseLeft, textHeight: 200) - .AddDBTextToEntity(); + var acText = DBTextEx.CreateDBText(Point3d.Origin, pr.StringResult, 200); acText.Normal = ed.CurrentUserCoordinateSystem.CoordinateSystem3d.Zaxis; btr.AppendEntity(acText); diff --git a/tests/TestShared/TestShared.projitems b/tests/TestShared/TestShared.projitems index bd01c5c..491333d 100644 --- a/tests/TestShared/TestShared.projitems +++ b/tests/TestShared/TestShared.projitems @@ -34,6 +34,7 @@ + diff --git a/tests/TestShared/TestText.cs b/tests/TestShared/TestText.cs new file mode 100644 index 0000000..bc23dc9 --- /dev/null +++ b/tests/TestShared/TestText.cs @@ -0,0 +1,32 @@ + +namespace TestShared; + +public class TestText +{ + + [CommandMethod(nameof(TestDBText))] + public void TestDBText() + { + using var tr = new DBTrans(); + tr.CurrentSpace.AddDBText(new(-1, -1, 0), "123", 2.5, t=> t.ColorIndex = 1); + + tr.CurrentSpace.AddDBText(new(0, 0, 0), "123", 2.5, t => { + t.Justify = AttachmentPoint.BaseCenter; + t.AlignmentPoint = new(1, 1, 0); + t.ColorIndex = 2; + }); + } + + [CommandMethod(nameof(TestMText))] + public void TestMText() + { + using var tr = new DBTrans(); + tr.CurrentSpace.AddMText(new(5, 5, 0), "123", 2.5, t => t.ColorIndex = 1); + + tr.CurrentSpace.AddMText(new(10, 10, 0), "123", 2.5, t => { + t.Attachment = AttachmentPoint.TopCenter; + t.ColorIndex = 2; + }); + } + +} -- Gitee From 8360085e09e15de1f2db2593da25b20824ab8b67 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Fri, 17 Mar 2023 12:24:46 +0800 Subject: [PATCH 014/453] =?UTF-8?q?=E7=9E=AC=E6=80=81=E5=9B=BA=E5=AE=9A?= =?UTF-8?q?=E7=9B=AE=E6=A0=87manager=EF=BC=8C=E9=81=BF=E5=85=8D=E5=A4=9A?= =?UTF-8?q?=E6=96=87=E6=A1=A3=E5=88=87=E6=8D=A2=E5=90=8E=E5=BD=93=E5=89=8D?= =?UTF-8?q?=E7=9E=AC=E6=80=81=E5=AE=B9=E5=99=A8=E6=94=B9=E5=8F=98=E9=80=A0?= =?UTF-8?q?=E6=88=90=E7=9A=84=E6=98=BE=E7=A4=BA=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/JigExTransient.cs | 24 +++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/JigExTransient.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/JigExTransient.cs index c7532b9..9d3bf6b 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/JigExTransient.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/JigExTransient.cs @@ -8,9 +8,10 @@ public class JigExTransient : IDisposable { #region 私有字段 // 整数集,暂时不知道有什么意义 - IntegerCollection _integerCollection; + readonly IntegerCollection _integerCollection; // 维护集合 - HashSet _entities; + readonly HashSet _entities; + readonly TransientManager _manager; #endregion #region 公开属性 @@ -31,7 +32,8 @@ public class JigExTransient : IDisposable public JigExTransient() { _integerCollection = new(); - _entities = new(); + _entities = new(); + _manager=TransientManager.CurrentTransientManager; } #endregion @@ -55,9 +57,7 @@ public void Add(Entity ent, TransientDrawingMode tdm = TransientDrawingMode.Main { if (_entities.Add(ent)) { - TransientManager - .CurrentTransientManager - .AddTransient(ent, tdm, 128, _integerCollection); + _manager.AddTransient(ent, tdm, 128, _integerCollection); } } @@ -70,9 +70,7 @@ public void Remove(Entity ent) { if (!Contains(ent)) return; - TransientManager - .CurrentTransientManager - .EraseTransient(ent, _integerCollection); + _manager.EraseTransient(ent, _integerCollection); _entities.Remove(ent); } @@ -83,9 +81,7 @@ public void Clear() { foreach (var ent in _entities) { - TransientManager - .CurrentTransientManager - .EraseTransient(ent, _integerCollection); + _manager.EraseTransient(ent, _integerCollection); } _entities.Clear(); } @@ -99,9 +95,7 @@ public void Update(Entity ent) { if (!Contains(ent)) return; - TransientManager - .CurrentTransientManager - .UpdateTransient(ent, _integerCollection); + _manager.UpdateTransient(ent, _integerCollection); } /// -- Gitee From f7ef34f3fdff2ed6564394311266f0497406ebc1 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Fri, 17 Mar 2023 18:25:04 +0800 Subject: [PATCH 015/453] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=9B=B4=E5=AE=8C?= =?UTF-8?q?=E7=BE=8E=E7=9A=84=E6=9B=B2=E7=BA=BF=E6=89=93=E6=96=AD=E5=87=BD?= =?UTF-8?q?=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/CurveEx.cs | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/CurveEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/CurveEx.cs index bfca634..b51b0ac 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/CurveEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/CurveEx.cs @@ -207,6 +207,77 @@ public static List BreakCurve(this List curves) return newCurves; } + /// + /// 打断曲线 + /// + /// 曲线列表 + /// 打断后的曲线列表 + /// 传入的曲线列表错误 + public static List BreakCurve2d(this List curves) + { + if (curves is null) + throw new ArgumentNullException(nameof(curves)); + + var curvesTemp = curves.Select(c => c.GetProjectedCurve(DYHEnv.PlaneZ, Vector3d.ZAxis)).ToList(); + var geCurves = new List(); // 存储曲线转换后的复合曲线 + var paramss = new List>(); // 存储每个曲线的交点参数值 + + for (int i = 0; i < curvesTemp.Count; i++) + { + paramss.Add(new HashSet()); + var cc3d = curvesTemp[i].ToCompositeCurve3d(); + if (cc3d is not null) + { + geCurves.Add(cc3d); + } + } + var newCurves = new List(); + var cci3d = new CurveCurveIntersector3d(); + + for (int i = 0; i < curvesTemp.Count; i++) + { + var gc1 = geCurves[i]; + var pars1 = paramss[i]; // 引用 + for (int j = i; j < curvesTemp.Count; j++) + { + var gc2 = geCurves[j]; + var pars2 = paramss[j]; // 引用 + + cci3d.Set(gc1, gc2, Vector3d.ZAxis); + + for (int k = 0; k < cci3d.NumberOfIntersectionPoints; k++) + { + var pars = cci3d.GetIntersectionParameters(k); + pars1.Add(pars[0]); // 引用修改会同步到源对象 + pars2.Add(pars[1]); // 引用修改会同步到源对象 + } + } + var curNow = curvesTemp[i]; + curNow.GetType().Name.Prompt(); + pars1.ForEach(p => p.Prompt()); + var length = curNow.GetLength(); + List np = pars1.Where(p => p >= 0 && p <= length).Select(curNow.GetParameterAtDistance).Where(p => !(Math.Abs(p - curNow.StartParam) < 1e-6 || Math.Abs(p - curNow.EndParam) < 1e-6)).ToList(); + np.ForEach(p => p.Prompt()); + if (np.Count > 0) + { + var splitCurs = curNow.GetSplitCurves(np, true); + if (splitCurs.Count() > 1) + { + newCurves.AddRange(splitCurs); + } + else + { + newCurves.Add(curNow.CloneEx()); + } + } + else + { + newCurves.Add(curNow.CloneEx()); + } + } + + return newCurves; + } // 转换DBCurve为GeCurved #region Curve -- Gitee From 70fabe69f3a5437e4c68543b87e8ef3e71aabf30 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Fri, 17 Mar 2023 18:45:01 +0800 Subject: [PATCH 016/453] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=97=A0=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E5=8C=B9=E9=85=8D=E7=9A=84GetObject=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs b/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs index b185b76..b685cc5 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs @@ -390,6 +390,21 @@ public static implicit operator Transaction(DBTrans tr) #region 获取对象 /// + /// 根据对象id获取对象 + /// + /// 对象id + /// 打开模式,默认为只读 + /// 是否打开已删除对象,默认为不打开 + /// 是否打开锁定图层对象,默认为不打开 + /// 数据库DBObject对象 + public DBObject GetObject(ObjectId id, + OpenMode openMode = OpenMode.ForRead, + bool openErased = false, + bool openLockedLayer = false) + { + return Transaction.GetObject(id, openMode, openErased, openLockedLayer); + } + /// /// 根据对象id获取图元对象 /// /// 要获取的图元对象的类型 -- Gitee From 9f9523d98422002f708d02394650db10bf4de0c4 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sat, 18 Mar 2023 12:13:35 +0800 Subject: [PATCH 017/453] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=9B=B2=E7=BA=BF?= =?UTF-8?q?=E6=89=93=E6=96=AD=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../IFox.CAD.Shared/ExtensionMethod/CurveEx.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/CurveEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/CurveEx.cs index b51b0ac..f8b83b5 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/CurveEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/CurveEx.cs @@ -208,17 +208,17 @@ public static List BreakCurve(this List curves) } /// - /// 打断曲线 + /// 在z法向量平面打断曲线 /// /// 曲线列表 /// 打断后的曲线列表 /// 传入的曲线列表错误 - public static List BreakCurve2d(this List curves) + public static List BreakCurveOnZPlane(this List curves) { if (curves is null) throw new ArgumentNullException(nameof(curves)); - - var curvesTemp = curves.Select(c => c.GetProjectedCurve(DYHEnv.PlaneZ, Vector3d.ZAxis)).ToList(); + var zPlane = new Plane(Point3d.Origin, Vector3d.ZAxis); + var curvesTemp = curves.Select(c => c.GetProjectedCurve(zPlane, Vector3d.ZAxis)).ToList(); var geCurves = new List(); // 存储曲线转换后的复合曲线 var paramss = new List>(); // 存储每个曲线的交点参数值 @@ -253,11 +253,11 @@ public static List BreakCurve2d(this List curves) } } var curNow = curvesTemp[i]; - curNow.GetType().Name.Prompt(); - pars1.ForEach(p => p.Prompt()); var length = curNow.GetLength(); - List np = pars1.Where(p => p >= 0 && p <= length).Select(curNow.GetParameterAtDistance).Where(p => !(Math.Abs(p - curNow.StartParam) < 1e-6 || Math.Abs(p - curNow.EndParam) < 1e-6)).ToList(); - np.ForEach(p => p.Prompt()); + List np = pars1.Where(p => p >= 0 && p <= length) + .Select(curNow.GetParameterAtDistance) + .Where(p => !(Math.Abs(p - curNow.StartParam) < 1e-6 || Math.Abs(p - curNow.EndParam) < 1e-6)) + .ToList(); if (np.Count > 0) { var splitCurs = curNow.GetSplitCurves(np, true); -- Gitee From e4c90cf2cb1a96458f8e1a1711510ebbc2d9b078 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sat, 18 Mar 2023 12:19:57 +0800 Subject: [PATCH 018/453] =?UTF-8?q?=E5=B8=A6=E6=B3=9B=E5=9E=8B=E7=9A=84Get?= =?UTF-8?q?Objext=E6=94=B9=E4=B8=BA=E4=B8=8D=E5=8C=B9=E9=85=8D=E6=8A=9B?= =?UTF-8?q?=E9=94=99=E5=90=8E=EF=BC=8C=E4=B8=8D=E8=83=BD=E5=86=8D=E7=94=A8?= =?UTF-8?q?=E4=BA=8E=E6=89=B9=E9=87=8F=E7=AD=9B=E9=80=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/DBDictionaryEx.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBDictionaryEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBDictionaryEx.cs index 3942b6c..66fe217 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBDictionaryEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBDictionaryEx.cs @@ -18,9 +18,8 @@ public static IEnumerable GetAllObjects(this DBDictionary dict) where T : var tr = DBTrans.GetTopTransaction(dict.Database); foreach (DBDictionaryEntry e in dict) { - var ent = tr.GetObject(e.Value, OpenMode.ForRead); - if (ent is not null) - yield return ent; + if(tr.GetObject(e.Value) is T tobj) + yield return tobj; } } -- Gitee From 2ad1ce7c7db8db382b885501f1838ebeac0a2560 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sun, 19 Mar 2023 13:54:53 +0800 Subject: [PATCH 019/453] =?UTF-8?q?=E4=BF=AE=E5=A4=8DAddEntity=E5=87=BD?= =?UTF-8?q?=E6=95=B0=E5=B5=8C=E5=A5=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs index 5a9cdf7..1518159 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs @@ -119,7 +119,7 @@ public static IEnumerable AddEntity(this BlockTableRecord btr, IEnu /// 对象 id 列表 public static IEnumerable AddEntity(this BlockTableRecord btr, params Entity[] ents) { - return btr.AddEntity(ents); + return btr.AddEntity(ents.ToList()); } #endregion -- Gitee From c4edd9c780d4fcd16e5e004c89d8f4efd72d934d Mon Sep 17 00:00:00 2001 From: vicwjb Date: Mon, 20 Mar 2023 21:44:43 +0800 Subject: [PATCH 020/453] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=97=A0=E7=94=A8?= =?UTF-8?q?=E7=9A=84=E6=B3=A8=E9=87=8A=E4=BB=A3=E7=A0=81=EF=BC=8C=E7=A7=BB?= =?UTF-8?q?=E9=99=A4=E6=96=B0=E5=BB=BA=E6=96=87=E5=AD=97=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E5=A4=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/AttachmentPointHelper.cs | 42 ------------------- .../IFox.CAD.Shared/IFox.CAD.Shared.projitems | 2 +- 2 files changed, 1 insertion(+), 43 deletions(-) rename "src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\346\226\207\345\255\227/AttachmentPointHelper.cs" => src/CAD/IFox.CAD.Shared/ExtensionMethod/AttachmentPointHelper.cs (62%) diff --git "a/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\346\226\207\345\255\227/AttachmentPointHelper.cs" b/src/CAD/IFox.CAD.Shared/ExtensionMethod/AttachmentPointHelper.cs similarity index 62% rename from "src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\346\226\207\345\255\227/AttachmentPointHelper.cs" rename to src/CAD/IFox.CAD.Shared/ExtensionMethod/AttachmentPointHelper.cs index f94fd08..42c78cd 100644 --- "a/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\346\226\207\345\255\227/AttachmentPointHelper.cs" +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/AttachmentPointHelper.cs @@ -54,45 +54,3 @@ public static string Get(AttachmentPoint value) return _alignment.FirstOrDefault(q => q.Value == value).Key; } } - -#if false -// 反射描述 -// 这些东西cad没有用到啊...所以不纳入了 -public enum AttachmentPoint2 -{ - [Description("下对齐")] - BottomAlign = 14, - [Description("中对齐")] - MiddleAlign = 15,// 0xF - [Description("上对齐")] - TopAlign = 16,// 0x10 - [Description("下铺满")] - BottomFit = 18, - [Description("中铺满")] - MiddleFit = 19, - [Description("上铺满")] - TopFit = 20, - [Description("下居中")] - BottomMid = 22, - [Description("中居中")] - MiddleMid = 23, - [Description("下居中")] - TopMid = 24, -} - -public static Dictionary GetEnumDic(Type enumType) -{ - Dictionary dic = new(); - var fieldinfos = enumType.GetFields(); - for (int i = 0; i < fieldinfos.Length; i++) - { - var field = fieldinfos[i]; - if (field.FieldType.IsEnum) - { - var objs = field.GetCustomAttributes(typeof(DescriptionAttribute), false); - dic.Add(field.Name, ((DescriptionAttribute)objs[0]).Description); - } - } - return dic; -} -#endif \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems b/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems index fa2fe30..3cfc4f0 100644 --- a/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems +++ b/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems @@ -63,7 +63,7 @@ - + -- Gitee From fe13d396dd71af1267020e36091cdfc71c6959a9 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Mon, 20 Mar 2023 21:48:05 +0800 Subject: [PATCH 021/453] =?UTF-8?q?=E5=B0=86=E6=8B=96=E6=9B=B3=E7=B1=BB?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E6=94=BE=E5=9C=A8=E4=B8=80=E4=B8=AA=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E5=A4=B9=E9=87=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/{ => Jig}/JigEx.cs | 0 .../ExtensionMethod/{ => Jig}/JigExTransient.cs | 0 src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems | 5 +++-- 3 files changed, 3 insertions(+), 2 deletions(-) rename src/CAD/IFox.CAD.Shared/ExtensionMethod/{ => Jig}/JigEx.cs (100%) rename src/CAD/IFox.CAD.Shared/ExtensionMethod/{ => Jig}/JigExTransient.cs (100%) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/JigEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigEx.cs similarity index 100% rename from src/CAD/IFox.CAD.Shared/ExtensionMethod/JigEx.cs rename to src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigEx.cs diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/JigExTransient.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigExTransient.cs similarity index 100% rename from src/CAD/IFox.CAD.Shared/ExtensionMethod/JigExTransient.cs rename to src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigExTransient.cs diff --git a/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems b/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems index 3cfc4f0..0ce7697 100644 --- a/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems +++ b/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems @@ -42,8 +42,8 @@ - - + + @@ -97,5 +97,6 @@ + \ No newline at end of file -- Gitee From ef3d93310966201ee42c16b6551ae36ae01cbbe2 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Mon, 20 Mar 2023 22:51:29 +0800 Subject: [PATCH 022/453] =?UTF-8?q?=E5=88=A0=E9=99=A4net35=E6=94=AF?= =?UTF-8?q?=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Basal/IFox.Basal.Shared/CLS/ValueTuple.cs | 29 - .../IFox.Basal.Shared.projitems | 5 - src/Basal/IFox.Basal.Shared/Sortedset/ISet.cs | 65 - src/Basal/IFox.Basal.Shared/Sortedset/SR.cs | 902 ----- .../IFox.Basal.Shared/Sortedset/Sortedset.cs | 2901 ----------------- .../Sortedset/ThrowHelper.cs | 381 --- .../IFox.Basal.Shared/Sortedset/bithelper.cs | 170 - src/Basal/IFox.Basal/IFox.Basal.csproj | 2 +- src/CAD/IFox.CAD.ACAD/IFox.CAD.ACAD.csproj | 8 +- src/CAD/IFox.CAD.Shared/AutoReg/AutoLoad.cs | 10 +- .../IFox.CAD.Shared/AutoReg/AutoRegAssem.cs | 4 - src/CAD/IFox.CAD.Shared/AutoReg/IAutoGo.cs | 4 +- .../IFox.CAD.Shared/CadVersion/CadVersion.cs | 56 +- .../Copyclip/TagClipboardInfo.cs | 5 +- .../ExtensionMethod/CadInternalUtils.cs | 30 - .../ExtensionMethod/CurveEx.cs | 4 - .../ExtensionMethod/EditorEx.cs | 95 +- .../ExtensionMethod/Entity/ArcEx.cs | 5 +- .../ExtensionMethod/Filer/DwgFiler.cs | 57 +- .../ExtensionMethod/Jig/JigExTransient.cs | 2 +- .../ExtensionMethod/ObjectIdEx.cs | 10 +- .../ExtensionMethod/SelectionSetEx.cs | 4 +- .../ExtensionMethod/SymbolTableRecordEx.cs | 4 +- .../IFox.CAD.Shared/ExtensionMethod/XrefEx.cs | 21 - .../HatchInfo.cs" | 30 - .../IFox.CAD.Shared/IFox.CAD.Shared.projitems | 2 - src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs | 13 +- .../IFox.CAD.Shared/Runtime/DBTransHelper.cs | 89 - src/CAD/IFox.CAD.Shared/Runtime/Env.cs | 10 - tests/TestAcad09plus/GlobalUsings.cs | 4 +- ...350\275\254cad\345\235\220\346\240\207.cs" | 15 +- ...71\347\202\271\344\276\213\345\255\220.cs" | 5 +- tests/TestShared/Copyclip.cs | 4 +- tests/TestShared/TestAddEntity.cs | 1 + tests/TestShared/TestBlock.cs | 4 +- tests/TestShared/TestCurve.cs | 4 - tests/TestShared/TestEnv.cs | 2 +- tests/TestShared/TestJigExTransient.cs | 3 +- tests/TestShared/TestLisp.cs | 8 +- tests/TestShared/TestXRecord.cs | 33 +- 40 files changed, 69 insertions(+), 4932 deletions(-) delete mode 100644 src/Basal/IFox.Basal.Shared/Sortedset/ISet.cs delete mode 100644 src/Basal/IFox.Basal.Shared/Sortedset/SR.cs delete mode 100644 src/Basal/IFox.Basal.Shared/Sortedset/Sortedset.cs delete mode 100644 src/Basal/IFox.Basal.Shared/Sortedset/ThrowHelper.cs delete mode 100644 src/Basal/IFox.Basal.Shared/Sortedset/bithelper.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/CadInternalUtils.cs delete mode 100644 src/CAD/IFox.CAD.Shared/Runtime/DBTransHelper.cs diff --git a/src/Basal/IFox.Basal.Shared/CLS/ValueTuple.cs b/src/Basal/IFox.Basal.Shared/CLS/ValueTuple.cs index c209024..3ce158c 100644 --- a/src/Basal/IFox.Basal.Shared/CLS/ValueTuple.cs +++ b/src/Basal/IFox.Basal.Shared/CLS/ValueTuple.cs @@ -4,19 +4,7 @@ // #pragma warning disable SA1141 // explicitly not using tuple syntax in tuple implementation #if !NOVALUETUPLE -using System.Diagnostics; using System.Numerics.Hashing; -/* - * 惊惊: - * 首先是因为有人想要编译的时候只形成一个dll,然后把元组塞入IFox,同时也补充了NET35没有元组的遗憾. - * - * 而利用nuget元组包必然会形成依赖地狱. - * - * 如果你的工程使用了nuget元组包,就造成了必须要剔除IFox. - * - * 改IFox的元组命名空间倒是可以分离两者,但是 vs编译器 无法识别带其他命名空间的元组. - * 所以元组本身就是冲突的,需要把其他元组卸载掉,由IFox提供. - */ /* * 1. 元组是net47之后提供的特性,所以net47之前的版本是都没有的 @@ -25,23 +13,6 @@ * 这些类库,所以还是使用源码包吧。 */ -#if NET35 -namespace System.Collections -{ - public interface IStructuralComparable - { - int CompareTo(object? other, IComparer comparer); - } - public interface IStructuralEquatable - { - bool Equals(object? other, IEqualityComparer comparer); - int GetHashCode(IEqualityComparer comparer); - } -} -#endif - - - namespace System.Numerics.Hashing { internal static class HashHelpers diff --git a/src/Basal/IFox.Basal.Shared/IFox.Basal.Shared.projitems b/src/Basal/IFox.Basal.Shared/IFox.Basal.Shared.projitems index 64a78d7..b5a563a 100644 --- a/src/Basal/IFox.Basal.Shared/IFox.Basal.Shared.projitems +++ b/src/Basal/IFox.Basal.Shared/IFox.Basal.Shared.projitems @@ -31,11 +31,6 @@ - - - - - diff --git a/src/Basal/IFox.Basal.Shared/Sortedset/ISet.cs b/src/Basal/IFox.Basal.Shared/Sortedset/ISet.cs deleted file mode 100644 index 22b9509..0000000 --- a/src/Basal/IFox.Basal.Shared/Sortedset/ISet.cs +++ /dev/null @@ -1,65 +0,0 @@ -#if NET35 -// ==++== -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// -// ==--== -/*============================================================ -** -** Interface: ISet -** -** kimhamil -** -** -** Purpose: Base interface for all generic sets. -** -** -===========================================================*/ -namespace System.Collections.Generic -{ - using System; - using System.Runtime.CompilerServices; - - - /// - /// Generic collection that guarantees the uniqueness of its elements, as defined - /// by some comparer. It also supports basic set operations such as Union, Intersection, - /// Complement and Exclusive Complement. - /// - public interface ISet : ICollection - { - // Add ITEM to the set, return true if added, false if duplicate - new bool Add(T item); - - // Transform this set into its union with the IEnumerable other - void UnionWith(IEnumerable other); - - // Transform this set into its intersection with the IEnumberable other - void IntersectWith(IEnumerable other); - - // Transform this set so it contains no elements that are also in other - void ExceptWith(IEnumerable other); - - // Transform this set so it contains elements initially in this or in other, but not both - void SymmetricExceptWith(IEnumerable other); - - // Check if this set is a subset of other - bool IsSubsetOf(IEnumerable other); - - // Check if this set is a superset of other - bool IsSupersetOf(IEnumerable other); - - // Check if this set is a subset of other, but not the same as it - bool IsProperSupersetOf(IEnumerable other); - - // Check if this set is a superset of other, but not the same as it - bool IsProperSubsetOf(IEnumerable other); - - // Check if this set has any elements in common with other - bool Overlaps(IEnumerable other); - - // Check if this set contains the same and only the same elements as other - bool SetEquals(IEnumerable other); - } -} -#endif \ No newline at end of file diff --git a/src/Basal/IFox.Basal.Shared/Sortedset/SR.cs b/src/Basal/IFox.Basal.Shared/Sortedset/SR.cs deleted file mode 100644 index 88b2bcf..0000000 --- a/src/Basal/IFox.Basal.Shared/Sortedset/SR.cs +++ /dev/null @@ -1,902 +0,0 @@ -#if NET35 -#pragma warning disable CS8603 // 可能返回 null 引用。 -namespace System; - - -using System; -using System.Reflection; -using System.Globalization; -using System.Resources; -using System.Text; -using System.ComponentModel; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; - -[AttributeUsage(AttributeTargets.All)] -internal sealed class SRDescriptionAttribute : DescriptionAttribute -{ - public SRDescriptionAttribute(string description) - { - DescriptionValue = SR.GetString(description); - } - - public SRDescriptionAttribute(string description, string resourceSet) - { - ResourceManager rm = new ResourceManager(resourceSet, Assembly.GetExecutingAssembly()); - DescriptionValue = rm.GetString(description); - System.Diagnostics.Debug.Assert(DescriptionValue != null, string.Format(CultureInfo.CurrentCulture, "String resource {0} not found.", new object[] { description })); - } -} - -[AttributeUsage(AttributeTargets.All)] -internal sealed class SRCategoryAttribute : CategoryAttribute -{ - private string resourceSet = String.Empty; - - public SRCategoryAttribute(string category) - : base(category) - { - } - - public SRCategoryAttribute(string category, string resourceSet) - : base(category) - { - this.resourceSet = resourceSet; - } - - protected override string GetLocalizedString(string value) - { - if (this.resourceSet.Length > 0) - { - ResourceManager rm = new ResourceManager(resourceSet, Assembly.GetExecutingAssembly()); - String localizedString = rm.GetString(value); - System.Diagnostics.Debug.Assert(localizedString != null, string.Format(CultureInfo.CurrentCulture, "String resource {0} not found.", new object[] { value })); - return localizedString; - } - else - { - return SR.GetString(value); - } - } -} - -[AttributeUsage(AttributeTargets.All)] -internal sealed class SRDisplayNameAttribute : DisplayNameAttribute -{ - public SRDisplayNameAttribute(string name) - { - DisplayNameValue = SR.GetString(name); - } - - public SRDisplayNameAttribute(string name, string resourceSet) - { - ResourceManager rm = new ResourceManager(resourceSet, Assembly.GetExecutingAssembly()); - DisplayNameValue = rm.GetString(name); - System.Diagnostics.Debug.Assert(DisplayNameValue != null, string.Format(CultureInfo.CurrentCulture, "String resource {0} not found.", new object[] { name })); - } -} - -/// -/// AutoGenerated resource class. Usage: -/// -/// string s = SR.GetString(SR.MyIdenfitier); -/// -internal sealed partial class SR -{ -#pragma warning disable CS8625 // 无法将 null 字面量转换为非 null 的引用类型。 - static SR loader = null; -#pragma warning restore CS8625 // 无法将 null 字面量转换为非 null 的引用类型。 - ResourceManager resources; - - internal SR() - { - resources = new System.Resources.ResourceManager("System.Workflow.ComponentModel.StringResources", Assembly.GetExecutingAssembly()); - } - - private static SR GetLoader() - { - if (loader == null) - loader = new SR(); - return loader; - } - - private static CultureInfo Culture - { - get { return null/*use ResourceManager default, CultureInfo.CurrentUICulture*/; } - } - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal static string GetString(string name, params object[] args) - { - return GetString(SR.Culture, name, args); - } - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal static string GetString(CultureInfo culture, string name, params object[] args) - { - SR sys = GetLoader(); - if (sys == null) - return null; - string res = sys.resources.GetString(name, culture); - System.Diagnostics.Debug.Assert(res != null, string.Format(CultureInfo.CurrentCulture, "String resource {0} not found.", new object[] { name })); - if (args != null && args.Length > 0) - return string.Format(CultureInfo.CurrentCulture, res, args); - return res; - } - - internal static string GetString(string name) - { - return GetString(SR.Culture, name); - } - - internal static string GetString(CultureInfo culture, string name) - { - SR sys = GetLoader(); - if (sys == null) - return null; - string res = sys.resources.GetString(name, culture); - System.Diagnostics.Debug.Assert(res != null, string.Format(CultureInfo.CurrentCulture, "String resource {0} not found.", new object[] { name })); - return res; - } - - // All these strings should be present in StringResources.resx - internal const string Activity = "Activity"; - internal const string Handlers = "Handlers"; - internal const string Conditions = "Conditions"; - internal const string ConditionedActivityConditions = "ConditionedActivityConditions"; - internal const string Correlations = "Correlations"; - internal const string CorrelationSet = "CorrelationSet"; - internal const string NameDescr = "NameDescr"; - internal const string EnabledDescr = "EnabledDescr"; - internal const string DescriptionDescr = "DescriptionDescr"; - internal const string UnlessConditionDescr = "UnlessConditionDescr"; - internal const string InitializeDescr = "InitializeDescr"; - internal const string CatchTypeDescr = "CatchTypeDescr"; - internal const string ExceptionTypeDescr = "ExceptionTypeDescr"; - internal const string FaultDescription = "FaultDescription"; - internal const string FaultTypeDescription = "FaultTypeDescription"; - internal const string ContainingAssemblyDescr = "ContainingAssemblyDescr"; - internal const string ExecutionModeDescr = "ExecutionModeDescr"; - internal const string Error_ReadOnlyTemplateActivity = "Error_ReadOnlyTemplateActivity"; - internal const string Error_TypeNotString = "Error_TypeNotString"; - internal const string Error_InvalidErrorType = "Error_InvalidErrorType"; - internal const string Error_LiteralConversionFailed = "Error_LiteralConversionFailed"; - internal const string Error_TypeNotPrimitive = "Error_TypeNotPrimitive"; - internal const string CompletedCaleeDescr = "CompletedCaleeDescr"; - internal const string ProxyClassDescr = "ProxyClassDescr"; - internal const string ActivitySetDescr = "ActivitySetDescr"; - internal const string VersionDescr = "VersionDescr"; - internal const string ActivationDescr = "ActivationDescr"; - internal const string CorrelationSetsDescr = "CorrelationSetsDescr"; - internal const string CompanionClassDescr = "CompanionClassDescr"; - internal const string TransactionTypeDescr = "TransactionTypeDescr"; - internal const string SynchronizedDescr = "SynchronizedDescr"; - internal const string IsolationLevelDescr = "IsolationLevelDescr"; - internal const string TimeoutDescr = "TimeoutDescr"; - internal const string BatchableDescr = "BatchableDescr"; - internal const string LRTTimeoutDescr = "LRTTimeoutDescr"; - internal const string OnGetCalleeCountDescr = "OnGetCalleeCountDescr"; - internal const string CompensatableActivityDescr = "CompensatableActivityDescr"; - internal const string OnAfterEventDescr = "OnAfterEventDescr"; - internal const string OnBeforeMethodInvokeDescr = "OnBeforeMethodInvokeDescr"; - internal const string AssignedToDescr = "AssignedToDescr"; - internal const string TypeDescr = "TypeDescr"; - internal const string TemplateActivityDescr = "TemplateActivityDescr"; - internal const string ErrorMessageDescr = "ErrorMessageDescr"; - internal const string WebServiceSynchronizedDescr = "WebServiceSynchronizedDescr"; - internal const string CorrelationSetDescr = "CorrelationSetDescr"; - internal const string ExecutionTypeDescr = "ExecutionTypeDescr"; - internal const string RoleDescr = "RoleDescr"; - internal const string OnInitializeClonesDescr = "OnInitializeClonesDescr"; - internal const string CorrelationSetDisplayName = "CorrelationSetDisplayName"; - internal const string PastingActivities = "PastingActivities"; - internal const string DeletingActivities = "DeletingActivities"; - internal const string DragDropActivities = "DragDropActivities"; - internal const string ChangingEnabled = "ChangingEnabled"; - internal const string ChangingHandler = "ChangingHandler"; - internal const string ChangingParameter = "ChangingParameter"; - internal const string CollectionItem = "CollectionItem"; - internal const string AddingConditionalBranch = "AddingConditionalBranch"; - internal const string AddingEventActivity = "AddingEventActivity"; - internal const string AddingListenBranch = "AddingListenBranch"; - internal const string AddingParallelBranch = "AddingParallelBranch"; - internal const string CurrentProject = "CurrentProject"; - internal const string ReferencedAssemblies = "ReferencedAssemblies"; - internal const string CollectionText = "CollectionText"; - internal const string ParameterDescription = "ParameterDescription"; - internal const string InvokeParameterDescription = "InvokeParameterDescription"; - internal const string ParametersDescription = "ParametersDescription"; - internal const string ChangingParameters = "ChangingParameters"; - internal const string Condition = "ConditionRule"; - internal const string MovingActivities = "MovingActivities"; - internal const string MemberNameDescr = "MemberNameDescr"; - internal const string OnScopeInitializedDescr = "OnScopeInitializedDescr"; - internal const string OnGeneratorInitializedDescr = "OnGeneratorInitializedDescr"; - internal const string OnScopeCompletedDescr = "OnScopeCompletedDescr"; - internal const string OnGeneratorCompletedDescr = "OnGeneratorCompletedDescr"; - internal const string DataElementRuntimeTypeDescr = "DataElementRuntimeTypeDescr"; - internal const string RuleConditionReferencesDescr = "RuleConditionReferencesDescr"; - internal const string CreateActivityFromToolbox = "CreateActivityFromToolbox"; - internal const string MoveMultipleActivities = "MoveMultipleActivities"; - internal const string MoveSingleActivity = "MoveSingleActivity"; - internal const string CutMultipleActivities = "CutMultipleActivities"; - internal const string CutSingleActivity = "CutSingleActivity"; - internal const string CutActivity = "CutActivity"; - internal const string FaultActivityDescription = "FaultActivityDescription"; - internal const string NullConditionExpression = "NullConditionExpression"; - internal const string ParameterTypeDescription = "ParameterTypeDescription"; - internal const string ParameterCategory = "ParameterCategory"; - internal const string ParameterDirectionDescription = "ParameterDirectionDescription"; - internal const string ParameterElementDescription = "ParameterElementDescription"; - internal const string ParameterDlgDescription = "ParameterDlgDescription"; - internal const string ParameterDlgHeader = "ParameterDlgHeader"; - internal const string SuspendActivityDescription = "SuspendActivityDescription"; - internal const string SuspendErrorMessageDescr = "SuspendErrorMessageDescr"; - internal const string TerminateActivityDescription = "TerminateActivityDescription"; - internal const string TerminateErrorMessageDescr = "TerminateErrorMessageDescr"; - internal const string DeclarationCategory = "DeclarationCategory"; - internal const string NoValidActivityPropertiesAvailable = "NoValidActivityPropertiesAvailable"; - internal const string ChooseActivityDatasource = "ChooseActivityDatasource"; - internal const string Promote = "Promote"; - internal const string Type = "Type"; - internal const string NoMatchingActivityProperties = "NoMatchingActivityProperties"; - internal const string ActivityBindIDDescription = "ActivityBindIDDescription"; - internal const string ActivityBindPathDescription = "ActivityBindPathDescription"; - internal const string XPathDescription = "XPathDescription"; - internal const string TransformerDescription = "TransformerDescription"; - internal const string CustomPropertiesCollectionFormHeader = "CustomPropertiesCollectionFormHeader"; - internal const string CustomPropertiesCollectionFormDescription = "CustomPropertiesCollectionFormDescription"; - internal const string BaseTypePropertyName = "BaseTypePropertyName"; - internal const string CustomActivityBaseClassTypeFilterProviderDesc = "CustomActivityBaseClassTypeFilterProviderDesc"; - internal const string CustomActivityDesignerTypeFilterProviderDesc = "CustomActivityDesignerTypeFilterProviderDesc"; - internal const string CustomActivityValidatorTypeFilterProviderDesc = "CustomActivityValidatorTypeFilterProviderDesc"; - internal const string CustomActivityExecutorTypeFilterProviderDesc = "CustomActivityExecutorTypeFilterProviderDesc"; - internal const string GenericParameters = "GenericParameters"; - internal const string ToolboxItem = "ToolboxItem"; - internal const string ToolboxItemCompanionClassDesc = "ToolboxItemCompanionClassDesc"; - internal const string Error_SerializationInsufficientState = "Error_SerializationInsufficientState"; - internal const string Error_ActivityHasParent = "Error_ActivityHasParent"; - internal const string Error_CompensantionParentNotScope = "Error_CompensantionParentNotScope"; - internal const string Error_ConditionedActivityParentNotCAG = "Error_ConditionedActivityParentNotCAG"; - internal const string Error_CorrelationTypeNotComparable = "Error_CorrelationTypeNotComparable"; - internal const string Error_ArgumentTypeNotMatchParameter = "Error_ArgumentTypeNotMatchParameter"; - internal const string Error_TypeTypeMismatch = "Error_TypeTypeMismatch"; - internal const string Error_ParameterTypeMismatch = "Error_ParameterTypeMismatch"; - internal const string Error_InvokeParameterTypeMismatch = "Error_InvokeParameterTypeMismatch"; - internal const string Error_ParameterPropertyNotSet = "Error_ParameterPropertyNotSet"; - internal const string Error_DataSourceNameNotSet = "Error_DataSourceNameNotSet"; - internal const string Error_DataSourceInvalidIdentifier = "Error_DataSourceInvalidIdentifier"; - internal const string Error_ParameterTypeNotExist = "Error_ParameterTypeNotExist"; - internal const string Error_InvalidParameterName = "Error_InvalidParameterName"; - internal const string Error_InvalidParameterType = "Error_InvalidParameterType"; - internal const string Error_InvalidParameterElement = "Error_InvalidParameterElement"; - internal const string Error_InvalidPropertyType = "Error_InvalidPropertyType"; - internal const string Error_TypeNotResolvedInMethodName = "Error_TypeNotResolvedInMethodName"; - internal const string Error_DelegateNoInvoke = "Error_DelegateNoInvoke"; - internal const string Error_TypeNotDelegate = "Error_TypeNotDelegate"; - internal const string Error_MethodSignatureMismatch = "Error_MethodSignatureMismatch"; - internal const string Error_MethodReturnTypeMismatch = "Error_MethodReturnTypeMismatch"; - internal const string Error_PropertyNotSet = "Error_PropertyNotSet"; - internal const string Error_ScopeCouldNotBeResolved = "Error_ScopeCouldNotBeResolved"; - internal const string Error_IfElseNotAllIfElseBranchDecl = "Error_ConditionalNotAllConditionalBranchDecl"; - internal const string Error_TypeTypeMismatchAmbiguity = "Error_TypeTypeMismatchAmbiguity"; - internal const string Error_InvalidCorrelationSetDatasource = "Error_InvalidCorrelationSetDatasource"; - internal const string Error_InvalidCorrelationSetType = "Error_InvalidCorrelationSetType"; - internal const string Error_MissingCorrelationParameterAttribute = "Error_MissingCorrelationParameterAttribute"; - internal const string Error_CorrelationTypeNotConsistent = "Error_CorrelationTypeNotConsistent"; - internal const string Error_CorrelationInvalid = "Error_CorrelationInvalid"; - internal const string Error_MissingDelegateMethod = "Error_MissingDelegateMethod"; - internal const string Error_MissingHostInterface = "Error_MissingHostInterface"; - internal const string Error_MissingMethodName = "Error_MissingMethodName"; - internal const string Error_NoBoundType = "Error_NoBoundType"; - internal const string Error_PortTypeNotAnInterface = "Error_PortTypeNotAnInterface"; - internal const string Error_MethodNotExists = "Error_MethodNotExists"; - internal const string Error_InvalidRequestResponseMethod = "Error_InvalidRequestResponseMethod"; - internal const string General_MissingService = "General_MissingService"; - internal const string Error_ScopeDuplicatedNameActivity = "Error_ScopeDuplicatedNameActivity"; - internal const string Error_DuplicatedActivityID = "Error_DuplicatedActivityID"; - internal const string Error_DuplicatedParameterName = "Error_DuplicatedParameterName"; - internal const string Error_ScopeMissingSerializableAttribute = "Error_ScopeMissingSerializableAttribute"; - internal const string Error_FieldNotExists = "Error_FieldNotExists"; - internal const string Error_PropertyNotExists = "Error_PropertyNotExists"; - internal const string Error_FieldTypeMismatch = "Error_FieldTypeMismatch"; - internal const string Error_PropertyTypeMismatch = "Error_PropertyTypeMismatch"; - internal const string Error_TypeNotResolvedInFieldName = "Error_TypeNotResolvedInFieldName"; - internal const string Error_TypeNotResolvedInPropertyName = "Error_TypeNotResolvedInPropertyName"; - internal const string Error_FieldGenericParamTypeMismatch = "Error_FieldGenericParamTypeMismatch"; - internal const string Error_TypeNotResolved = "Error_TypeNotResolved"; - internal const string Error_TypeIsUnboundedGeneric = "Error_TypeIsUnboundedGeneric"; - internal const string Error_MissingRootActivity = "Error_MissingRootActivity"; - internal const string Error_PropertyNotReadable = "Error_PropertyNotReadable"; - internal const string Error_PropertyNotWritable = "Error_PropertyNotWritable"; - internal const string Error_NotCompositeActivity = "Error_NotCompositeActivity"; - internal const string Error_TypeNotExist = "Error_TypeNotExist"; - internal const string Error_ActivityRefNotResolved = "Error_ActivityRefNotResolved"; - internal const string Error_ActivityRefNotMatchType = "Error_ActivityRefNotMatchType"; - internal const string Error_ActivityValidation = "Error_ActivityValidation"; - internal const string Error_ActiveChildExist = "Error_ActiveChildExist"; - internal const string Error_ActiveChildContextExist = "Error_ActiveChildContextExist"; - internal const string Error_CannotCompleteContext = "Error_CannotCompleteContext"; - internal const string Error_NoPasteSupport = "Error_NoPasteSupport"; - internal const string Error_UnknownSerializationStore = "Error_UnknownSerializationStore"; - internal const string Error_MissingCorrelationSet = "Error_MissingCorrelationSet"; - internal const string Error_CreateVariable = "Error_CreateVariable"; - internal const string Error_DuplicateCorrelationSetName = "Error_DuplicateCorrelationSetName"; - internal const string Error_DragDropInvalid = "Error_DragDropInvalid"; - internal const string AddingImplicitActivity = "AddingImplicitActivity"; - internal const string Failure_DoDefaultAction = "Failure_DoDefaultAction"; - internal const string Failure_DoDefaultActionCaption = "Failure_DoDefaultActionCaption"; - internal const string Error_FaultInsideAtomicScope = "Error_FaultInsideAtomicScope"; - internal const string Error_ListenNotMoreThanOneDelay = "Error_ListenNotMoreThanOneDelay"; - internal const string Error_AtomicScopeWithFaultHandlersActivityDecl = "Error_AtomicScopeWithFaultHandlersActivityDecl"; - internal const string Error_AtomicScopeWithCancellationHandlerActivity = "Error_AtomicScopeWithCancellationHandlerActivity"; - internal const string Error_ScopeDuplicateFaultHandlerActivityForAll = "Error_ScopeDuplicateFaultHandlerActivityForAll"; - internal const string Error_ScopeDuplicateFaultHandlerActivityFor = "Error_ScopeDuplicateFaultHandlerActivityFor"; - internal const string Error_AtomicScopeNestedInNonLRT = "Error_AtomicScopeNestedInNonLRT"; - internal const string Error_LRTScopeNestedInNonLRT = "Error_LRTScopeNestedInNonLRT"; - internal const string Error_CAGNotAllChildrenConditioned = "Error_CAGNotAllChildrenConditioned"; - internal const string Error_ConditionedActivityChildCount = "Error_ConditionedActivityChildCount"; - internal const string Error_NegativeValue = "Error_NegativeValue"; - internal const string Error_MethodWithReturnType = "Error_MethodWithReturnType"; - internal const string Error_SendReceiveOrderIncorrect = "Error_SendReceiveOrderIncorrect"; - internal const string Error_ReceiveSendOrderIncorrect = "Error_ReceiveSendOrderIncorrect"; - internal const string Error_CompensateBadNesting = "Error_CompensateBadNesting"; - internal const string Error_ReferencedAssemblyIsInvalid = "Error_ReferencedAssemblyIsInvalid"; - internal const string Error_TypeToXsdConversion = "Error_TypeToXsdConversion"; - internal const string Error_FieldTypeNotResolved = "Error_FieldTypeNotResolved"; - internal const string Error_PropertyTypeNotResolved = "Error_PropertyTypeNotResolved"; - internal const string Error_CouldNotDeserializeXomlFile = "Error_CouldNotDeserializeXomlFile"; - internal const string Error_InternalCompilerError = "Error_InternalCompilerError"; - internal const string Error_TypeNotAsseblyQualified = "Error_TypeNotAsseblyQualified"; - internal const string CompilerWarning_StandardAssemlbyInReferences = "CompilerWarning_StandardAssemlbyInReferences"; - internal const string Error_SuspendInAtomicScope = "Error_SuspendInAtomicScope"; - internal const string Error_InvalidActivityExecutionContext = "Error_InvalidActivityExecutionContext"; - internal const string Error_NoRuntimeAvailable = "Error_NoRuntimeAvailable"; - internal const string Error_CanNotChangeAtRuntime = "Error_CanNotChangeAtRuntime"; - internal const string Error_DataContextNotInitialized = "Error_DataContextNotInitialized"; - internal const string Error_DataContextAlreadyInitialized = "Error_DataContextAlreadyInitialized"; - internal const string Error_ParseActivityNameDoesNotExist = "Error_ParseActivityNameDoesNotExist"; - internal const string Error_NoParameterPropertyDeclared = "Error_NoParameterPropertyDeclared"; - internal const string Error_PropertyInvalidIdentifier = "Error_PropertyInvalidIdentifier"; - internal const string Error_WorkflowDefinitionModified = "Error_WorkflowDefinitionModified"; - internal const string Error_FieldAlreadyExist = "Error_FieldAlreadyExist"; - internal const string Failure_FieldAlreadyExist = "Failure_FieldAlreadyExist"; - internal const string Error_DifferentTypeFieldExists = "Error_DifferentTypeFieldExists"; - internal const string Error_RootActivityTypeInvalid = "Error_RootActivityTypeInvalid"; - internal const string Error_RootActivityTypeInvalid2 = "Error_RootActivityTypeInvalid2"; - internal const string Error_CannotCompile_No_XClass = "Error_CannotCompile_No_XClass"; - internal const string Error_TemplateActivityIsNotActivity = "Error_TemplateActivityIsNotActivity"; - internal const string Error_TypeIsNotRootActivity = "Error_TypeIsNotRootActivity"; - internal const string Error_NoTypeProvider = "Error_NoTypeProvider"; - internal const string Error_NotCodeGeneratorType = "Error_NotCodeGeneratorType"; - internal const string Error_NotDataContext = "Error_NotDataContext"; - internal const string Error_MissingDefaultConstructor = "Error_MissingDefaultConstructor"; - internal const string Error_ContextStackItemMissing = "Error_ContextStackItemMissing"; - internal const string Error_UnexpectedArgumentType = "Error_UnexpectedArgumentType"; - internal const string Error_EmptyArgument = "Error_EmptyArgument"; - internal const string Error_DPAlreadyExist = "Error_DPAlreadyExist"; - internal const string Error_DuplicateDynamicProperty = "Error_DuplicateDynamicProperty"; - internal const string Error_DynamicPropertyTypeValueMismatch = "Error_DynamicPropertyTypeValueMismatch"; - internal const string Error_DynamicPropertyNoSupport = "Error_DynamicPropertyNoSupport"; - internal const string Error_NoContextForDatasource = "Error_NoContextForDatasource"; - internal const string Error_NoContextForDatasourceCaption = "Error_NoContextForDatasourceCaption"; - internal const string Error_DataSourceHasParent = "Error_DataSourceHasParent"; - internal const string OnTaskCompletedDescr = "OnTaskCompletedDescr"; - internal const string OnTaskInitializedDescr = "OnTaskInitializedDescr"; - internal const string Error_InvalidXmlData = "Error_InvalidXmlData"; - internal const string Error_HandlerNotOnRoot = "Error_HandlerNotOnRoot"; - internal const string Error_InvalidArgumentIndex = "Error_InvalidArgumentIndex"; - internal const string Error_UITypeEditorTypeNotUITypeEditor = "Error_UITypeEditorTypeNotUITypeEditor"; - internal const string FilterDescription_UITypeEditor = "FilterDescription_UITypeEditor"; - internal const string Error_UserCodeFilesNotAllowed = "Error_UserCodeFilesNotAllowed"; - internal const string Error_CodeWithinNotAllowed = "Error_CodeWithinNotAllowed"; - internal const string Error_TypeNotAuthorized = "Error_TypeNotAuthorized"; - internal const string Error_CantDetermineBaseType = "Error_CantDetermineBaseType"; - internal const string Error_MultipleSelectNotSupportedForBindAndPromote = "Error_MultipleSelectNotSupportedForBindAndPromote"; - internal const string Error_CantDetermineBaseTypeCaption = "Error_CantDetermineBaseTypeCaption"; - internal const string Error_CantDeterminePropertyBaseType = "Error_CantDeterminePropertyBaseType"; - internal const string Error_NullCustomActivityTypeName = "Error_NullCustomActivityTypeName"; - internal const string Error_InvalidAttribute = "Error_InvalidAttribute"; - internal const string Error_InvalidAttributes = "Error_InvalidAttributes"; - internal const string Error_ConfigFileMissingOrInvalid = "Error_ConfigFileMissingOrInvalid"; - internal const string Error_CantHaveContextActivity = "Error_CantHaveContextActivity"; - internal const string Error_SynchronizedNeedsDataContext = "Error_SynchronizedNeedsDataContext"; - internal const string Error_MoreThanOneFaultHandlersActivityDecl = "Error_MoreThanOneFaultHandlersActivityDecl"; - internal const string Error_MoreThanOneEventHandlersDecl = "Error_MoreThanOneEventHandlersDecl"; - internal const string Error_MoreThanOneCancelHandler = "Error_MoreThanOneCancelHandler"; - internal const string Error_MetaDataInterfaceMissing = "Error_MetaDataInterfaceMissing"; - internal const string Error_NonActivityExecutor = "Error_NonActivityExecutor"; - internal const string Error_DynamicUpdateEvaluation = "Error_DynamicUpdateEvaluation"; - internal const string Error_CollectionHasNullEntry = "Error_CollectionHasNullEntry"; - internal const string Error_MissingContextProperty = "Error_MissingContextProperty"; - internal const string Error_AssociatedDesignerMissing = "Error_AssociatedDesignerMissing"; - internal const string Error_MissingContextActivityProperty = "Error_MissingContextActivityProperty"; - internal const string Error_MissingActivityProperty = "Error_MissingActivityProperty"; - internal const string Error_MissingOwnerTypeProperty = "Error_MissingOwnerTypeProperty"; - internal const string Error_DOIsNotAnActivity = "Error_DOIsNotAnActivity"; - internal const string Error_PropertyCanBeOnlyCleared = "Error_PropertyCanBeOnlyCleared"; - internal const string Error_PropertyDefaultTypeMismatch = "Error_PropertyDefaultTypeMismatch"; - internal const string Error_PropertyDefaultIsReference = "Error_PropertyDefaultIsReference"; - // workflow load errors - internal const string Error_WorkflowLoadFailed = "Error_WorkflowLoadFailed"; - internal const string Error_WorkflowLoadValidationFailed = "Error_WorkflowLoadValidationFailed"; - internal const string Error_WorkflowLoadDeserializationFailed = "Error_WorkflowLoadDeserializationFailed"; - internal const string Error_WorkflowLoadTypeMismatch = "Error_WorkflowLoadTypeMismatch"; - internal const string Error_WorkflowLoadInvalidXoml = "Error_WorkflowLoadInvalidXoml"; - internal const string Error_WorkflowLoadNotValidRootType = "Error_WorkflowLoadNotValidRootType"; - internal const string Error_CantCreateInstanceOfComponent = "Error_CantCreateInstanceOfComponent"; - internal const string Error_NotComponentFactoryType = "Error_NotComponentFactoryType"; - internal const string Error_WorkflowTerminated = "Error_WorkflowTerminated"; - - // serializer errrors - internal const string Error_SerializerAttributesFoundInComplexProperty = "Error_SerializerAttributesFoundInComplexProperty"; - internal const string Error_InvalidDataFound = "Error_InvalidDataFound"; - internal const string Error_InvalidDataFoundForType = "Error_InvalidDataFoundForType"; - internal const string Error_InvalidDataFoundForType1 = "Error_InvalidDataFoundForType1"; - internal const string Error_SerializerTypeNotResolved = "Error_SerializerTypeNotResolved"; - internal const string Error_MarkupSerializerTypeNotResolved = "Error_MarkupSerializerTypeNotResolved"; - internal const string Error_SerializerTypeNotResolvedWithInnerError = "Error_SerializerTypeNotResolvedWithInnerError"; - internal const string Error_SerializerNotAvailable = "Error_SerializerNotAvailable"; - internal const string Error_SerializerNotAvailableForSerialize = "Error_SerializerNotAvailableForSerialize"; - internal const string Error_SerializerCreateInstanceFailed = "Error_SerializerCreateInstanceFailed"; - internal const string Error_SerializerAddChildFailed = "Error_SerializerAddChildFailed"; - internal const string Error_SerializerNoPropertyAvailable = "Error_SerializerNoPropertyAvailable"; - internal const string Error_SerializerPrimitivePropertyReadOnly = "Error_SerializerPrimitivePropertyReadOnly"; - internal const string Error_SerializerCantChangeIsLocked = "Error_SerializerCantChangeIsLocked"; - internal const string Error_SerializerPrimitivePropertySetFailed = "Error_SerializerPrimitivePropertySetFailed"; - internal const string Error_SerializerPropertyGetFailed = "Error_SerializerPropertyGetFailed"; - internal const string Error_SerializerPrimitivePropertyNoLogic = "Error_SerializerPrimitivePropertyNoLogic"; - internal const string Error_SerializerPrimitivePropertyParentIsNull = "Error_SerializerPrimitivePropertyParentIsNull"; - internal const string Error_SerializerComplexPropertySetFailed = "Error_SerializerComplexPropertySetFailed"; - internal const string Error_SerializerNoChildNotion = "Error_SerializerNoChildNotion"; - internal const string Error_SerializerNoDynamicPropertySupport = "Error_SerializerNoDynamicPropertySupport"; - internal const string Error_SerializerNoSerializeLogic = "Error_SerializerNoSerializeLogic"; - internal const string Error_SerializerReadOnlyPropertyAndValueIsNull = "Error_SerializerReadOnlyPropertyAndValueIsNull"; - internal const string Error_SerializerReadOnlyParametersNoChild = "Error_SerializerReadOnlyParametersNoChild"; - internal const string Error_SerializerNotParameterBindingObject = "Error_SerializerNotParameterBindingObject"; - internal const string Error_SerializerThrewException = "Error_SerializerThrewException"; - internal const string Error_ActivityCollectionSerializer = "Error_ActivityCollectionSerializer"; - internal const string Error_MissingClassAttribute = "Error_MissingClassAttribute"; - internal const string Error_MissingClassAttributeValue = "Error_MissingClassAttributeValue"; - internal const string ExecutorCreationFailedErrorMessage = "ExecutorCreationFailedErrorMessage"; - internal const string VariableGetterCode_VB = "VariableGetterCode_VB"; - internal const string VariableGetterCode_CS = "VariableGetterCode_CS"; - internal const string VariableSetterCode_VB = "VariableSetterCode_VB"; - internal const string VariableSetterCode_CS = "VariableSetterCode_CS"; - internal const string StaticVariableGetterCode_VB = "StaticVariableGetterCode_VB"; - internal const string StaticVariableGetterCode_CS = "StaticVariableGetterCode_CS"; - internal const string StaticVariableSetterCode_VB = "StaticVariableSetterCode_VB"; - internal const string StaticVariableSetterCode_CS = "StaticVariableSetterCode_CS"; - internal const string EnterCodeBesidesCode_VB = "EnterCodeBesidesCode_VB"; - internal const string EnterCodeBesidesCode_CS = "EnterCodeBesidesCode_CS"; - internal const string LeaveCodeBesides1Code_VB = "LeaveCodeBesides1Code_VB"; - internal const string LeaveCodeBesides2Code_VB = "LeaveCodeBesides2Code_VB"; - internal const string LeaveCodeBesides1Code_CS = "LeaveCodeBesides1Code_CS"; - internal const string LeaveCodeBesides2Code_CS = "LeaveCodeBesides2Code_CS"; - internal const string VariableSetterName = "VariableSetterName"; - internal const string VariableGetterName = "VariableGetterName"; - internal const string HandlerGetterName = "HandlerGetterName"; - internal const string WorkflowCreatorName = "WorkflowCreatorName"; - internal const string ActivityMethod = "ActivityMethod"; - internal const string CustomActivityPrivateField = "CustomActivityPrivateField"; - internal const string InitializedVariableDeclaration_VB = "InitializedVariableDeclaration_VB"; - internal const string InitializedVariableDeclaration_CS = "InitializedVariableDeclaration_CS"; - internal const string In = "In"; - internal const string Out = "Out"; - internal const string Ref = "Ref"; - internal const string Required = "Required"; - internal const string Optional = "Optional"; - internal const string Parameters = "Parameters"; - internal const string Properties = "Properties"; - internal const string Error_RecursionDetected = "Error_RecursionDetected"; - internal const string Warning_UnverifiedRecursion = "Warning_UnverifiedRecursion"; - internal const string AddConstructorCode = "AddConstructorCode"; - internal const string Error_UninitializedCorrelation = "Error_UninitializedCorrelation"; - internal const string Error_CorrelationAlreadyInitialized = "Error_CorrelationAlreadyInitialized"; - internal const string Error_CorrelatedSendReceiveAtomicScope = "Error_CorrelatedSendReceiveAtomicScope"; - internal const string Warning_ActivityValidation = "Warning_ActivityValidation"; - internal const string Warning_EmptyBehaviourActivity = "Warning_EmptyBehaviourActivity"; - internal const string Error_ParallelActivationNoCorrelation = "Error_ParallelActivationNoCorrelation"; - internal const string Error_MethodNotAccessible = "Error_MethodNotAccessible"; - internal const string Error_FieldNotAccessible = "Error_FieldNotAccessible"; - internal const string Error_PropertyNotAccessible = "Error_PropertyNotAccessible"; - internal const string Error_GenericArgumentsNotAllowed = "Error_GenericArgumentsNotAllowed"; - internal const string Error_InvalidIdentifier = "Error_InvalidIdentifier"; - internal const string Error_InvalidLanguageIdentifier = "Error_InvalidLanguageIdentifier"; - internal const string DuplicateActivityIdentifier = "DuplicateActivityIdentifier"; - internal const string Error_MissingAttribute = "Error_MissingAttribute"; - internal const string Error_LoadUIPropertiesFile = "Error_LoadUIPropertiesFile"; - internal const string Error_SerializerEventGetFailed = "Error_SerializerEventGetFailed"; - internal const string Error_SerializerEventFailed = "Error_SerializerEventFailed"; - internal const string Error_SerializerNoMemberFound = "Error_SerializerNoMemberFound"; - internal const string Error_DynamicEventConflict = "Error_DynamicEventConflict"; - internal const string Error_SerializerMemberSetFailed = "Error_SerializerMemberSetFailed"; - internal const string Error_ContentPropertyCouldNotBeFound = "Error_ContentPropertyCouldNotBeFound"; - internal const string Error_ContentPropertyValueInvalid = "Error_ContentPropertyValueInvalid"; - internal const string Error_ContentPropertyNoSetter = "Error_ContentPropertyNoSetter"; - internal const string Error_ContentCanNotBeConverted = "Error_ContentCanNotBeConverted"; - internal const string Error_ContentPropertyCanNotBeNull = "Error_ContentPropertyCanNotBeNull"; - internal const string Error_SerializerTypeMismatch = "Error_SerializerTypeMismatch"; - internal const string Error_CouldNotAddValueInContentProperty = "Error_CouldNotAddValueInContentProperty"; - internal const string Error_SerializerTypeRequirement = "Error_SerializerTypeRequirement"; - internal const string Error_CanNotAddActivityInBlackBoxActivity = "Error_CanNotAddActivityInBlackBoxActivity"; - internal const string Error_ContentPropertyCanNotSupportCompactFormat = "Error_ContentPropertyCanNotSupportCompactFormat"; - internal const string Error_ContentPropertyNoMultipleContents = "Error_ContentPropertyNoMultipleContents"; - internal const string Error_InternalSerializerError = "Error_InternalSerializerError"; - internal const string Error_DictionarySerializerNonDictionaryObject = "Error_DictionarySerializerNonDictionaryObject"; - internal const string Error_DictionarySerializerKeyNotFound = "Error_DictionarySerializerKeyNotFound"; - internal const string Error_InvalidCancelActivityState = "Error_InvalidCancelActivityState"; - internal const string Error_InvalidCompensateActivityState = "Error_InvalidCompensateActivityState"; - internal const string Error_InvalidCloseActivityState = "Error_InvalidCloseActivityState"; - internal const string Error_SealedPropertyMetadata = "Error_SealedPropertyMetadata"; - internal const string Error_MemberNotFound = "Error_MemberNotFound"; - internal const string Error_EmptyPathValue = "Error_EmptyPathValue"; - internal const string Error_InvalidCompensatingState = "Error_InvalidCompensatingState"; - internal const string Error_InvalidCancelingState = "Error_InvalidCancelingState"; - internal const string Error_InvalidClosingState = "Error_InvalidClosingState"; - internal const string Error_InvalidStateToExecuteChild = "Error_InvalidStateToExecuteChild"; - internal const string Error_InvalidExecutionState = "Error_InvalidExecutionState"; - internal const string Error_InvalidInitializingState = "Error_InvalidInitializingState"; - internal const string Error_InvalidInvokingState = "Error_InvalidInvokingState"; - internal const string Error_NotRegisteredAs = "Error_NotRegisteredAs"; - internal const string Error_AlreadyRegisteredAs = "Error_AlreadyRegisteredAs"; - internal const string Error_InsertingChildControls = "Error_InsertingChildControls"; - internal const string Error_EmptyToolTipRectangle = "Error_EmptyToolTipRectangle"; - internal const string Error_EmptyRectangleValue = "Error_EmptyRectangleValue"; - internal const string Error_InvalidShadowRectangle = "Error_InvalidShadowRectangle"; - internal const string Error_InvalidShadowDepth = "Error_InvalidShadowDepth"; - internal const string Error_InvalidLightSource = "Error_InvalidLightSource"; - internal const string Error_ChangingDock = "Error_ChangingDock"; - internal const string Error_NullOrEmptyValue = "Error_NullOrEmptyValue"; - internal const string Error_InvalidStateImages = "Error_InvalidStateImages"; - internal const string Error_InvalidConnectorSegment = "Error_InvalidConnectorSegment"; - internal const string Error_InvalidConnectorSource = "Error_InvalidConnectorSource"; - internal const string Error_CreatingToolTip = "Error_CreatingToolTip"; - internal const string Error_InvalidDockStyle = "Error_InvalidDockStyle"; - internal const string Error_InvalidConnectorValue = "Error_InvalidConnectorValue"; - internal const string Error_InvalidDesignerVerbValue = "Error_InvalidDesignerVerbValue"; - internal const string Error_InvalidRuntimeType = "Error_InvalidRuntimeType"; - internal const string Error_InvalidArgumentValue = "Error_InvalidArgumentValue"; - internal const string Error_InvalidRadiusValue = "Error_InvalidRadiusValue"; - internal const string ToolTipString = "ToolTipString"; - - // Collection Editor Resources - internal const string CollectionEditorCaption = "CollectionEditorCaption"; - internal const string CollectionEditorProperties = "CollectionEditorProperties"; - internal const string CollectionEditorPropertiesMultiSelect = "CollectionEditorPropertiesMultiSelect"; - internal const string CollectionEditorPropertiesNone = "CollectionEditorPropertiesNone"; - internal const string CollectionEditorCantRemoveItem = "CollectionEditorCantRemoveItem"; - internal const string CollectionEditorUndoBatchDesc = "CollectionEditorUndoBatchDesc"; - internal const string CollectionEditorInheritedReadOnlySelection = "CollectionEditorInheritedReadOnlySelection"; - internal const string Error_ParameterAlreadyExists = "Error_ParameterAlreadyExists"; - internal const string Error_PropertyAlreadyExists = "Error_PropertyAlreadyExists"; - internal const string Error_HiddenPropertyAlreadyExists = "Error_HiddenPropertyAlreadyExists"; - internal const string Error_CorrelationInUse = "Error_CorrelationInUse"; - internal const string Error_ItemNotExists = "Error_ItemNotExists"; - internal const string Error_NoHelpAvailable = "Error_NoHelpAvailable"; - internal const string Error_DuplicateWorkflow = "Error_DuplicateWorkflow"; - internal const string Error_Recursion = "Error_Recursion"; - internal const string Error_RootActivity = "Error_RootActivity"; - internal const string Error_ConditionDefinitionDeserializationFailed = "Error_ConditionDefinitionDeserializationFailed"; - internal const string Error_InvalidConditionDefinition = "Error_InvalidConditionDefinition"; - internal const string SR_InvokeTransactionalFromAtomic = "SR_InvokeTransactionalFromAtomic"; - internal const string Error_SuspendInAtomicCallChain = "Error_SuspendInAtomicCallChain"; - internal const string Error_LiteralPassedToOutRef = "Error_LiteralPassedToOutRef"; - internal const string Error_GeneratorShouldContainSingleActivity = "Error_GeneratorShouldContainSingleActivity"; - internal const string Error_DeclaringPropertyNotSupported = "Error_DeclaringPropertyNotSupported"; - internal const string Error_DeclaringEventNotSupported = "Error_DeclaringEventNotSupported"; - internal const string Error_DynamicEventNotSupported = "Error_DynamicEventNotSupported"; - internal const string Error_DynamicPropertyNotSupported = "Error_DynamicPropertyNotSupported"; - internal const string Error_ParameterTypeResolution = "Error_ParameterTypeResolution"; - - // Dynamic Validations - internal const string Error_DynamicActivity = "Error_DynamicActivity"; - internal const string Error_DynamicActivity2 = "Error_DynamicActivity2"; - internal const string Error_CompilerValidationFailed = "Error_CompilerValidationFailed"; - internal const string Error_RuntimeValidationFailed = "Error_RuntimeValidationFailed"; - internal const string Error_TransactionAlreadyCanceled = "Error_TransactionAlreadyCanceled"; - internal const string Error_RemoveExecutingActivity = "Error_RemoveExecutingActivity"; - internal const string Error_InsideAtomicScope = "Error_InsideAtomicScope"; - internal const string SuspendReason_WorkflowChange = "SuspendReason_WorkflowChange"; - - // type filtering - internal const string FilterDescription_ParameterDeclaration = "FilterDescription_ParameterDeclaration"; - internal const string FilterDescription_GenericArgument = "FilterDescription_GenericArgument"; - - - internal const string LibraryPathIsInvalid = "LibraryPathIsInvalid"; - - // Activity Set - internal const string Error_CreateValidator = "Error_CreateValidator"; - internal const string Error_InvalidPackageFile = "Error_InvalidPackageFile"; - internal const string Error_AddAssemblyRef = "Error_AddAssemblyRef"; - internal const string Error_AssemblyBadImage = "Error_AssemblyBadImage"; - internal const string BindPropertySetterName = "BindPropertySetterName"; - - // Bind validations - internal const string Error_CannotResolveActivity = "Error_CannotResolveActivity"; - internal const string Error_CannotResolveRelativeActivity = "Error_CannotResolveRelativeActivity"; - internal const string Error_PathNotSetForActivitySource = "Error_PathNotSetForActivitySource"; - internal const string Error_InvalidMemberPath = "Error_InvalidMemberPath"; - internal const string Error_TargetTypeMismatch = "Error_TargetTypeMismatch"; - internal const string Warning_ParameterBinding = "Warning_ParameterBinding"; - internal const string Error_ReferencedActivityPropertyNotBind = "Error_ReferencedActivityPropertyNotBind"; - internal const string Error_TargetTypeDataSourcePathMismatch = "Error_TargetTypeDataSourcePathMismatch"; - internal const string Bind_ActivityDataSourceRecursionDetected = "Bind_ActivityDataSourceRecursionDetected"; - internal const string Bind_DuplicateDataSourceNames = "Bind_DuplicateDataSourceNames"; - internal const string Error_PathNotSetForXmlDataSource = "Error_PathNotSetForXmlDataSource"; - internal const string Error_XmlDocumentLoadFailed = "Error_XmlDocumentLoadFailed"; - internal const string Error_XmlDataSourceInvalidPath = "Error_XmlDataSourceInvalidPath"; - internal const string Error_XmlDataSourceMultipleNodes = "Error_XmlDataSourceMultipleNodes"; - internal const string Error_XmlDataSourceInvalidXPath = "Error_XmlDataSourceInvalidXPath"; - internal const string Error_InvalidObjectRefFormat = "Error_InvalidObjectRefFormat"; - internal const string Error_ReadOnlyDataSource = "Error_ReadOnlyDataSource"; - internal const string Error_HandlerReadOnly = "Error_HandlerReadOnly"; - internal const string Error_XmlDataSourceReadOnly = "Error_XmlDataSourceReadOnly"; - internal const string Error_DataSourceNotExist = "Error_DataSourceNotExist"; - internal const string Error_PropertyNoGetter = "Error_PropertyNoGetter"; - internal const string Error_PropertyNoSetter = "Error_PropertyNoSetter"; - internal const string Error_PropertyHasNoGetterDefined = "Error_PropertyHasNoGetterDefined"; - internal const string Error_PropertyHasNoSetterDefined = "Error_PropertyHasNoSetterDefined"; - internal const string Error_PropertyReferenceNoGetter = "Error_PropertyReferenceNoGetter"; - internal const string Error_PropertyReferenceGetterNoAccess = "Error_PropertyReferenceGetterNoAccess"; - internal const string Error_PropertyHasIndexParameters = "Error_PropertyHasIndexParameters"; - internal const string Error_ReadOnlyField = "Error_ReadOnlyField"; - internal const string Error_NoEnclosingContext = "Error_NoEnclosingContext"; - internal const string Error_NestedPersistOnClose = "Error_NestedPersistOnClose"; - internal const string Error_NestedCompensatableActivity = "Error_NestedCompensatableActivity"; - internal const string Error_InvalidActivityForObjectDatasource = "Error_InvalidActivityForObjectDatasource"; - internal const string Error_DataSourceTypeConversionFailed = "Error_DataSourceTypeConversionFailed"; - internal const string Error_BindDialogWrongPropertyType = "Error_BindDialogWrongPropertyType"; - internal const string Error_BindDialogNoValidPropertySelected = "Error_BindDialogNoValidPropertySelected"; - internal const string Error_BindDialogBindNotValid = "Error_BindDialogBindNotValid"; - internal const string Error_BindDialogCanNotBindToItself = "Error_BindDialogCanNotBindToItself"; - internal const string Error_BindActivityReference = "Error_BindActivityReference"; - internal const string Error_NoTargetTypeForMethod = "Error_NoTargetTypeForMethod"; - internal const string Error_MethodDataSourceIsReadOnly = "Error_MethodDataSourceIsReadOnly"; - internal const string Error_NotMethodDataSource = "Error_NotMethodDataSource"; - internal const string Error_MethodDataSourceWithPath = "Error_MethodDataSourceWithPath"; - internal const string Error_PathSyntax = "Error_PathSyntax"; - internal const string Error_UnmatchedParen = "Error_UnmatchedParen"; - internal const string Error_UnmatchedBracket = "Error_UnmatchedBracket"; - internal const string Error_MemberWithSameNameExists = "Error_MemberWithSameNameExists"; - internal const string Error_ActivityIdentifierCanNotBeEmpty = "Error_ActivityIdentifierCanNotBeEmpty"; - internal const string Error_InvalidActivityIdentifier = "Error_InvalidActivityIdentifier"; - internal const string Error_ActivityBindTypeConversionError = "Error_ActivityBindTypeConversionError"; - internal const string EmptyValue = "EmptyValue"; - internal const string Error_PropertyTypeNotDefined = "Error_PropertyTypeNotDefined"; - - internal const string Error_CompilationFailed = "Error_CompilationFailed"; - internal const string Error_MissingCompilationContext = "Error_MissingCompilationContext"; - - internal const string InvokeWorkflowReference_VB = "InvokeWorkflowReference_VB"; - internal const string InvokeWorkflowReference_CS = "InvokeWorkflowReference_CS"; - internal const string Error_InvalidListItem = "Error_InvalidListItem"; - - internal const string ParserMapPINoWhitespace = "ParserMapPINoWhitespace"; - internal const string ParserMapPIBadCharEqual = "ParserMapPIBadCharEqual"; - internal const string ParserMapPIBadCharQuote = "ParserMapPIBadCharQuote"; - internal const string ParserMapPIBadKey = "ParserMapPIBadKey"; - internal const string ParserMapPIMissingKey = "ParserMapPIMissingKey"; - internal const string ParserMapPIKeyNotSet = "ParserMapPIKeyNotSet"; - internal const string ParserMismatchDelimiter = "ParserMismatchDelimiter"; - internal const string ParserDanglingClause = "ParserDanglingClause"; - internal const string UnknownDefinitionTag = "UnknownDefinitionTag"; - internal const string CDATASection = "CDATASection"; - internal const string TextSection = "TextSection"; - internal const string IncorrectSyntax = "IncorrectSyntax"; - internal const string IncorrectTypeSyntax = "IncorrectTypeSyntax"; - internal const string Error_MultipleRootActivityCreator = "Error_MultipleRootActivityCreator"; - internal const string Error_MustHaveParent = "Error_MustHaveParent"; - - // Workflow References - internal const string Error_ReferenceObjNotInitialized = "Error_ReferenceObjNotInitialized"; - internal const string Error_ReferenceInitResourceManager = "Error_ReferenceInitResourceManager"; - internal const string Error_ResourceReferenceGetObject = "Error_ResourceReferenceGetObject"; - internal const string Error_RefBindCantFindRef = "Error_RefBindCantFindRef"; - internal const string Error_RefBindMissingReferenceName = "Error_RefBindMissingReferenceName"; - internal const string Error_RefBindMissingAttribute = "Error_RefBindMissingAttribute"; - internal const string Error_ReferenceLoad = "Error_ReferenceLoad"; - internal const string Error_ReferenceMissingAttribute = "Error_ReferenceMissingAttribute"; - internal const string Error_ReferenceInvalidResourceFile = "Error_ReferenceInvalidResourceFile"; - internal const string Error_ReferenceEmptyName = "Error_ReferenceEmptyName"; - - internal const string HandlerInvokerName = "HandlerInvokerName"; - internal const string HandlerInvokerSwitchPrefix_CS = "HandlerInvokerSwitchPrefix_CS"; - internal const string HandlerInvokerSwitchPrefix_VB = "HandlerInvokerSwitchPrefix_VB"; - internal const string HandlerInvokerSwitchSuffix_CS = "HandlerInvokerSwitchSuffix_CS"; - internal const string HandlerInvokerSwitchSuffix_VB = "HandlerInvokerSwitchSuffix_VB"; - internal const string HandlerInvokerCaseBegin_CS = "HandlerInvokerCaseBegin_CS"; - internal const string HandlerInvokerCaseBegin_VB = "HandlerInvokerCaseBegin_VB"; - - // Activity Category - internal const string Standard = "Standard"; - internal const string Base = "Base"; - - // CustomActivityDesigner - internal const string ValidatorCompanionClassDesc = "ValidatorCompanionClassDesc"; - internal const string ExecutorCompanionClassDesc = "ExecutorCompanionClassDesc"; - internal const string DesignerCompanionClassDesc = "DesignerCompanionClassDesc"; - internal const string CustomActivityBaseTypeDesc = "CustomActivityBaseTypeDesc"; - internal const string ActivityProperties = "ActivityProperties"; - internal const string ActivityPropertiesDesc = "ActivityPropertiesDesc"; - internal const string CompanionClasses = "CompanionClasses"; - internal const string ActivityDesc = "Activity"; - internal const string Error_TypeConversionFailed = "Error_TypeConversionFailed"; - internal const string SupportDataContext = "SupportDataContext"; - internal const string AdvancedCategory = "AdvancedCategory"; - internal const string SupportDataContextDesc = "SupportDataContextDesc"; - internal const string BaseCompanionClassName = "BaseCompanionClassName"; - internal const string BaseCompanionClassDesc = "BaseCompanionClassDesc"; - internal const string Designer = "Designer"; - internal const string Validator = "Validator"; - internal const string Executor = "Executor"; - internal const string BaseActivityType = "BaseActivityType"; - internal const string Error_NotBuiltInActivity = "Error_NotBuiltInActivity"; - internal const string NoChildActivities_Message = "NoChildActivities_Message"; - internal const string NoChildActivities_Caption = "NoChildActivities_Caption"; - internal const string Error_CustomActivityCantCreate = "Error_CustomActivityCantCreate"; - internal const string Error_CantChangeBuiltInActivity = "Error_CantChangeBuiltInActivity"; - internal const string Error_CantAddBeforeBuiltInActivity = "Error_CantAddBeforeBuiltInActivity"; - internal const string Error_CantAddAfterNonBuiltInActivity = "Error_CantAddAfterNonBuiltInActivity"; - internal const string Error_CannotAddRemoveChildActivities = "Error_CannotAddRemoveChildActivities"; - internal const string Error_CantFindBuiltInActivity = "Error_CantFindBuiltInActivity"; - internal const string Error_MissingBaseCompanionClassAttribute = "Error_MissingBaseCompanionClassAttribute"; - internal const string Error_CantFindBuiltInParent = "Error_CantFindBuiltInParent"; - internal const string Error_CantCreateInstanceOfBaseType = "Error_CantCreateInstanceOfBaseType"; - internal const string Error_CustomActivityTypeCouldNotBeFound = "Error_CustomActivityTypeCouldNotBeFound"; - internal const string None = "None"; - internal const string AtomicTransaction = "AtomicTransaction"; - internal const string LocalDataContext = "LocalDataContext"; - internal const string LocalDataContextDesc = "LocalDataContextDesc"; - internal const string CompanionClass = "CompanionClass"; - internal const string Error_AlreadyRootActivity = "Error_AlreadyRootActivity"; - internal const string RootActivityName = "RootActivityName"; - internal const string RootActivityNameDesc = "RootActivityNameDesc"; - internal const string CustomProperties = "CustomProperties"; - internal const string VisibleDescr = "VisibleDescr"; - internal const string EditableDescr = "EditableDescr"; - internal const string Error_CantCreateMethod = "Error_CantCreateMethod"; - internal const string Error_CantEditNullValue = "Error_CantEditNullValue"; - internal const string Error_CompanionTypeNotSet = "Error_CompanionTypeNotSet"; - internal const string Error_CompanionClassNameCanNotBeEmpty = "Error_CompanionClassNameCanNotBeEmpty"; - internal const string Error_CouldNotEmitFieldInLocalDataContext = "Error_CouldNotEmitFieldInLocalDataContext"; - internal const string Error_CouldNotEmitMethodInLocalDataContext = "Error_CouldNotEmitMethodInLocalDataContext"; - internal const string Error_DerivationFromTypeWithLocalDataContext = "Error_DerivationFromTypeWithLocalDataContext"; - internal const string Error_CompanionTypeDerivationError = "Error_CompanionTypeDerivationError"; - internal const string Error_CantCreateDataContextClass = "Error_CantCreateDataContextClass"; - internal const string ArrayExistingBind = "ArrayExistingBind"; - internal const string Error_NoMatchingFieldsOrProperties = "Error_NoMatchingFieldsOrProperties"; - internal const string ChooseFieldPropertyDatasource = "ChooseFieldPropertyDatasource"; - - internal const string SupportsTransaction = "SupportsTransaction"; - internal const string SupportsExceptions = "SupportsExceptions"; - internal const string SupportsCancellationHandlerActivity = "SupportsCancellationHandlerActivity"; - internal const string SupportsEvents = "SupportsEvents"; - internal const string SupportsDataSources = "SupportsDataSources"; - internal const string SupportsCompensationHandler = "SupportsCompensationHandler"; - internal const string SupportsCompensationHandlerDesc = "SupportsCompensationHandlerDesc"; - internal const string SupportsTransactionDesc = "SupportsTransactionDesc"; - internal const string SupportsExceptionsDesc = "SupportsExceptionsDesc"; - internal const string SupportsCancelHandlerDesc = "SupportsCancelHandlerDesc"; - internal const string SupportsEventsDesc = "SupportsEventsDesc"; - internal const string TransactionDesc = "TransactionDesc"; - - internal const string Error_BaseTypeMustBeActivity = "Error_BaseTypeMustBeActivity"; - internal const string ExistingActivityBindTitle = "ExistingActivityBindTitle"; - internal const string ExistingActivityBindLabel = "ExistingActivityBindLabel"; - internal const string ExistingFieldPropBindTitle = "ExistingFieldPropBindTitle"; - internal const string ExistingFieldPropBindLabel = "ExistingFieldPropBindLabel"; - internal const string ProvidesSynchronization = "ProvidesSynchronization"; - internal const string ProvidesSynchronizationDesc = "ProvidesSynchronizationDesc"; - internal const string SynchronizationHandles = "SynchronizationHandles"; - internal const string SynchronizationHandlesDesc = "SynchronizationHandlesDesc"; - - internal const string Error_TransactionAlreadyApplied = "Error_TransactionAlreadyApplied"; - internal const string Error_BindBaseTypeNotSpecified = "Error_BindBaseTypeNotSpecified"; - internal const string NonDelegateTargetType = "NonDelegateTargetType"; - internal const string Error_ClassnameNotInRootNamespace = "Error_ClassnameNotInRootNamespace"; - internal const string Error_CantUseCurrentProjectTypeAsBase = "Error_CantUseCurrentProjectTypeAsBase"; - internal const string Error_UnboundGenericType = "Error_UnboundGenericType"; - internal const string Error_UnboundGenericTypeDataSource = "Error_UnboundGenericTypeDataSource"; - internal const string Error_BaseTypeUnknown = "Error_BaseTypeUnknown"; - internal const string Error_UnconfiguredBind = "Error_UnconfiguredBind"; - internal const string Error_CanNotEmitMemberInLocalDataContext = "Error_CanNotEmitMemberInLocalDataContext"; - internal const string Error_DesignedTypeNotFound = "Error_DesignedTypeNotFound"; - internal const string Error_PathCouldNotBeResolvedToMember = "Error_PathCouldNotBeResolvedToMember"; - internal const string Error_EdittingNullCollection = "Error_EdittingNullCollection"; - internal const string Error_MoreThanOneCompensationDecl = "Error_MoreThanOneCompensationDecl"; - internal const string Error_ParentDoesNotSupportCompensation = "Error_ParentDoesNotSupportCompensation"; - internal const string Error_CantResolveEventHandler = "Error_CantResolveEventHandler"; - internal const string Error_XSDObjectTypeNotSerializable = "Error_XSDObjectTypeNotSerializable"; - internal const string AEC_InvalidActivity = "AEC_InvalidActivity"; - internal const string GetDynamicActivities_InvalidActivity = "GetDynamicActivities_InvalidActivity"; - internal const string AEC_InvalidNestedActivity = "AEC_InvalidNestedActivity"; - internal const string Error_IDNotSetForActivitySource = "Error_IDNotSetForActivitySource"; - internal const string Error_InvalidCustomPropertyName = "Error_InvalidCustomPropertyName"; - internal const string Error_InvalidCustomPropertyType = "Error_InvalidCustomPropertyType"; - - internal const string Error_DPReadOnly = "Error_DPReadOnly"; - internal const string Error_DPMetaPropertyBinding = "Error_DPMetaPropertyBinding"; - internal const string Error_DPSetValueBind = "Error_DPSetValueBind"; - internal const string Error_DPSetValueHandler = "Error_DPSetValueHandler"; - internal const string Error_DPGetValueHandler = "Error_DPGetValueHandler"; - internal const string Error_DPAddHandlerNonEvent = "Error_DPAddHandlerNonEvent"; - internal const string Error_DPAddHandlerMetaProperty = "Error_DPAddHandlerMetaProperty"; - internal const string Error_DPRemoveHandlerBind = "Error_DPRemoveHandlerBind"; - internal const string Error_LanguageNeedsToBeVBCSharp = "Error_LanguageNeedsToBeVBCSharp"; - internal const string Error_TargetFxNotSupported = "Error_TargetFxNotSupported"; - internal const string Error_CantConvertValueValue = "Error_CantConvertValueValue"; - internal const string Error_TypeIsNotValid = "Error_TypeIsNotValid"; - internal const string Error_TypePropertyInvalid = "Error_TypePropertyInvalid"; - internal const string Error_EventCantBeMetaProperty = "Error_EventCantBeMetaProperty"; - internal const string Error_EventMustBeDelegate = "Error_EventMustBeDelegate"; - internal const string Error_DPPropertyTypeMissing = "Error_DPPropertyTypeMissing"; - - internal const string TransactionalContextActivityDescription = "TransactionalContextActivityDescription"; - internal const string CompensatableTransactionalContextActivityDescription = "CompensatableTransactionalContextActivityDescription"; - internal const string SynchronizationScopeActivityDescription = "SynchronizationScopeActivityDescription"; - internal const string SequenceActivityDescription = "SequenceActivityDescription"; - internal const string CompensateActivityDescription = "CompensateActivityDescription"; - internal const string Error_CompensateBadTargetTX = "Error_CompensateBadTargetTX"; - internal const string Error_CancelHandlerParentNotScope = "Error_CancelHandlerParentNotScope"; - internal const string FaultHandlerActivityDescription = "FaultHandlerActivityDescription"; - internal const string Error_ExceptionTypeNotException = "Error_ExceptionTypeNotException"; - internal const string Error_FaultIsNotOfFaultType = "Error_FaultIsNotOfFaultType"; - internal const string Error_FaultTypeNoDefaultConstructor = "Error_FaultTypeNoDefaultConstructor"; - internal const string FilterDescription_FaultHandlerActivity = "FilterDescription_FaultHandlerActivity"; - internal const string Error_FaultHandlerActivityParentNotFaultHandlersActivity = "Error_FaultHandlerActivityParentNotFaultHandlersActivity"; - internal const string Error_FaultHandlerActivityAllMustBeLast = "Error_FaultHandlerActivityAllMustBeLast"; - internal const string Error_FaultHandlersActivityDeclNotAllFaultHandlerActivityDecl = "Error_FaultHandlersActivityDeclNotAllFaultHandlerActivityDecl"; - internal const string Error_FaultHandlerActivityWrongOrder = "Error_FaultHandlerActivityWrongOrder"; - internal const string Error_SenderMustBeActivityExecutionContext = "Error_SenderMustBeActivityExecutionContext"; - internal const string Error_XomlWorkflowHasCode = "Error_XomlWorkflowHasCode"; - internal const string Error_WrongParamForActivityResolveEventArgs = "Error_WrongParamForActivityResolveEventArgs"; - internal const string Error_ValidatorThrewException = "Error_ValidatorThrewException"; - internal const string Error_Missing_CanModifyProperties_True = "Error_Missing_CanModifyProperties_True"; - internal const string Error_Missing_CanModifyProperties_False = "Error_Missing_CanModifyProperties_False"; - internal const string Error_ModelingConstructsCanNotContainModelingConstructs = "Error_ModelingConstructsCanNotContainModelingConstructs"; - internal const string Error_RootIsNotEnabled = "Error_RootIsNotEnabled"; - internal const string Error_MissingSetAccessor = "Error_MissingSetAccessor"; - internal const string Error_MissingAddHandler = "Error_MissingAddHandler"; - internal const string Error_MissingCLRProperty = "Error_MissingCLRProperty"; - - internal const string Error_NotReadOnlyProperty = "Error_NotReadOnlyProperty"; - internal const string Error_InvalidDependencyProperty = "Error_InvalidDependencyProperty"; - internal const string Error_ActivityNameExist = "Error_ActivityNameExist"; - internal const string CannotCreateAttribute = "CannotCreateAttribute"; - internal const string NamespaceAndDeclaringTypeCannotBeNull = "NamespaceAndDeclaringTypeCannotBeNull"; - internal const string NotElementType = "NotElementType"; - - // Layout persistence errors - internal const string Error_LayoutSerializationActivityNotFound = "Error_LayoutSerializationActivityNotFound"; - internal const string Error_LayoutSerializationAssociatedActivityNotFound = "Error_LayoutSerializationAssociatedActivityNotFound"; - internal const string Error_LayoutSerializationPersistenceSupport = "Error_LayoutSerializationPersistenceSupport"; - internal const string Error_LayoutSerializationRootDesignerNotFound = "Error_LayoutSerializationRootDesignerNotFound"; - internal const string Error_ParameterCannotBeEmpty = "Error_ParameterCannotBeEmpty"; - internal const string InvalidExecutionStatus = "InvalidExecutionStatus"; - internal const string Error_LayoutDeserialization = "Error_LayoutDeserialization"; - internal const string Error_LayoutSerialization = "Error_LayoutSerialization"; - - internal const string Error_SerializerStackOverflow = "Error_SerializerStackOverflow"; - internal const string Error_InvalidActivityForWorkflowChanges = "Error_InvalidActivityForWorkflowChanges"; - internal const string Error_InvalidMemberType = "Error_InvalidMemberType"; - internal const string Error_BindPathNullValue = "Error_BindPathNullValue"; - internal const string Error_MarkupExtensionMissingTerminatingCharacter = "Error_MarkupExtensionMissingTerminatingCharacter"; - internal const string Error_MarkupExtensionDeserializeFailed = "Error_MarkupExtensionDeserializeFailed"; - internal const string Error_ApplyDynamicChangeFailed = "Error_ApplyDynamicChangeFailed"; - internal const string Error_ActivityCircularReference = "Error_ActivityCircularReference"; - internal const string Error_ValidatorTypeIsInvalid = "Error_ValidatorTypeIsInvalid"; - internal const string Error_InvalidServiceProvider = "Error_InvalidServiceProvider"; - internal const string Error_InvalidRootForWorkflowChanges = "Error_InvalidRootForWorkflowChanges"; - internal const string Error_ExtraCharacterFoundAtEnd = "Error_ExtraCharacterFoundAtEnd"; - internal const string Error_WorkflowChangesNotSupported = "Error_WorkflowChangesNotSupported"; - internal const string Error_TypeSystemAttributeArgument = "Error_TypeSystemAttributeArgument"; - - internal const string Error_InvalidElementFoundForType = "Error_InvalidElementFoundForType"; - internal const string Error_ActivitySaveLoadNotCalled = "Error_ActivitySaveLoadNotCalled"; - internal const string Error_CanNotBindProperty = "Error_CanNotBindProperty"; -} -#pragma warning restore CS8603 // 可能返回 null 引用。 - -#endif \ No newline at end of file diff --git a/src/Basal/IFox.Basal.Shared/Sortedset/Sortedset.cs b/src/Basal/IFox.Basal.Shared/Sortedset/Sortedset.cs deleted file mode 100644 index 66a6a7f..0000000 --- a/src/Basal/IFox.Basal.Shared/Sortedset/Sortedset.cs +++ /dev/null @@ -1,2901 +0,0 @@ -#if NET35 -#pragma warning disable CS8603 // 可能返回 null 引用。 -#pragma warning disable CS8601 // 引用类型赋值可能为 null。 -#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。 -#pragma warning disable CS8625 // 无法将 null 字面量转换为非 null 的引用类型。 -#pragma warning disable IDE0059 // 不需要赋值 -#pragma warning disable CS8600 // 将 null 字面量或可能为 null 的值转换为非 null 类型。 -#pragma warning disable CS8602 // 解引用可能出现空引用。 -#pragma warning disable CS8604 // 引用类型参数可能为 null。 -// #define USING_HASH_SET -// ==++== -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// -// ==--== -/*============================================================ -** -** Class: SortedSet -** -** Purpose: A generic sorted set. -** -** Date: August 15, 2008 -** -===========================================================*/ - - -namespace System.Collections.Generic -{ - using IFoxCAD.Basal; - using System; - using System.Diagnostics; - using System.Diagnostics.CodeAnalysis; - using System.Runtime.Serialization; - - - - // - // A binary search tree is a red-black tree if it satisfies the following red-black properties: - // 1. Every node is either red or black - // 2. Every leaf (nil node) is black - // 3. If a node is red, then both its children are black - // 4. Every simple path from a node to a descendant leaf contains the same number of black nodes - // - // The basic idea of red-black tree is to represent 2-3-4 trees as standard BSTs but to add one extra bit of information - // per node to encode 3-nodes and 4-nodes. - // 4-nodes will be represented as: B - // R R - // 3 -node will be represented as: B or B - // R B B R - // - // For a detailed description of the algorithm, take a look at "Algorithms" by Robert Sedgewick. - // - - internal delegate bool TreeWalkPredicate(SortedSet.Node node); - - internal enum TreeRotation - { - LeftRotation = 1, - RightRotation = 2, - RightLeftRotation = 3, - LeftRightRotation = 4, - } - - [SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix", Justification = "by design name choice")] - [DebuggerTypeProxy(nameof(SortedSet))]/*这句改了*/ - [DebuggerDisplay("Count = {Count}")] -#if !FEATURE_NETCORE - [Serializable] - public class SortedSet : ISet, ICollection, ICollection, ISerializable, IDeserializationCallback// , IReadOnlyCollection - { -#else - public class SortedSet : ISet, ICollection, ICollection, IReadOnlyCollection { -#endif // !FEATURE_NETCORE - #region local variables/constants - Node root; - IComparer comparer; - int count; - int version; - private Object _syncRoot; - - private const String ComparerName = "Comparer"; - private const String CountName = "Count"; - private const String ItemsName = "Items"; - private const String VersionName = "Version"; - // needed for enumerator - private const String TreeName = "Tree"; - private const String NodeValueName = "Item"; - private const String EnumStartName = "EnumStarted"; - private const String ReverseName = "Reverse"; - private const String EnumVersionName = "EnumVersion"; - -#if !FEATURE_NETCORE - // needed for TreeSubset - private const String minName = "Min"; - private const String maxName = "Max"; - private const String lBoundActiveName = "lBoundActive"; - private const String uBoundActiveName = "uBoundActive"; - - private SerializationInfo siInfo; // A temporary variable which we need during deserialization. -#endif - internal const int StackAllocThreshold = 100; - - #endregion - - #region Constructors - public SortedSet() - { - this.comparer = Comparer.Default; - } - - public SortedSet(IComparer comparer) - { - if (comparer == null) - { - this.comparer = Comparer.Default; - } - else - { - this.comparer = comparer; - } - } - - - public SortedSet(IEnumerable collection) : this(collection, Comparer.Default) - { - } - - public SortedSet(IEnumerable collection, IComparer comparer) - : this(comparer) - { - //if (collection == null) - //{ - // throw new ArgumentNullException("collection"); - //} - collection.NotNull(nameof(collection)); - // these are explicit type checks in the mould of HashSet. It would have worked better - // with something like an ISorted (we could make this work for SortedList.Keys etc) - SortedSet baseTreeSubSet = collection as TreeSubSet; - if (collection is SortedSet baseSortedSet && baseTreeSubSet == null && AreComparersEqual(this, baseSortedSet)) - { - // breadth first traversal to recreate nodes - if (baseSortedSet.Count == 0) - { - count = 0; - version = 0; - root = null; - return; - } - - - // pre order way to replicate nodes - Stack theirStack = new(2 * Log2(baseSortedSet.Count) + 2); - Stack myStack = new(2 * Log2(baseSortedSet.Count) + 2); - Node theirCurrent = baseSortedSet.root; - Node myCurrent = (theirCurrent != null ? new SortedSet.Node(theirCurrent.Item, theirCurrent.IsRed) : null); - root = myCurrent; - while (theirCurrent != null) - { - theirStack.Push(theirCurrent); - myStack.Push(myCurrent); - myCurrent.Left = (theirCurrent.Left != null ? new SortedSet.Node(theirCurrent.Left.Item, theirCurrent.Left.IsRed) : null); - theirCurrent = theirCurrent.Left; - myCurrent = myCurrent.Left; - } - while (theirStack.Count != 0) - { - theirCurrent = theirStack.Pop(); - myCurrent = myStack.Pop(); - Node theirRight = theirCurrent.Right; - Node myRight = null; - if (theirRight != null) - { - myRight = new SortedSet.Node(theirRight.Item, theirRight.IsRed); - } - myCurrent.Right = myRight; - - while (theirRight != null) - { - theirStack.Push(theirRight); - myStack.Push(myRight); - myRight.Left = (theirRight.Left != null ? new SortedSet.Node(theirRight.Left.Item, theirRight.Left.IsRed) : null); - theirRight = theirRight.Left; - myRight = myRight.Left; - } - } - count = baseSortedSet.count; - version = 0; - } - else - { // As it stands, you're doing an NlogN sort of the collection - List els = new(collection); - els.Sort(this.comparer); - for (int i = 1; i < els.Count; i++) - { - if (comparer.Compare(els[i], els[i - 1]) == 0) - { - els.RemoveAt(i); - i--; - } - } - root = ConstructRootFromSortedArray(els.ToArray(), 0, els.Count - 1, null); - count = els.Count; - version = 0; - } - } - - -#if !FEATURE_NETCORE - - protected SortedSet(SerializationInfo info, StreamingContext context) - { - siInfo = info; - } -#endif - #endregion - - #region Bulk Operation Helpers - private void AddAllElements(IEnumerable collection) - { - foreach (T item in collection) - { - if (!this.Contains(item)) - Add(item); - } - } - - private void RemoveAllElements(IEnumerable collection) - { - T min = this.Min; - T max = this.Max; - foreach (T item in collection) - { - if (!(comparer.Compare(item, min) < 0 || comparer.Compare(item, max) > 0) && this.Contains(item)) - this.Remove(item); - } - } - - private bool ContainsAllElements(IEnumerable collection) - { - foreach (T item in collection) - { - if (!this.Contains(item)) - { - return false; - } - } - return true; - } - - // - // Do a in order walk on tree and calls the delegate for each node. - // If the action delegate returns false, stop the walk. - // - // Return true if the entire tree has been walked. - // Otherwise returns false. - // - internal bool InOrderTreeWalk(TreeWalkPredicate action) - { - return InOrderTreeWalk(action, false); - } - - // Allows for the change in traversal direction. Reverse visits nodes in descending order - internal virtual bool InOrderTreeWalk(TreeWalkPredicate action, bool reverse) - { - if (root == null) - { - return true; - } - - // The maximum height of a red-black tree is 2*lg(n+1). - // See page 264 of "Introduction to algorithms" by Thomas H. Cormen - // note: this should be logbase2, but since the stack grows itself, we - // don't want the extra cost - Stack stack = new(2 * (int)(SortedSet.Log2(Count + 1))); - Node current = root; - while (current != null) - { - stack.Push(current); - current = (reverse ? current.Right : current.Left); - } - while (stack.Count != 0) - { - current = stack.Pop(); - if (!action(current)) - { - return false; - } - - Node node = (reverse ? current.Left : current.Right); - while (node != null) - { - stack.Push(node); - node = (reverse ? node.Right : node.Left); - } - } - return true; - } - - // - // Do a left to right breadth first walk on tree and - // calls the delegate for each node. - // If the action delegate returns false, stop the walk. - // - // Return true if the entire tree has been walked. - // Otherwise returns false. - // - internal virtual bool BreadthFirstTreeWalk(TreeWalkPredicate action) - { - if (root == null) - { - return true; - } - - List processQueue = new() - { - root - }; - Node current; - - while (processQueue.Count != 0) - { - current = processQueue[0]; - processQueue.RemoveAt(0); - if (!action(current)) - { - return false; - } - if (current.Left != null) - { - processQueue.Add(current.Left); - } - if (current.Right != null) - { - processQueue.Add(current.Right); - } - } - return true; - } - #endregion - - #region Properties - public int Count - { - get - { - VersionCheck(); - return count; - } - } - - public IComparer Comparer - { - get - { - return comparer; - } - } - - bool ICollection.IsReadOnly - { - get - { - return false; - } - } - - bool ICollection.IsSynchronized - { - get - { - return false; - } - } - - object ICollection.SyncRoot - { - get - { - if (_syncRoot == null) - { - System.Threading.Interlocked.CompareExchange(ref _syncRoot, new Object(), null); - } - return _syncRoot; - } - } - #endregion - - #region Subclass helpers - - // virtual function for subclass that needs to update count - internal virtual void VersionCheck() { } - - - // virtual function for subclass that needs to do range checks - internal virtual bool IsWithinRange(T item) - { - return true; - } - #endregion - - #region ICollection Members - /// - /// Add the value ITEM to the tree, returns true if added, false if duplicate - /// - /// item to be added - public bool Add(T item) - { - return AddIfNotPresent(item); - } - - void ICollection.Add(T item) - { - AddIfNotPresent(item); - } - - - /// - /// Adds ITEM to the tree if not already present. Returns TRUE if value was successfully added - /// or FALSE if it is a duplicate - /// - internal virtual bool AddIfNotPresent(T item) - { - if (root == null) - { // empty tree - root = new Node(item, false); - count = 1; - version++; - return true; - } - - // - // Search for a node at bottom to insert the new node. - // If we can guanratee the node we found is not a 4-node, it would be easy to do insertion. - // We split 4-nodes along the search path. - // - Node current = root; - Node parent = null; - Node grandParent = null; - Node greatGrandParent = null; - - // even if we don't actually add to the set, we may be altering its structure (by doing rotations - // and such). so update version to disable any enumerators/subsets working on it - version++; - - - int order = 0; - while (current != null) - { - order = comparer.Compare(item, current.Item); - if (order == 0) - { - // We could have changed root node to red during the search process. - // We need to set it to black before we return. - root.IsRed = false; - return false; - } - - // split a 4-node into two 2-nodes - if (Is4Node(current)) - { - Split4Node(current); - // We could have introduced two consecutive red nodes after split. Fix that by rotation. - if (IsRed(parent)) - { - InsertionBalance(current, ref parent, grandParent, greatGrandParent); - } - } - greatGrandParent = grandParent; - grandParent = parent; - parent = current; - current = (order < 0) ? current.Left : current.Right; - } - - Debug.Assert(parent != null, "Parent node cannot be null here!"); - // ready to insert the new node - Node node = new(item); - if (order > 0) - { - parent.Right = node; - } - else - { - parent.Left = node; - } - - // the new node will be red, so we will need to adjust the colors if parent node is also red - if (parent.IsRed) - { - InsertionBalance(node, ref parent, grandParent, greatGrandParent); - } - - // Root node is always black - root.IsRed = false; - ++count; - return true; - } - - /// - /// Remove the T ITEM from this SortedSet. Returns true if successfully removed. - /// - /// - /// - public bool Remove(T item) - { - return this.DoRemove(item); // so it can be made non-virtual - } - - internal virtual bool DoRemove(T item) - { - if (root == null) - { - return false; - } - - - // Search for a node and then find its succesor. - // Then copy the item from the succesor to the matching node and delete the successor. - // If a node doesn't have a successor, we can replace it with its left child (if not empty.) - // or delete the matching node. - // - // In top-down implementation, it is important to make sure the node to be deleted is not a 2-node. - // Following code will make sure the node on the path is not a 2 Node. - - // even if we don't actually remove from the set, we may be altering its structure (by doing rotations - // and such). so update version to disable any enumerators/subsets working on it - version++; - - Node current = root; - Node parent = null; - Node grandParent = null; - Node match = null; - Node parentOfMatch = null; - bool foundMatch = false; - while (current != null) - { - if (Is2Node(current)) - { // fix up 2-Node - if (parent == null) - { // current is root. Mark it as red - current.IsRed = true; - } - else - { - Node sibling = GetSibling(current, parent); - if (sibling.IsRed) - { - // If parent is a 3-node, flip the orientation of the red link. - // We can acheive this by a single rotation - // This case is converted to one of other cased below. - Debug.Assert(!parent.IsRed, "parent must be a black node!"); - if (parent.Right == sibling) - { - RotateLeft(parent); - } - else - { - RotateRight(parent); - } - - parent.IsRed = true; - sibling.IsRed = false; // parent's color - // sibling becomes child of grandParent or root after rotation. Update link from grandParent or root - ReplaceChildOfNodeOrRoot(grandParent, parent, sibling); - // sibling will become grandParent of current node - grandParent = sibling; - if (parent == match) - { - parentOfMatch = sibling; - } - - // update sibling, this is necessary for following processing - sibling = (parent.Left == current) ? parent.Right : parent.Left; - } - Debug.Assert(sibling != null || sibling.IsRed == false, "sibling must not be null and it must be black!"); - - if (Is2Node(sibling)) - { - Merge2Nodes(parent, current, sibling); - } - else - { - // current is a 2-node and sibling is either a 3-node or a 4-node. - // We can change the color of current to red by some rotation. - TreeRotation rotation = RotationNeeded(parent, current, sibling); - Node newGrandParent = null; - switch (rotation) - { - case TreeRotation.RightRotation: - Debug.Assert(parent.Left == sibling, "sibling must be left child of parent!"); - Debug.Assert(sibling.Left.IsRed, "Left child of sibling must be red!"); - sibling.Left.IsRed = false; - newGrandParent = RotateRight(parent); - break; - case TreeRotation.LeftRotation: - Debug.Assert(parent.Right == sibling, "sibling must be left child of parent!"); - Debug.Assert(sibling.Right.IsRed, "Right child of sibling must be red!"); - sibling.Right.IsRed = false; - newGrandParent = RotateLeft(parent); - break; - - case TreeRotation.RightLeftRotation: - Debug.Assert(parent.Right == sibling, "sibling must be left child of parent!"); - Debug.Assert(sibling.Left.IsRed, "Left child of sibling must be red!"); - newGrandParent = RotateRightLeft(parent); - break; - - case TreeRotation.LeftRightRotation: - Debug.Assert(parent.Left == sibling, "sibling must be left child of parent!"); - Debug.Assert(sibling.Right.IsRed, "Right child of sibling must be red!"); - newGrandParent = RotateLeftRight(parent); - break; - } - - newGrandParent.IsRed = parent.IsRed; - parent.IsRed = false; - current.IsRed = true; - ReplaceChildOfNodeOrRoot(grandParent, parent, newGrandParent); - if (parent == match) - { - parentOfMatch = newGrandParent; - } - grandParent = newGrandParent; - } - } - } - - // we don't need to compare any more once we found the match - int order = foundMatch ? -1 : comparer.Compare(item, current.Item); - if (order == 0) - { - // save the matching node - foundMatch = true; - match = current; - parentOfMatch = parent; - } - - grandParent = parent; - parent = current; - - if (order < 0) - { - current = current.Left; - } - else - { - current = current.Right; // continue the search in right sub tree after we find a match - } - } - - // move successor to the matching node position and replace links - if (match != null) - { - ReplaceNode(match, parentOfMatch, parent, grandParent); - --count; - } - - if (root != null) - { - root.IsRed = false; - } - return foundMatch; - } - - public virtual void Clear() - { - root = null; - count = 0; - ++version; - } - - - public virtual bool Contains(T item) - { - return FindNode(item) != null; - } - - - - - public void CopyTo(T[] array) - { - CopyTo(array, 0, Count); - } - - public void CopyTo(T[] array, int index) - { - CopyTo(array, index, Count); - } - - public void CopyTo(T[] array, int index, int count) - { - if (array == null) - { - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); - } - - if (index < 0) - { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); - } - - if (count < 0) - { - throw new ArgumentOutOfRangeException("count", SR.GetString("SR.ArgumentOutOfRange_NeedNonNegNum")); - } - - // will array, starting at arrayIndex, be able to hold elements? Note: not - // checking arrayIndex >= array.Length (consistency with list of allowing - // count of 0; subsequent check takes care of the rest) - if (index > array.Length || count > array.Length - index) - { - throw new ArgumentException(SR.GetString("SR.Arg_ArrayPlusOffTooSmall")); - } - // upper bound - count += index; - - InOrderTreeWalk(delegate (Node node) - { - if (index >= count) - { - return false; - } - else - { - array[index++] = node.Item; - return true; - } - }); - } - - void ICollection.CopyTo(Array array, int index) - { - if (array == null) - { - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); - } - - if (array.Rank != 1) - { - ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported); - } - - if (array.GetLowerBound(0) != 0) - { - ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NonZeroLowerBound); - } - - if (index < 0) - { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.arrayIndex, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); - } - - if (array.Length - index < Count) - { - ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall); - } - - if (array is T[] tarray) - { - CopyTo(tarray, index); - } - else - { - object[] objects = array as object[]; - if (objects == null) - { - ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType); - } - - try - { - InOrderTreeWalk(delegate (Node node) { objects[index++] = node.Item; return true; }); - } - catch (ArrayTypeMismatchException) - { - ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType); - } - } - } - - #endregion - - #region IEnumerable members - [System.Diagnostics.DebuggerStepThrough] - public Enumerator GetEnumerator() - { - return new Enumerator(this); - } - - [System.Diagnostics.DebuggerStepThrough] - IEnumerator IEnumerable.GetEnumerator() - { - return new Enumerator(this); - } - - [System.Diagnostics.DebuggerStepThrough] - IEnumerator IEnumerable.GetEnumerator() - { - return new Enumerator(this); - } - #endregion - - #region Tree Specific Operations - - private static Node GetSibling(Node node, Node parent) - { - if (parent.Left == node) - { - return parent.Right; - } - return parent.Left; - } - - // After calling InsertionBalance, we need to make sure current and parent up-to-date. - // It doesn't matter if we keep grandParent and greatGrantParent up-to-date - // because we won't need to split again in the next node. - // By the time we need to split again, everything will be correctly set. - // - private void InsertionBalance(Node current, ref Node parent, Node grandParent, Node greatGrandParent) - { - Debug.Assert(grandParent != null, "Grand parent cannot be null here!"); - bool parentIsOnRight = (grandParent.Right == parent); - bool currentIsOnRight = (parent.Right == current); - - Node newChildOfGreatGrandParent; - if (parentIsOnRight == currentIsOnRight) - { // same orientation, single rotation - newChildOfGreatGrandParent = currentIsOnRight ? RotateLeft(grandParent) : RotateRight(grandParent); - } - else - { // different orientaton, double rotation - newChildOfGreatGrandParent = currentIsOnRight ? RotateLeftRight(grandParent) : RotateRightLeft(grandParent); - // current node now becomes the child of greatgrandparent - parent = greatGrandParent; - } - // grand parent will become a child of either parent of current. - grandParent.IsRed = true; - newChildOfGreatGrandParent.IsRed = false; - - ReplaceChildOfNodeOrRoot(greatGrandParent, grandParent, newChildOfGreatGrandParent); - } - - private static bool Is2Node(Node node) - { - Debug.Assert(node != null, "node cannot be null!"); - return IsBlack(node) && IsNullOrBlack(node.Left) && IsNullOrBlack(node.Right); - } - - private static bool Is4Node(Node node) - { - return IsRed(node.Left) && IsRed(node.Right); - } - - private static bool IsBlack(Node node) - { - return (node != null && !node.IsRed); - } - - private static bool IsNullOrBlack(Node node) - { - return (node == null || !node.IsRed); - } - - private static bool IsRed(Node node) - { - return (node != null && node.IsRed); - } - - private static void Merge2Nodes(Node parent, Node child1, Node child2) - { - Debug.Assert(IsRed(parent), "parent must be be red"); - // combing two 2-nodes into a 4-node - parent.IsRed = false; - child1.IsRed = true; - child2.IsRed = true; - } - - // Replace the child of a parent node. - // If the parent node is null, replace the root. - private void ReplaceChildOfNodeOrRoot(Node parent, Node child, Node newChild) - { - if (parent != null) - { - if (parent.Left == child) - { - parent.Left = newChild; - } - else - { - parent.Right = newChild; - } - } - else - { - root = newChild; - } - } - - // Replace the matching node with its succesor. - private void ReplaceNode(Node match, Node parentOfMatch, Node succesor, Node parentOfSuccesor) - { - if (succesor == match) - { // this node has no successor, should only happen if right child of matching node is null. - Debug.Assert(match.Right == null, "Right child must be null!"); - succesor = match.Left; - } - else - { - Debug.Assert(parentOfSuccesor != null, "parent of successor cannot be null!"); - Debug.Assert(succesor.Left == null, "Left child of succesor must be null!"); - Debug.Assert((succesor.Right == null && succesor.IsRed) || (succesor.Right.IsRed && !succesor.IsRed), "Succesor must be in valid state"); - if (succesor.Right != null) - { - succesor.Right.IsRed = false; - } - - if (parentOfSuccesor != match) - { // detach succesor from its parent and set its right child - parentOfSuccesor.Left = succesor.Right; - succesor.Right = match.Right; - } - - succesor.Left = match.Left; - } - - if (succesor != null) - { - succesor.IsRed = match.IsRed; - } - - ReplaceChildOfNodeOrRoot(parentOfMatch, match, succesor); - } - - internal virtual Node FindNode(T item) - { - Node current = root; - while (current != null) - { - int order = comparer.Compare(item, current.Item); - if (order == 0) - { - return current; - } - else - { - current = (order < 0) ? current.Left : current.Right; - } - } - - return null; - } - - // used for bithelpers. Note that this implementation is completely different - // from the Subset's. The two should not be mixed. This indexes as if the tree were an array. - // http://en.wikipedia.org/wiki/Binary_Tree#Methods_for_storing_binary_trees - internal virtual int InternalIndexOf(T item) - { - Node current = root; - int count = 0; - while (current != null) - { - int order = comparer.Compare(item, current.Item); - if (order == 0) - { - return count; - } - else - { - current = (order < 0) ? current.Left : current.Right; - count = (order < 0) ? (2 * count + 1) : (2 * count + 2); - } - } - return -1; - } - - - - internal Node FindRange(T from, T to) - { - return FindRange(from, to, true, true); - } - internal Node FindRange(T from, T to, bool lowerBoundActive, bool upperBoundActive) - { - Node current = root; - while (current != null) - { - if (lowerBoundActive && comparer.Compare(from, current.Item) > 0) - { - current = current.Right; - } - else - { - if (upperBoundActive && comparer.Compare(to, current.Item) < 0) - { - current = current.Left; - } - else - { - return current; - } - } - } - - return null; - } - - internal void UpdateVersion() - { - ++version; - } - - - private static Node RotateLeft(Node node) - { - Node x = node.Right; - node.Right = x.Left; - x.Left = node; - return x; - } - - private static Node RotateLeftRight(Node node) - { - Node child = node.Left; - Node grandChild = child.Right; - - node.Left = grandChild.Right; - grandChild.Right = node; - child.Right = grandChild.Left; - grandChild.Left = child; - return grandChild; - } - - private static Node RotateRight(Node node) - { - Node x = node.Left; - node.Left = x.Right; - x.Right = node; - return x; - } - - private static Node RotateRightLeft(Node node) - { - Node child = node.Right; - Node grandChild = child.Left; - - node.Right = grandChild.Left; - grandChild.Left = node; - child.Left = grandChild.Right; - grandChild.Right = child; - return grandChild; - } - /// - /// Testing counter that can track rotations - /// - - - private static TreeRotation RotationNeeded(Node parent, Node current, Node sibling) - { - Debug.Assert(IsRed(sibling.Left) || IsRed(sibling.Right), "sibling must have at least one red child"); - if (IsRed(sibling.Left)) - { - if (parent.Left == current) - { - return TreeRotation.RightLeftRotation; - } - return TreeRotation.RightRotation; - } - else - { - if (parent.Left == current) - { - return TreeRotation.LeftRotation; - } - return TreeRotation.LeftRightRotation; - } - } - - /// - /// Used for deep equality of SortedSet testing - /// - /// - public static IEqualityComparer> CreateSetComparer() - { - return new SortedSetEqualityComparer(); - } - - /// - /// Create a new set comparer for this set, where this set's members' equality is defined by the - /// memberEqualityComparer. Note that this equality comparer's definition of equality must be the - /// same as this set's Comparer's definition of equality - /// - public static IEqualityComparer> CreateSetComparer(IEqualityComparer memberEqualityComparer) - { - return new SortedSetEqualityComparer(memberEqualityComparer); - } - - - /// - /// Decides whether these sets are the same, given the comparer. If the EC's are the same, we can - /// just use SetEquals, but if they aren't then we have to manually check with the given comparer - /// - internal static bool SortedSetEquals(SortedSet set1, SortedSet set2, IComparer comparer) - { - // handle null cases first - if (set1 == null) - { - return (set2 == null); - } - else if (set2 == null) - { - // set1 != null - return false; - } - - if (AreComparersEqual(set1, set2)) - { - if (set1.Count != set2.Count) - return false; - - return set1.SetEquals(set2); - } - else - { - bool found = false; - foreach (T item1 in set1) - { - found = false; - foreach (T item2 in set2) - { - if (comparer.Compare(item1, item2) == 0) - { - found = true; - break; - } - } - if (!found) - return false; - } - return true; - } - } - - - // This is a little frustrating because we can't support more sorted structures - private static bool AreComparersEqual(SortedSet set1, SortedSet set2) - { - return set1.Comparer.Equals(set2.Comparer); - } - - - private static void Split4Node(Node node) - { - node.IsRed = true; - node.Left.IsRed = false; - node.Right.IsRed = false; - } - - /// - /// Copies this to an array. Used for DebugView - /// - /// - internal T[] ToArray() - { - T[] newArray = new T[Count]; - CopyTo(newArray); - return newArray; - } - - - #endregion - - #region ISet Members - - /// - /// Transform this set into its union with the IEnumerable OTHER - /// Attempts to insert each element and rejects it if it exists. - /// NOTE: The caller object is important as UnionWith uses the Comparator - /// associated with THIS to check equality - /// Throws ArgumentNullException if OTHER is null - /// - /// - public void UnionWith(IEnumerable other) - { - //if (other == null) - //{ - // throw new ArgumentNullException("other"); - //} - other.NotNull(nameof(other)); - - SortedSet s = other as SortedSet; - TreeSubSet t = this as TreeSubSet; - - if (t != null) - VersionCheck(); - - if (s != null && t == null && this.count == 0) - { - SortedSet dummy = new(s, this.comparer); - this.root = dummy.root; - this.count = dummy.count; - this.version++; - return; - } - - - if (s != null && t == null && AreComparersEqual(this, s) && (s.Count > this.Count / 2)) - { // this actually hurts if N is much greater than M the /2 is arbitrary - // first do a merge sort to an array. - T[] merged = new T[s.Count + this.Count]; - int c = 0; - Enumerator mine = this.GetEnumerator(); - Enumerator theirs = s.GetEnumerator(); - bool mineEnded = !mine.MoveNext(), theirsEnded = !theirs.MoveNext(); - while (!mineEnded && !theirsEnded) - { - int comp = Comparer.Compare(mine.Current, theirs.Current); - if (comp < 0) - { - merged[c++] = mine.Current; - mineEnded = !mine.MoveNext(); - } - else if (comp == 0) - { - merged[c++] = theirs.Current; - mineEnded = !mine.MoveNext(); - theirsEnded = !theirs.MoveNext(); - } - else - { - merged[c++] = theirs.Current; - theirsEnded = !theirs.MoveNext(); - } - } - - if (!mineEnded || !theirsEnded) - { - Enumerator remaining = (mineEnded ? theirs : mine); - do - { - merged[c++] = remaining.Current; - } while (remaining.MoveNext()); - } - - // now merged has all c elements - - // safe to gc the root, we have all the elements - root = null; - - - root = SortedSet.ConstructRootFromSortedArray(merged, 0, c - 1, null); - count = c; - version++; - } - else - { - AddAllElements(other); - } - } - - - private static Node ConstructRootFromSortedArray(T[] arr, int startIndex, int endIndex, Node redNode) - { - // what does this do? - // you're given a sorted array... say 1 2 3 4 5 6 - // 2 cases: - // If there are odd # of elements, pick the middle element (in this case 4), and compute - // its left and right branches - // If there are even # of elements, pick the left middle element, save the right middle element - // and call the function on the rest - // 1 2 3 4 5 6 -> pick 3, save 4 and call the fn on 1,2 and 5,6 - // now add 4 as a red node to the lowest element on the right branch - // 3 3 - // 1 5 -> 1 5 - // 2 6 2 4 6 - // As we're adding to the leftmost of the right branch, nesting will not hurt the red-black properties - // Leaf nodes are red if they have no sibling (if there are 2 nodes or if a node trickles - // down to the bottom - - - // the iterative way to do this ends up wasting more space than it saves in stack frames (at - // least in what i tried) - // so we're doing this recursively - // base cases are described below - int size = endIndex - startIndex + 1; - if (size == 0) - { - return null; - } - Node root = null; - if (size == 1) - { - root = new Node(arr[startIndex], false); - if (redNode != null) - { - root.Left = redNode; - } - } - else if (size == 2) - { - root = new Node(arr[startIndex], false) - { - Right = new Node(arr[endIndex], false) - }; - root.Right.IsRed = true; - if (redNode != null) - { - root.Left = redNode; - } - } - else if (size == 3) - { - root = new Node(arr[startIndex + 1], false) - { - Left = new Node(arr[startIndex], false), - Right = new Node(arr[endIndex], false) - }; - if (redNode != null) - { - root.Left.Left = redNode; - } - } - else - { - int midpt = ((startIndex + endIndex) / 2); - root = new Node(arr[midpt], false) - { - Left = ConstructRootFromSortedArray(arr, startIndex, midpt - 1, redNode) - }; - if (size % 2 == 0) - { - root.Right = ConstructRootFromSortedArray(arr, midpt + 2, endIndex, new Node(arr[midpt + 1], true)); - } - else - { - root.Right = ConstructRootFromSortedArray(arr, midpt + 1, endIndex, null); - } - } - return root; - } - - - /// - /// Transform this set into its intersection with the IEnumerable OTHER - /// NOTE: The caller object is important as IntersectionWith uses the - /// comparator associated with THIS to check equality - /// Throws ArgumentNullException if OTHER is null - /// - /// - public virtual void IntersectWith(IEnumerable other) - { - //if (other == null) - //{ - // throw new ArgumentNullException("other"); - //} - other.NotNull(nameof(other)); - - if (Count == 0) - return; - - // HashSet optimizations can't be done until equality comparers and comparers are related - - // Technically, this would work as well with an ISorted - TreeSubSet t = this as TreeSubSet; - if (t != null) - VersionCheck(); - // only let this happen if i am also a SortedSet, not a SubSet - if (other is SortedSet s && t == null && AreComparersEqual(this, s)) - { - // first do a merge sort to an array. - T[] merged = new T[this.Count]; - int c = 0; - Enumerator mine = this.GetEnumerator(); - Enumerator theirs = s.GetEnumerator(); - bool mineEnded = !mine.MoveNext(), theirsEnded = !theirs.MoveNext(); - T max = Max; - T min = Min; - - while (!mineEnded && !theirsEnded && Comparer.Compare(theirs.Current, max) <= 0) - { - int comp = Comparer.Compare(mine.Current, theirs.Current); - if (comp < 0) - { - mineEnded = !mine.MoveNext(); - } - else if (comp == 0) - { - merged[c++] = theirs.Current; - mineEnded = !mine.MoveNext(); - theirsEnded = !theirs.MoveNext(); - } - else - { - theirsEnded = !theirs.MoveNext(); - } - } - - // now merged has all c elements - - // safe to gc the root, we have all the elements - root = null; - - root = SortedSet.ConstructRootFromSortedArray(merged, 0, c - 1, null); - count = c; - version++; - } - else - { - IntersectWithEnumerable(other); - } - } - - internal virtual void IntersectWithEnumerable(IEnumerable other) - { - // - List toSave = new(this.Count); - foreach (T item in other) - { - if (this.Contains(item)) - { - toSave.Add(item); - this.Remove(item); - } - } - this.Clear(); - AddAllElements(toSave); - } - - - - /// - /// Transform this set into its complement with the IEnumerable OTHER - /// NOTE: The caller object is important as ExceptWith uses the - /// comparator associated with THIS to check equality - /// Throws ArgumentNullException if OTHER is null - /// - /// - public void ExceptWith(IEnumerable other) - { - //if (other == null) - //{ - // throw new ArgumentNullException("other"); - //} - other.NotNull(nameof(other)); - - if (count == 0) - return; - - if (other == this) - { - this.Clear(); - return; - } - - - if (other is SortedSet asSorted && AreComparersEqual(this, asSorted)) - { - // outside range, no point doing anything - if (!(comparer.Compare(asSorted.Max, this.Min) < 0 || comparer.Compare(asSorted.Min, this.Max) > 0)) - { - T min = this.Min; - T max = this.Max; - foreach (T item in other) - { - if (comparer.Compare(item, min) < 0) - continue; - if (comparer.Compare(item, max) > 0) - break; - Remove(item); - } - } - } - else - { - RemoveAllElements(other); - } - } - - /// - /// Transform this set so it contains elements in THIS or OTHER but not both - /// NOTE: The caller object is important as SymmetricExceptWith uses the - /// comparator associated with THIS to check equality - /// Throws ArgumentNullException if OTHER is null - /// - /// - public void SymmetricExceptWith(IEnumerable other) - { - //if (other == null) - //{ - // throw new ArgumentNullException("other"); - //} - other.NotNull(nameof(other)); - if (this.Count == 0) - { - this.UnionWith(other); - return; - } - - if (other == this) - { - this.Clear(); - return; - } - - - -#if USING_HASH_SET - HashSet asHash = other as HashSet; -#endif - if (other is SortedSet asSorted && AreComparersEqual(this, asSorted)) - { - SymmetricExceptWithSameEC(asSorted); - } -#if USING_HASH_SET - else if (asHash != null && this.comparer.Equals(Comparer.Default) && asHash.Comparer.Equals(EqualityComparer.Default)) { - SymmetricExceptWithSameEC(asHash); - } -#endif - else - { - // need perf improvement on this - T[] elements = (new List(other)).ToArray(); - Array.Sort(elements, this.Comparer); - SymmetricExceptWithSameEC(elements); - } - } - - // OTHER must be a set - internal void SymmetricExceptWithSameEC(ISet other) - { - foreach (T item in other) - { - // yes, it is classier to say - // if (!this.Remove(item))this.Add(item); - // but this ends up saving on rotations - if (this.Contains(item)) - { - this.Remove(item); - } - else - { - this.Add(item); - } - } - } - - // OTHER must be a sorted array - internal void SymmetricExceptWithSameEC(T[] other) - { - if (other.Length == 0) - { - return; - } - T last = other[0]; - for (int i = 0; i < other.Length; i++) - { - while (i < other.Length && i != 0 && comparer.Compare(other[i], last) == 0) - i++; - if (i >= other.Length) - break; - if (this.Contains(other[i])) - { - this.Remove(other[i]); - } - else - { - this.Add(other[i]); - } - last = other[i]; - } - } - - - /// - /// Checks whether this Tree is a subset of the IEnumerable other - /// - /// - /// - [System.Security.SecuritySafeCritical] - public bool IsSubsetOf(IEnumerable other) - { - //if (other == null) - //{ - // throw new ArgumentNullException("other"); - //} - other.NotNull(nameof(other)); - if (Count == 0) - return true; - - - if (other is SortedSet asSorted && AreComparersEqual(this, asSorted)) - { - if (this.Count > asSorted.Count) - return false; - return IsSubsetOfSortedSetWithSameEC(asSorted); - } - else - { - // worst case: mark every element in my set and see if i've counted all - // O(MlogN) - - ElementCount result = CheckUniqueAndUnfoundElements(other, false); - return (result.uniqueCount == Count && result.unfoundCount >= 0); - } - } - - private bool IsSubsetOfSortedSetWithSameEC(SortedSet asSorted) - { - SortedSet prunedOther = asSorted.GetViewBetween(this.Min, this.Max); - foreach (T item in this) - { - if (!prunedOther.Contains(item)) - return false; - } - return true; - } - - - /// - /// Checks whether this Tree is a proper subset of the IEnumerable other - /// - /// - /// - [System.Security.SecuritySafeCritical] - public bool IsProperSubsetOf(IEnumerable other) - { - //if (other == null) - //{ - // throw new ArgumentNullException("other"); - //} - other.NotNull(nameof(other)); - if ((other as ICollection) != null) - { - if (Count == 0) - return (other as ICollection).Count > 0; - } - - -#if USING_HASH_SET - // do it one way for HashSets - HashSet asHash = other as HashSet; - if (asHash != null && comparer.Equals(Comparer.Default) && asHash.Comparer.Equals(EqualityComparer.Default)) { - return asHash.IsProperSupersetOf(this); - } -#endif - // another for sorted sets with the same comparer - if (other is SortedSet asSorted && AreComparersEqual(this, asSorted)) - { - if (this.Count >= asSorted.Count) - return false; - return IsSubsetOfSortedSetWithSameEC(asSorted); - } - - - // worst case: mark every element in my set and see if i've counted all - // O(MlogN). - ElementCount result = CheckUniqueAndUnfoundElements(other, false); - return (result.uniqueCount == Count && result.unfoundCount > 0); - } - - - /// - /// Checks whether this Tree is a super set of the IEnumerable other - /// - /// - /// - public bool IsSupersetOf(IEnumerable other) - { - //if (other == null) - //{ - // throw new ArgumentNullException("other"); - //} - other.NotNull(nameof(other)); - if ((other as ICollection) != null && (other as ICollection).Count == 0) - return true; - - // do it one way for HashSets -#if USING_HASH_SET - HashSet asHash = other as HashSet; - if (asHash != null && comparer.Equals(Comparer.Default) && asHash.Comparer.Equals(EqualityComparer.Default)) { - return asHash.IsSubsetOf(this); - } -#endif - // another for sorted sets with the same comparer - if (other is SortedSet asSorted && AreComparersEqual(this, asSorted)) - { - if (this.Count < asSorted.Count) - return false; - SortedSet pruned = GetViewBetween(asSorted.Min, asSorted.Max); - foreach (T item in asSorted) - { - if (!pruned.Contains(item)) - return false; - } - return true; - } - // and a third for everything else - return ContainsAllElements(other); - } - - /// - /// Checks whether this Tree is a proper super set of the IEnumerable other - /// - /// - /// - [System.Security.SecuritySafeCritical] - public bool IsProperSupersetOf(IEnumerable other) - { - //if (other == null) - //{ - // throw new ArgumentNullException("other"); - //} - other.NotNull(nameof(other)); - if (Count == 0) - return false; - - if ((other as ICollection) != null && (other as ICollection).Count == 0) - return true; - -#if USING_HASH_SET - // do it one way for HashSets - - HashSet asHash = other as HashSet; - if (asHash != null && comparer.Equals(Comparer.Default) && asHash.Comparer.Equals(EqualityComparer.Default)) { - return asHash.IsProperSubsetOf(this); - } -#endif - // another way for sorted sets - if (other is SortedSet asSorted && AreComparersEqual(asSorted, this)) - { - if (asSorted.Count >= this.Count) - return false; - SortedSet pruned = GetViewBetween(asSorted.Min, asSorted.Max); - foreach (T item in asSorted) - { - if (!pruned.Contains(item)) - return false; - } - return true; - } - - - // worst case: mark every element in my set and see if i've counted all - // O(MlogN) - // slight optimization, put it into a HashSet and then check can do it in O(N+M) - // but slower in better cases + wastes space - ElementCount result = CheckUniqueAndUnfoundElements(other, true); - return (result.uniqueCount < Count && result.unfoundCount == 0); - } - - - - /// - /// Checks whether this Tree has all elements in common with IEnumerable other - /// - /// - /// - [System.Security.SecuritySafeCritical] - public bool SetEquals(IEnumerable other) - { - //if (other == null) - //{ - // throw new ArgumentNullException("other"); - //} - other.NotNull(nameof(other)); -#if USING_HASH_SET - HashSet asHash = other as HashSet; - if (asHash != null && comparer.Equals(Comparer.Default) && asHash.Comparer.Equals(EqualityComparer.Default)) { - return asHash.SetEquals(this); - } -#endif - if (other is SortedSet asSorted && AreComparersEqual(this, asSorted)) - { - IEnumerator mine = this.GetEnumerator(); - IEnumerator theirs = asSorted.GetEnumerator(); - bool mineEnded = !mine.MoveNext(); - bool theirsEnded = !theirs.MoveNext(); - while (!mineEnded && !theirsEnded) - { - if (Comparer.Compare(mine.Current, theirs.Current) != 0) - { - return false; - } - mineEnded = !mine.MoveNext(); - theirsEnded = !theirs.MoveNext(); - } - return mineEnded && theirsEnded; - } - - // worst case: mark every element in my set and see if i've counted all - // O(N) by size of other - ElementCount result = CheckUniqueAndUnfoundElements(other, true); - return (result.uniqueCount == Count && result.unfoundCount == 0); - } - - - - /// - /// Checks whether this Tree has any elements in common with IEnumerable other - /// - /// - /// - public bool Overlaps(IEnumerable other) - { - //if (other == null) - //{ - // throw new ArgumentNullException("other"); - //} - other.NotNull(nameof(other)); - if (this.Count == 0) - return false; - - if ((other as ICollection != null) && (other as ICollection).Count == 0) - return false; - - if (other is SortedSet asSorted && AreComparersEqual(this, asSorted) && (comparer.Compare(Min, asSorted.Max) > 0 || comparer.Compare(Max, asSorted.Min) < 0)) - { - return false; - } -#if USING_HASH_SET - HashSet asHash = other as HashSet; - if (asHash != null && comparer.Equals(Comparer.Default) && asHash.Comparer.Equals(EqualityComparer.Default)) { - return asHash.Overlaps(this); - } -#endif - foreach (T item in other) - { - if (this.Contains(item)) - { - return true; - } - } - return false; - } - - /// - /// This works similar to HashSet's CheckUniqueAndUnfound (description below), except that the bit - /// array maps differently than in the HashSet. We can only use this for the bulk boolean checks. - /// - /// Determines counts that can be used to determine equality, subset, and superset. This - /// is only used when other is an IEnumerable and not a HashSet. If other is a HashSet - /// these properties can be checked faster without use of marking because we can assume - /// other has no duplicates. - /// - /// The following count checks are performed by callers: - /// 1. Equals: checks if unfoundCount = 0 and uniqueFoundCount = Count; i.e. everything - /// in other is in this and everything in this is in other - /// 2. Subset: checks if unfoundCount >= 0 and uniqueFoundCount = Count; i.e. other may - /// have elements not in this and everything in this is in other - /// 3. Proper subset: checks if unfoundCount > 0 and uniqueFoundCount = Count; i.e - /// other must have at least one element not in this and everything in this is in other - /// 4. Proper superset: checks if unfound count = 0 and uniqueFoundCount strictly less - /// than Count; i.e. everything in other was in this and this had at least one element - /// not contained in other. - /// - /// An earlier implementation used delegates to perform these checks rather than returning - /// an ElementCount struct; however this was changed due to the perf overhead of delegates. - /// - /// - /// Allows us to finish faster for equals and proper superset - /// because unfoundCount must be 0. - /// - // - // - // - // - // - // - [System.Security.SecurityCritical] - private unsafe ElementCount CheckUniqueAndUnfoundElements(IEnumerable other, bool returnIfUnfound) - { - ElementCount result; - - // need special case in case this has no elements. - if (Count == 0) - { - int numElementsInOther = 0; - foreach (T item in other) - { - numElementsInOther++; - // break right away, all we want to know is whether other has 0 or 1 elements - break; - } - result.uniqueCount = 0; - result.unfoundCount = numElementsInOther; - return result; - } - - - int originalLastIndex = Count; - int intArrayLength = BitHelper.ToIntArrayLength(originalLastIndex); - - BitHelper bitHelper; - if (intArrayLength <= StackAllocThreshold) - { - int* bitArrayPtr = stackalloc int[intArrayLength]; - bitHelper = new BitHelper(bitArrayPtr, intArrayLength); - } - else - { - int[] bitArray = new int[intArrayLength]; - bitHelper = new BitHelper(bitArray, intArrayLength); - } - - // count of items in other not found in this - int unfoundCount = 0; - // count of unique items in other found in this - int uniqueFoundCount = 0; - - foreach (T item in other) - { - int index = InternalIndexOf(item); - if (index >= 0) - { - if (!bitHelper.IsMarked(index)) - { - // item hasn't been seen yet - bitHelper.MarkBit(index); - uniqueFoundCount++; - } - } - else - { - unfoundCount++; - if (returnIfUnfound) - { - break; - } - } - } - - result.uniqueCount = uniqueFoundCount; - result.unfoundCount = unfoundCount; - return result; - } - public int RemoveWhere(Predicate match) - { - //if (match == null) - //{ - // throw new ArgumentNullException("match"); - //} - match.NotNull(nameof(match)); - List matches = new(this.Count); - - BreadthFirstTreeWalk(delegate (Node n) - { - if (match(n.Item)) - { - matches.Add(n.Item); - } - return true; - }); - // reverse breadth first to (try to) incur low cost - int actuallyRemoved = 0; - for (int i = matches.Count - 1; i >= 0; i--) - { - if (this.Remove(matches[i])) - { - actuallyRemoved++; - } - } - - return actuallyRemoved; - } - - - #endregion - - #region ISorted Members - - - public T Min - { - get - { - T ret = default; - InOrderTreeWalk(delegate (SortedSet.Node n) { ret = n.Item; return false; }); - return ret; - } - } - - public T Max - { - get - { - T ret = default; - InOrderTreeWalk(delegate (SortedSet.Node n) { ret = n.Item; return false; }, true); - return ret; - } - } - - public IEnumerable Reverse() - { - Enumerator e = new(this, true); - while (e.MoveNext()) - { - yield return e.Current; - } - } - - - /// - /// Returns a subset of this tree ranging from values lBound to uBound - /// Any changes made to the subset reflect in the actual tree - /// - /// Lowest Value allowed in the subset - /// Highest Value allowed in the subset - public virtual SortedSet GetViewBetween(T lowerValue, T upperValue) - { - if (Comparer.Compare(lowerValue, upperValue) > 0) - { - throw new ArgumentException("lowerBound is greater than upperBound"); - } - return new TreeSubSet(this, lowerValue, upperValue, true, true); - } - -#if DEBUG - - /// - /// debug status to be checked whenever any operation is called - /// - /// - internal virtual bool VersionUpToDate() - { - return true; - } -#endif - - - /// - /// This class represents a subset view into the tree. Any changes to this view - /// are reflected in the actual tree. Uses the Comparator of the underlying tree. - /// - /// -#if !FEATURE_NETCORE - [Serializable] - internal sealed class TreeSubSet : SortedSet, ISerializable, IDeserializationCallback - { -#else - internal sealed class TreeSubSet : SortedSet { -#endif - SortedSet underlying; - T min, max; - // these exist for unbounded collections - // for instance, you could allow this subset to be defined for i>10. The set will throw if - // anything <=10 is added, but there is no upperbound. These features Head(), Tail(), were punted - // in the spec, and are not available, but the framework is there to make them available at some point. - bool lBoundActive, uBoundActive; - // used to see if the count is out of date - - -#if DEBUG - internal override bool VersionUpToDate() - { - return (this.version == underlying.version); - } -#endif - - public TreeSubSet(SortedSet Underlying, T Min, T Max, bool lowerBoundActive, bool upperBoundActive) - : base(Underlying.Comparer) - { - underlying = Underlying; - min = Min; - max = Max; - lBoundActive = lowerBoundActive; - uBoundActive = upperBoundActive; - root = underlying.FindRange(min, max, lBoundActive, uBoundActive); // root is first element within range - count = 0; - version = -1; - VersionCheckImpl(); - } - -#if !FEATURE_NETCORE - /// - /// For serialization and deserialization - /// - private TreeSubSet() - { - comparer = null; - } - - - [SuppressMessage("Microsoft.Usage", "CA2236:CallBaseClassMethodsOnISerializableTypes", Justification = "special case TreeSubSet serialization")] - private TreeSubSet(SerializationInfo info, StreamingContext context) - { - siInfo = info; - OnDeserializationImpl(info); - } -#endif // !FEATURE_NETCORE - - /// - /// Additions to this tree need to be added to the underlying tree as well - /// - - internal override bool AddIfNotPresent(T item) - { - if (!IsWithinRange(item)) - { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.collection); - } - - bool ret = underlying.AddIfNotPresent(item); - VersionCheck(); -#if DEBUG - Debug.Assert(this.VersionUpToDate() && this.root == this.underlying.FindRange(min, max)); -#endif - - return ret; - } - - - public override bool Contains(T item) - { - VersionCheck(); -#if DEBUG - Debug.Assert(this.VersionUpToDate() && this.root == this.underlying.FindRange(min, max)); -#endif - return base.Contains(item); - } - - internal override bool DoRemove(T item) - { - if (!IsWithinRange(item)) - { - return false; - } - - bool ret = underlying.Remove(item); - VersionCheck(); -#if DEBUG - Debug.Assert(this.VersionUpToDate() && this.root == this.underlying.FindRange(min, max)); -#endif - return ret; - } - - public override void Clear() - { - if (count == 0) - { - return; - } - - List toRemove = new(); - BreadthFirstTreeWalk(delegate (Node n) { toRemove.Add(n.Item); return true; }); - while (toRemove.Count != 0) - { - underlying.Remove(toRemove[^1]); - toRemove.RemoveAt(toRemove.Count - 1); - } - root = null; - count = 0; - version = underlying.version; - } - - - internal override bool IsWithinRange(T item) - { - int comp = (lBoundActive ? Comparer.Compare(min, item) : -1); - if (comp > 0) - { - return false; - } - comp = (uBoundActive ? Comparer.Compare(max, item) : 1); - if (comp < 0) - { - return false; - } - return true; - } - - internal override bool InOrderTreeWalk(TreeWalkPredicate action, Boolean reverse) - { - VersionCheck(); - - if (root == null) - { - return true; - } - - // The maximum height of a red-black tree is 2*lg(n+1). - // See page 264 of "Introduction to algorithms" by Thomas H. Cormen - Stack stack = new(2 * (int)SortedSet.Log2(count + 1)); // this is not exactly right if count is out of date, but the stack can grow - Node current = root; - while (current != null) - { - if (IsWithinRange(current.Item)) - { - stack.Push(current); - current = (reverse ? current.Right : current.Left); - } - else if (lBoundActive && Comparer.Compare(min, current.Item) > 0) - { - current = current.Right; - } - else - { - current = current.Left; - } - } - - while (stack.Count != 0) - { - current = stack.Pop(); - if (!action(current)) - { - return false; - } - - Node node = (reverse ? current.Left : current.Right); - while (node != null) - { - if (IsWithinRange(node.Item)) - { - stack.Push(node); - node = (reverse ? node.Right : node.Left); - } - else if (lBoundActive && Comparer.Compare(min, node.Item) > 0) - { - node = node.Right; - } - else - { - node = node.Left; - } - } - } - return true; - } - - internal override bool BreadthFirstTreeWalk(TreeWalkPredicate action) - { - VersionCheck(); - - if (root == null) - { - return true; - } - - List processQueue = new() - { - root - }; - Node current; - - while (processQueue.Count != 0) - { - current = processQueue[0]; - processQueue.RemoveAt(0); - if (IsWithinRange(current.Item) && !action(current)) - { - return false; - } - if (current.Left != null && (!lBoundActive || Comparer.Compare(min, current.Item) < 0)) - { - processQueue.Add(current.Left); - } - if (current.Right != null && (!uBoundActive || Comparer.Compare(max, current.Item) > 0)) - { - processQueue.Add(current.Right); - } - } - return true; - } - - internal override SortedSet.Node FindNode(T item) - { - if (!IsWithinRange(item)) - { - return null; - } - VersionCheck(); -#if DEBUG - Debug.Assert(this.VersionUpToDate() && this.root == this.underlying.FindRange(min, max)); -#endif - return base.FindNode(item); - } - - // this does indexing in an inefficient way compared to the actual sortedset, but it saves a - // lot of space - internal override int InternalIndexOf(T item) - { - int count = -1; - foreach (T i in this) - { - count++; - if (Comparer.Compare(item, i) == 0) - return count; - } -#if DEBUG - Debug.Assert(this.VersionUpToDate() && this.root == this.underlying.FindRange(min, max)); -#endif - return -1; - } - /// - /// checks whether this subset is out of date. updates if necessary. - /// - internal override void VersionCheck() - { - VersionCheckImpl(); - } - - private void VersionCheckImpl() - { - Debug.Assert(underlying != null, "Underlying set no longer exists"); - if (this.version != underlying.version) - { - this.root = underlying.FindRange(min, max, lBoundActive, uBoundActive); - this.version = underlying.version; - count = 0; - InOrderTreeWalk(delegate (Node n) { count++; return true; }); - } - } - - - - // This passes functionality down to the underlying tree, clipping edges if necessary - // There's nothing gained by having a nested subset. May as well draw it from the base - // Cannot increase the bounds of the subset, can only decrease it - public override SortedSet GetViewBetween(T lowerValue, T upperValue) - { - if (lBoundActive && Comparer.Compare(min, lowerValue) > 0) - { - // lBound = min; - throw new ArgumentOutOfRangeException("lowerValue"); - } - if (uBoundActive && Comparer.Compare(max, upperValue) < 0) - { - // uBound = max; - throw new ArgumentOutOfRangeException("upperValue"); - } - TreeSubSet ret = (TreeSubSet)underlying.GetViewBetween(lowerValue, upperValue); - return ret; - } - - internal override void IntersectWithEnumerable(IEnumerable other) - { - List toSave = new(this.Count); - foreach (T item in other) - { - if (this.Contains(item)) - { - toSave.Add(item); - this.Remove(item); - } - } - this.Clear(); - this.AddAllElements(toSave); -#if DEBUG - Debug.Assert(this.VersionUpToDate() && this.root == this.underlying.FindRange(min, max)); -#endif - } - -#if !FEATURE_NETCORE - void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) - { - GetObjectData(info, context); - } - - protected override void GetObjectData(SerializationInfo info, StreamingContext context) - { - if (info == null) - { - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.info); - } - info.AddValue(maxName, max, typeof(T)); - info.AddValue(minName, min, typeof(T)); - info.AddValue(lBoundActiveName, lBoundActive); - info.AddValue(uBoundActiveName, uBoundActive); - base.GetObjectData(info, context); - } - - void IDeserializationCallback.OnDeserialization(Object sender) - { - // don't do anything here as its already been done by the constructor - // OnDeserialization(sender); - } - - protected override void OnDeserialization(Object sender) - { - OnDeserializationImpl(sender); - } - - private void OnDeserializationImpl(Object sender) - { - if (siInfo == null) - { - ThrowHelper.ThrowSerializationException(ExceptionResource.Serialization_InvalidOnDeser); - } - - comparer = (IComparer)siInfo.GetValue(ComparerName, typeof(IComparer)); - int savedCount = siInfo.GetInt32(CountName); - max = (T)siInfo.GetValue(maxName, typeof(T)); - min = (T)siInfo.GetValue(minName, typeof(T)); - lBoundActive = siInfo.GetBoolean(lBoundActiveName); - uBoundActive = siInfo.GetBoolean(uBoundActiveName); - underlying = new SortedSet(); - - if (savedCount != 0) - { - T[] items = (T[])siInfo.GetValue(ItemsName, typeof(T[])); - - if (items == null) - { - ThrowHelper.ThrowSerializationException(ExceptionResource.Serialization_MissingValues); - } - - for (int i = 0; i < items.Length; i++) - { - underlying.Add(items[i]); - } - } - underlying.version = siInfo.GetInt32(VersionName); - count = underlying.count; - version = underlying.version - 1; - VersionCheck(); // this should update the count to be right and update root to be right - - if (count != savedCount) - { - ThrowHelper.ThrowSerializationException(ExceptionResource.Serialization_MismatchedCount); - } - siInfo = null; - } -#endif // !FEATURE_NETCORE - } - - - #endregion - - #region Serialization methods - -#if !FEATURE_NETCORE - // LinkDemand here is unnecessary as this is a methodimpl and linkdemand from the interface should suffice - void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) - { - GetObjectData(info, context); - } - - protected virtual void GetObjectData(SerializationInfo info, StreamingContext context) - { - if (info == null) - { - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.info); - } - - info.AddValue(CountName, count); // This is the length of the bucket array. - info.AddValue(ComparerName, comparer, typeof(IComparer)); - info.AddValue(VersionName, version); - - if (root != null) - { - T[] items = new T[Count]; - CopyTo(items, 0); - info.AddValue(ItemsName, items, typeof(T[])); - } - } - - void IDeserializationCallback.OnDeserialization(Object sender) - { - OnDeserialization(sender); - } - - protected virtual void OnDeserialization(Object sender) - { - if (comparer != null) - { - return; // Somebody had a dependency on this class and fixed us up before the ObjectManager got to it. - } - - if (siInfo == null) - { - ThrowHelper.ThrowSerializationException(ExceptionResource.Serialization_InvalidOnDeser); - } - - comparer = (IComparer)siInfo.GetValue(ComparerName, typeof(IComparer)); - int savedCount = siInfo.GetInt32(CountName); - - if (savedCount != 0) - { - T[] items = (T[])siInfo.GetValue(ItemsName, typeof(T[])); - - if (items == null) - { - ThrowHelper.ThrowSerializationException(ExceptionResource.Serialization_MissingValues); - } - - for (int i = 0; i < items.Length; i++) - { - Add(items[i]); - } - } - - version = siInfo.GetInt32(VersionName); - if (count != savedCount) - { - ThrowHelper.ThrowSerializationException(ExceptionResource.Serialization_MismatchedCount); - } - siInfo = null; - } -#endif // !FEATURE_NETCORE - #endregion - - #region Helper Classes - internal class Node - { - public bool IsRed; - public T Item; - public Node Left; - public Node Right; - - public Node(T item) - { - // The default color will be red, we never need to create a black node directly. - this.Item = item; - IsRed = true; - } - - public Node(T item, bool isRed) - { - // The default color will be red, we never need to create a black node directly. - this.Item = item; - this.IsRed = isRed; - } - } - - [SuppressMessage("Microsoft.Performance", "CA1815:OverrideEqualsAndOperatorEqualsOnValueTypes", Justification = "not an expected scenario")] -#if !FEATURE_NETCORE - [Serializable] - public struct Enumerator : IEnumerator, IEnumerator, ISerializable, IDeserializationCallback - { -#else - public struct Enumerator : IEnumerator, IEnumerator { -#endif - private SortedSet tree; - private int version; - - - private Stack.Node> stack; - private SortedSet.Node current; - static readonly SortedSet.Node dummyNode = new(default); - - private bool reverse; - -#if !FEATURE_NETCORE - private readonly SerializationInfo siInfo; -#endif - internal Enumerator(SortedSet set) - { - tree = set; - // this is a hack to make sure that the underlying subset has not been changed since - // - tree.VersionCheck(); - - version = tree.version; - - // 2lg(n + 1) is the maximum height - stack = new Stack.Node>(2 * (int)SortedSet.Log2(set.Count + 1)); - current = null; - reverse = false; -#if !FEATURE_NETCORE - siInfo = null; -#endif - Intialize(); - } - - internal Enumerator(SortedSet set, bool reverse) - { - tree = set; - // this is a hack to make sure that the underlying subset has not been changed since - // - tree.VersionCheck(); - version = tree.version; - - // 2lg(n + 1) is the maximum height - stack = new Stack.Node>(2 * (int)SortedSet.Log2(set.Count + 1)); - current = null; - this.reverse = reverse; -#if !FEATURE_NETCORE - siInfo = null; -#endif - Intialize(); - } - -#if !FEATURE_NETCORE - private Enumerator(SerializationInfo info, StreamingContext context) - { - tree = null; - version = -1; - current = null; - reverse = false; - stack = null; - this.siInfo = info; - } - - void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) - { - GetObjectData(info, context); - } - - private void GetObjectData(SerializationInfo info, StreamingContext context) - { - if (info == null) - { - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.info); - } - info.AddValue(TreeName, tree, typeof(SortedSet)); - info.AddValue(EnumVersionName, version); - info.AddValue(ReverseName, reverse); - info.AddValue(EnumStartName, !NotStartedOrEnded); - info.AddValue(NodeValueName, (current == null ? dummyNode.Item : current.Item), typeof(T)); - } - - void IDeserializationCallback.OnDeserialization(Object sender) - { - OnDeserialization(sender); - } - - private void OnDeserialization(Object sender) - { - if (siInfo == null) - { - ThrowHelper.ThrowSerializationException(ExceptionResource.Serialization_InvalidOnDeser); - } - - tree = (SortedSet)siInfo.GetValue(TreeName, typeof(SortedSet)); - version = siInfo.GetInt32(EnumVersionName); - reverse = siInfo.GetBoolean(ReverseName); - bool EnumStarted = siInfo.GetBoolean(EnumStartName); - stack = new Stack.Node>(2 * (int)SortedSet.Log2(tree.Count + 1)); - current = null; - if (EnumStarted) - { - T item = (T)siInfo.GetValue(NodeValueName, typeof(T)); - Intialize(); - // go until it reaches the value we want - while (this.MoveNext()) - { - if (tree.Comparer.Compare(this.Current, item) == 0) - break; - } - } - } -#endif // !FEATURE_NETCORE - - - private void Intialize() - { - current = null; - SortedSet.Node node = tree.root; - Node next = null, other = null; - while (node != null) - { - next = (reverse ? node.Right : node.Left); - other = (reverse ? node.Left : node.Right); - if (tree.IsWithinRange(node.Item)) - { - stack.Push(node); - node = next; - } - else if (next == null || !tree.IsWithinRange(next.Item)) - { - node = other; - } - else - { - node = next; - } - } - } - - public bool MoveNext() - { - // this is a hack to make sure that the underlying subset has not been changed since - // - tree.VersionCheck(); - - if (version != tree.version) - { - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion); - } - - if (stack.Count == 0) - { - current = null; - return false; - } - - current = stack.Pop(); - SortedSet.Node node = (reverse ? current.Left : current.Right); - - Node next = null, other = null; - while (node != null) - { - next = (reverse ? node.Right : node.Left); - other = (reverse ? node.Left : node.Right); - if (tree.IsWithinRange(node.Item)) - { - stack.Push(node); - node = next; - } - else if (other == null || !tree.IsWithinRange(other.Item)) - { - node = next; - } - else - { - node = other; - } - } - return true; - } - - public void Dispose() - { - } - - public T Current - { - get - { - if (current != null) - { - return current.Item; - } - return default; - } - } - - object IEnumerator.Current - { - get - { - if (current == null) - { - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen); - } - - return current.Item; - } - } - - internal bool NotStartedOrEnded - { - get - { - return current == null; - } - } - - internal void Reset() - { - if (version != tree.version) - { - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion); - } - - stack.Clear(); - Intialize(); - } - - void IEnumerator.Reset() - { - Reset(); - } - } - - - - internal struct ElementCount - { - internal int uniqueCount; - internal int unfoundCount; - } - #endregion - - #region misc - - /// - /// Searches the set for a given value and returns the equal value it finds, if any. - /// - /// The value to search for. - /// The value from the set that the search found, or the default value of when the search yielded no match. - /// A value indicating whether the search was successful. - /// - /// This can be useful when you want to reuse a previously stored reference instead of - /// a newly constructed one (so that more sharing of references can occur) or to look up - /// a value that has more complete data than the value you currently have, although their - /// comparer functions indicate they are equal. - /// - public bool TryGetValue(T equalValue, out T actualValue) - { - Node node = FindNode(equalValue); - if (node != null) - { - actualValue = node.Item; - return true; - } - actualValue = default; - return false; - } - - // used for set checking operations (using enumerables) that rely on counting - private static int Log2(int value) - { - // Contract.Requires(value>0) - int c = 0; - while (value > 0) - { - c++; - value >>= 1; - } - return c; - } - #endregion - } - - /// - /// A class that generates an IEqualityComparer for this SortedSet. Requires that the definition of - /// equality defined by the IComparer for this SortedSet be consistent with the default IEqualityComparer - /// for the type T. If not, such an IEqualityComparer should be provided through the constructor. - /// - internal class SortedSetEqualityComparer : IEqualityComparer> - { - private readonly IComparer comparer; - private readonly IEqualityComparer e_comparer; - - public SortedSetEqualityComparer() : this(null, null) - { - } - - public SortedSetEqualityComparer(IComparer comparer) : this(comparer, null) - { - } - - public SortedSetEqualityComparer(IEqualityComparer memberEqualityComparer) : this(null, memberEqualityComparer) - { - } - - /// - /// Create a new SetEqualityComparer, given a comparer for member order and another for member equality (these - /// must be consistent in their definition of equality) - /// - public SortedSetEqualityComparer(IComparer comparer, IEqualityComparer memberEqualityComparer) - { - if (comparer == null) - this.comparer = Comparer.Default; - else - this.comparer = comparer; - if (memberEqualityComparer == null) - e_comparer = EqualityComparer.Default; - else - e_comparer = memberEqualityComparer; - } - - - // using comparer to keep equals properties in tact; don't want to choose one of the comparers - public bool Equals(SortedSet x, SortedSet y) - { - return SortedSet.SortedSetEquals(x, y, comparer); - } - // IMPORTANT: this part uses the fact that GetHashCode() is consistent with the notion of equality in - // the set - public int GetHashCode(SortedSet obj) - { - int hashCode = 0; - if (obj != null) - { - foreach (T t in obj) - { - hashCode ^= (e_comparer.GetHashCode(t) & 0x7FFFFFFF); - } - } // else returns hashcode of 0 for null HashSets - return hashCode; - } - - // Equals method for the comparer itself. - public override bool Equals(Object obj) - { - if (obj is not SortedSetEqualityComparer comparer) - { - return false; - } - return (this.comparer == comparer.comparer); - } - - public override int GetHashCode() - { - return comparer.GetHashCode() ^ e_comparer.GetHashCode(); - } - } -} - - - -#pragma warning restore CS8604 // 引用类型参数可能为 null。 -#pragma warning restore CS8602 // 解引用可能出现空引用。 -#pragma warning restore CS8600 // 将 null 字面量或可能为 null 的值转换为非 null 类型。 -#pragma warning restore IDE0059 // 不需要赋值 -#pragma warning restore CS8625 // 无法将 null 字面量转换为非 null 的引用类型。 -#pragma warning restore CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。 -#pragma warning restore CS8601 // 引用类型赋值可能为 null。 -#pragma warning restore CS8603 // 可能返回 null 引用。 -#endif \ No newline at end of file diff --git a/src/Basal/IFox.Basal.Shared/Sortedset/ThrowHelper.cs b/src/Basal/IFox.Basal.Shared/Sortedset/ThrowHelper.cs deleted file mode 100644 index ebb2f41..0000000 --- a/src/Basal/IFox.Basal.Shared/Sortedset/ThrowHelper.cs +++ /dev/null @@ -1,381 +0,0 @@ -#if NET35 -#pragma warning disable IDE0059 // 不需要赋值 -#pragma warning disable CS8600 // 将 null 字面量或可能为 null 的值转换为非 null 类型。 - -namespace System -{ - // This file defines an internal class used to throw exceptions in BCL code. - // The main purpose is to reduce code size. - // - // The old way to throw an exception generates quite a lot IL code and assembly code. - // Following is an example: - // C# source - // throw new ArgumentNullException("key", SR.GetString("ArgumentNull_Key")); - // IL code: - // IL_0003: ldstr "key" - // IL_0008: ldstr "ArgumentNull_Key" - // IL_000d: call string System.Environment::GetResourceString(string) - // IL_0012: newobj instance void System.ArgumentNullException::.ctor(string,string) - // IL_0017: throw - // which is 21bytes in IL. - // - // So we want to get rid of the ldstr and call to Environment.GetResource in IL. - // In order to do that, I created two enums: ExceptionResource, ExceptionArgument to represent the - // argument name and resource name in a small integer. The source code will be changed to - // ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key, ExceptionResource.ArgumentNull_Key); - // - // The IL code will be 7 bytes. - // IL_0008: ldc.i4.4 - // IL_0009: ldc.i4.4 - // IL_000a: call void System.ThrowHelper::ThrowArgumentNullException(valuetype System.ExceptionArgument) - // IL_000f: ldarg.0 - // - // This will also reduce the Jitted code size a lot. - // - // It is very important we do this for generic classes because we can easily generate the same code - // multiple times for different instantiation. - // - // < - - - - - - - - - - -#if !SILVERLIGHT - using System.Runtime.Serialization; -#endif - - using System.Diagnostics; - internal static class ThrowHelper - { - internal static void ThrowWrongKeyTypeArgumentException(object key, Type targetType) - { - throw new ArgumentException(SR.GetString("SR.Arg_WrongType", key, targetType), "key"); - } - - internal static void ThrowWrongValueTypeArgumentException(object value, Type targetType) - { - throw new ArgumentException(SR.GetString("SR.Arg_WrongType", value, targetType), "value"); - } - - internal static void ThrowKeyNotFoundException() - { - throw new System.Collections.Generic.KeyNotFoundException(); - } - - internal static void ThrowArgumentException(ExceptionResource resource) - { - throw new ArgumentException(SR.GetString(GetResourceName(resource))); - } - - internal static void ThrowArgumentNullException(ExceptionArgument argument) - { - throw new ArgumentNullException(GetArgumentName(argument)); - } - - internal static void ThrowArgumentOutOfRangeException(ExceptionArgument argument) - { - throw new ArgumentOutOfRangeException(GetArgumentName(argument)); - } - - internal static void ThrowArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource) - { - throw new ArgumentOutOfRangeException(GetArgumentName(argument), SR.GetString(GetResourceName(resource))); - } - - internal static void ThrowInvalidOperationException(ExceptionResource resource) - { - throw new InvalidOperationException(SR.GetString(GetResourceName(resource))); - } - -#if !SILVERLIGHT - internal static void ThrowSerializationException(ExceptionResource resource) - { - throw new SerializationException(SR.GetString(GetResourceName(resource))); - } -#endif - - internal static void ThrowNotSupportedException(ExceptionResource resource) - { - throw new NotSupportedException(SR.GetString(GetResourceName(resource))); - } - - // Allow nulls for reference types and Nullable, but not for value types. - internal static void IfNullAndNullsAreIllegalThenThrow(object value, ExceptionArgument argName) - { - // Note that default(T) is not equal to null for value types except when T is Nullable. - if (value == null && !(default(T) == null)) - ThrowHelper.ThrowArgumentNullException(argName); - } - - // - // This function will convert an ExceptionArgument enum value to the argument name string. - // - internal static string GetArgumentName(ExceptionArgument argument) - { - string argumentName = null; - - switch (argument) - { - case ExceptionArgument.array: - argumentName = "array"; - break; - - case ExceptionArgument.arrayIndex: - argumentName = "arrayIndex"; - break; - - case ExceptionArgument.capacity: - argumentName = "capacity"; - break; - - case ExceptionArgument.collection: - argumentName = "collection"; - break; - - case ExceptionArgument.converter: - argumentName = "converter"; - break; - - case ExceptionArgument.count: - argumentName = "count"; - break; - - case ExceptionArgument.dictionary: - argumentName = "dictionary"; - break; - - case ExceptionArgument.index: - argumentName = "index"; - break; - - case ExceptionArgument.info: - argumentName = "info"; - break; - - case ExceptionArgument.key: - argumentName = "key"; - break; - - case ExceptionArgument.match: - argumentName = "match"; - break; - - case ExceptionArgument.obj: - argumentName = "obj"; - break; - - case ExceptionArgument.queue: - argumentName = "queue"; - break; - - case ExceptionArgument.stack: - argumentName = "stack"; - break; - - case ExceptionArgument.startIndex: - argumentName = "startIndex"; - break; - - case ExceptionArgument.value: - argumentName = "value"; - break; - - case ExceptionArgument.item: - argumentName = "item"; - break; - - default: - Debug.Assert(false, "The enum value is not defined, please checked ExceptionArgumentName Enum."); - return string.Empty; - } - - return argumentName; - } - - // - // This function will convert an ExceptionResource enum value to the resource string. - // - internal static string GetResourceName(ExceptionResource resource) - { - string resourceName = null; - - switch (resource) - { - case ExceptionResource.Argument_ImplementIComparable: - resourceName = "SR.Argument_ImplementIComparable"; - break; - - case ExceptionResource.Argument_AddingDuplicate: - resourceName = "SR.Argument_AddingDuplicate"; - break; - - case ExceptionResource.ArgumentOutOfRange_Index: - resourceName = "SR.ArgumentOutOfRange_Index"; - break; - - case ExceptionResource.ArgumentOutOfRange_NeedNonNegNum: - resourceName = "SR.ArgumentOutOfRange_NeedNonNegNum"; - break; - - case ExceptionResource.ArgumentOutOfRange_NeedNonNegNumRequired: - resourceName = "SR.ArgumentOutOfRange_NeedNonNegNumRequired"; - break; - - case ExceptionResource.ArgumentOutOfRange_SmallCapacity: - resourceName = "SR.ArgumentOutOfRange_SmallCapacity"; - break; - - case ExceptionResource.Arg_ArrayPlusOffTooSmall: - resourceName = "SR.Arg_ArrayPlusOffTooSmall"; - break; - - case ExceptionResource.Arg_RankMultiDimNotSupported: - resourceName = "SR.Arg_MultiRank"; - break; - - case ExceptionResource.Arg_NonZeroLowerBound: - resourceName = "SR.Arg_NonZeroLowerBound"; - break; - - case ExceptionResource.Argument_InvalidArrayType: - resourceName = "SR.Invalid_Array_Type"; - break; - - case ExceptionResource.Argument_InvalidOffLen: - resourceName = "SR.Argument_InvalidOffLen"; - break; - - case ExceptionResource.InvalidOperation_CannotRemoveFromStackOrQueue: - resourceName = "SR.InvalidOperation_CannotRemoveFromStackOrQueue"; - break; - - case ExceptionResource.InvalidOperation_EmptyCollection: - resourceName = "SR.InvalidOperation_EmptyCollection"; - break; - - case ExceptionResource.InvalidOperation_EmptyQueue: - resourceName = "SR.InvalidOperation_EmptyQueue"; - break; - - case ExceptionResource.InvalidOperation_EnumOpCantHappen: - resourceName = "SR.InvalidOperation_EnumOpCantHappen"; - break; - - case ExceptionResource.InvalidOperation_EnumFailedVersion: - resourceName = "SR.InvalidOperation_EnumFailedVersion"; - break; - - case ExceptionResource.InvalidOperation_EmptyStack: - resourceName = "SR.InvalidOperation_EmptyStack"; - break; - - case ExceptionResource.InvalidOperation_EnumNotStarted: - resourceName = "SR.InvalidOperation_EnumNotStarted"; - break; - - case ExceptionResource.InvalidOperation_EnumEnded: - resourceName = "SR.InvalidOperation_EnumEnded"; - break; - - case ExceptionResource.NotSupported_KeyCollectionSet: - resourceName = "SR.NotSupported_KeyCollectionSet"; - break; - - case ExceptionResource.NotSupported_SortedListNestedWrite: - resourceName = "SR.NotSupported_SortedListNestedWrite"; - break; - -#if !SILVERLIGHT - case ExceptionResource.Serialization_InvalidOnDeser: - resourceName = "SR.Serialization_InvalidOnDeser"; - break; - - case ExceptionResource.Serialization_MissingValues: - resourceName = "SR.Serialization_MissingValues"; - break; - - case ExceptionResource.Serialization_MismatchedCount: - resourceName = "SR.Serialization_MismatchedCount"; - break; -#endif - - case ExceptionResource.NotSupported_ValueCollectionSet: - resourceName = "SR.NotSupported_ValueCollectionSet"; - break; - - default: - Debug.Assert(false, "The enum value is not defined, please checked ExceptionArgumentName Enum."); - return string.Empty; - } - - return resourceName; - } - } - - // - // The convention for this enum is using the argument name as the enum name - // - internal enum ExceptionArgument - { - obj, - dictionary, - array, - info, - key, - collection, - match, - converter, - queue, - stack, - capacity, - index, - startIndex, - value, - count, - arrayIndex, - item, - } - - // - // The convention for this enum is using the resource name as the enum name - // - internal enum ExceptionResource - { - Argument_ImplementIComparable, - ArgumentOutOfRange_NeedNonNegNum, - ArgumentOutOfRange_NeedNonNegNumRequired, - Arg_ArrayPlusOffTooSmall, - Argument_AddingDuplicate, - Serialization_InvalidOnDeser, - Serialization_MismatchedCount, - Serialization_MissingValues, - Arg_RankMultiDimNotSupported, - Arg_NonZeroLowerBound, - Argument_InvalidArrayType, - NotSupported_KeyCollectionSet, - ArgumentOutOfRange_SmallCapacity, - ArgumentOutOfRange_Index, - Argument_InvalidOffLen, - NotSupported_ReadOnlyCollection, - InvalidOperation_CannotRemoveFromStackOrQueue, - InvalidOperation_EmptyCollection, - InvalidOperation_EmptyQueue, - InvalidOperation_EnumOpCantHappen, - InvalidOperation_EnumFailedVersion, - InvalidOperation_EmptyStack, - InvalidOperation_EnumNotStarted, - InvalidOperation_EnumEnded, - NotSupported_SortedListNestedWrite, - NotSupported_ValueCollectionSet, - } -} - -#pragma warning restore CS8600 // 将 null 字面量或可能为 null 的值转换为非 null 类型。 -#pragma warning restore IDE0059 // 不需要赋值 -#endif \ No newline at end of file diff --git a/src/Basal/IFox.Basal.Shared/Sortedset/bithelper.cs b/src/Basal/IFox.Basal.Shared/Sortedset/bithelper.cs deleted file mode 100644 index 665b435..0000000 --- a/src/Basal/IFox.Basal.Shared/Sortedset/bithelper.cs +++ /dev/null @@ -1,170 +0,0 @@ -#if NET35 -#pragma warning disable CS8603 // 可能返回 null 引用。 -#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。 - - -using System; -using System.Collections; -using System.Text; - -namespace System.Collections.Generic -{ - /// - /// ABOUT: - /// Helps with operations that rely on bit marking to indicate whether an item in the - /// collection should be added, removed, visited already, etc. - /// - /// BitHelper doesn't allocate the array; you must pass in an array or ints allocated on the - /// stack or heap. ToIntArrayLength() tells you the int array size you must allocate. - /// - /// USAGE: - /// Suppose you need to represent a bit array of length (i.e. logical bit array length) - /// BIT_ARRAY_LENGTH. Then this is the suggested way to instantiate BitHelper: - /// *************************************************************************** - /// int intArrayLength = BitHelper.ToIntArrayLength(BIT_ARRAY_LENGTH); - /// BitHelper bitHelper; - /// if (intArrayLength less than stack alloc threshold) - /// int* m_arrayPtr = stackalloc int[intArrayLength]; - /// bitHelper = new BitHelper(m_arrayPtr, intArrayLength); - /// else - /// int[] m_arrayPtr = new int[intArrayLength]; - /// bitHelper = new BitHelper(m_arrayPtr, intArrayLength); - /// *************************************************************************** - /// - /// IMPORTANT: - /// The second ctor args, length, should be specified as the length of the int array, not - /// the logical bit array. Because length is used for bounds checking into the int array, - /// it's especially important to get this correct for the stackalloc version. See the code - /// samples above; this is the value gotten from ToIntArrayLength(). - /// - /// The length ctor argument is the only exception; for other methods -- MarkBit and - /// IsMarked -- pass in values as indices into the logical bit array, and it will be mapped - /// to the position within the array of ints. - /// - /// - - - - - unsafe internal class BitHelper - { // should not be serialized - private const byte MarkedBitFlag = 1; - private const byte IntSize = 32; - - // m_length of underlying int array (not logical bit array) - private int m_length; - - // ptr to stack alloc'd array of ints - [System.Security.SecurityCritical] - private int* m_arrayPtr; - - // array of ints - private int[] m_array; - - // whether to operate on stack alloc'd or heap alloc'd array - private bool useStackAlloc; - - /// - /// Instantiates a BitHelper with a heap alloc'd array of ints - /// - /// int array to hold bits - /// length of int array - // - // - // - // - [System.Security.SecurityCritical] - internal BitHelper(int* bitArrayPtr, int length) - { - this.m_arrayPtr = bitArrayPtr; - this.m_length = length; - useStackAlloc = true; - } - - /// - /// Instantiates a BitHelper with a heap alloc'd array of ints - /// - /// int array to hold bits - /// length of int array - internal BitHelper(int[] bitArray, int length) - { - this.m_array = bitArray; - this.m_length = length; - } - - /// - /// Mark bit at specified position - /// - /// - // - // - // - [System.Security.SecurityCritical] - internal unsafe void MarkBit(int bitPosition) - { - if (useStackAlloc) - { - int bitArrayIndex = bitPosition / IntSize; - if (bitArrayIndex < m_length && bitArrayIndex >= 0) - { - m_arrayPtr[bitArrayIndex] |= (MarkedBitFlag << (bitPosition % IntSize)); - } - } - else - { - int bitArrayIndex = bitPosition / IntSize; - if (bitArrayIndex < m_length && bitArrayIndex >= 0) - { - m_array[bitArrayIndex] |= (MarkedBitFlag << (bitPosition % IntSize)); - } - } - } - - /// - /// Is bit at specified position marked? - /// - /// - /// - // - // - // - [System.Security.SecurityCritical] - internal unsafe bool IsMarked(int bitPosition) - { - if (useStackAlloc) - { - int bitArrayIndex = bitPosition / IntSize; - if (bitArrayIndex < m_length && bitArrayIndex >= 0) - { - return ((m_arrayPtr[bitArrayIndex] & (MarkedBitFlag << (bitPosition % IntSize))) != 0); - } - return false; - } - else - { - int bitArrayIndex = bitPosition / IntSize; - if (bitArrayIndex < m_length && bitArrayIndex >= 0) - { - return ((m_array[bitArrayIndex] & (MarkedBitFlag << (bitPosition % IntSize))) != 0); - } - return false; - } - } - - /// - /// How many ints must be allocated to represent n bits. Returns (n+31)/32, but - /// avoids overflow - /// - /// - /// - internal static int ToIntArrayLength(int n) - { - return n > 0 ? ((n - 1) / IntSize + 1) : 0; - } - } -} - -#pragma warning restore CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。 -#pragma warning restore CS8603 // 可能返回 null 引用。 - -#endif \ No newline at end of file diff --git a/src/Basal/IFox.Basal/IFox.Basal.csproj b/src/Basal/IFox.Basal/IFox.Basal.csproj index db74995..bb1713c 100644 --- a/src/Basal/IFox.Basal/IFox.Basal.csproj +++ b/src/Basal/IFox.Basal/IFox.Basal.csproj @@ -1,7 +1,7 @@  - NET35;NET40;NET45 + NET40;NET45 true true MSB3270 diff --git a/src/CAD/IFox.CAD.ACAD/IFox.CAD.ACAD.csproj b/src/CAD/IFox.CAD.ACAD/IFox.CAD.ACAD.csproj index 4b99921..46fc18e 100644 --- a/src/CAD/IFox.CAD.ACAD/IFox.CAD.ACAD.csproj +++ b/src/CAD/IFox.CAD.ACAD/IFox.CAD.ACAD.csproj @@ -1,7 +1,7 @@  - NET35;NET40;NET45 + NET40;NET45 true true MSB3270 @@ -10,9 +10,6 @@ DEBUG - - $(Configuration);acad;ac2009 - $(Configuration);acad;ac2013 @@ -20,9 +17,6 @@ $(Configuration);acad;ac2015 - - - diff --git a/src/CAD/IFox.CAD.Shared/AutoReg/AutoLoad.cs b/src/CAD/IFox.CAD.Shared/AutoReg/AutoLoad.cs index b2e65d2..a3efa5c 100644 --- a/src/CAD/IFox.CAD.Shared/AutoReg/AutoLoad.cs +++ b/src/CAD/IFox.CAD.Shared/AutoReg/AutoLoad.cs @@ -53,11 +53,8 @@ public AutoLoad() private static RegistryKey GetAcAppKey() { -#if NET35 - string key = HostApplicationServices.Current.RegistryProductRootKey; -#else + string key = HostApplicationServices.Current.UserRegistryProductRootKey; -#endif RegistryKey ackey = Registry.CurrentUser.OpenSubKey(key, true); return ackey.CreateSubKey("Applications"); } @@ -67,11 +64,8 @@ private static RegistryKey GetAcAppKey() /// 目录 protected static void AppendSupportPath(string path) { -#if NET35 - string key = HostApplicationServices.Current.RegistryProductRootKey; -#else + string key = HostApplicationServices.Current.UserRegistryProductRootKey; -#endif // 计算机\HKEY_CURRENT_USER\SOFTWARE\Autodesk\AutoCAD\R24.0\ACAD-4101:804 RegistryKey ackey = Registry.CurrentUser.OpenSubKey($@"{key}\Profiles"); diff --git a/src/CAD/IFox.CAD.Shared/AutoReg/AutoRegAssem.cs b/src/CAD/IFox.CAD.Shared/AutoReg/AutoRegAssem.cs index e8bb720..88d084c 100644 --- a/src/CAD/IFox.CAD.Shared/AutoReg/AutoRegAssem.cs +++ b/src/CAD/IFox.CAD.Shared/AutoReg/AutoRegAssem.cs @@ -89,11 +89,7 @@ public static RegistryKey GetAcAppKey(bool writable = true) RegistryKey? ackey = null; var hc = HostApplicationServices.Current; #if acad || zcad // 中望此处缺乏测试 -#if NET35 - string key = hc.RegistryProductRootKey; -#else string key = hc.UserRegistryProductRootKey; -#endif ackey = Registry.CurrentUser.OpenSubKey(key, writable); #endif diff --git a/src/CAD/IFox.CAD.Shared/AutoReg/IAutoGo.cs b/src/CAD/IFox.CAD.Shared/AutoReg/IAutoGo.cs index 3b71d4c..f6f7ec4 100644 --- a/src/CAD/IFox.CAD.Shared/AutoReg/IAutoGo.cs +++ b/src/CAD/IFox.CAD.Shared/AutoReg/IAutoGo.cs @@ -175,12 +175,12 @@ public static void AppDomainGetTypes(Action action, string? dllNameWithout try { var assemblies = AppDomain.CurrentDomain.GetAssemblies(); -#if !NET35 + // cad2021出现如下报错 // System.NotSupportedException:动态程序集中不支持已调用的成员 // assemblies = assemblies.Where(p => !p.IsDynamic).ToArray();// 这个要容器类型转换 assemblies = Array.FindAll(assemblies, p => !p.IsDynamic); -#endif + // 主程序域 for (int ii = 0; ii < assemblies.Length; ii++) { diff --git a/src/CAD/IFox.CAD.Shared/CadVersion/CadVersion.cs b/src/CAD/IFox.CAD.Shared/CadVersion/CadVersion.cs index cffbf71..98d05a9 100644 --- a/src/CAD/IFox.CAD.Shared/CadVersion/CadVersion.cs +++ b/src/CAD/IFox.CAD.Shared/CadVersion/CadVersion.cs @@ -1,58 +1,5 @@ namespace IFoxCAD.Cad; -#if ac2009 - -public class CadVersion -{ - /// - /// 主版本 - /// - public int Major { get; set; } - - /// - /// 次版本 - /// - public int Minor { get; set; } - - /// - /// 版本号 - /// - public double ProgId => double.Parse($"{Major}.{Minor}"); - - /// - /// 注册表名称 - /// - public string? ProductName { get; set; } - - /// - /// 注册表位置 - /// - public string? ProductRootKey { get; set; } - - /// - /// 转换为字符串 - /// - /// 表示版本号的字符串 - public override string ToString() - { - return $"名称:{ProductName}\n版本号:{ProgId}\n注册表位置:{ProductRootKey}"; - } - // public override bool Equals(object obj) - // { - // return base.Equals(obj); - // } - - // public override int GetHashCode() - // { - // return base.GetHashCode(); - // } - - // // public override string ToString() - // // { - // // return base.ToString(); - // // } -} -#else /// /// CAD版本 /// @@ -91,5 +38,4 @@ public override string ToString() { return $"名称:{ProductName}\n版本号:{ProgId}\n注册表位置:{ProductRootKey}"; } -} -#endif \ No newline at end of file +} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/Copyclip/TagClipboardInfo.cs b/src/CAD/IFox.CAD.Shared/Copyclip/TagClipboardInfo.cs index ed9195b..2fbdbe3 100644 --- a/src/CAD/IFox.CAD.Shared/Copyclip/TagClipboardInfo.cs +++ b/src/CAD/IFox.CAD.Shared/Copyclip/TagClipboardInfo.cs @@ -138,11 +138,8 @@ public void testAcedGetAcadDwgview() /// /// 获取视口指针 /// -#if NET35 - [DllImport("acad.exe", EntryPoint = "?acedGetAcadDwgView@@YAPAVCView@@XZ")] //acad08 -#else + [DllImport("acad.exe", EntryPoint = "?acedGetAcadDwgView@@YAPEAVCView@@XZ")]//acad21 -#endif static extern IntPtr AcedGetAcadDwgview(); #endregion diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/CadInternalUtils.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/CadInternalUtils.cs deleted file mode 100644 index d56e0dc..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/CadInternalUtils.cs +++ /dev/null @@ -1,30 +0,0 @@ -#if NET35 -namespace Autodesk.AutoCAD.Internal -{ - public class Utils - { - public static void SetFocusToDwgView() - { - IntPtr window; - if (Acap.DocumentManager.Count == 0) - { - window = Acap.MainWindow.Handle; - } - else - { - // 它们是层级关系 - // Main - // -->MDI(大小被 DwgView 局限) - // ---->docW(比MDI大) - // -------->msctls_statusbar32 - // -------->DwgView - var docW = Acap.DocumentManager.MdiActiveDocument.Window.Handle; - var msctls_statusbar32 = IFoxCAD.Basal.WindowsAPI.GetTopWindow(docW); - window = IFoxCAD.Basal.WindowsAPI.GetWindow(msctls_statusbar32, 2U); - } - if (window != IntPtr.Zero) - IFoxCAD.Basal.WindowsAPI.SetFocus(window); - } - } -} -#endif \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/CurveEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/CurveEx.cs index f8b83b5..47b42ad 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/CurveEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/CurveEx.cs @@ -116,11 +116,7 @@ public static IEnumerable GetAllCycle(this IEnumerable curves) foreach (var curve in curves) { #if !gcad -#if NET35 - graph.AddEdge(curve.ToCurve3d()!); -#else graph.AddEdge(curve.GetGeCurve()); -#endif #else graph.AddEdge(curve.ToCurve3d()!); #endif diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs index 14ca11c..ffd9019 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs @@ -712,62 +712,6 @@ public static Matrix3d GetMatrixFromPDcsToMDcs(this Editor editor) /// 变换矩阵 public static Matrix3d GetMatrix(this Editor editor, CoordinateSystemCode from, CoordinateSystemCode to) { -#if ac2009 - switch (from) - { - case CoordinateSystemCode.Wcs: - switch (to) - { - case CoordinateSystemCode.Ucs: - return editor.GetMatrixFromWcsToUcs(); - - case CoordinateSystemCode.MDcs: - return editor.GetMatrixFromMDcsToWcs(); - - case CoordinateSystemCode.PDcs: - throw new Exception("To be used only with DCS...ErrorStatus.InvalidInput"); - } - break; - case CoordinateSystemCode.Ucs: - switch (to) - { - case CoordinateSystemCode.Wcs: - return editor.GetMatrixFromUcsToWcs(); - - case CoordinateSystemCode.MDcs: - return editor.GetMatrixFromUcsToWcs() * editor.GetMatrixFromWcsToMDcs(); - - case CoordinateSystemCode.PDcs: - throw new Exception("To be used only with DCS... ErrorStatus.InvalidInput"); - } - break; - case CoordinateSystemCode.MDcs: - switch (to) - { - case CoordinateSystemCode.Wcs: - return editor.GetMatrixFromMDcsToWcs(); - - case CoordinateSystemCode.Ucs: - return editor.GetMatrixFromMDcsToWcs() * editor.GetMatrixFromWcsToUcs(); - - case CoordinateSystemCode.PDcs: - return editor.GetMatrixFromMDcsToPDcs(); - } - break; - case CoordinateSystemCode.PDcs: - switch (to) - { - case CoordinateSystemCode.Wcs: - throw new Exception("To be used only with DCS... ErrorStatus.InvalidInput"); - case CoordinateSystemCode.Ucs: - throw new Exception("To be used only with DCS... ErrorStatus.InvalidInput"); - case CoordinateSystemCode.MDcs: - return editor.GetMatrixFromPDcsToMDcs(); - } - break; - } - return Matrix3d.Identity; -#else return (from, to) switch { (CoordinateSystemCode.Wcs, CoordinateSystemCode.Ucs) => editor.GetMatrixFromWcsToUcs(), @@ -782,7 +726,6 @@ public static Matrix3d GetMatrix(this Editor editor, CoordinateSystemCode from, or (CoordinateSystemCode.Wcs or CoordinateSystemCode.Ucs, CoordinateSystemCode.PDcs) => throw new Exception("To be used only with DCS...ErrorStatus.InvalidInput"), (_, _) => Matrix3d.Identity }; -#endif } #endregion @@ -1001,31 +944,18 @@ public static PromptResult GetString(this Editor ed, string Message, string Defa #endregion #region 执行lisp -#if NET35 - [DllImport("acad.exe", -#else - [DllImport("accore.dll", -#endif - CallingConvention = CallingConvention.Cdecl, EntryPoint = "acedInvoke")] + [DllImport("accore.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "acedInvoke")] static extern int AcedInvoke(IntPtr args, out IntPtr result); -#if NET35 - [DllImport("acad.exe", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, - EntryPoint = "?acedEvaluateLisp@@YAHPB_WAAPAUresbuf@@@Z")] -#else + // 高版本此接口不能使用lisp(command "xx"),但是可以直接在自动运行接口上 [DllImport("accore.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, EntryPoint = "?acedEvaluateLisp@@YAHPEB_WAEAPEAUresbuf@@@Z")] -#endif [System.Security.SuppressUnmanagedCodeSecurity]// 初始化默认值 static extern int AcedEvaluateLisp(string lispLine, out IntPtr result); -#if NET35 - [DllImport("acad.exe", -#else - [DllImport("accore.dll", -#endif - CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ads_queueexpr")] + + [DllImport("accore.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ads_queueexpr")] static extern int Ads_queueexpr(string strExpr); public enum RunLispFlag : byte @@ -1148,21 +1078,4 @@ public static void ComExportWMF(this Editor editor, string saveFile, } #endregion - /// - /// 可以发送透明命令的状态
- /// 福萝卜:这个应该是修正ribbon里输入丢焦点的问题,低版本可以不要 - ///
- /// - /// - public static bool IsQuiescentForTransparentCommand(this Editor ed) - { -#if NET35 - //if (ed.IsQuiescent) - //{ - //} - return true; -#else - return ed.IsQuiescentForTransparentCommand; -#endif - } } \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/ArcEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/ArcEx.cs index f3ef950..a037653 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/ArcEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/ArcEx.cs @@ -40,11 +40,8 @@ public static Arc CreateArc(Point3d startPoint, Point3d pointOnArc, Point3d endP CircularArc3d geArc = new(startPoint, pointOnArc, endPoint); // 将几何类圆弧对象的圆心和半径赋值给圆弧 #if !gcad -#if NET35 - return (Arc)geArc.ToCurve(); -#else + return (Arc)Curve.CreateFromGeCurve(geArc); -#endif #else return (Arc)geArc.ToCurve(); #endif diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Filer/DwgFiler.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Filer/DwgFiler.cs index 6820f37..d40f7a3 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Filer/DwgFiler.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Filer/DwgFiler.cs @@ -14,11 +14,8 @@ [Newtonsoft.Json.JsonIgnore] 设置成员 不可序列化 [Serializable] public class DwgFiler : Cad_DwgFiler { -#if NET35 - public int m_Position; -#else + public long m_Position; -#endif public FilerType m_FilerType; public Cad_ErrorStatus m_FilerStatus; public List AddressList; @@ -47,10 +44,10 @@ public class DwgFiler : Cad_DwgFiler public int Int16ListPt = 0; public List Int32List; public int Int32ListPt = 0; -#if !NET35 + public List Int64List; public int Int64ListPt = 0; -#endif + public List Point2dList; public int Point2dListPt = 0; public List Point3dList; @@ -71,10 +68,10 @@ public class DwgFiler : Cad_DwgFiler public int uint16ListPt = 0; public List Uint32List; public int uint32ListPt = 0; -#if !NET35 + public List Uint64List; public int uint64ListPt = 0; -#endif + public List Vector2dList; public int Vector2dListPt = 0; public List Vector3dList; @@ -96,9 +93,9 @@ public DwgFiler() HardPointerIdList = new(); Int16List = new(); Int32List = new(); -#if !NET35 + Int64List = new(); -#endif + Point2dList = new(); Point3dList = new(); Scale3dList = new(); @@ -107,18 +104,15 @@ public DwgFiler() StringList = new(); Uint16List = new(); Uint32List = new(); -#if !NET35 + Uint64List = new(); -#endif + Vector2dList = new(); Vector3dList = new(); } -#if NET35 - public override int Position => m_Position; -#else + public override long Position => m_Position; -#endif public override FilerType FilerType => m_FilerType; public override Cad_ErrorStatus FilerStatus @@ -205,14 +199,14 @@ public override int ReadInt32() return Int32List[Int32ListPt++]; } -#if !NET35 + public override long ReadInt64() { if (Int64List.Count == 0) return 0; return Int64List[Int64ListPt++]; } -#endif + public override Point2d ReadPoint2d() { @@ -270,14 +264,14 @@ public override uint ReadUInt32() return Uint32List[uint32ListPt++]; } -#if !NET35 + public override ulong ReadUInt64() { if (Uint64List.Count == 0) return 0; return Uint64List[uint64ListPt++]; } -#endif + public override Vector2d ReadVector2d() { @@ -317,10 +311,10 @@ public override void ResetFilerStatus() Int16ListPt = 0; Int32List.Clear(); Int32ListPt = 0; -#if !NET35 + Int64List.Clear(); Int64ListPt = 0; -#endif + Point2dList.Clear(); Point2dListPt = 0; Point3dList.Clear(); @@ -337,10 +331,10 @@ public override void ResetFilerStatus() uint16ListPt = 0; Uint32List.Clear(); uint32ListPt = 0; -#if !NET35 + Uint64List.Clear(); uint64ListPt = 0; -#endif + Vector2dList.Clear(); Vector2dListPt = 0; Vector3dList.Clear(); @@ -362,13 +356,7 @@ public override void Seek(long offset, int method) #endif #if acad || gcad - public override void Seek( -#if NET35 - int -#else - long -#endif - offset, int method) + public override void Seek(long offset, int method) { var ed = Acap.DocumentManager.MdiActiveDocument.Editor; ed.WriteMessage(MethodInfo.GetCurrentMethod().Name + " = " + " \n "); @@ -430,12 +418,11 @@ public override void WriteInt32(int value) Int32List.Add(value); } -#if !NET35 public override void WriteInt64(long value) { Int64List.Add(value); } -#endif + public override void WritePoint2d(Point2d value) { Point2dList.Add(value); @@ -476,12 +463,12 @@ public override void WriteUInt32(uint value) Uint32List.Add(value); } -#if !NET35 + public override void WriteUInt64(ulong value) { Uint64List.Add(value); } -#endif + public override void WriteVector2d(Vector2d value) { diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigExTransient.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigExTransient.cs index 9d3bf6b..55f9e8e 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigExTransient.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigExTransient.cs @@ -1,4 +1,4 @@ -#if acad && !ac2008 +#if acad namespace IFoxCAD.Cad; /// diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs index 63050c3..eb1f8ed 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs @@ -55,18 +55,10 @@ public static class ObjectIdEx public static IEnumerable OfType(this IEnumerable ids) where T : DBObject { string dxfName = RXClass.GetClass(typeof(T)).DxfName; - return ids.Where(id => id.ObjectClass().DxfName == dxfName); + return ids.Where(id => id.ObjectClass.DxfName == dxfName); } #endregion GetObject - public static RXClass ObjectClass(this ObjectId id) - { -#if NET35 - return RXClass.GetClass(id.GetType()); -#else - return id.ObjectClass; -#endif - } /// /// id是否有效,未被删除 diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SelectionSetEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SelectionSetEx.cs index d8aed4c..0bf2af9 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SelectionSetEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SelectionSetEx.cs @@ -44,7 +44,7 @@ public static IEnumerable GetObjectIds(this SelectionSet ss) where return ss .GetObjectIds() - .Where(id => id.ObjectClass().DxfName == dxfName); + .Where(id => id.ObjectClass.DxfName == dxfName); } /// @@ -58,7 +58,7 @@ public static IEnumerable> GetObjectIdGroup(this Sel return ss .GetObjectIds() - .GroupBy(id => id.ObjectClass().DxfName); + .GroupBy(id => id.ObjectClass.DxfName); } #endregion diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs index 1518159..f0ae5bb 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs @@ -344,7 +344,7 @@ public static IEnumerable GetObjectIds(this BlockTableRecord btr) w { string dxfName = RXClass.GetClass(typeof(T)).DxfName; return btr.Cast() - .Where(id => id.ObjectClass()?.DxfName == dxfName); + .Where(id => id.ObjectClass.DxfName == dxfName); } /// @@ -355,7 +355,7 @@ public static IEnumerable GetObjectIds(this BlockTableRecord btr) w public static IEnumerable> GetObjectIds(this BlockTableRecord btr) { return btr.Cast() - .GroupBy(id => id.ObjectClass().DxfName); + .GroupBy(id => id.ObjectClass.DxfName); } diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/XrefEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/XrefEx.cs index db54edc..5706251 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/XrefEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/XrefEx.cs @@ -332,26 +332,6 @@ void DoubleBind() // 内部删除嵌套参照的块操作 if (EraseNested) { -#if ac2008 - // 因为Acad08索引器存在会暴露isErase的(桌子底层的原因), - // 也就是可能获取两个名称一样的,只能用遍历的方式进行 - HashSet nestedHash = new(); - foreach (var item in nested) - nestedHash.Add(item.Value); - - // 遍历全图,找到参照名称一样的删除 - _tr.BlockTable.ForEach(btr => { - if (btr.IsLayout) - return; - if (nestedHash.Contains(btr.Name)) - { - btr.UpgradeOpen(); - btr.Erase(); - btr.DowngradeOpen(); - btr.Dispose(); - } - }, checkIdOk: true); -#else foreach (var item in nested) { var name = item.Value; @@ -359,7 +339,6 @@ void DoubleBind() _tr.GetObject(_tr.BlockTable[name], OpenMode.ForWrite)? .Erase(); } -#endif } } #endregion diff --git "a/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchInfo.cs" "b/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchInfo.cs" index 1763aaf..a57beb8 100644 --- "a/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchInfo.cs" +++ "b/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchInfo.cs" @@ -298,43 +298,13 @@ public HatchInfo AppendLoop(Point2dCollection pts, // throw new ArgumentNullException(nameof(pts)); pts.NotNull(nameof(pts)); pts.End2End(); -#if NET35 - _boundaryIds.Add(CreateAddBoundary(pts, bluges, btrOfAddEntitySpace)); -#else // 2011新增API,可以不生成图元的情况下加入边界, // 通过这里进入的话,边界 _boundaryIds 是空的,那么 Build() 时候就需要过滤空的 _hatch.AppendLoop(hatchLoopTypes, pts, bluges); -#endif return this; } -#if NET35 - /// - /// 通过点集和凸度生成边界的多段线 - /// - /// 点集 - /// 凸度集 - /// 加入此空间 - /// 多段线id - static ObjectId CreateAddBoundary(Point2dCollection? pts, - DoubleCollection? bluges, - BlockTableRecord btrOfAddEntitySpace) - { - if (pts is null) - throw new ArgumentException(null, nameof(pts)); - if (bluges is null) - throw new ArgumentException(null, nameof(bluges)); - - var bvws = new List(); - var itor1 = pts.GetEnumerator(); - var itor2 = bluges.GetEnumerator(); - while (itor1.MoveNext() && itor2.MoveNext()) - bvws.Add(new BulgeVertexWidth(itor1.Current, itor2.Current)); - - return btrOfAddEntitySpace.AddPline(bvws); - } -#endif #endregion #region 枚举 diff --git a/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems b/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems index 0ce7697..cc8992b 100644 --- a/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems +++ b/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems @@ -77,7 +77,6 @@ - @@ -87,7 +86,6 @@ - diff --git a/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs b/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs index b685cc5..b4ada8f 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs @@ -375,7 +375,7 @@ public static implicit operator Transaction(DBTrans tr) /// public DBDictionary DataLinkDict => GetObject(Database.DataLinkDictionaryId)!; -#if !ac2009 + /// /// 详细视图样式字典 /// @@ -384,7 +384,7 @@ public static implicit operator Transaction(DBTrans tr) /// 剖面视图样式字典 /// public DBDictionary SectionViewStyleDict => GetObject(Database.SectionViewStyleDictionaryId)!; -#endif + #endif #endregion @@ -431,7 +431,14 @@ public ObjectId GetObjectId(string handleString) { var hanle = new Handle(Convert.ToInt64(handleString, 16)); // return Database.GetObjectId(false, hanle, 0); - return DBTransHelper.TryGetObjectId(Database, hanle); + if(Database.TryGetObjectId(hanle, out ObjectId id)) + { + return id; + } + else + { + return ObjectId.Null; + } } #endregion diff --git a/src/CAD/IFox.CAD.Shared/Runtime/DBTransHelper.cs b/src/CAD/IFox.CAD.Shared/Runtime/DBTransHelper.cs deleted file mode 100644 index ebc1a90..0000000 --- a/src/CAD/IFox.CAD.Shared/Runtime/DBTransHelper.cs +++ /dev/null @@ -1,89 +0,0 @@ -namespace IFoxCAD.Cad; - -/// -/// dbtrans辅助类 -/// -public class DBTransHelper -{ -#if NET35 - /* - * id = db.GetObjectId(false, handle, 0); - * 参数意义: db.GetObjectId(如果没有找到就创建,句柄号,标记..将来备用) - * 在vs的输出会一直抛出: - * 引发的异常:“Autodesk.AutoCAD.Runtime.Exception”(位于 AcdbMgd.dll 中) - * "eUnknownHandle" - * 这就是为什么慢的原因,所以直接运行就好了!而Debug还是需要用arx的API替代. - */ - - [System.Security.SuppressUnmanagedCodeSecurity] - [DllImport("acdb17.dll", CallingConvention = CallingConvention.ThisCall/*08的调用约定 高版本是__cdecl*/, - EntryPoint = "?getAcDbObjectId@AcDbDatabase@@QAE?AW4ErrorStatus@Acad@@AAVAcDbObjectId@@_NABVAcDbHandle@@K@Z")] - extern static int getAcDbObjectId17x32(IntPtr db, out ObjectId id, [MarshalAs(UnmanagedType.U1)] bool createnew, ref Handle h, uint reserved); - - [System.Security.SuppressUnmanagedCodeSecurity] - [DllImport("acdb17.dll", CallingConvention = CallingConvention.ThisCall/*08的调用约定 高版本是__cdecl*/, - EntryPoint = "?getAcDbObjectId@AcDbDatabase@@QEAA?AW4ErrorStatus@Acad@@AEAVAcDbObjectId@@_NAEBVAcDbHandle@@K@Z")] - extern static int getAcDbObjectId17x64(IntPtr db, out ObjectId id, [MarshalAs(UnmanagedType.U1)] bool createnew, ref Handle h, uint reserved); - - [System.Security.SuppressUnmanagedCodeSecurity] - [DllImport("acdb18.dll", CallingConvention = CallingConvention.ThisCall/*08的调用约定 高版本是__cdecl*/, - EntryPoint = "?getAcDbObjectId@AcDbDatabase@@QAE?AW4ErrorStatus@Acad@@AAVAcDbObjectId@@_NABVAcDbHandle@@K@Z")] - extern static int getAcDbObjectId18x32(IntPtr db, out ObjectId id, [MarshalAs(UnmanagedType.U1)] bool createnew, ref Handle h, uint reserved); - - [System.Security.SuppressUnmanagedCodeSecurity] - [DllImport("acdb18.dll", CallingConvention = CallingConvention.ThisCall/*08的调用约定 高版本是__cdecl*/, - EntryPoint = "?getAcDbObjectId@AcDbDatabase@@QEAA?AW4ErrorStatus@Acad@@AEAVAcDbObjectId@@_NAEBVAcDbHandle@@K@Z")] - extern static int getAcDbObjectId18x64(IntPtr db, out ObjectId id, [MarshalAs(UnmanagedType.U1)] bool createnew, ref Handle h, uint reserved); - - /// - /// 句柄转id,NET35(08~12)专用的 - /// - /// 数据库 - /// 句柄 - /// 返回的id - /// 不存在则创建 - /// 保留,用于未来 - /// 成功0,其他值都是错误.可以强转ErrorStatus - static int GetAcDbObjectId(IntPtr db, Handle handle, out ObjectId id, bool createIfNotFound = false, uint reserved = 0) - { - id = ObjectId.Null; - switch (Acap.Version.Major) - { - case 17: - { - if (IntPtr.Size == 4) - return getAcDbObjectId17x32(db, out id, createIfNotFound, ref handle, reserved); - else - return getAcDbObjectId17x64(db, out id, createIfNotFound, ref handle, reserved); - } - case 18: - { - if (IntPtr.Size == 4) - return getAcDbObjectId18x32(db, out id, createIfNotFound, ref handle, reserved); - else - return getAcDbObjectId18x64(db, out id, createIfNotFound, ref handle, reserved); - } - } - return -1; - } -#endif - /// - /// 句柄转id - /// - /// 数据库 - /// 句柄 - /// id - public static ObjectId TryGetObjectId(Database db, Handle handle) - { -#if !NET35 - // 高版本直接利用 - var es = db.TryGetObjectId(handle, out ObjectId id); - // if (!es) -#else - var es = GetAcDbObjectId(db.UnmanagedObject, handle, out ObjectId id); - // if (ErrorStatus.OK != (ErrorStatus)es) -#endif - return id; - } - -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/Runtime/Env.cs b/src/CAD/IFox.CAD.Shared/Runtime/Env.cs index df64594..5e7b2ee 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/Env.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/Env.cs @@ -468,15 +468,6 @@ public static void SetVar(string? varName, object? value, bool echo = true) #region 环境变量 #if acad -#if NET35 - [System.Security.SuppressUnmanagedCodeSecurity] - [DllImport("acad.exe", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, EntryPoint = "acedGetEnv")] - static extern int AcedGetEnv(string? envName, StringBuilder ReturnValue); - - [System.Security.SuppressUnmanagedCodeSecurity] - [DllImport("acad.exe", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, EntryPoint = "acedSetEnv")] - static extern int AcedSetEnv(string? envName, StringBuilder NewValue); -#else [System.Security.SuppressUnmanagedCodeSecurity] [DllImport("accore.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, EntryPoint = "acedGetEnv")] static extern int AcedGetEnv(string? envName, StringBuilder ReturnValue); @@ -485,7 +476,6 @@ public static void SetVar(string? varName, object? value, bool echo = true) [DllImport("accore.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, EntryPoint = "acedSetEnv")] static extern int AcedSetEnv(string? envName, StringBuilder NewValue); #endif -#endif #if gcad [System.Security.SuppressUnmanagedCodeSecurity] diff --git a/tests/TestAcad09plus/GlobalUsings.cs b/tests/TestAcad09plus/GlobalUsings.cs index 82e3ea7..1bede1f 100644 --- a/tests/TestAcad09plus/GlobalUsings.cs +++ b/tests/TestAcad09plus/GlobalUsings.cs @@ -45,9 +45,9 @@ /// ifoxcad global using IFoxCAD.Cad; global using IFoxCAD.Basal; -#if !ac2008 + global using IFoxCAD.WPF; -#endif + #if !NewtonsoftJson global using System.Web.Script.Serialization; diff --git "a/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/\345\261\217\345\271\225\345\235\220\346\240\207\350\275\254cad\345\235\220\346\240\207.cs" "b/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/\345\261\217\345\271\225\345\235\220\346\240\207\350\275\254cad\345\235\220\346\240\207.cs" index 1856a61..6c3d29d 100644 --- "a/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/\345\261\217\345\271\225\345\235\220\346\240\207\350\275\254cad\345\235\220\346\240\207.cs" +++ "b/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/\345\261\217\345\271\225\345\235\220\346\240\207\350\275\254cad\345\235\220\346\240\207.cs" @@ -71,12 +71,7 @@ public static Point CadToScreen(Point3d pt3d, Point mousePosition) return ptScrWin; } - //#if NET35 - // [DllImport("acad.exe", EntryPoint = "?acedGetAcadDwgView@@YAPAVCView@@XZ")] //acad08 - //#else - // [DllImport("acad.exe", EntryPoint = "?acedGetAcadDwgView@@YAPEAVCView@@XZ")]//acad21 - //#endif - // static extern IntPtr AcedGetAcadDwgview(); + delegate IntPtr DelegateAcedGetAcadDwgview(); static DelegateAcedGetAcadDwgview? acedGetAcadDwgView; @@ -119,15 +114,7 @@ public static int AcedGetWinNum(int x, int y) /// /// /// -#if NET35 - // 此处都是acad08这个有重载,不知道PeInfo能不能正常运行 - [DllImport("acad.exe", EntryPoint = "?acedCoordFromPixelToWorld@@YAHHVCPoint@@QAN@Z")] - static extern int AcedCoordFromPixelToWorld(int windnum, Point pt, out Point3D ptOut); - [DllImport("acad.exe", EntryPoint = "?acedCoordFromPixelToWorld@@YAXABVCPoint@@QAN@Z")]//这个重载参数不知道 - static extern int AcedCoordFromPixelToWorld(Point pt, out Point3D ptOut); -#else [DllImport("accore.dll", EntryPoint = "?acedCoordFromPixelToWorld@@YAHHVCPoint@@QEAN@Z")] static extern int AcedCoordFromPixelToWorld(int windnum, Point pt, out Point3D ptOut); -#endif } \ No newline at end of file diff --git "a/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/\350\277\207\347\250\213\346\226\207\344\273\266/\350\216\267\345\217\226\345\244\271\347\202\271\344\276\213\345\255\220.cs" "b/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/\350\277\207\347\250\213\346\226\207\344\273\266/\350\216\267\345\217\226\345\244\271\347\202\271\344\276\213\345\255\220.cs" index a2d7a98..7aad795 100644 --- "a/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/\350\277\207\347\250\213\346\226\207\344\273\266/\350\216\267\345\217\226\345\244\271\347\202\271\344\276\213\345\255\220.cs" +++ "b/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/\350\277\207\347\250\213\346\226\207\344\273\266/\350\216\267\345\217\226\345\244\271\347\202\271\344\276\213\345\255\220.cs" @@ -1,4 +1,4 @@ -#if !ac2008 + namespace GripOverruleTest; // https://through-the-interface.typepad.com/through_the_interface/2009/08/knowing-when-an-autocad-object-is-grip-edited-using-overrules-in-net.html @@ -96,5 +96,4 @@ public static void GripOverruleOnOff() Overruling = overruling; ed.WriteMessage("\nGrip overruling turned {0}.", overruling ? "on" : "off"); } -} -#endif \ No newline at end of file +} \ No newline at end of file diff --git a/tests/TestShared/Copyclip.cs b/tests/TestShared/Copyclip.cs index cc4558c..ac4b591 100644 --- a/tests/TestShared/Copyclip.cs +++ b/tests/TestShared/Copyclip.cs @@ -688,7 +688,7 @@ static string CreateTempFileName(string format = "X") } } -#if !ac2008 + public class TestImageFormat { public ImageFormat GetFormat(string filename) @@ -738,7 +738,7 @@ public void CreatePreviewImage() }); } } -#endif + public class OleTestClass { diff --git a/tests/TestShared/TestAddEntity.cs b/tests/TestShared/TestAddEntity.cs index 3db0db8..8d374c9 100644 --- a/tests/TestShared/TestAddEntity.cs +++ b/tests/TestShared/TestAddEntity.cs @@ -47,6 +47,7 @@ public void Test_Addent() tr.ModelSpace.AddEntity(line1); Line line2 = new(new(-10, 10, 0), new(41, 1, 0)); tr.PaperSpace.AddEntity(line2); + } [CommandMethod(nameof(Test_Drawarc))] diff --git a/tests/TestShared/TestBlock.cs b/tests/TestShared/TestBlock.cs index 88dcdee..4d84829 100644 --- a/tests/TestShared/TestBlock.cs +++ b/tests/TestShared/TestBlock.cs @@ -566,7 +566,7 @@ public void Test_Cbll() tr.Database.Insert(blkdefname, tr1.Database, false); // 插入了块定义,未插入块参照 } -#if !NET35 + [CommandMethod(nameof(Test_CombineBlocksIntoLibrary))] public void Test_CombineBlocksIntoLibrary() { @@ -668,5 +668,5 @@ public void Test_CombineBlocksIntoLibrary() pathName ); } -#endif + } \ No newline at end of file diff --git a/tests/TestShared/TestCurve.cs b/tests/TestShared/TestCurve.cs index 803d760..6669999 100644 --- a/tests/TestShared/TestCurve.cs +++ b/tests/TestShared/TestCurve.cs @@ -48,11 +48,7 @@ public void Test_Graphspeed() var graph = new IFoxCAD.Cad.Graph(); // 为了调试先把图的访问改为internal foreach (var curve in ents) { -#if NET35 - graph.AddEdge(curve!.ToCurve3d()!); -#else graph.AddEdge(curve!.GetGeCurve()); -#endif } // 新建 dfs diff --git a/tests/TestShared/TestEnv.cs b/tests/TestShared/TestEnv.cs index 8b9d2f2..9aaaa0c 100644 --- a/tests/TestShared/TestEnv.cs +++ b/tests/TestShared/TestEnv.cs @@ -89,7 +89,7 @@ public void Test_GetVar() //} -#if !NET35 && !NET40 +#if !NET40 // 通过此功能获取全部变量,尚不清楚此处如何设置,没有通过测试 [CommandMethod(nameof(Test_GetvarAll))] public static void Test_GetvarAll() diff --git a/tests/TestShared/TestJigExTransient.cs b/tests/TestShared/TestJigExTransient.cs index 3761171..52eb3f4 100644 --- a/tests/TestShared/TestJigExTransient.cs +++ b/tests/TestShared/TestJigExTransient.cs @@ -1,4 +1,4 @@ -#if !ac2008 + namespace Test; public partial class Test @@ -86,4 +86,3 @@ public static void Test_JigExTransentDim() tr.CurrentSpace.AddEntity(dimension); } } -#endif \ No newline at end of file diff --git a/tests/TestShared/TestLisp.cs b/tests/TestShared/TestLisp.cs index 8f79a39..d7740e4 100644 --- a/tests/TestShared/TestLisp.cs +++ b/tests/TestShared/TestLisp.cs @@ -50,18 +50,18 @@ public static object LispTest_RunLisp(ResultBuffer rb) [CommandMethod("CmdTest_RunLisp19", CommandFlags.NoUndoMarker)] // 不能在参照块中使用命令 [CommandMethod("CmdTest_RunLisp20", CommandFlags.NoBlockEditor)] -#if !ac2008 + // acad09增,不会被动作录制器 捕捉到 [CommandMethod("CmdTest_RunLisp21", CommandFlags.NoActionRecording)] // acad09增,会被动作录制器捕捉 [CommandMethod("CmdTest_RunLisp22", CommandFlags.ActionMacro)] -#endif -#if !NET35 + + // 推断约束时不能使用命令 [CommandMethod("CmdTest_RunLisp23", CommandFlags.NoInferConstraint)] // 命令允许在选择图元时临时显示动态尺寸 [CommandMethod("CmdTest_RunLisp24", CommandFlags.TempShowDynDimension)] -#endif + public static void CmdTest_RunLisp() { // 测试方法1: (command "CmdTest_RunLisp1") diff --git a/tests/TestShared/TestXRecord.cs b/tests/TestShared/TestXRecord.cs index 313bf8c..1fcb85c 100644 --- a/tests/TestShared/TestXRecord.cs +++ b/tests/TestShared/TestXRecord.cs @@ -192,36 +192,7 @@ static void BytesTask(byte[] buffer, int max, Action action) } #endregion -#if NET35 - /// - /// 设置描述(容量无限) - /// - /// - /// - /// - public static void SetSummaryInfoAtt(this Database db, string key, string value) - { - var info = new DatabaseSummaryInfoBuilder(db.SummaryInfo); - if (!info.CustomProperties.ContainsKey(key)) - info.CustomProperties.Add(key, value); - else - info.CustomProperties[key] = value; - db.SummaryInfo = info.ToDatabaseSummaryInfo(); - } - /// - /// 获取描述 - /// - /// - /// - /// - public static object? GetSummaryInfoAtt(this Database db, string key) - { - var info = new DatabaseSummaryInfoBuilder(db.SummaryInfo); - if (info.CustomProperties.ContainsKey(key)) - return info.CustomProperties[key]; - return null; - } -#else + /// /// 设置描述(容量无限) /// @@ -250,7 +221,7 @@ public static void SetSummaryInfoAtt(this Database db, string key, object value) return info.CustomPropertyTable[key]; return null; } -#endif + } public class TestABCList : List -- Gitee From 81abb4d67686488c9ca39e312fa6bb696a253dbc Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 23 Mar 2023 00:33:49 +0800 Subject: [PATCH 023/453] =?UTF-8?q?Env=E7=B1=BB=E5=A2=9E=E5=8A=A0=E5=88=A4?= =?UTF-8?q?=E6=96=AD=E6=98=AF=E5=90=A6=E6=9C=89=E6=B4=BB=E5=8A=A8=E5=91=BD?= =?UTF-8?q?=E4=BB=A4=E7=9A=84=E5=B1=9E=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/Runtime/Env.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CAD/IFox.CAD.Shared/Runtime/Env.cs b/src/CAD/IFox.CAD.Shared/Runtime/Env.cs index 5e7b2ee..6128683 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/Env.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/Env.cs @@ -91,6 +91,7 @@ public static bool CmdEcho set => Acap.SetSystemVariable("cmdecho", Convert.ToInt16(value)); } + public static bool CmdActive => Convert.ToBoolean(Acap.GetSystemVariable("CMDACTIVE")); /// /// 控制在光标是否为正交模式, 为打开正交, 为关闭正交 /// -- Gitee From 18e63ad59f4b03a9f4b02c772162a5a720d4d470 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 23 Mar 2023 00:34:27 +0800 Subject: [PATCH 024/453] =?UTF-8?q?Env=E7=B1=BB=E5=A2=9E=E5=8A=A0=E5=88=A4?= =?UTF-8?q?=E6=96=AD=E6=98=AF=E5=90=A6=E6=9C=89=E6=B4=BB=E5=8A=A8=E5=91=BD?= =?UTF-8?q?=E4=BB=A4=E7=9A=84=E5=B1=9E=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/Runtime/Env.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/CAD/IFox.CAD.Shared/Runtime/Env.cs b/src/CAD/IFox.CAD.Shared/Runtime/Env.cs index 6128683..7e8085a 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/Env.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/Env.cs @@ -90,7 +90,9 @@ public static bool CmdEcho get => Convert.ToInt16(Acap.GetSystemVariable("cmdecho")) == 1; set => Acap.SetSystemVariable("cmdecho", Convert.ToInt16(value)); } - + /// + /// 获取Cad当前是否有活动命令 + /// public static bool CmdActive => Convert.ToBoolean(Acap.GetSystemVariable("CMDACTIVE")); /// /// 控制在光标是否为正交模式, 为打开正交, 为关闭正交 -- Gitee From 9734a7efd30119b85e94f70de309cb57d33c478b Mon Sep 17 00:00:00 2001 From: vicwjb Date: Thu, 23 Mar 2023 20:40:47 +0800 Subject: [PATCH 025/453] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=99=AE=E9=80=9A?= =?UTF-8?q?=E5=BF=AB=E5=8F=82=E7=85=A7=E5=92=8C=E5=B1=9E=E6=80=A7=E5=9D=97?= =?UTF-8?q?=E5=8F=82=E7=85=A7=E7=9A=84GetBoundingBoxEx=E4=BC=9A=E8=B7=91?= =?UTF-8?q?=E5=81=8F=20fixed=20#I6MC2T?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Entity/EntityBoundingInfo.cs | 15 +++--- tests/TestShared/TestExtents.cs | 48 +++++++++++++++++++ tests/TestShared/TestShared.projitems | 1 + 3 files changed, 57 insertions(+), 7 deletions(-) create mode 100644 tests/TestShared/TestExtents.cs diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs index baf2fc4..3f8ae79 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs @@ -201,13 +201,14 @@ static BoundingInfo GetBoxInfoInBlockReference(BlockReference brf) { // 这个获取是原点附近,需要平移到块基点 var fit = brf.GeometryExtentsBestFit(); - var minX = fit.MinPoint.X + brf.Position.X; - var minY = fit.MinPoint.Y + brf.Position.Y; - var minZ = fit.MinPoint.Z + brf.Position.Z; - var maxX = fit.MaxPoint.X + brf.Position.X; - var maxY = fit.MaxPoint.Y + brf.Position.Y; - var maxZ = fit.MaxPoint.Z + brf.Position.Z; - return new(minX, minY, minZ, maxX, maxY, maxZ, true); + //var minX = fit.MinPoint.X + brf.Position.X; + //var minY = fit.MinPoint.Y + brf.Position.Y; + //var minZ = fit.MinPoint.Z + brf.Position.Z; + //var maxX = fit.MaxPoint.X + brf.Position.X; + //var maxY = fit.MaxPoint.Y + brf.Position.Y; + //var maxZ = fit.MaxPoint.Z + brf.Position.Z; + //return new(minX, minY, minZ, maxX, maxY, maxZ, true); + return new(fit.MinPoint, fit.MaxPoint, true); } catch { diff --git a/tests/TestShared/TestExtents.cs b/tests/TestShared/TestExtents.cs new file mode 100644 index 0000000..0eb0cc7 --- /dev/null +++ b/tests/TestShared/TestExtents.cs @@ -0,0 +1,48 @@ + + +namespace TestShared +{ + public class TestExtents + { + [CommandMethod(nameof(TestExtents))] + public void TestBlockExtents() + { + using var tr = new DBTrans(); + var ent = Env.Editor.GetEntity("pick the entity"); + if (ent.Status != PromptStatus.OK ) + { + return; + } + + var block = ent.ObjectId.GetObject(); + if (block != null && block.Bounds.HasValue) + { + var extent = block.GeometricExtents; + var pts = new List() { + extent.MinPoint, + new Point3d(extent.MinPoint.X,extent.MaxPoint.Y,0), + extent.MaxPoint, + new Point3d(extent.MaxPoint.X,extent.MinPoint.Y,0), + + }; + + tr.CurrentSpace.AddPline(pts, action: e => e.ColorIndex = 1); + if (block is BlockReference block1) + { + var extents = block1.GeometryExtentsBestFit(); + var pts1 = new List() { + extents.MinPoint, + new Point3d(extents.MinPoint.X,extents.MaxPoint.Y,0), + extents.MaxPoint, + new Point3d(extents.MaxPoint.X,extents.MinPoint.Y,0),}; + tr.CurrentSpace.AddPline(pts1, action: e => e.ColorIndex = 2); + + var extents2 = block1.GetBoundingBoxEx(); + tr.CurrentSpace.AddLine(extents2.Min,extents2.Max,e=>e.ColorIndex = 3); + } + + + } + } + } +} diff --git a/tests/TestShared/TestShared.projitems b/tests/TestShared/TestShared.projitems index 491333d..edbd45b 100644 --- a/tests/TestShared/TestShared.projitems +++ b/tests/TestShared/TestShared.projitems @@ -21,6 +21,7 @@ + -- Gitee From 58fdd31fd8e34d7785f23f8022f7515aecc19ef1 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Tue, 28 Mar 2023 00:02:26 +0800 Subject: [PATCH 026/453] =?UTF-8?q?=E5=8F=96=E6=B6=88JigEx=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E6=B7=BB=E5=8A=A0=E7=9A=84=E2=80=9C=E7=A9=BA=E6=A0=BC?= =?UTF-8?q?=E9=80=80=E5=87=BA=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExpressionTrees/SqlExpressionVisitor.cs | 2 ++ .../ExtensionMethod/Jig/JigEx.cs | 19 +++++-------------- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/src/Basal/IFox.Basal.Shared/ExpressionTrees/SqlExpressionVisitor.cs b/src/Basal/IFox.Basal.Shared/ExpressionTrees/SqlExpressionVisitor.cs index bfd6283..17ce385 100644 --- a/src/Basal/IFox.Basal.Shared/ExpressionTrees/SqlExpressionVisitor.cs +++ b/src/Basal/IFox.Basal.Shared/ExpressionTrees/SqlExpressionVisitor.cs @@ -1,4 +1,6 @@ #if NET45 +using Microsoft.CSharp.RuntimeBinder; + namespace IFoxCAD.Basal; /// diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigEx.cs index 15024ab..c6f1296 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigEx.cs @@ -216,25 +216,16 @@ public JigPromptPointOptions SetOptions(string msg, _options = JigPointOptions(); _options.Message = Environment.NewLine + msg; - - // 加入关键字,加入时候将空格内容放到最后 - string spaceValue = string.Empty; - const string spaceKey = " "; + if (keywords != null) foreach (var item in keywords) - if (item.Key == spaceKey) - spaceValue = item.Value; - else _options.Keywords.Add(item.Key, item.Key, item.Value); - /// 因为默认配置函数导致此处空格触发是无效的, - /// 但是用户如果想触发,就需要在外部减去默认UserInputControls配置 - /// 要放最后,才能优先触发其他关键字 - if (spaceValue != string.Empty) - _options.Keywords.Add(spaceKey, spaceKey, spaceValue); - else - _options.Keywords.Add(spaceKey, spaceKey, "<空格退出>"); + // 因为默认配置函数导致此处空格触发是无效的, + // 但是用户如果想触发,就需要在外部减去默认UserInputControls配置 + // 要放最后,才能优先触发其他关键字 + // 外部设置减去配置 // _options.UserInputControls = -- Gitee From 9170bd9fbbebd2332ac5646841e53ca157d08461 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Thu, 23 Mar 2023 23:37:25 +0800 Subject: [PATCH 027/453] =?UTF-8?q?=E8=A1=A5=E5=85=852023=E7=9A=84?= =?UTF-8?q?=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/Directory.Build.props | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/CAD/Directory.Build.props b/src/CAD/Directory.Build.props index 4aed4b2..85131fa 100644 --- a/src/CAD/Directory.Build.props +++ b/src/CAD/Directory.Build.props @@ -1,8 +1,13 @@  +<<<<<<< HEAD 0.6.0.0 修复TextInfo.AddDBTextToEntity()报错的问题 +======= + 0.5.2.4 + 补充2023的信息 +>>>>>>> 05896d6 (补充2023的信息) -- Gitee From 8724574d2d4b0db2f4c93074d07ea5ad04626bf3 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Tue, 28 Mar 2023 23:48:52 +0800 Subject: [PATCH 028/453] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=90=88=E5=B9=B6?= =?UTF-8?q?=E5=A4=B1=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/Directory.Build.props | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/CAD/Directory.Build.props b/src/CAD/Directory.Build.props index 85131fa..4aed4b2 100644 --- a/src/CAD/Directory.Build.props +++ b/src/CAD/Directory.Build.props @@ -1,13 +1,8 @@  -<<<<<<< HEAD 0.6.0.0 修复TextInfo.AddDBTextToEntity()报错的问题 -======= - 0.5.2.4 - 补充2023的信息 ->>>>>>> 05896d6 (补充2023的信息) -- Gitee From 899afd84aa4e69450aa9274e5e27a72bf92d4710 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Tue, 28 Mar 2023 23:53:35 +0800 Subject: [PATCH 029/453] =?UTF-8?q?=E5=8F=91=E5=B8=83=E4=B8=AAalpha?= =?UTF-8?q?=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Basal/Directory.Build.props | 4 ++-- src/CAD/Directory.Build.props | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Basal/Directory.Build.props b/src/Basal/Directory.Build.props index 98c0b4e..fcc6dc4 100644 --- a/src/Basal/Directory.Build.props +++ b/src/Basal/Directory.Build.props @@ -1,8 +1,8 @@  - 0.6.0.0 - 调整目录结构 + 0.6.0-alpha1 + 发布个alpha版 diff --git a/src/CAD/Directory.Build.props b/src/CAD/Directory.Build.props index 4aed4b2..b89f89a 100644 --- a/src/CAD/Directory.Build.props +++ b/src/CAD/Directory.Build.props @@ -1,8 +1,8 @@  - 0.6.0.0 - 修复TextInfo.AddDBTextToEntity()报错的问题 + 0.6.0-alpha1 + 发布个alpha版 -- Gitee From 6f59cf4e98b2beeba517e4cc34f7ed87f9c7531f Mon Sep 17 00:00:00 2001 From: vicwjb Date: Fri, 31 Mar 2023 23:32:00 +0800 Subject: [PATCH 030/453] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Entity/EntityBoundingInfo.cs | 76 +------- .../ExtensionMethod/LogEx/DBLogger.cs | 108 ----------- .../ExtensionMethod/LogEx/EventLogger.cs | 147 -------------- .../ExtensionMethod/LogEx/FileLogger.cs | 118 ------------ .../ExtensionMethod/LogEx/LogBase.cs | 94 --------- .../ExtensionMethod/LogEx/LogHelper.cs | 181 ------------------ .../ExtensionMethod/LogEx/LogTarget.cs | 110 ----------- .../ExtensionMethod/LogEx/LogTxt.cs | 60 ------ .../ExtensionMethod/SymbolTableRecordEx.cs | 3 +- .../IFox.CAD.Shared/IFox.CAD.Shared.projitems | 7 - 10 files changed, 7 insertions(+), 897 deletions(-) delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/DBLogger.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/EventLogger.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/FileLogger.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/LogBase.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/LogHelper.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/LogTarget.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/LogTxt.cs diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs index 3f8ae79..fb3d5fa 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs @@ -76,19 +76,7 @@ public void Move(Point3d pt1, Point3d pt2) public class EntityBoundingInfo { #region 保存异常类型的日志 - /// - /// 包围盒错误文件路径 - /// - public static string BoxLogAddress - { - get - { - _BoxLogAddress ??= LogHelper.GetDefaultOption(nameof(GetBoundingInfo) + ".config"); - return _BoxLogAddress; - } - set { _BoxLogAddress = value; } - } - static string? _BoxLogAddress; + static readonly HashSet _typeNames; /// /// 为了保证更好的性能, @@ -98,65 +86,13 @@ public static string BoxLogAddress static EntityBoundingInfo() { _typeNames = new(); - if (!File.Exists(BoxLogAddress)) - return; - ExceptionToHashSet(); + + } - /// - /// 读取日志的异常到容器 - /// - static void ExceptionToHashSet() - { - var old_LogAddress = LogHelper.LogAddress; - try - { - LogHelper.OptionFile(BoxLogAddress); - var logTxts = new FileLogger().ReadLog(); - for (int i = 0; i < logTxts.Length; i++) - { - var line = logTxts[i]; - if (line.Contains(nameof(LogTxt.备注信息))) - { - int index = line.IndexOf(":"); - index = line.IndexOf("\"", index) + 1;// 1是"\"" - int index2 = line.IndexOf("\"", index); - var msg = line.Substring(index, index2 - index); - _typeNames.Add(msg); - } - } - } - finally - { - LogHelper.LogAddress = old_LogAddress; - } - } + - /// - /// 写入容器类型到异常日志 - /// - /// - /// - static void ExceptionToLog(Exception e, Entity ent) - { - // 无法处理的错误类型将被记录 - // 如果错误无法try,而是cad直接致命错误,那么此处也不会被写入, - // 这种情况无法避免程序安全性,总不能写了日志再去删除日志词条,这样会造成频繁IO的 - // 遇到一个不认识的类型再去写入?然后记录它是否可以写入? - var old_LogAddress = LogHelper.LogAddress; - var old_FlagOutFile = LogHelper.FlagOutFile; - try - { - LogHelper.FlagOutFile = true; - LogHelper.OptionFile(BoxLogAddress); - e.WriteLog(ent.GetType().Name, LogTarget.FileNotException); - } - finally - { - LogHelper.LogAddress = old_LogAddress; - LogHelper.FlagOutFile = old_FlagOutFile; - } - } + #endregion /// @@ -188,7 +124,7 @@ public static BoundingInfo GetBoundingInfo(Entity ent) { return new(ent.GeometricExtents.MinPoint, ent.GeometricExtents.MaxPoint, true); } - catch (Exception e) { ExceptionToLog(e, ent); } + catch (Exception e) { } return new(Point3d.Origin, Point3d.Origin, false); } diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/DBLogger.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/DBLogger.cs deleted file mode 100644 index 0724412..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/DBLogger.cs +++ /dev/null @@ -1,108 +0,0 @@ -namespace IFoxCAD.Cad; - -using System; -#region 写入日志到不同的环境中 - -/// -/// 写入到数据库(暂时不支持) -/// -public class DBLogger : LogBase -{ - public override void DeleteLog() - { - throw new NotImplementedException(); - } - public override string[] ReadLog() - { - throw new NotImplementedException(); - } - public override void WriteLog(string? message) - { - throw new NotImplementedException(); - } -} -#endregion - - -#if false // 最简单的实现 -public static class Log -{ - /// - /// 读写锁 - /// 当资源处于写入模式时,其他线程写入需要等待本次写入结束之后才能继续写入 - /// - static readonly ReaderWriterLockSlim _logWriteLock = new(); - - /// - /// 日志文件完整路径 - /// - static readonly string _logAddress; - - static Log() - { - // 微软回复:静态构造函数只会被调用一次, - // 并且在它执行完成之前,任何其它线程都不能创建这个类的实例或使用这个类的静态成员 - // https://blog.csdn.net/weixin_34204722/article/details/90095812 - var sb = new StringBuilder(); - sb.Append(Environment.CurrentDirectory); - sb.Append("\\ErrorLog"); - - // 新建文件夹 - var path = sb.ToString(); - if (!Directory.Exists(path)) - { - Directory.CreateDirectory(path) - .Attributes = FileAttributes.Normal; // 设置文件夹属性为普通 - } - - sb.Append('\\'); - sb.Append(DateTime.Now.ToString("yy-MM-dd")); - sb.Append(".log"); - _logAddress = sb.ToString(); - } - - - /// - /// 将异常打印到日志文件 - /// - /// 异常 - /// 备注 - /// DEBUG模式打印到vs输出窗口 - public static string? WriteLog(this Exception? ex, - string? remarks = null, - bool printDebugWindow = true) - { - try - { - _logWriteLock.EnterWriteLock();// 写模式锁定 读写锁 - - var logtxt = new LogTxt(ex, remarks); - // var logtxtJson = Newtonsoft.Json.JsonConvert.SerializeObject(logtxt, Formatting.Indented); - var logtxtJson = logtxt.ToString(); - - if (logtxtJson == null) - return string.Empty; - - // 把异常信息输出到文件 - var sw = new StreamWriter(_logAddress, true/*当天日志文件存在就追加,否则就创建*/); - sw.Write(logtxtJson); - sw.Flush(); - sw.Close(); - sw.Dispose(); - - if (printDebugWindow) - { - Debugx.Printl("错误日志: " + _logAddress); - Debug.Write(logtxtJson); - // Debugger.Break(); - // Debug.Assert(false, "终止进程"); - } - return logtxtJson; - } - finally - { - _logWriteLock.ExitWriteLock();// 解锁 读写锁 - } - } -} -#endif \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/EventLogger.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/EventLogger.cs deleted file mode 100644 index 4e011e4..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/EventLogger.cs +++ /dev/null @@ -1,147 +0,0 @@ -namespace IFoxCAD.Cad; - -using System.Diagnostics; -using Exception = Exception; -#region 写入日志到不同的环境中 - -/// -/// 写入到win日志 -/// -public class EventLogger : LogBase -{ - // 需要win权限 - // https://blog.csdn.net/weixin_38208401/article/details/77870909 - // NET50要加 - // https://docs.microsoft.com/en-us/answers/questions/526018/windows-event-log-with-net-5.html - - public string LogName = "IFoxCadLog"; - public override void DeleteLog() - { -#if !NET5_0 && !NET6_0 - if (EventLog.Exists(LogName)) - EventLog.Delete(LogName); -#endif - } - public override string[] ReadLog() - { - List lines = new(); -#if !NET5_0 && !NET6_0 - try - { - EventLog eventLog = new() - { - Log = LogName - }; - foreach (EventLogEntry entry in eventLog.Entries) - lines.Add(entry.Message); - } - catch (System.Security.SecurityException e) - { - throw new Exception("您没有权限读取win日志::" + e.Message); - } -#endif - return lines.ToArray(); - } - public override void WriteLog(string? message) - { -#if !NET5_0 && !NET6_0 - try - { - EventLog eventLog = new() - { - Source = LogName - }; - eventLog.WriteEntry(message, EventLogEntryType.Information); - } - catch (System.Security.SecurityException e) - { - throw new Exception("您没有权限写入win日志::" + e.Message); - } -#endif - } -} -#endregion - - -#if false // 最简单的实现 -public static class Log -{ - /// - /// 读写锁 - /// 当资源处于写入模式时,其他线程写入需要等待本次写入结束之后才能继续写入 - /// - static readonly ReaderWriterLockSlim _logWriteLock = new(); - - /// - /// 日志文件完整路径 - /// - static readonly string _logAddress; - - static Log() - { - // 微软回复:静态构造函数只会被调用一次, - // 并且在它执行完成之前,任何其它线程都不能创建这个类的实例或使用这个类的静态成员 - // https://blog.csdn.net/weixin_34204722/article/details/90095812 - var sb = new StringBuilder(); - sb.Append(Environment.CurrentDirectory); - sb.Append("\\ErrorLog"); - - // 新建文件夹 - var path = sb.ToString(); - if (!Directory.Exists(path)) - { - Directory.CreateDirectory(path) - .Attributes = FileAttributes.Normal; // 设置文件夹属性为普通 - } - - sb.Append('\\'); - sb.Append(DateTime.Now.ToString("yy-MM-dd")); - sb.Append(".log"); - _logAddress = sb.ToString(); - } - - - /// - /// 将异常打印到日志文件 - /// - /// 异常 - /// 备注 - /// DEBUG模式打印到vs输出窗口 - public static string? WriteLog(this Exception? ex, - string? remarks = null, - bool printDebugWindow = true) - { - try - { - _logWriteLock.EnterWriteLock();// 写模式锁定 读写锁 - - var logtxt = new LogTxt(ex, remarks); - // var logtxtJson = Newtonsoft.Json.JsonConvert.SerializeObject(logtxt, Formatting.Indented); - var logtxtJson = logtxt.ToString(); - - if (logtxtJson == null) - return string.Empty; - - // 把异常信息输出到文件 - var sw = new StreamWriter(_logAddress, true/*当天日志文件存在就追加,否则就创建*/); - sw.Write(logtxtJson); - sw.Flush(); - sw.Close(); - sw.Dispose(); - - if (printDebugWindow) - { - Debugx.Printl("错误日志: " + _logAddress); - Debug.Write(logtxtJson); - // Debugger.Break(); - // Debug.Assert(false, "终止进程"); - } - return logtxtJson; - } - finally - { - _logWriteLock.ExitWriteLock();// 解锁 读写锁 - } - } -} -#endif \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/FileLogger.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/FileLogger.cs deleted file mode 100644 index de84385..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/FileLogger.cs +++ /dev/null @@ -1,118 +0,0 @@ -namespace IFoxCAD.Cad; -#region 写入日志到不同的环境中 - -/// -/// 写入到文件中 -/// -public class FileLogger : LogBase -{ - public override void DeleteLog() - { - File.Delete(LogHelper.LogAddress); - } - public override string[] ReadLog() - { - List lines = new(); - using (var sr = new StreamReader(LogHelper.LogAddress, true/*自动识别文件头*/)) - { - string line; - while ((line = sr.ReadLine()) != null) - lines.Add(line); - } - return lines.ToArray(); - } - public override void WriteLog(string? message) - { - // 把异常信息输出到文件 - var sw = new StreamWriter(LogHelper.LogAddress, true/*当天日志文件存在就追加,否则就创建*/); - sw.Write(message); - sw.Flush(); - sw.Close(); - sw.Dispose(); - } -} -#endregion - - -#if false // 最简单的实现 -public static class Log -{ - /// - /// 读写锁 - /// 当资源处于写入模式时,其他线程写入需要等待本次写入结束之后才能继续写入 - /// - static readonly ReaderWriterLockSlim _logWriteLock = new(); - - /// - /// 日志文件完整路径 - /// - static readonly string _logAddress; - - static Log() - { - // 微软回复:静态构造函数只会被调用一次, - // 并且在它执行完成之前,任何其它线程都不能创建这个类的实例或使用这个类的静态成员 - // https://blog.csdn.net/weixin_34204722/article/details/90095812 - var sb = new StringBuilder(); - sb.Append(Environment.CurrentDirectory); - sb.Append("\\ErrorLog"); - - // 新建文件夹 - var path = sb.ToString(); - if (!Directory.Exists(path)) - { - Directory.CreateDirectory(path) - .Attributes = FileAttributes.Normal; // 设置文件夹属性为普通 - } - - sb.Append('\\'); - sb.Append(DateTime.Now.ToString("yy-MM-dd")); - sb.Append(".log"); - _logAddress = sb.ToString(); - } - - - /// - /// 将异常打印到日志文件 - /// - /// 异常 - /// 备注 - /// DEBUG模式打印到vs输出窗口 - public static string? WriteLog(this Exception? ex, - string? remarks = null, - bool printDebugWindow = true) - { - try - { - _logWriteLock.EnterWriteLock();// 写模式锁定 读写锁 - - var logtxt = new LogTxt(ex, remarks); - // var logtxtJson = Newtonsoft.Json.JsonConvert.SerializeObject(logtxt, Formatting.Indented); - var logtxtJson = logtxt.ToString(); - - if (logtxtJson == null) - return string.Empty; - - // 把异常信息输出到文件 - var sw = new StreamWriter(_logAddress, true/*当天日志文件存在就追加,否则就创建*/); - sw.Write(logtxtJson); - sw.Flush(); - sw.Close(); - sw.Dispose(); - - if (printDebugWindow) - { - Debugx.Printl("错误日志: " + _logAddress); - Debug.Write(logtxtJson); - // Debugger.Break(); - // Debug.Assert(false, "终止进程"); - } - return logtxtJson; - } - finally - { - _logWriteLock.ExitWriteLock();// 解锁 读写锁 - } - } -} -#endif \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/LogBase.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/LogBase.cs deleted file mode 100644 index 73ff44e..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/LogBase.cs +++ /dev/null @@ -1,94 +0,0 @@ -namespace IFoxCAD.Cad; -#region 写入日志到不同的环境中 -// https://zhuanlan.zhihu.com/p/338492989 -public abstract class LogBase -{ - public abstract void DeleteLog(); - public abstract string[] ReadLog(); - public abstract void WriteLog(string message); -} -#endregion - - -#if false // 最简单的实现 -public static class Log -{ - /// - /// 读写锁 - /// 当资源处于写入模式时,其他线程写入需要等待本次写入结束之后才能继续写入 - /// - static readonly ReaderWriterLockSlim _logWriteLock = new(); - - /// - /// 日志文件完整路径 - /// - static readonly string _logAddress; - - static Log() - { - // 微软回复:静态构造函数只会被调用一次, - // 并且在它执行完成之前,任何其它线程都不能创建这个类的实例或使用这个类的静态成员 - // https://blog.csdn.net/weixin_34204722/article/details/90095812 - var sb = new StringBuilder(); - sb.Append(Environment.CurrentDirectory); - sb.Append("\\ErrorLog"); - - // 新建文件夹 - var path = sb.ToString(); - if (!Directory.Exists(path)) - { - Directory.CreateDirectory(path) - .Attributes = FileAttributes.Normal; // 设置文件夹属性为普通 - } - - sb.Append('\\'); - sb.Append(DateTime.Now.ToString("yy-MM-dd")); - sb.Append(".log"); - _logAddress = sb.ToString(); - } - - - /// - /// 将异常打印到日志文件 - /// - /// 异常 - /// 备注 - /// DEBUG模式打印到vs输出窗口 - public static string? WriteLog(this Exception? ex, - string? remarks = null, - bool printDebugWindow = true) - { - try - { - _logWriteLock.EnterWriteLock();// 写模式锁定 读写锁 - - var logtxt = new LogTxt(ex, remarks); - // var logtxtJson = Newtonsoft.Json.JsonConvert.SerializeObject(logtxt, Formatting.Indented); - var logtxtJson = logtxt.ToString(); - - if (logtxtJson == null) - return string.Empty; - - // 把异常信息输出到文件 - var sw = new StreamWriter(_logAddress, true/*当天日志文件存在就追加,否则就创建*/); - sw.Write(logtxtJson); - sw.Flush(); - sw.Close(); - sw.Dispose(); - - if (printDebugWindow) - { - Debugx.Printl("错误日志: " + _logAddress); - Debug.Write(logtxtJson); - // Debugger.Break(); - // Debug.Assert(false, "终止进程"); - } - return logtxtJson; - } - finally - { - _logWriteLock.ExitWriteLock();// 解锁 读写锁 - } - } -} -#endif \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/LogHelper.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/LogHelper.cs deleted file mode 100644 index e1e6b0b..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/LogHelper.cs +++ /dev/null @@ -1,181 +0,0 @@ -namespace IFoxCAD.Cad; - -using System; -using System.Diagnostics; -using System.Threading; -using Exception = Exception; - - - - -public static class LogHelper -{ -#pragma warning disable CA2211 // 非常量字段应当不可见 - /// - /// 日志文件完整路径 - /// - public static string? LogAddress; - /// - /// 输出错误信息到日志文件的开关 - /// - public static bool FlagOutFile = false; - /// - /// 输出错误信息到vs输出窗口的开关 - /// - public static bool FlagOutVsOutput = true; -#pragma warning restore CA2211 // 非常量字段应当不可见 - - /// - /// 读写锁 - /// 当资源处于写入模式时,其他线程写入需要等待本次写入结束之后才能继续写入 - /// - static readonly ReaderWriterLockSlim _logWriteLock = new(); - - /// - /// 提供给外部设置log文件保存路径 - /// - /// null就生成默认配置 - public static void OptionFile(string? newlogAddress = null) - { - _logWriteLock.EnterWriteLock();// 写模式锁定 读写锁 - try - { - LogAddress = newlogAddress; - if (string.IsNullOrEmpty(LogAddress)) - LogAddress = GetDefaultOption(DateTime.Now.ToString("yy-MM-dd") + ".log"); - } - finally - { - _logWriteLock.ExitWriteLock();// 解锁 读写锁 - } - } - - /// - /// 输入文件名,获取保存路径的完整路径 - /// - /// 文件名,null获取默认路径 - /// 创建路径 - /// 完整路径 - public static string GetDefaultOption(string fileName, bool createDirectory = true) - { - // 微软回复:静态构造函数只会被调用一次, - // 并且在它执行完成之前,任何其它线程都不能创建这个类的实例或使用这个类的静态成员 - // https://blog.csdn.net/weixin_34204722/article/details/90095812 - var sb = new StringBuilder(); - sb.Append(Environment.CurrentDirectory); - sb.Append("\\ErrorLog"); - - // 新建文件夹 - if (createDirectory) - { - var path = sb.ToString(); - if (!Directory.Exists(path)) - { - // 设置文件夹属性为普通 - Directory.CreateDirectory(path) - .Attributes = FileAttributes.Normal; - } - } - sb.Append('\\'); - sb.Append(fileName); - return sb.ToString(); - } - - public static string WriteLog(this string? message, - LogTarget target = LogTarget.File) - { - if (message == null) - return string.Empty; - return LogAction(null, message, target); - } - - public static string WriteLog(this Exception? exception, - LogTarget target = LogTarget.File) - { - if (exception == null) - return string.Empty; - return LogAction(exception, null, target); - } - - public static string WriteLog(this Exception? exception, string? message, - LogTarget target = LogTarget.File) - { - if (exception == null) - return string.Empty; - return LogAction(exception, message, target); - } - - - /// 错误 - /// 备注信息 - /// 记录方式 - static string LogAction(Exception? ex, - string? message, - LogTarget target) - { - if (ex == null && message == null) - return string.Empty; - - if (LogAddress == null) - { - if (target == LogTarget.File || - target == LogTarget.FileNotException) - OptionFile(); - } - - // 不写入错误 - if (target == LogTarget.FileNotException) - ex = null; - - try - { - _logWriteLock.EnterWriteLock();// 写模式锁定 读写锁 - - var logtxt = new LogTxt(ex, message); - // var logtxtJson = Newtonsoft.Json.JsonConvert.SerializeObject(logtxt, Formatting.Indented); - var logtxtJson = logtxt?.ToString(); - if (logtxtJson == null) - return string.Empty; - - if (FlagOutFile) - { - LogBase? logger; - switch (target) - { - case LogTarget.File: - logger = new FileLogger(); - logger.WriteLog(logtxtJson); - break; - case LogTarget.FileNotException: - logger = new FileLogger(); - logger.WriteLog(logtxtJson); - break; - case LogTarget.Database: - logger = new DBLogger(); - logger.WriteLog(logtxtJson); - break; - case LogTarget.EventLog: - logger = new EventLogger(); - logger.WriteLog(logtxtJson); - break; - } - } - - if (FlagOutVsOutput) - { - Debugx.Printl("错误日志: " + LogAddress); - Debug.Write(logtxtJson); - } - return logtxtJson; - } - finally - { - _logWriteLock.ExitWriteLock();// 解锁 读写锁 - } - } -} - - - - - diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/LogTarget.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/LogTarget.cs deleted file mode 100644 index 1ac2277..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/LogTarget.cs +++ /dev/null @@ -1,110 +0,0 @@ -namespace IFoxCAD.Cad; -#region 写入日志到不同的环境中 - -/// -/// 日志输出环境 -/// -public enum LogTarget -{ - /// - /// 文件(包含错误和备注) - /// - File = 1, - /// - /// 文件(不包含错误,也就是只写备注信息) - /// - FileNotException = 2, - /// - /// 数据库 - /// - Database = 4, - /// - /// windows日志 - /// - EventLog = 8, -} -#endregion - - -#if false // 最简单的实现 -public static class Log -{ - /// - /// 读写锁 - /// 当资源处于写入模式时,其他线程写入需要等待本次写入结束之后才能继续写入 - /// - static readonly ReaderWriterLockSlim _logWriteLock = new(); - - /// - /// 日志文件完整路径 - /// - static readonly string _logAddress; - - static Log() - { - // 微软回复:静态构造函数只会被调用一次, - // 并且在它执行完成之前,任何其它线程都不能创建这个类的实例或使用这个类的静态成员 - // https://blog.csdn.net/weixin_34204722/article/details/90095812 - var sb = new StringBuilder(); - sb.Append(Environment.CurrentDirectory); - sb.Append("\\ErrorLog"); - - // 新建文件夹 - var path = sb.ToString(); - if (!Directory.Exists(path)) - { - Directory.CreateDirectory(path) - .Attributes = FileAttributes.Normal; // 设置文件夹属性为普通 - } - - sb.Append('\\'); - sb.Append(DateTime.Now.ToString("yy-MM-dd")); - sb.Append(".log"); - _logAddress = sb.ToString(); - } - - - /// - /// 将异常打印到日志文件 - /// - /// 异常 - /// 备注 - /// DEBUG模式打印到vs输出窗口 - public static string? WriteLog(this Exception? ex, - string? remarks = null, - bool printDebugWindow = true) - { - try - { - _logWriteLock.EnterWriteLock();// 写模式锁定 读写锁 - - var logtxt = new LogTxt(ex, remarks); - // var logtxtJson = Newtonsoft.Json.JsonConvert.SerializeObject(logtxt, Formatting.Indented); - var logtxtJson = logtxt.ToString(); - - if (logtxtJson == null) - return string.Empty; - - // 把异常信息输出到文件 - var sw = new StreamWriter(_logAddress, true/*当天日志文件存在就追加,否则就创建*/); - sw.Write(logtxtJson); - sw.Flush(); - sw.Close(); - sw.Dispose(); - - if (printDebugWindow) - { - Debugx.Printl("错误日志: " + _logAddress); - Debug.Write(logtxtJson); - // Debugger.Break(); - // Debug.Assert(false, "终止进程"); - } - return logtxtJson; - } - finally - { - _logWriteLock.ExitWriteLock();// 解锁 读写锁 - } - } -} -#endif \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/LogTxt.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/LogTxt.cs deleted file mode 100644 index fb98424..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/LogEx/LogTxt.cs +++ /dev/null @@ -1,60 +0,0 @@ -namespace IFoxCAD.Cad; - -using System; -using Exception = Exception; - - -#region 序列化 -[Serializable] -public class LogTxt -{ - public string? 当前时间; - public string? 备注信息; - public string? 异常信息; - public string? 异常对象; - public string? 触发方法; - public string? 调用堆栈; - - public LogTxt() { } - - public LogTxt(Exception? ex, string? message) : this() - { - if (ex == null && message == null) - throw new ArgumentNullException(nameof(ex)); - - // 以不同语言显示日期 - // DateTime.Now.ToString("f", new System.Globalization.CultureInfo("es-ES")) - // DateTime.Now.ToString("f", new System.Globalization.CultureInfo("zh-cn")) - // 为了最小信息熵,所以用这样的格式,并且我喜欢补0 - 当前时间 = DateTime.Now.ToString("yy-MM-dd hh:mm:ss"); - - if (ex != null) - { - 异常信息 = ex.Message; - 异常对象 = ex.Source; - 触发方法 = ex.TargetSite == null ? string.Empty : ex.TargetSite.ToString(); - 调用堆栈 = ex.StackTrace == null ? string.Empty : ex.StackTrace.Trim(); - } - if (message != null) - 备注信息 = message; - } - - /// 为了不引入json的dll,所以这里自己构造 - public override string? ToString() - { - var sb = new StringBuilder(); - sb.Append('{'); - sb.Append(Environment.NewLine); - sb.AppendLine($" \"{nameof(当前时间)}\": \"{当前时间}\""); - sb.AppendLine($" \"{nameof(备注信息)}\": \"{备注信息}\""); - sb.AppendLine($" \"{nameof(异常信息)}\": \"{异常信息}\""); - sb.AppendLine($" \"{nameof(异常对象)}\": \"{异常对象}\""); - sb.AppendLine($" \"{nameof(触发方法)}\": \"{触发方法}\""); - sb.AppendLine($" \"{nameof(调用堆栈)}\": \"{调用堆栈}\""); - sb.Append('}'); - return sb.ToString(); - } -} -#endregion - - diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs index f0ae5bb..a7db3be 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs @@ -42,8 +42,7 @@ public static void DeepCloneEx(this BlockTableRecord btr, ObjectIdCollection obj } catch (System.Exception e) { - LogHelper.FlagOutVsOutput = true; - e.WriteLog("深度克隆出错了"); + } } } diff --git a/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems b/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems index cc8992b..383e4a8 100644 --- a/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems +++ b/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems @@ -45,13 +45,6 @@ - - - - - - - -- Gitee From 2c69c355f117d3f271122f2a4c730cd873262401 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Sat, 1 Apr 2023 00:05:04 +0800 Subject: [PATCH 031/453] =?UTF-8?q?=E6=B5=8B=E8=AF=95=E5=90=8E=E5=8F=B0?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=96=87=E5=AD=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/TestShared/TestText.cs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/TestShared/TestText.cs b/tests/TestShared/TestText.cs index bc23dc9..11b19cb 100644 --- a/tests/TestShared/TestText.cs +++ b/tests/TestShared/TestText.cs @@ -17,6 +17,22 @@ public void TestDBText() }); } + [CommandMethod(nameof(TestBackDBText))] + public void TestBackDBText() + { + using var tr = new DBTrans(@"C:\Users\vic\Desktop\test.dwg"); + tr.CurrentSpace.AddDBText(new(-1, -1, 0), "123", 2.5, t => t.ColorIndex = 1); + + tr.CurrentSpace.AddDBText(new(0, 0, 0), "123", 2.5, t => { + t.Justify = AttachmentPoint.BaseCenter; + t.AlignmentPoint = new(1, 1, 0); + t.ColorIndex = 2; + }); + tr.SaveDwgFile(); + } + + + [CommandMethod(nameof(TestMText))] public void TestMText() { -- Gitee From 46abd9c828bee5ea607813271b794f7176e57930 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Sat, 1 Apr 2023 00:08:50 +0800 Subject: [PATCH 032/453] =?UTF-8?q?=E5=88=A0=E9=99=A4=E5=A4=9A=E4=BD=99?= =?UTF-8?q?=E7=9A=84tr=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/SelectionSetEx.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SelectionSetEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SelectionSetEx.cs index 0bf2af9..faee9ef 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SelectionSetEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SelectionSetEx.cs @@ -70,7 +70,6 @@ public static IEnumerable> GetObjectIdGroup(this Sel /// 指定类型 /// 选择集 /// 打开模式 - /// 事务 /// 是否打开已删除对象,默认为不打开 /// 是否打开锁定图层对象,默认为不打开 /// 图元集合 @@ -98,14 +97,12 @@ public static IEnumerable GetEntities(this SelectionSet ss, /// 选择集 /// 处理函数;(图元) /// 打开模式 - /// 事务 /// 是否打开已删除对象,默认为不打开 /// 是否打开锁定图层对象,默认为不打开 [System.Diagnostics.DebuggerStepThrough] public static void ForEach(this SelectionSet ss, Action action, OpenMode openMode = OpenMode.ForRead, - DBTrans? tr = default, bool openErased = false, bool openLockedLayer = false) where T : Entity { @@ -121,7 +118,6 @@ public static void ForEach(this SelectionSet ss, /// 选择集 /// 处理函数;(图元,终止方式) /// 打开模式 - /// 事务 /// 是否打开已删除对象,默认为不打开 /// 是否打开锁定图层对象,默认为不打开 /// -- Gitee From dd80b30b5979c632f8a7fa605d967045e3e2686b Mon Sep 17 00:00:00 2001 From: vicwjb Date: Tue, 4 Apr 2023 23:03:19 +0800 Subject: [PATCH 033/453] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BA=8B=E5=8A=A1?= =?UTF-8?q?=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../General/ArgumentNullEx.cs | 12 ++-- src/Basal/IFox.Basal/IFox.Basal.csproj | 7 ++ src/CAD/IFox.CAD.ACAD/IFox.CAD.ACAD.csproj | 7 ++ src/CAD/IFox.CAD.GCAD/IFox.CAD.GCAD.csproj | 7 ++ .../ExtensionMethod/DBDictionaryEx.cs | 21 +++--- .../ExtensionMethod/EditorEx.cs | 13 ++-- .../Entity/BlockReferenceEx.cs | 34 ++++++---- .../ExtensionMethod/Entity/PolylineEx.cs | 17 +++-- .../ExtensionMethod/ObjectIdEx.cs | 3 +- .../ExtensionMethod/RedrawEx.cs | 2 +- .../ExtensionMethod/SymbolTableRecordEx.cs | 11 ++- .../ExtensionMethod/TransactionEx.cs | 45 ++++++++++++ .../IFox.CAD.Shared/ExtensionMethod/XrefEx.cs | 2 +- .../IFox.CAD.Shared/IFox.CAD.Shared.projitems | 1 + src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs | 59 ++++++++++++---- .../IFox.CAD.Shared/Runtime/SymbolTable.cs | 8 ++- src/CAD/IFox.CAD.ZCAD/IFox.CAD.ZCAD.csproj | 7 ++ ...53\345\205\205\344\272\213\344\273\266.cs" | 2 +- tests/TestShared/TestAOP.cs | 68 ------------------- tests/TestShared/TestEditor.cs | 2 +- tests/TestShared/TestQuadTree.cs | 2 - tests/TestShared/TestShared.projitems | 1 - 22 files changed, 188 insertions(+), 143 deletions(-) create mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/TransactionEx.cs delete mode 100644 tests/TestShared/TestAOP.cs diff --git a/src/Basal/IFox.Basal.Shared/General/ArgumentNullEx.cs b/src/Basal/IFox.Basal.Shared/General/ArgumentNullEx.cs index b969143..75c779d 100644 --- a/src/Basal/IFox.Basal.Shared/General/ArgumentNullEx.cs +++ b/src/Basal/IFox.Basal.Shared/General/ArgumentNullEx.cs @@ -1,5 +1,7 @@  +using System.Diagnostics.CodeAnalysis; + namespace IFoxCAD.Basal { /// @@ -10,14 +12,12 @@ public static class ArgumentNullEx /// /// 检查参数是否为 null /// - /// 参数类型 - /// 参数 - /// 参数为null时的提示信息 + /// 参数 + /// 参数为null时的提示信息 /// - public static void NotNull(this T? argument, string? argumentExpression = null) + public static void NotNull([NotNull] this object? value, string valueExpression = "") { - if (argument == null) throw new ArgumentNullException(paramName: argumentExpression); + _ = value ?? throw new ArgumentNullException(nameof(value), valueExpression); } - } } diff --git a/src/Basal/IFox.Basal/IFox.Basal.csproj b/src/Basal/IFox.Basal/IFox.Basal.csproj index bb1713c..f5542ed 100644 --- a/src/Basal/IFox.Basal/IFox.Basal.csproj +++ b/src/Basal/IFox.Basal/IFox.Basal.csproj @@ -13,6 +13,13 @@ + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/src/CAD/IFox.CAD.ACAD/IFox.CAD.ACAD.csproj b/src/CAD/IFox.CAD.ACAD/IFox.CAD.ACAD.csproj index 46fc18e..f8a92bb 100644 --- a/src/CAD/IFox.CAD.ACAD/IFox.CAD.ACAD.csproj +++ b/src/CAD/IFox.CAD.ACAD/IFox.CAD.ACAD.csproj @@ -32,6 +32,13 @@ + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/src/CAD/IFox.CAD.GCAD/IFox.CAD.GCAD.csproj b/src/CAD/IFox.CAD.GCAD/IFox.CAD.GCAD.csproj index 506d96e..838bb41 100644 --- a/src/CAD/IFox.CAD.GCAD/IFox.CAD.GCAD.csproj +++ b/src/CAD/IFox.CAD.GCAD/IFox.CAD.GCAD.csproj @@ -29,6 +29,13 @@ + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBDictionaryEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBDictionaryEx.cs index 66fe217..d0ca018 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBDictionaryEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBDictionaryEx.cs @@ -10,7 +10,6 @@ public static class DBDictionaryEx /// /// 对象类型的泛型 /// 字典 - /// 事务 /// 对象迭代器 [System.Diagnostics.DebuggerStepThrough] public static IEnumerable GetAllObjects(this DBDictionary dict) where T : DBObject @@ -28,7 +27,6 @@ public static IEnumerable GetAllObjects(this DBDictionary dict) where T : /// /// 对象类型的泛型 /// 字典 - /// 事务 /// 指定的键值 /// T 类型的对象 public static T? GetAt(this DBDictionary dict, string key) where T : DBObject @@ -48,7 +46,6 @@ public static IEnumerable GetAllObjects(this DBDictionary dict) where T : /// /// 对象类型 /// 字典 - /// 事务 /// 键 /// 值 public static void SetAt(this DBDictionary dict, string key, T newValue) where T : DBObject @@ -58,7 +55,7 @@ public static void SetAt(this DBDictionary dict, string key, T newValue) wher using (dict.ForWrite()) { dict.SetAt(key, newValue); - tr.Transaction.AddNewlyCreatedDBObject(newValue, true); + tr.AddNewlyCreatedDBObject(newValue, true); } } @@ -97,12 +94,9 @@ public static void SetXRecord(this DBDictionary dict, string key, XRecordDataLis /// 获取扩展字典 /// /// 对象 - /// 事务 /// 扩展字典对象 - public static DBDictionary? GetXDictionary(this DBObject obj, DBTrans? trans = null) + public static DBDictionary? GetXDictionary(this DBObject obj) { - var tr = DBTrans.GetTopTransaction(obj.Database); - ObjectId id = obj.ExtensionDictionary; if (id.IsNull) { @@ -209,7 +203,6 @@ public static void SetValue(this DataCell cell, CellType type, object value) /// 获取子字典 /// /// 根字典 - /// 事务 /// 是否创建子字典 /// 键值列表 /// 字典 @@ -272,6 +265,7 @@ public static void SetValue(this DataCell cell, CellType type, object value) /// /// 添加编组 /// + /// 字典 /// 组名 /// 实体Id集合 /// 编组Id @@ -286,7 +280,7 @@ public static ObjectId AddGroup(this DBDictionary dict, string name, ObjectIdCol g.Append(ids); dict.SetAt(name, g); var tr = DBTrans.GetTopTransaction(dict.Database); - tr.Transaction.AddNewlyCreatedDBObject(g, true); + tr.AddNewlyCreatedDBObject(g, true); return g.ObjectId; } } @@ -294,6 +288,7 @@ public static ObjectId AddGroup(this DBDictionary dict, string name, ObjectIdCol /// /// 添加编组 /// + /// 字典 /// 组名 /// 实体Id集合 /// 编组Id @@ -310,6 +305,7 @@ public static ObjectId AddGroup(this DBDictionary dict, string name, IEnumerable /// /// 按选择条件获取编组集合 /// + /// 字典 /// 选择条件,过滤函数 /// g.NumEntities < 2);]]> /// 编组集合 @@ -352,8 +348,11 @@ public static List RemoveNullGroup(this DBDictionary dict) /// /// 移除所有空组 /// + /// /// 过滤条件,过滤要删除的组名的规则函数 - /// RemoveNullGroup(g => g.StartsWith("hah")) + /// + /// g.StartsWith("hah"));]]> + /// /// 被移除编组的名称集合 public static List RemoveNullGroup(this DBDictionary dict, Func func) { diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs index ffd9019..bf142b2 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs @@ -66,7 +66,7 @@ public static SelectionSet SelectByLineWeight(this Editor editor, LineWeight lin public static PromptSelectionResult SSGet(this Editor editor, string? mode = null, SelectionFilter? filter = null, - string[]? messages = null, + (string add, string remove)? messages = null, Dictionary? keywords = null) { PromptSelectionOptions pso = new(); @@ -87,8 +87,8 @@ public static PromptSelectionResult SSGet(this Editor editor, } if (messages is not null) { - pso.MessageForAdding = messages[0]; - pso.MessageForRemoval = messages[1]; + pso.MessageForAdding = messages.Value.add; + pso.MessageForRemoval = messages.Value.remove; } if (keywords is not null) @@ -99,8 +99,8 @@ public static PromptSelectionResult SSGet(this Editor editor, pso.MessageForAdding = "选择对象"; pso.MessageForAdding += $"[{string.Join(" / ", keywords.Keys.ToArray())}]"; pso.KeywordInput += (s, e) => { - if (keywords.ContainsKey(e.Input)) - keywords[e.Input].Invoke(); + if (keywords.TryGetValue(e.Input, out Action value)) + value.Invoke(); }; } try @@ -665,7 +665,8 @@ public static Matrix3d GetMatrixFromMDcsToPDcs(this Editor editor) throw new ArgumentException("TILEMODE == 1..Espace papier uniquement"); Matrix3d mat = Matrix3d.Identity; - using DBTrans tr = new(); + //using DBTrans tr = new(); + var tr = DBTrans.GetTopTransaction(editor.Document.Database); var vp = tr.GetObject(editor.CurrentViewportObjectId); if (vp == null) return mat; diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs index 218697b..0de0963 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs @@ -99,10 +99,14 @@ public static void ForEach(this BlockReference brf, Action action) // throw new ArgumentNullException(nameof(action)); action.NotNull(nameof(action)); var tr = DBTrans.GetTopTransaction(brf.Database); - var btr = tr.GetObject(brf.BlockTableRecord); - if (btr == null) - return; - btr.ForEach(action); + //var btr = tr.GetObject(brf.BlockTableRecord); + //if (btr == null) + // return; + //btr.ForEach(action); + if (tr.GetObject(brf.BlockTableRecord) is BlockTableRecord btr) + { + btr.ForEach(action); + } } /// /// 遍历块内 @@ -118,26 +122,30 @@ public static void ForEach(this BlockReference brf, Action // throw new ArgumentNullException(nameof(action)); action.NotNull(nameof(action)); var tr = DBTrans.GetTopTransaction(brf.Database); - var btr = tr.GetObject(brf.BlockTableRecord); - if (btr == null) - return; - btr.ForEach(action); + //var btr = tr.GetObject(brf.BlockTableRecord); + //if (btr == null) + // return; + //btr.ForEach(action); + if (tr.GetObject(brf.BlockTableRecord) is BlockTableRecord btr) + { + btr.ForEach(action); + } } /// /// 遍历块内 /// /// /// - /// /// [System.Diagnostics.DebuggerStepThrough] public static void ForEach(this BlockReference brf, Action action) { action.NotNull(nameof(action)); var tr = DBTrans.GetTopTransaction(brf.Database); - var btr = tr.GetObject(brf.BlockTableRecord); - if (btr == null) - return; - btr.ForEach(action); + if (tr.GetObject(brf.BlockTableRecord) is BlockTableRecord btr) + { + btr.ForEach(action); + } + } } \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/PolylineEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/PolylineEx.cs index 41aa787..b5de171 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/PolylineEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/PolylineEx.cs @@ -16,9 +16,13 @@ public static IEnumerable GetPoints(this Polyline2d pl2d) var tr = DBTrans.GetTopTransaction(pl2d.Database); foreach (ObjectId id in pl2d) { - var vertex = tr.GetObject(id, OpenMode.ForRead); - if (vertex != null) + //var vertex = tr.GetObject(id, OpenMode.ForRead); + //if (vertex != null) + // yield return vertex.Position; + if (tr.GetObject(id) is Vertex2d vertex) + { yield return vertex.Position; + } } } @@ -34,8 +38,8 @@ public static IEnumerable GetPoints(this Polyline3d pl3d) var tr = DBTrans.GetTopTransaction(pl3d.Database); foreach (ObjectId id in pl3d) { - var vertex = tr.GetObject(id); - if (vertex != null) + //var vertex = tr.GetObject(id); + if (tr.GetObject(id) is PolylineVertex3d vertex) yield return vertex.Position; } } @@ -45,11 +49,12 @@ public static IEnumerable GetPoints(this Polyline3d pl3d) /// /// 多段线 /// 端点坐标集合 - public static IEnumerable GetPoints(this Polyline pl) + public static List GetPoints(this Polyline pl) { return Enumerable .Range(0, pl.NumberOfVertices) - .Select(pl.GetPoint3dAt); + .Select(pl.GetPoint3dAt) + .ToList(); } } \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs index eb1f8ed..f5ebcb6 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs @@ -14,11 +14,10 @@ public static class ObjectIdEx /// 指定的泛型 /// 对象id /// 打开模式 - /// 事务 /// 是否打开已删除对象,默认为不打开 /// 是否打开锁定图层对象,默认为不打开 /// 指定类型对象 - public static T? GetObject(this ObjectId id, + public static T GetObject(this ObjectId id, OpenMode openMode = OpenMode.ForRead, bool openErased = false, bool openLockedLayer = false) where T : DBObject diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/RedrawEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/RedrawEx.cs index b0cb47b..c42ec5c 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/RedrawEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/RedrawEx.cs @@ -174,7 +174,7 @@ public static void Redraw(this Entity ent, BrightEntity bright) [Obsolete("此处已经被RedrawEx代替")] public static void Flush(this Entity entity) { - var tr = DBTrans.GetTopTransaction(entity.Database); + var tr = DBTrans.GetTop(entity.Database); entity.RecordGraphicsModified(true); tr.Transaction.TransactionManager.QueueForGraphicsFlush(); tr.Document?.TransactionManager.FlushGraphics(); diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs index a7db3be..7a959a3 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs @@ -68,7 +68,6 @@ public static void DeepCloneEx(this BlockTableRecord btr, ObjectIdCollection obj /// /// 块表记录 /// 实体 - /// 事务管理器 /// 对象 id public static ObjectId AddEntity(this BlockTableRecord btr, Entity entity) { @@ -80,7 +79,7 @@ public static ObjectId AddEntity(this BlockTableRecord btr, Entity entity) using (btr.ForWrite()) { id = btr.AppendEntity(entity); - tr.Transaction.AddNewlyCreatedDBObject(entity, true); + tr.AddNewlyCreatedDBObject(entity, true); } return id; @@ -104,7 +103,7 @@ public static IEnumerable AddEntity(this BlockTableRecord btr, IEnu { return ents.Select(ent => { ObjectId id = btr.AppendEntity(ent); - tr.Transaction.AddNewlyCreatedDBObject(ent, true); + tr.AddNewlyCreatedDBObject(ent, true); return id; }).ToList(); } @@ -366,7 +365,7 @@ public static IEnumerable> GetObjectIds(this BlockTa /// 是否打开已删除对象,默认为不打开 /// 是否打开锁定图层对象,默认为不打开 /// 绘制顺序表 - public static DrawOrderTable? GetDrawOrderTable(this BlockTableRecord btr, + public static DrawOrderTable GetDrawOrderTable(this BlockTableRecord btr, Transaction? trans = null, bool openErased = false, bool openLockedLayer = false) @@ -394,7 +393,7 @@ public static ObjectId InsertBlock(this BlockTableRecord blockTableRecord, Point double rotation = default, Dictionary? atts = null) { - var tr = DBTrans.GetTopTransaction(blockTableRecord.Database); + var tr = DBTrans.GetTop(blockTableRecord.Database); if (!tr.BlockTable.Has(blockName)) { tr.Editor?.WriteMessage($"\n不存在名字为{blockName}的块定义。"); @@ -419,7 +418,7 @@ public static ObjectId InsertBlock(this BlockTableRecord blockTableRecord, Dictionary? atts = null) { //trans ??= DBTrans.Top.Transaction; - var tr = DBTrans.GetTopTransaction(blockTableRecord.Database); + var tr = DBTrans.GetTop(blockTableRecord.Database); if (!tr.BlockTable.Has(blockId)) { diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/TransactionEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/TransactionEx.cs new file mode 100644 index 0000000..bafd5d1 --- /dev/null +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/TransactionEx.cs @@ -0,0 +1,45 @@ +using System.Diagnostics.CodeAnalysis; + +namespace IFoxCAD.Cad +{ + /// + /// cad的事务的扩展类 + /// + public static class TransactionEx + { + /// + /// 根据对象id获取对象 + /// + /// + /// 对象id + /// 打开模式,默认为只读 + /// 是否打开已删除对象,默认为不打开 + /// 是否打开锁定图层对象,默认为不打开 + /// 数据库DBObject对象 + public static DBObject GetObject([DisallowNull] this Transaction tr, ObjectId id, + OpenMode openMode = OpenMode.ForRead, + bool openErased = false, + bool openLockedLayer = false) + { + return tr.GetObject(id, openMode, openErased, openLockedLayer); + } + /// + /// 根据对象id获取图元对象 + /// + /// 要获取的图元对象的类型 + /// + /// 对象id + /// 打开模式,默认为只读 + /// 是否打开已删除对象,默认为不打开 + /// 是否打开锁定图层对象,默认为不打开 + /// 图元对象,类型不匹配时抛异常 + public static T GetObject([DisallowNull] this Transaction tr, ObjectId id, + OpenMode openMode = OpenMode.ForRead, + bool openErased = false, + bool openLockedLayer = false) where T : DBObject + { + return tr.GetObject(id, openMode, openErased, openLockedLayer) as T + ?? throw new ArgumentNullException(nameof(T), $"你传入的 id 不能转换为 {nameof(T)} 类型"); + } + } +} diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/XrefEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/XrefEx.cs index 5706251..9d2e1b1 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/XrefEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/XrefEx.cs @@ -573,7 +573,7 @@ static string GetRelativePath(string directory, string file) if (result.Length == 0) result.Append(".\\"); // result.Append(strXrefPaths[^1]);// 下级目录加入 - result.Append(files[files.Length - 1]);// 下级目录加入 + result.Append(files[^1]);// 下级目录加入 return result.ToString(); } #endif diff --git a/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems b/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems index 383e4a8..13b7df2 100644 --- a/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems +++ b/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems @@ -52,6 +52,7 @@ + diff --git a/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs b/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs index b4ada8f..5e3ae02 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs @@ -2,6 +2,7 @@ namespace IFoxCAD.Cad; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Threading; using System.Windows.Forms; @@ -23,7 +24,31 @@ public class DBTrans : IDisposable /// /// 数据库 /// 事务对象 - public static DBTrans GetTopTransaction(Database database) + public static Transaction GetTopTransaction([DisallowNull] Database database) + { + + var tr = database.TransactionManager.TopTransaction; + if (tr is not null) + { + return tr; + + } +#if acad + throw new Autodesk.AutoCAD.Runtime.Exception(ErrorStatus.NoActiveTransactions); +#elif zcad + throw new ZwSoft.ZwCAD.Runtime.Exception(ErrorStatus.NoActiveTransactions); +#elif gcad + throw new GrxCAD.Runtime.Exception(ErrorStatus.NoActiveTransactions); +#endif + } + + /// + /// 获取给点数据库的顶层 DBTrans 事务 + /// + /// 数据库 + /// DBTrans 事务 + /// + public static DBTrans GetTop(Database database) { database.NotNull(nameof(database)); var trans = database.TransactionManager.TopTransaction; @@ -37,9 +62,11 @@ public static DBTrans GetTopTransaction(Database database) } } // 匹配事务栈内dbtrans的transaction的指针与数据库的顶层事务的指针 + return Top; + } - #endregion +#endregion #region 私有字段 /// @@ -94,7 +121,7 @@ public static DBTrans Top return trans; } } - + /// @@ -386,7 +413,7 @@ public static implicit operator Transaction(DBTrans tr) public DBDictionary SectionViewStyleDict => GetObject(Database.SectionViewStyleDictionaryId)!; #endif - #endregion +#endregion #region 获取对象 /// @@ -412,7 +439,7 @@ public DBObject GetObject(ObjectId id, /// 打开模式,默认为只读 /// 是否打开已删除对象,默认为不打开 /// 是否打开锁定图层对象,默认为不打开 - /// 图元对象,类型不匹配时返回 + /// 图元对象,类型不匹配时抛异常 public T GetObject(ObjectId id, OpenMode openMode = OpenMode.ForRead, bool openErased = false, @@ -737,16 +764,18 @@ public string ToString(IFormatProvider? provider) } public string ToString(string? format = null, IFormatProvider? formatProvider = null) { - List lines = new(); - lines.Add($"StackCount = {_dBTrans.Count}"); - lines.Add($"_fileName = \"{_fileName}\""); - lines.Add($"_commit = {_commit}"); - lines.Add($"_documentLock = {_documentLock != null}"); - - lines.Add($"Document = {Document != null}"); - lines.Add($"Editor = {Editor != null}"); - lines.Add($"Transaction = {Transaction != null}"); - lines.Add($"Database = {Database != null}"); + List lines = new() + { + $"StackCount = {_dBTrans.Count}", + $"_fileName = \"{_fileName}\"", + $"_commit = {_commit}", + $"_documentLock = {_documentLock != null}", + + $"Document = {Document != null}", + $"Editor = {Editor != null}", + $"Transaction = {Transaction != null}", + $"Database = {Database != null}" + }; if (!string.IsNullOrEmpty(format)) return string.Join(format, lines.ToArray()); diff --git a/src/CAD/IFox.CAD.Shared/Runtime/SymbolTable.cs b/src/CAD/IFox.CAD.Shared/Runtime/SymbolTable.cs index 22fadac..b411504 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/SymbolTable.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/SymbolTable.cs @@ -1,7 +1,9 @@ -//using static System.Windows.Forms.AxHost; - namespace IFoxCAD.Cad; - +/// +/// 符号表管理类 +/// +/// 符号表 +/// 符号表记录 public class SymbolTable : IEnumerable where TTable : SymbolTable where TRecord : SymbolTableRecord, new() diff --git a/src/CAD/IFox.CAD.ZCAD/IFox.CAD.ZCAD.csproj b/src/CAD/IFox.CAD.ZCAD/IFox.CAD.ZCAD.csproj index e99b5ef..a810b27 100644 --- a/src/CAD/IFox.CAD.ZCAD/IFox.CAD.ZCAD.csproj +++ b/src/CAD/IFox.CAD.ZCAD/IFox.CAD.ZCAD.csproj @@ -28,6 +28,13 @@ + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git "a/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/02.\346\213\211\344\274\270\345\241\253\345\205\205\344\272\213\344\273\266.cs" "b/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/02.\346\213\211\344\274\270\345\241\253\345\205\205\344\272\213\344\273\266.cs" index b4535b1..8da9e57 100644 --- "a/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/02.\346\213\211\344\274\270\345\241\253\345\205\205\344\272\213\344\273\266.cs" +++ "b/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/02.\346\213\211\344\274\270\345\241\253\345\205\205\344\272\213\344\273\266.cs" @@ -501,7 +501,7 @@ void Md_ImpliedSelectionChanged(object sender, EventArgs e) void CreatHatchConverter(Hatch hatch, HashSet outSsgetIds) { //tr ??= DBTrans.Top; - var tr = DBTrans.GetTopTransaction(hatch.Database); + var tr = DBTrans.GetTop(hatch.Database); var hc = new HatchConverter(hatch); ObjectId newid; diff --git a/tests/TestShared/TestAOP.cs b/tests/TestShared/TestAOP.cs deleted file mode 100644 index 872bf35..0000000 --- a/tests/TestShared/TestAOP.cs +++ /dev/null @@ -1,68 +0,0 @@ -namespace Test; - -// 被注入的函数将不能使用断点, -// 因此用户要充分了解才能使用 -#if false -/* - * 类库用户想侵入的命名空间是用户的, - * 所以需要用户手动进行AOP.Run(), - * 默认情况不侵入用户的命令,必须用户手动启用此功能; - * 启动执行策略之后,侵入命名空间下的命令, - * 此时有拒绝特性的策略保证豁免,因为用户肯定是想少写一个事务注入的特性; - */ -public class AutoAOP -{ - [IFoxInitialize] - public void Initialize() - { - AOP.Run(nameof(Test_)); - } -} - -namespace Test -{ - /* - * 天秀的事务注入,让你告别事务处理 - * https://www.cnblogs.com/JJBox/p/16157578.html - */ - public class AopTestClass - { - // 类不拒绝,这里拒绝 - [IFoxRefuseInjectionTransaction] - [CommandMethod(nameof(IFoxRefuseInjectionTransaction))] - public void IFoxRefuseInjectionTransaction() - { - } - - // 不拒绝 - [CommandMethod(nameof(InjectionTransaction))] - public void InjectionTransaction() - { - // 怎么用事务呢? - // 直接用 DBTrans.Top - var dBTrans = new DBTrans(); - dBTrans.Commit(); - } - } - - // 拒绝注入事务,写类上,则方法全都拒绝 - [IFoxRefuseInjectionTransaction] - public class AopTestClassRefuseInjection - { - // 此时这个也是拒绝的..这里加特性只是无所谓 - [IFoxRefuseInjectionTransaction] - [CommandMethod(nameof(IFoxRefuseInjectionTransaction2))] - public void IFoxRefuseInjectionTransaction2() - { - // 拒绝注入就要自己开事务,通常用在循环提交事务上面. - // 另见 报错0x02 https://www.cnblogs.com/JJBox/p/10798940.html - using DBTrans tr = new(); - } - - [CommandMethod(nameof(InjectionTransaction2))] - public void InjectionTransaction2() - { - } - } -} -#endif \ No newline at end of file diff --git a/tests/TestShared/TestEditor.cs b/tests/TestShared/TestEditor.cs index 656ddaa..ed45db3 100644 --- a/tests/TestShared/TestEditor.cs +++ b/tests/TestShared/TestEditor.cs @@ -56,7 +56,7 @@ public void Test_Ssget() { "B", action_b } }; - var ss = Env.Editor.SSGet(":S", messages: new string[2] { "get", "del" }, + var ss = Env.Editor.SSGet(":S", messages: ("get", "del" ), keywords: keyword); Env.Print(ss!); } diff --git a/tests/TestShared/TestQuadTree.cs b/tests/TestShared/TestQuadTree.cs index 74cd52d..fc87b9a 100644 --- a/tests/TestShared/TestQuadTree.cs +++ b/tests/TestShared/TestQuadTree.cs @@ -1,6 +1,5 @@ namespace Test; -#pragma warning disable CS8632 // 只能在 "#nullable" 注释上下文内的代码中使用可为 null 的引用类型的注释。 /* * 这里属于用户调用例子, * 调用时候必须要继承它,再提供给四叉树 @@ -28,7 +27,6 @@ public override int GetHashCode() return (base.GetHashCode(), ObjectId.GetHashCode()).GetHashCode(); } } -#pragma warning restore CS8632 // 只能在 "#nullable" 注释上下文内的代码中使用可为 null 的引用类型的注释。 diff --git a/tests/TestShared/TestShared.projitems b/tests/TestShared/TestShared.projitems index edbd45b..0581627 100644 --- a/tests/TestShared/TestShared.projitems +++ b/tests/TestShared/TestShared.projitems @@ -12,7 +12,6 @@ - -- Gitee From 338763fc713ef565753f553ba8eca99de8e20955 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Tue, 4 Apr 2023 23:12:58 +0800 Subject: [PATCH 034/453] =?UTF-8?q?=E4=BC=98=E5=8C=96GetTopTransaction?= =?UTF-8?q?=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Basal/Directory.Build.props | 2 +- src/CAD/Directory.Build.props | 2 +- src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs | 17 ++++------------- src/CAD/IFox.CAD.Shared/Runtime/SymbolTable.cs | 1 + 4 files changed, 7 insertions(+), 15 deletions(-) diff --git a/src/Basal/Directory.Build.props b/src/Basal/Directory.Build.props index fcc6dc4..0b335fd 100644 --- a/src/Basal/Directory.Build.props +++ b/src/Basal/Directory.Build.props @@ -1,7 +1,7 @@  - 0.6.0-alpha1 + 0.6.0-alpha2 发布个alpha版 diff --git a/src/CAD/Directory.Build.props b/src/CAD/Directory.Build.props index b89f89a..3460c56 100644 --- a/src/CAD/Directory.Build.props +++ b/src/CAD/Directory.Build.props @@ -1,7 +1,7 @@  - 0.6.0-alpha1 + 0.6.0-alpha2 发布个alpha版 diff --git a/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs b/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs index 5e3ae02..0b12c1d 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs @@ -26,20 +26,11 @@ public class DBTrans : IDisposable /// 事务对象 public static Transaction GetTopTransaction([DisallowNull] Database database) { - - var tr = database.TransactionManager.TopTransaction; - if (tr is not null) + return database.TransactionManager.TopTransaction switch { - return tr; - - } -#if acad - throw new Autodesk.AutoCAD.Runtime.Exception(ErrorStatus.NoActiveTransactions); -#elif zcad - throw new ZwSoft.ZwCAD.Runtime.Exception(ErrorStatus.NoActiveTransactions); -#elif gcad - throw new GrxCAD.Runtime.Exception(ErrorStatus.NoActiveTransactions); -#endif + Transaction tr => tr, + _ => throw new Exception("没有顶层事务!") + }; } /// diff --git a/src/CAD/IFox.CAD.Shared/Runtime/SymbolTable.cs b/src/CAD/IFox.CAD.Shared/Runtime/SymbolTable.cs index b411504..1e5a121 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/SymbolTable.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/SymbolTable.cs @@ -390,6 +390,7 @@ public void ForEach(Action task, i++; } } +/// #line default #endregion -- Gitee From 5a112c2e9f5629ba3abe782411849439504b537b Mon Sep 17 00:00:00 2001 From: vicwjb Date: Sun, 9 Apr 2023 23:17:15 +0800 Subject: [PATCH 035/453] =?UTF-8?q?GetExtents=E5=A2=9E=E5=8A=A0=E6=A3=80?= =?UTF-8?q?=E6=B5=8B=E5=AF=B9=E8=B1=A1=E6=98=AF=E5=90=A6=E6=9C=89=E5=8C=85?= =?UTF-8?q?=E5=9B=B4=E7=9B=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityEx.cs | 3 ++- src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityEx.cs index 65f7ee4..9186a1c 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityEx.cs @@ -99,7 +99,8 @@ public static Extents3d GetExtents(this IEnumerable ents) var ext = new Extents3d(); foreach (var item in ents) { - ext.AddExtents(item.GeometricExtents); + if (item.Bounds.HasValue) + ext.AddExtents(item.GeometricExtents); } return ext; } diff --git a/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs b/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs index 0b12c1d..9ebd444 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs @@ -34,7 +34,7 @@ public static Transaction GetTopTransaction([DisallowNull] Database database) } /// - /// 获取给点数据库的顶层 DBTrans 事务 + /// 获取给定数据库的顶层 DBTrans 事务 /// /// 数据库 /// DBTrans 事务 -- Gitee From 909c832456c1402345942a5bd7762593c373999d Mon Sep 17 00:00:00 2001 From: vicwjb Date: Mon, 10 Apr 2023 00:10:23 +0800 Subject: [PATCH 036/453] =?UTF-8?q?=E4=B8=BA=E4=BA=86=E5=9B=9B=E4=BB=A3?= =?UTF-8?q?=E7=9B=AE=EF=BC=8C=E6=8A=8Aadd=E5=87=BD=E6=95=B0=E5=88=A0?= =?UTF-8?q?=E6=8E=89=E5=88=A0=E6=8E=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Entity/BlockReferenceEx.cs | 14 -- .../ExtensionMethod/Entity/DBTextEx.cs | 16 -- .../ExtensionMethod/Entity/MTextEx.cs | 19 -- .../ExtensionMethod/Entity/PolylineEx.cs | 53 ++++- .../ExtensionMethod/SymbolTableRecordEx.cs | 209 +----------------- tests/TestShared/TestAddEntity.cs | 6 +- tests/TestShared/TestDBTrans.cs | 6 +- tests/TestShared/TestExtents.cs | 6 +- tests/TestShared/TestQuadTree.cs | 2 +- tests/TestShared/TestText.cs | 27 +-- 10 files changed, 74 insertions(+), 284 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs index 0de0963..7576e5f 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs @@ -90,19 +90,12 @@ public static void ChangeBlockProperty(this BlockReference blockReference, /// /// /// - /// /// [System.Diagnostics.DebuggerStepThrough] public static void ForEach(this BlockReference brf, Action action) { - //if (action == null) - // throw new ArgumentNullException(nameof(action)); action.NotNull(nameof(action)); var tr = DBTrans.GetTopTransaction(brf.Database); - //var btr = tr.GetObject(brf.BlockTableRecord); - //if (btr == null) - // return; - //btr.ForEach(action); if (tr.GetObject(brf.BlockTableRecord) is BlockTableRecord btr) { btr.ForEach(action); @@ -113,19 +106,12 @@ public static void ForEach(this BlockReference brf, Action action) /// /// /// - /// /// [System.Diagnostics.DebuggerStepThrough] public static void ForEach(this BlockReference brf, Action action) { - //if (action == null) - // throw new ArgumentNullException(nameof(action)); action.NotNull(nameof(action)); var tr = DBTrans.GetTopTransaction(brf.Database); - //var btr = tr.GetObject(brf.BlockTableRecord); - //if (btr == null) - // return; - //btr.ForEach(action); if (tr.GetObject(brf.BlockTableRecord) is BlockTableRecord btr) { btr.ForEach(action); diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/DBTextEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/DBTextEx.cs index ddc9ac9..1f8105f 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/DBTextEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/DBTextEx.cs @@ -39,22 +39,6 @@ public static DBText CreateDBText(Point3d position, string text, double height, return acText; } - /// - /// 添加单行文字到块表记录 - /// - /// 块表记录 - /// 插入点 - /// 文本内容 - /// 文字高度 - /// 文字属性设置委托 - /// 文字对象id - /// - public static ObjectId AddDBText(this BlockTableRecord btr, Point3d position, string text, double height, Action? action = null) - { - var acText = CreateDBText(position, text, height, btr.Database, action); - return btr.AddEntity(acText); - } - /// /// 更正单行文字的镜像属性 /// diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/MTextEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/MTextEx.cs index 1a27abd..6cbaf08 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/MTextEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/MTextEx.cs @@ -34,25 +34,6 @@ public static MText CreateMText(Point3d position, string text, double height, Da return mText; } - - /// - /// 添加多行文字到块表记录 - /// - /// 块表记录 - /// 插入点 - /// 文本内容 - /// 文字高度 - /// 文字属性设置委托 - /// 文字对象id - /// - public static ObjectId AddMText(this BlockTableRecord btr, Point3d position, string text, double height, Action? action = null) - { - var mText = CreateMText(position, text, height, btr.Database, action); - - return btr.AddEntity(mText); - } - - /// /// 炸散多行文字 /// diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/PolylineEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/PolylineEx.cs index b5de171..fde2f72 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/PolylineEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/PolylineEx.cs @@ -1,24 +1,24 @@ -namespace IFoxCAD.Cad; +using System; +using System.Data.SqlTypes; + +namespace IFoxCAD.Cad; /// /// 多段线扩展类 /// public static class PolylineEx { + #region 获取多段线端点 /// /// 获取二维多段线的端点坐标 /// /// 二维多段线 - /// 事务 /// 端点坐标集合 public static IEnumerable GetPoints(this Polyline2d pl2d) { var tr = DBTrans.GetTopTransaction(pl2d.Database); foreach (ObjectId id in pl2d) { - //var vertex = tr.GetObject(id, OpenMode.ForRead); - //if (vertex != null) - // yield return vertex.Position; if (tr.GetObject(id) is Vertex2d vertex) { yield return vertex.Position; @@ -38,7 +38,6 @@ public static IEnumerable GetPoints(this Polyline3d pl3d) var tr = DBTrans.GetTopTransaction(pl3d.Database); foreach (ObjectId id in pl3d) { - //var vertex = tr.GetObject(id); if (tr.GetObject(id) is PolylineVertex3d vertex) yield return vertex.Position; } @@ -57,4 +56,46 @@ public static List GetPoints(this Polyline pl) .Select(pl.GetPoint3dAt) .ToList(); } + #endregion + + #region 创建多段线 + /// + /// 根据点集创建多段线
+ /// 此多段线无默认全局宽度0,无圆弧段 + ///
+ /// 点集 + /// 是否闭合 + /// 多段线对象 + public static Polyline CreatePolyline(this IEnumerable points, Action? action = null) + { + Polyline pl = new(); + pl.SetDatabaseDefaults(); + points.ForEach((pt, state, index) => { + pl.AddVertexAt(index, pt.Point2d(), 0, 0, 0); + }); + action?.Invoke(pl); + return pl; + } + + /// + /// 根据点集创建多段线 + /// + /// 端点表,利用元组(Point3d pt, double bulge, double startWidth, double endWidth) + /// 轻多段线属性设置委托 + /// 轻多段线对象 + public static Polyline CreatePolyline(this IEnumerable<(Point3d pt, double bulge, double startWidth, double endWidth)> pts, + Action? action = null) + { + Polyline pl = new(); + pl.SetDatabaseDefaults(); + + pts.ForEach((vertex, state, index) => { + pl.AddVertexAt(index, vertex.pt.Point2d(), vertex.bulge, vertex.startWidth, vertex.endWidth); + }); + action?.Invoke(pl); + return pl; + } + + #endregion + } \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs index 7a959a3..3884bfc 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs @@ -47,19 +47,6 @@ public static void DeepCloneEx(this BlockTableRecord btr, ObjectIdCollection obj } } - /// - /// 克隆图元实体(这个函数有问题,会出现偶尔成功,偶尔失败,拖动过变成匿名块) - /// 若为块则进行设置属性,因此控制动态块属性丢失; - /// - /// 图元 - /// 矩阵 - // public static void EntityTransformedCopy(this Entity ent, Matrix3d matrix) - // { - // var entNew = ent.GetTransformedCopy(matrix); - // if (ent is BlockReference blockReference) - // entNew.SetPropertiesFrom(blockReference); - // } - #endregion #region 添加实体 @@ -71,8 +58,6 @@ public static void DeepCloneEx(this BlockTableRecord btr, ObjectIdCollection obj /// 对象 id public static ObjectId AddEntity(this BlockTableRecord btr, Entity entity) { - // if (entity is null) - // throw new ArgumentNullException(nameof(entity), "对象为 null"); ObjectId id; var tr = DBTrans.GetTopTransaction(btr.Database); @@ -91,12 +76,9 @@ public static ObjectId AddEntity(this BlockTableRecord btr, Entity entity) /// 实体类型 /// 块表记录 /// 实体集合 - /// 事务 /// 对象 id 列表 public static IEnumerable AddEntity(this BlockTableRecord btr, IEnumerable ents) where T : Entity { - // if (ents.Any(ent => ent is null)) - // throw new ArgumentNullException(nameof(ents), "实体集合内存在 null 对象"); var tr = DBTrans.GetTopTransaction(btr.Database); using (btr.ForWrite()) @@ -121,193 +103,6 @@ public static IEnumerable AddEntity(this BlockTableRecord btr, params } #endregion - #region 添加图元 - /// - /// 在指定绘图空间添加图元 - /// - /// 图元类型 - /// 绘图空间 - /// 图元对象 - /// 图元属性设置委托 - /// 事务管理器 - /// 图元id - private static ObjectId AddEnt(this BlockTableRecord btr, T ent, - Action? action) where T : Entity - { - action?.Invoke(ent); - return btr.AddEntity(ent); - } - /// - /// 委托式的添加图元 - /// - /// 块表 - /// 返回图元的委托 - /// 事务 - /// 图元id,如果委托返回 null,则为 ObjectId.Null - public static ObjectId AddEnt(this BlockTableRecord btr, Func action, Transaction? trans = null) - { - var ent = action.Invoke(); - if (ent is null) - return ObjectId.Null; - - return btr.AddEntity(ent); - } - - /// - /// 在指定绘图空间添加直线 - /// - /// 事务管理器 - /// 起点 - /// 终点 - /// 绘图空间 - /// 直线属性设置委托 - /// 直线的id - public static ObjectId AddLine(this BlockTableRecord btr, Point3d start, Point3d end, - Action? action = null) - { - var line = new Line(start, end); - return btr.AddEnt(line, action); - } - /// - /// 在指定绘图空间X-Y平面添加圆 - /// - /// 绘图空间 - /// 圆心 - /// 半径 - /// 圆属性设置委托 - /// 事务管理器 - /// 圆的id - public static ObjectId AddCircle(this BlockTableRecord btr, Point3d center, double radius, - Action? action = null, Transaction? trans = null) - { - var circle = new Circle(center, Vector3d.ZAxis, radius); - return btr.AddEnt(circle, action); - } - - /// - /// 在指定绘图空间X-Y平面3点画外接圆 - /// - /// 绘图空间 - /// 第一点 - /// 第二点 - /// 第三点 - /// 圆属性设置委托 - /// 事务管理器 - /// 三点有外接圆则返回圆的id,否则返回ObjectId.Null - public static ObjectId AddCircle(this BlockTableRecord btr, Point3d p0, Point3d p1, Point3d p2, - Action? action = null) - { - var circle = CircleEx.CreateCircle(p0, p1, p2); - // return circle is not null ? btr.AddEnt(circle, action, trans) : throw new ArgumentNullException(nameof(circle), "对象为 null"); - //if (circle is null) - // throw new ArgumentNullException(nameof(circle), "对象为 null"); - circle.NotNull(nameof(circle)); - return btr.AddEnt(circle, action); - } - /// - /// 在指定的绘图空间添加轻多段线 - /// - /// 绘图空间 - /// 多段线信息 - /// 线宽 - /// 是否闭合 - /// 轻多段线属性设置委托 - /// 事务管理器 - /// 轻多段线id - public static ObjectId AddPline(this BlockTableRecord btr, - List bvws, - double? constantWidth = null, - bool isClosed = true, - Action? action = null, Transaction? trans = null) - { - Polyline pl = new(); - pl.SetDatabaseDefaults(); - if (constantWidth is not null) - { - for (int i = 0; i < bvws.Count; i++) - pl.AddVertexAt(i, bvws[i].Vertex, bvws[i].Bulge, constantWidth.Value, constantWidth.Value); - } - else - { - for (int i = 0; i < bvws.Count; i++) - pl.AddVertexAt(i, bvws[i].Vertex, bvws[i].Bulge, bvws[i].StartWidth, bvws[i].EndWidth); - } - pl.Closed = isClosed;// 闭合 - return btr.AddEnt(pl, action); - } - /// - /// 在指定的绘图空间添加轻多段线 - /// - /// 绘图空间 - /// 端点表 - /// 凸度表 - /// 端点的起始宽度 - /// 端点的终止宽度 - /// 轻多段线属性设置委托 - /// 事务管理器 - /// 轻多段线id - public static ObjectId AddPline(this BlockTableRecord btr, - List pts, - List? bulges = null, - List? startWidths = null, - List? endWidths = null, - Action? action = null, - Transaction? trans = null) - { - bulges ??= new(new double[pts.Count]); - startWidths ??= new(new double[pts.Count]); - endWidths ??= new(new double[pts.Count]); - - Polyline pl = new(); - pl.SetDatabaseDefaults(); - - for (int i = 0; i < pts.Count; i++) - pl.AddVertexAt(i, pts[i].Point2d(), bulges[i], startWidths[i], endWidths[i]); - return btr.AddEnt(pl, action); - } - - /// - /// 在指定的绘图空间添加轻多段线 - /// - /// 绘图空间 - /// 端点表,利用元组(Point3d pt, double bulge, double startWidth, double endWidth) - /// 轻多段线属性设置委托 - /// 事务管理器 - /// 轻多段线id - public static ObjectId AddPline(this BlockTableRecord btr, - List<(Point3d pt, double bulge, double startWidth, double endWidth)> pts, - Action? action = null, - Transaction? trans = null) - { - Polyline pl = new(); - pl.SetDatabaseDefaults(); - - pts.ForEach((vertex, state, index) => { - pl.AddVertexAt(index, vertex.pt.Point2d(), vertex.bulge, vertex.startWidth, vertex.endWidth); - }); - - return btr.AddEnt(pl, action); - } - - /// - /// 在指定绘图空间X-Y平面3点画圆弧 - /// - /// 绘图空间 - /// 圆弧起点 - /// 圆弧上的点 - /// 圆弧终点 - /// 圆弧属性设置委托 - /// 事务管理器 - /// 圆弧id - public static ObjectId AddArc(this BlockTableRecord btr, - Point3d startPoint, Point3d pointOnArc, Point3d endPoint, - Action? action = null, Transaction? trans = null) - { - var arc = ArcEx.CreateArc(startPoint, pointOnArc, endPoint); - return btr.AddEnt(arc, action); - } - #endregion - #region 获取实体/实体id /// /// 获取块表记录内的指定类型的实体 @@ -316,7 +111,6 @@ public static ObjectId AddArc(this BlockTableRecord btr, /// 实体类型 /// 块表记录 /// 打开模式 - /// 事务 /// 是否打开已删除对象,默认为不打开 /// 是否打开锁定图层对象,默认为不打开 /// 实体集合 @@ -467,6 +261,7 @@ public static ObjectId InsertBlock(this BlockTableRecord blockTableRecord, /// /// 遍历符号表记录,执行委托 /// + /// 符号表记录 /// 要运行的委托 public static void ForEach(this TRecord record, Action task) where TRecord : SymbolTableRecord, IEnumerable @@ -478,6 +273,7 @@ public static void ForEach(this TRecord record, Action task) /// /// 遍历符号表记录,执行委托(允许循环中断) /// + /// 符号表记录 /// 要执行的委托 public static void ForEach(this TRecord record, Action task) where TRecord : SymbolTableRecord, IEnumerable @@ -494,6 +290,7 @@ public static void ForEach(this TRecord record, Action /// 遍历符号表记录,执行委托(允许循环中断,输出索引值) /// + /// 符号表记录 /// 要执行的委托 [System.Diagnostics.DebuggerStepThrough] public static void ForEach(this TRecord record, Action task) diff --git a/tests/TestShared/TestAddEntity.cs b/tests/TestShared/TestAddEntity.cs index 8d374c9..774ffb9 100644 --- a/tests/TestShared/TestAddEntity.cs +++ b/tests/TestShared/TestAddEntity.cs @@ -58,7 +58,6 @@ public void Test_Drawarc() Arc arc2 = ArcEx.CreateArc(new Point3d(4, 0, 0), new Point3d(0, 0, 0), Math.PI / 2); // 起点,圆心,弧度 Arc arc3 = ArcEx.CreateArc(new Point3d(1, 0, 0), new Point3d(0, 0, 0), new Point3d(0, 1, 0)); // 起点,圆上一点,终点 tr.CurrentSpace.AddEntity(arc1, arc2, arc3); - tr.CurrentSpace.AddArc(new Point3d(0, 0, 0), new Point3d(1, 1, 0), new Point3d(2, 0, 0));// 起点,圆上一点,终点 } @@ -75,8 +74,6 @@ public void Test_DrawCircle() else tr.Editor?.WriteMessage("三点画圆失败"); tr.CurrentSpace.AddEntity(circle3!); - tr.CurrentSpace.AddCircle(new Point3d(0, 0, 0), new Point3d(1, 1, 0), new Point3d(2, 0, 0));// 三点画圆,成功 - tr.CurrentSpace.AddCircle(new Point3d(0, 0, 0), new Point3d(1, 1, 0), new Point3d(2, 2, 0));// 起点,圆上一点,终点(共线) } [CommandMethod(nameof(Test_LayerAdd0))] @@ -183,7 +180,8 @@ public void Test_AddPolyline2() (new Point3d(5,5,0),0,0,0) }; using DBTrans tr = new(); - tr.CurrentSpace.AddPline(pts); + var pl = pts.CreatePolyline(); + tr.CurrentSpace.AddEntity(pl); } diff --git a/tests/TestShared/TestDBTrans.cs b/tests/TestShared/TestDBTrans.cs index 0dc6050..2c6c77a 100644 --- a/tests/TestShared/TestDBTrans.cs +++ b/tests/TestShared/TestDBTrans.cs @@ -94,7 +94,8 @@ public void Test_SaveDwgFile() { string filename = @"C:\Users\vic\Desktop\test.dwg"; using DBTrans tr = new(filename); - tr.ModelSpace.AddCircle(new Point3d(10, 10, 0), 20); + var circle = CircleEx.CreateCircle(new Point3d(10, 10, 0), 20)!; + tr.ModelSpace.AddEntity(circle); // tr.Database.SaveAs(filename,DwgVersion.Current); tr.SaveDwgFile(); } @@ -102,7 +103,8 @@ public void Test_SaveDwgFile() public void Test_DBTransAbort() { using DBTrans tr = new(); - tr.ModelSpace.AddCircle(new Point3d(0, 0, 0), 20); + var circle = CircleEx.CreateCircle(new Point3d(10, 10, 0), 20)!; + tr.ModelSpace.AddEntity(circle); tr.Abort(); // tr.Commit(); } diff --git a/tests/TestShared/TestExtents.cs b/tests/TestShared/TestExtents.cs index 0eb0cc7..da59ebd 100644 --- a/tests/TestShared/TestExtents.cs +++ b/tests/TestShared/TestExtents.cs @@ -26,7 +26,7 @@ public void TestBlockExtents() }; - tr.CurrentSpace.AddPline(pts, action: e => e.ColorIndex = 1); + tr.CurrentSpace.AddEntity(pts.CreatePolyline(action: e => e.ColorIndex = 1)); if (block is BlockReference block1) { var extents = block1.GeometryExtentsBestFit(); @@ -35,10 +35,10 @@ public void TestBlockExtents() new Point3d(extents.MinPoint.X,extents.MaxPoint.Y,0), extents.MaxPoint, new Point3d(extents.MaxPoint.X,extents.MinPoint.Y,0),}; - tr.CurrentSpace.AddPline(pts1, action: e => e.ColorIndex = 2); + tr.CurrentSpace.AddEntity(pts.CreatePolyline(action: e => e.ColorIndex = 2)); var extents2 = block1.GetBoundingBoxEx(); - tr.CurrentSpace.AddLine(extents2.Min,extents2.Max,e=>e.ColorIndex = 3); + tr.CurrentSpace.AddEntity(pts.CreatePolyline(action: e => e.ColorIndex = 3)); } diff --git a/tests/TestShared/TestQuadTree.cs b/tests/TestShared/TestQuadTree.cs index fc87b9a..8dad5cc 100644 --- a/tests/TestShared/TestQuadTree.cs +++ b/tests/TestShared/TestQuadTree.cs @@ -77,7 +77,7 @@ public void Test_QuadTree() (new Point3d(pl[2].X,pl[2].Y,0),0,0,0), (new Point3d(pl[3].X,pl[3].Y,0),0,0,0), }; - tr.CurrentSpace.AddPline(databaseBoundary); + tr.CurrentSpace.AddEntity(databaseBoundary.CreatePolyline(action: e => e.Closed = true)); // 生成多少个图元,导致cad会令undo出错(八叉树深度过大 treemax) // int maximumItems = 30_0000; diff --git a/tests/TestShared/TestText.cs b/tests/TestShared/TestText.cs index 11b19cb..e147fbc 100644 --- a/tests/TestShared/TestText.cs +++ b/tests/TestShared/TestText.cs @@ -8,26 +8,27 @@ public class TestText public void TestDBText() { using var tr = new DBTrans(); - tr.CurrentSpace.AddDBText(new(-1, -1, 0), "123", 2.5, t=> t.ColorIndex = 1); + tr.CurrentSpace.AddEntity(DBTextEx.CreateDBText(new(-1, -1, 0), "123", 2.5, action:t=> t.ColorIndex = 1)); - tr.CurrentSpace.AddDBText(new(0, 0, 0), "123", 2.5, t => { + tr.CurrentSpace.AddEntity(DBTextEx.CreateDBText(new(-1, -1, 0), "123", 2.5, action: t => { t.Justify = AttachmentPoint.BaseCenter; t.AlignmentPoint = new(1, 1, 0); t.ColorIndex = 2; - }); + })); } [CommandMethod(nameof(TestBackDBText))] public void TestBackDBText() { using var tr = new DBTrans(@"C:\Users\vic\Desktop\test.dwg"); - tr.CurrentSpace.AddDBText(new(-1, -1, 0), "123", 2.5, t => t.ColorIndex = 1); - - tr.CurrentSpace.AddDBText(new(0, 0, 0), "123", 2.5, t => { - t.Justify = AttachmentPoint.BaseCenter; - t.AlignmentPoint = new(1, 1, 0); - t.ColorIndex = 2; - }); + tr.CurrentSpace.AddEntity(DBTextEx.CreateDBText(new(-1, -1, 0), "123", 2.5, action: t => t.ColorIndex = 1)); + + tr.CurrentSpace.AddEntity(DBTextEx.CreateDBText(new(-1, -1, 0), "123", 2.5, action: t => + { + t.Justify = AttachmentPoint.BaseCenter; + t.AlignmentPoint = new(1, 1, 0); + t.ColorIndex = 2; + })); tr.SaveDwgFile(); } @@ -37,12 +38,12 @@ public void TestBackDBText() public void TestMText() { using var tr = new DBTrans(); - tr.CurrentSpace.AddMText(new(5, 5, 0), "123", 2.5, t => t.ColorIndex = 1); + tr.CurrentSpace.AddEntity(MTextEx.CreateMText(new(5, 5, 0), "123", 2.5, action: t => t.ColorIndex = 1)); - tr.CurrentSpace.AddMText(new(10, 10, 0), "123", 2.5, t => { + tr.CurrentSpace.AddEntity(MTextEx.CreateMText(new(5, 5, 0), "123", 2.5, action: t => { t.Attachment = AttachmentPoint.TopCenter; t.ColorIndex = 2; - }); + })); } } -- Gitee From 3d4b61789dcf416264547c0a61f52d75658b3783 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Tue, 11 Apr 2023 00:21:46 +0800 Subject: [PATCH 037/453] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=83=A8=E5=88=86?= =?UTF-8?q?=E5=9D=97=E6=93=8D=E4=BD=9C=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Entity/BlockReferenceEx.cs | 96 +++++++++++++++++-- .../ExtensionMethod/Entity/PolylineEx.cs | 2 +- tests/TestShared/TestBlock.cs | 17 +++- 3 files changed, 105 insertions(+), 10 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs index 7576e5f..7ce17d2 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs @@ -68,14 +68,9 @@ public static void ClipBlockRef(this BlockReference bref, Point3d pt1, Point3d p /// /// 更新动态块属性值 /// - /// 动态块 - /// 属性值字典 - public static void ChangeBlockProperty(this BlockReference blockReference, - Dictionary propertyNameValues) + private static void ChangeDynamicBlockProperty(BlockReference blockReference, + Dictionary propertyNameValues) { - if (!blockReference.IsDynamicBlock) - return; - using (blockReference.ForWrite()) { foreach (DynamicBlockReferenceProperty item in blockReference.DynamicBlockReferencePropertyCollection) @@ -83,6 +78,93 @@ public static void ChangeBlockProperty(this BlockReference blockReference, item.Value = propertyNameValues[item.PropertyName]; } } + /// + /// 更新普通块的属性值 + /// + private static void ChangePureBlockProperty(BlockReference blockReference, Dictionary propertyNameValues) + { + var tr = DBTrans.GetTopTransaction(blockReference.Database); + AttributeReference att; + foreach (var item in blockReference.AttributeCollection) + { + if (item is ObjectId id) + { + // 通常情况下返回的都是 ObjectId + att = tr.GetObject(id); + } + else + { + // 某些情况下,比如你exploded炸开块后的子块块参照是没有在数据库里的,这时候返回的结果就是 AttributeReference + att = (AttributeReference)item; + } + att.ForWrite(obj => { + if (propertyNameValues.ContainsKey(obj.Tag)) + { + obj.TextString = propertyNameValues[obj.Tag]?.ToString(); + } + }); + } + } + /// + /// 更新块属性值 + /// + /// 块 + /// 属性值字典 + public static void ChangeBlockProperty(this BlockReference blockReference, Dictionary propertyNameValues) + { + if (blockReference.IsDynamicBlock) + { + ChangeDynamicBlockProperty(blockReference, propertyNameValues); + } + else + { + ChangePureBlockProperty(blockReference, propertyNameValues); + } + } + /// + /// 获取嵌套块的位置(wcs) + /// + /// 父块 + /// 子块名 + /// 子块的位置 + /// + public static Point3d GetNestedBlockPosition(this BlockReference parentBlockRef, string nestedBlockName) + { + var tr = DBTrans.GetTopTransaction(parentBlockRef.Database); + + var btr = tr.GetObject(parentBlockRef.BlockTableRecord); + foreach (ObjectId id in btr) + { + if (id.ObjectClass.Name == "AcDbBlockReference") + { + var nestedBlockRef = tr.GetObject(id); + if (nestedBlockRef.Name == nestedBlockName) + { + return nestedBlockRef.Position.TransformBy(parentBlockRef.BlockTransform); + } + } + } + throw new ArgumentException($"Block {nestedBlockName} not found."); + } + /// + /// 获取普通块参照的属性集合 + /// + /// 普通块参照 + /// 属性集合 + public static IEnumerable GetAttributes(this BlockReference owner) + { + var trans = DBTrans.GetTopTransaction(owner.Database); + if (owner.Database != null) + { + foreach (ObjectId id in owner.AttributeCollection) + yield return (AttributeReference)trans.GetObject(id); + } + else + { + foreach (AttributeReference att in owner.AttributeCollection) + yield return att; + } + } #endregion /// diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/PolylineEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/PolylineEx.cs index fde2f72..6552bb3 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/PolylineEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/PolylineEx.cs @@ -64,7 +64,7 @@ public static List GetPoints(this Polyline pl) /// 此多段线无默认全局宽度0,无圆弧段 /// /// 点集 - /// 是否闭合 + /// 多段线属性设置委托 /// 多段线对象 public static Polyline CreatePolyline(this IEnumerable points, Action? action = null) { diff --git a/tests/TestShared/TestBlock.cs b/tests/TestShared/TestBlock.cs index 4d84829..cb45f67 100644 --- a/tests/TestShared/TestBlock.cs +++ b/tests/TestShared/TestBlock.cs @@ -515,8 +515,8 @@ void Wblock() var db = curdb.Wblock(ids, Point3d.Origin); db.SaveAs(@"c:\test.dwg", DwgVersion.Current); } - - void ChangeDynameicBlock() + [CommandMethod(nameof(ChangeDynameicBlock))] + public void ChangeDynameicBlock() { var pro = new Dictionary { @@ -528,6 +528,19 @@ void ChangeDynameicBlock() brf.ChangeBlockProperty(pro); // 这是第一个函数的用法 } + [CommandMethod(nameof(ChangeBlockProperty))] + public void ChangeBlockProperty() + { + Dictionary? pro = new Dictionary + { + { "haha", "1" } + }; + var blockid = Env.Editor.GetEntity("选择个块").ObjectId; + using DBTrans tr = new(); + var brf = tr.GetObject(blockid)!; + brf.ChangeBlockProperty(pro); + // 这是第一个函数的用法 + } [CommandMethod(nameof(Test_Back))] public void Test_Back() -- Gitee From d2b6f7406717c9b14930c39bfe5da6f6b812e542 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Tue, 11 Apr 2023 23:00:10 +0800 Subject: [PATCH 038/453] =?UTF-8?q?Point2d=E7=9A=84=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E4=B8=AD=E7=82=B9=E5=87=BD=E6=95=B0=E5=90=8D=E4=B8=8EPoint3d?= =?UTF-8?q?=E7=BB=9F=E4=B8=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/PointEx.cs | 2 +- .../HatchConverter.cs" | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/PointEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/PointEx.cs index 2cfa8d2..54b3f77 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/PointEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/PointEx.cs @@ -56,7 +56,7 @@ public static double GetAngle(this Point2d startPoint, Point2d endPoint) /// /// /// - public static Point2d GetCenter(this Point2d a, Point2d b) + public static Point2d GetMidPointTo(this Point2d a, Point2d b) { // (p1 + p2) / 2; // 溢出风险 return new Point2d(a.X * 0.5 + b.X * 0.5, diff --git "a/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchConverter.cs" "b/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchConverter.cs" index 34a1604..688bf78 100644 --- "a/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchConverter.cs" +++ "b/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchConverter.cs" @@ -25,7 +25,7 @@ class CircleData /// 对称点2 public CircleData(PointV symmetryAxisPoint1, PointV symmetryAxisPoint2) { - Center = symmetryAxisPoint1.GetCenter(symmetryAxisPoint2); + Center = PointEx.GetMidPointTo(symmetryAxisPoint1, symmetryAxisPoint2); Radius = symmetryAxisPoint1.GetDistanceTo(symmetryAxisPoint2) * 0.5; } } -- Gitee From e1603e6c1ca97fa743810e1f7b6dc99ec865b744 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Tue, 11 Apr 2023 23:03:18 +0800 Subject: [PATCH 039/453] =?UTF-8?q?=E6=B7=BB=E5=8A=A0Point3d=20Z=E5=80=BC?= =?UTF-8?q?=E5=BD=92=E9=9B=B6=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/PointEx.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/PointEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/PointEx.cs index 54b3f77..e059633 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/PointEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/PointEx.cs @@ -62,6 +62,15 @@ public static Point2d GetMidPointTo(this Point2d a, Point2d b) return new Point2d(a.X * 0.5 + b.X * 0.5, a.Y * 0.5 + b.Y * 0.5); } + /// + /// Z值归零 + /// + /// 点 + /// 新点 + internal static Point3d Z20(this Point3d point) + { + return new Point3d(point.X, point.Y, 0); + } /// http://www.lee-mac.com/bulgeconversion.html /// -- Gitee From e822efdcbb74f0b0127bbfef87d583eb3642742a Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Tue, 11 Apr 2023 23:55:29 +0800 Subject: [PATCH 040/453] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=B8=8D=E4=BD=BF?= =?UTF-8?q?=E7=94=A8DBTrans=E6=A0=B9=E6=8D=AE=E5=AF=B9=E8=B1=A1=E5=8F=A5?= =?UTF-8?q?=E6=9F=84=E5=AD=97=E7=AC=A6=E4=B8=B2=E8=8E=B7=E5=8F=96=E5=AF=B9?= =?UTF-8?q?=E8=B1=A1Id=E7=9A=84=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/ObjectIdEx.cs | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs index f5ebcb6..e9333fb 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs @@ -58,6 +58,30 @@ public static IEnumerable OfType(this IEnumerable ids) wh } #endregion GetObject + /// + /// 根据对象句柄字符串获取对象Id + /// + /// 数据库 + /// 句柄字符串 + /// 对象的ObjectId + public static ObjectId GetObjectId(this Database db, string handleString) + { + long l; + try + { + l = Convert.ToInt64(handleString, 16); + } + catch + { + return ObjectId.Null; + } + var hanle = new Handle(l); + if (db.TryGetObjectId(hanle, out ObjectId id)) + { + return id; + } + return ObjectId.Null; + } /// /// id是否有效,未被删除 -- Gitee From 3af2811c8817f74652d26314eb2258ca0416d4d9 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Tue, 11 Apr 2023 23:57:21 +0800 Subject: [PATCH 041/453] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=B8=8D=E4=BD=BF?= =?UTF-8?q?=E7=94=A8DBTrans=E6=A0=B9=E6=8D=AE=E5=AF=B9=E8=B1=A1=E5=8F=A5?= =?UTF-8?q?=E6=9F=84=E5=AD=97=E7=AC=A6=E4=B8=B2=E8=8E=B7=E5=8F=96=E5=AF=B9?= =?UTF-8?q?=E8=B1=A1Id=E7=9A=84=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/ObjectIdEx.cs | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs index e9333fb..c2ab322 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs @@ -66,19 +66,13 @@ public static IEnumerable OfType(this IEnumerable ids) wh /// 对象的ObjectId public static ObjectId GetObjectId(this Database db, string handleString) { - long l; - try + if (long.TryParse(handleString, System.Globalization.NumberStyles.HexNumber, null, out long l)) { - l = Convert.ToInt64(handleString, 16); - } - catch - { - return ObjectId.Null; - } - var hanle = new Handle(l); - if (db.TryGetObjectId(hanle, out ObjectId id)) - { - return id; + var hanle = new Handle(l); + if (db.TryGetObjectId(hanle, out ObjectId id)) + { + return id; + } } return ObjectId.Null; } -- Gitee From aa2ac1e0d78307d881eba2ea2acf65be1ee77ade Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Wed, 12 Apr 2023 00:02:20 +0800 Subject: [PATCH 042/453] =?UTF-8?q?=E4=BF=AE=E6=94=B9ObjectIdEx.OfType?= =?UTF-8?q?=E5=87=BD=E6=95=B0=EF=BC=8C=E5=A2=9E=E5=8A=A0=E7=B2=BE=E7=A1=AE?= =?UTF-8?q?=E5=8C=B9=E9=85=8D=E9=80=89=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/ObjectIdEx.cs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs index c2ab322..2e74dd2 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs @@ -1,4 +1,5 @@ using System.Data.Common; +using System.Text.RegularExpressions; namespace IFoxCAD.Cad; @@ -50,11 +51,20 @@ public static T GetObject(this ObjectId id, /// /// 对象类型 /// 对象id集合 + /// 精确匹配 /// 对象id集合 - public static IEnumerable OfType(this IEnumerable ids) where T : DBObject + public static IEnumerable OfType(this IEnumerable ids,bool exactMatch =false) where T : DBObject { - string dxfName = RXClass.GetClass(typeof(T)).DxfName; - return ids.Where(id => id.ObjectClass.DxfName == dxfName); + var rxc = RXClass.GetClass(typeof(T)); + if (exactMatch) + { + var dxfName = rxc.DxfName; + return ids.Where(id => id.ObjectClass.DxfName == dxfName); + } + else + { + return ids.Where(id => id.ObjectClass.IsDerivedFrom(rxc)); + } } #endregion GetObject -- Gitee From 797de3492f32acde6c8cf352a1e25a56a3aea9a7 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Wed, 12 Apr 2023 00:19:11 +0800 Subject: [PATCH 043/453] =?UTF-8?q?=E5=B0=86net=E7=9A=84=E9=A2=84=E7=BC=96?= =?UTF-8?q?=E8=AF=91=E7=AC=A6=E5=8F=B7=E6=94=B9=E4=B8=BANET45=5FOR=5FGREAT?= =?UTF-8?q?ER?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Basal/IFox.Basal.Shared/CLS/Index.cs | 14 +++++++------- src/Basal/IFox.Basal.Shared/CLS/Range.cs | 6 ++---- .../ExpressionTrees/ParameterRebinder.cs | 2 +- .../ExpressionTrees/PredicateBuilder.cs | 2 +- .../ExpressionTrees/SqlExpressionVisitor.cs | 3 +-- src/Basal/IFox.Basal/GlobalUsings.cs | 2 +- 6 files changed, 13 insertions(+), 16 deletions(-) diff --git a/src/Basal/IFox.Basal.Shared/CLS/Index.cs b/src/Basal/IFox.Basal.Shared/CLS/Index.cs index b84f4df..ae562f8 100644 --- a/src/Basal/IFox.Basal.Shared/CLS/Index.cs +++ b/src/Basal/IFox.Basal.Shared/CLS/Index.cs @@ -5,9 +5,9 @@ namespace System; -#if NET45 -using System.Runtime.CompilerServices; -#endif + + + /// Represent a type can be used to index a collection either from the start or the end. /// /// Index is used by the C# compiler to support the new index syntax @@ -26,7 +26,7 @@ namespace System; /// /// If the Index constructed from the end, index value 1 means pointing at the last element and index value 0 means pointing at beyond last element. /// -#if NET45 +#if NET45_OR_GREATER [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif public Index(int value, bool fromEnd = false) @@ -56,7 +56,7 @@ private Index(int value) /// Create an Index from the start at the position indicated by the value. /// The index value from the start. -#if NET45 +#if NET45_OR_GREATER [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif public static Index FromStart(int value) @@ -71,7 +71,7 @@ public static Index FromStart(int value) /// Create an Index from the end at the position indicated by the value. /// The index value from the end. -#if NET45 +#if NET45_OR_GREATER [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif public static Index FromEnd(int value) @@ -107,7 +107,7 @@ public int Value /// It is expected Index will be used with collections which always have non negative length/count. If the returned offset is negative and /// then used to index a collection will get out of range exception which will be same affect as the validation. /// -#if NET45 +#if NET45_OR_GREATER [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif public int GetOffset(int length) diff --git a/src/Basal/IFox.Basal.Shared/CLS/Range.cs b/src/Basal/IFox.Basal.Shared/CLS/Range.cs index 0318216..0da227e 100644 --- a/src/Basal/IFox.Basal.Shared/CLS/Range.cs +++ b/src/Basal/IFox.Basal.Shared/CLS/Range.cs @@ -6,9 +6,7 @@ namespace System; -#if NET45 -using System.Runtime.CompilerServices; -#endif + /// Represent a range has start and end indexes. /// @@ -75,7 +73,7 @@ public override string ToString() /// It is expected Range will be used with collections which always have non negative length/count. /// We validate the range is inside the length scope though. /// -#if NET45 +#if NET45_OR_GREATER [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif // [CLSCompliant(false)] diff --git a/src/Basal/IFox.Basal.Shared/ExpressionTrees/ParameterRebinder.cs b/src/Basal/IFox.Basal.Shared/ExpressionTrees/ParameterRebinder.cs index e4dfcd4..b0098bc 100644 --- a/src/Basal/IFox.Basal.Shared/ExpressionTrees/ParameterRebinder.cs +++ b/src/Basal/IFox.Basal.Shared/ExpressionTrees/ParameterRebinder.cs @@ -1,4 +1,4 @@ -#if NET45 +#if NET45_OR_GREATER namespace IFoxCAD.Basal; /// diff --git a/src/Basal/IFox.Basal.Shared/ExpressionTrees/PredicateBuilder.cs b/src/Basal/IFox.Basal.Shared/ExpressionTrees/PredicateBuilder.cs index 7153e79..11ae2d3 100644 --- a/src/Basal/IFox.Basal.Shared/ExpressionTrees/PredicateBuilder.cs +++ b/src/Basal/IFox.Basal.Shared/ExpressionTrees/PredicateBuilder.cs @@ -1,5 +1,5 @@ -#if NET45 +#if NET45_OR_GREATER namespace IFoxCAD.Basal; /// /// Predicateίй diff --git a/src/Basal/IFox.Basal.Shared/ExpressionTrees/SqlExpressionVisitor.cs b/src/Basal/IFox.Basal.Shared/ExpressionTrees/SqlExpressionVisitor.cs index 17ce385..1fb88be 100644 --- a/src/Basal/IFox.Basal.Shared/ExpressionTrees/SqlExpressionVisitor.cs +++ b/src/Basal/IFox.Basal.Shared/ExpressionTrees/SqlExpressionVisitor.cs @@ -1,5 +1,4 @@ -#if NET45 -using Microsoft.CSharp.RuntimeBinder; +#if NET45_OR_GREATER namespace IFoxCAD.Basal; diff --git a/src/Basal/IFox.Basal/GlobalUsings.cs b/src/Basal/IFox.Basal/GlobalUsings.cs index cb820d5..d75b153 100644 --- a/src/Basal/IFox.Basal/GlobalUsings.cs +++ b/src/Basal/IFox.Basal/GlobalUsings.cs @@ -16,6 +16,6 @@ global using System.Collections.ObjectModel; -#if NET45 +#if NET45_OR_GREATER global using Microsoft.CSharp.RuntimeBinder; #endif \ No newline at end of file -- Gitee From b8fff237cf924f5e298a6ad2f2172fb72425d9bc Mon Sep 17 00:00:00 2001 From: vicwjb Date: Thu, 13 Apr 2023 23:17:47 +0800 Subject: [PATCH 044/453] =?UTF-8?q?IsNullOrEmpty=E6=9B=BF=E6=8D=A2?= =?UTF-8?q?=E4=B8=BAIsNullOrWhiteSpace?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs b/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs index 9ebd444..cb00536 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs @@ -183,7 +183,7 @@ public DBTrans(string fileName, string? password = null, bool activeOpen = false) { - if (fileName == null || string.IsNullOrEmpty(fileName.Trim())) + if (fileName == null || string.IsNullOrWhiteSpace(fileName.Trim())) throw new ArgumentNullException(nameof(fileName)); _fileName = fileName.Replace("/", "\\");// doc.Name总是"D:\\JX.dwg" @@ -507,7 +507,7 @@ public void SaveFile(DwgVersion version = DwgVersion.AC1800, string? fileMsg; bool creatFlag = false; saveAsFile = saveAsFile?.Trim(); - if (string.IsNullOrEmpty(saveAsFile)) + if (string.IsNullOrWhiteSpace(saveAsFile)) { fileMsg = _fileName; saveAsFile = fileMsg; @@ -519,7 +519,7 @@ public void SaveFile(DwgVersion version = DwgVersion.AC1800, // 路径失败也保存到桌面 var path = Path.GetDirectoryName(saveAsFile); - if (string.IsNullOrEmpty(path)) + if (string.IsNullOrWhiteSpace(path)) { creatFlag = true; } @@ -531,13 +531,13 @@ public void SaveFile(DwgVersion version = DwgVersion.AC1800, // 文件名缺失时 if (!creatFlag && - string.IsNullOrEmpty(Path.GetFileName(saveAsFile).Trim())) + string.IsNullOrWhiteSpace(Path.GetFileName(saveAsFile).Trim())) creatFlag = true; } if (saveAsFile != null) { var fileNameWith = Path.GetFileNameWithoutExtension(saveAsFile).Trim(); - if (string.IsNullOrEmpty(fileNameWith)) + if (string.IsNullOrWhiteSpace(fileNameWith)) creatFlag = true; } else @@ -584,7 +584,7 @@ public void SaveFile(DwgVersion version = DwgVersion.AC1800, (bool error, string path) GetOrCreateSaveAsFile() { var file = Database.Filename; - if (!string.IsNullOrEmpty(file)) + if (!string.IsNullOrWhiteSpace(file)) return (false, file); // 为了防止用户输入了错误的路径造成无法保存, @@ -594,9 +594,9 @@ public void SaveFile(DwgVersion version = DwgVersion.AC1800, var fileName = Path.GetFileNameWithoutExtension(_fileName).Trim(); var fileExt = Path.GetExtension(_fileName); - if (string.IsNullOrEmpty(fileName)) + if (string.IsNullOrWhiteSpace(fileName)) fileName = DateTime.Now.ToString("--yyMMdd--hhmmssffff"); - if (string.IsNullOrEmpty(fileExt)) + if (string.IsNullOrWhiteSpace(fileExt)) fileExt = ".dwg"; // 构造函数(fileName)用了不存在的路径进行后台打开,就会出现此问题 @@ -768,7 +768,7 @@ public string ToString(string? format = null, IFormatProvider? formatProvider = $"Database = {Database != null}" }; - if (!string.IsNullOrEmpty(format)) + if (!string.IsNullOrWhiteSpace(format)) return string.Join(format, lines.ToArray()); return string.Join("\n", lines.ToArray()); -- Gitee From efd87ea7c3b57c88e993c9dc3519231bddea68bd Mon Sep 17 00:00:00 2001 From: vicwjb Date: Thu, 13 Apr 2023 23:39:06 +0800 Subject: [PATCH 045/453] =?UTF-8?q?=E4=BC=98=E5=8C=96=20NotNull=20?= =?UTF-8?q?=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../General/ArgumentNullEx.cs | 29 ++++++++++++++++--- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/src/Basal/IFox.Basal.Shared/General/ArgumentNullEx.cs b/src/Basal/IFox.Basal.Shared/General/ArgumentNullEx.cs index 75c779d..bb24c23 100644 --- a/src/Basal/IFox.Basal.Shared/General/ArgumentNullEx.cs +++ b/src/Basal/IFox.Basal.Shared/General/ArgumentNullEx.cs @@ -1,6 +1,4 @@ - - -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; namespace IFoxCAD.Basal { @@ -15,9 +13,32 @@ public static class ArgumentNullEx /// 参数 /// 参数为null时的提示信息 /// - public static void NotNull([NotNull] this object? value, string valueExpression = "") + public static void NotNull([NotNull] this object? value, [CallerArgumentExpression(nameof(value))] string valueExpression = "") { _ = value ?? throw new ArgumentNullException(nameof(value), valueExpression); } } } + +namespace System.Runtime.CompilerServices +{ + /// + /// 指示参数将为另一个参数传递的表达式捕获为字符串。 + /// + [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] + public sealed class CallerArgumentExpressionAttribute : Attribute + { + /// + /// 初始化 CallerArgumentExpressionAttribute 类的新实例。 + /// + /// + public CallerArgumentExpressionAttribute(string parameterName) + { + ParameterName = parameterName; + } + /// + /// 获取其表达式应捕获为字符串的参数的名称。 + /// + public string ParameterName { get; } + } +} \ No newline at end of file -- Gitee From 9649c8fad710e3d0bf81a383d7ed330954c2c729 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Fri, 14 Apr 2023 00:01:37 +0800 Subject: [PATCH 046/453] =?UTF-8?q?=E6=B8=85=E7=90=86=E6=97=A0=E7=94=A8?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=EF=BC=8C=E5=A2=9E=E5=8A=A0=E9=83=A8=E5=88=86?= =?UTF-8?q?=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/ObjectIdEx.cs | 6 +---- src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs | 26 +++++++++++++------ 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs index 2e74dd2..548a724 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs @@ -1,7 +1,4 @@ -using System.Data.Common; -using System.Text.RegularExpressions; - -namespace IFoxCAD.Cad; +namespace IFoxCAD.Cad; /// /// 对象id扩展类 @@ -33,7 +30,6 @@ public static T GetObject(this ObjectId id, /// 指定的泛型 /// 对象id集合 /// 打开模式 - /// 事务 /// 是否打开已删除对象,默认为不打开 /// 是否打开锁定图层对象,默认为不打开 /// 指定类型对象集合 diff --git a/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs b/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs index cb00536..ac45666 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs @@ -183,7 +183,7 @@ public DBTrans(string fileName, string? password = null, bool activeOpen = false) { - if (fileName == null || string.IsNullOrWhiteSpace(fileName.Trim())) + if (string.IsNullOrWhiteSpace(fileName)) throw new ArgumentNullException(nameof(fileName)); _fileName = fileName.Replace("/", "\\");// doc.Name总是"D:\\JX.dwg" @@ -498,7 +498,7 @@ public void SaveFile(DwgVersion version = DwgVersion.AC1800, if (saveAsFile == null) doc.SendStringToExecute("_qsave\n", false, true, true); else - /// 无法把 给这个面板 + // 无法把 给这个面板 doc.SendStringToExecute($"_Saveas\n", false, true, true); return; } @@ -506,7 +506,6 @@ public void SaveFile(DwgVersion version = DwgVersion.AC1800, // 后台开图,用数据库保存 string? fileMsg; bool creatFlag = false; - saveAsFile = saveAsFile?.Trim(); if (string.IsNullOrWhiteSpace(saveAsFile)) { fileMsg = _fileName; @@ -531,12 +530,12 @@ public void SaveFile(DwgVersion version = DwgVersion.AC1800, // 文件名缺失时 if (!creatFlag && - string.IsNullOrWhiteSpace(Path.GetFileName(saveAsFile).Trim())) + string.IsNullOrWhiteSpace(Path.GetFileName(saveAsFile))) creatFlag = true; } if (saveAsFile != null) { - var fileNameWith = Path.GetFileNameWithoutExtension(saveAsFile).Trim(); + var fileNameWith = Path.GetFileNameWithoutExtension(saveAsFile); if (string.IsNullOrWhiteSpace(fileNameWith)) creatFlag = true; } @@ -591,7 +590,7 @@ public void SaveFile(DwgVersion version = DwgVersion.AC1800, // 所以此处将进行保存到桌面, // 而不是弹出警告就结束 // 防止前台关闭了所有文档导致没有Editor,所以使用 MessageBox 发送警告 - var fileName = Path.GetFileNameWithoutExtension(_fileName).Trim(); + var fileName = Path.GetFileNameWithoutExtension(_fileName); var fileExt = Path.GetExtension(_fileName); if (string.IsNullOrWhiteSpace(fileName)) @@ -682,7 +681,9 @@ public void Commit() _commit = true; Dispose(); } - + /// + /// 是否释放事务 + /// public bool IsDisposed { get; private set; } = false; /// @@ -701,7 +702,10 @@ public void Dispose() { Dispose(false); } - + /// + /// 释放函数 + /// + /// protected virtual void Dispose(bool disposing) { /* 事务dispose流程: @@ -742,18 +746,24 @@ protected virtual void Dispose(bool disposing) // 将当前事务栈弹栈 _dBTrans.Pop(); } + #endregion #region ToString + /// public override string ToString() { return ToString(null, null); } + /// public string ToString(IFormatProvider? provider) { return ToString(null, provider); } + /// +#pragma warning disable IDE0060 // 删除未使用的参数 public string ToString(string? format = null, IFormatProvider? formatProvider = null) +#pragma warning restore IDE0060 // 删除未使用的参数 { List lines = new() { -- Gitee From d17b14fb54138311b981a0e1d5e6091c5f19e49b Mon Sep 17 00:00:00 2001 From: vicwjb Date: Sat, 15 Apr 2023 00:02:31 +0800 Subject: [PATCH 047/453] =?UTF-8?q?=E5=B0=86getobj=E5=87=BD=E6=95=B0?= =?UTF-8?q?=E7=9A=84=E8=BF=94=E5=9B=9E=E5=80=BC=E6=94=B9=E4=B8=BA=E5=8F=AF?= =?UTF-8?q?=E7=A9=BA=E7=B1=BB=E5=9E=8B=E3=80=82=20link=20#I6VFD5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../IFox.CAD.Shared/Algorithms/Graph/Graph.cs | 1 + .../IFox.CAD.Shared/Algorithms/Graph/IGraph.cs | 1 - .../IFox.CAD.Shared/ExtensionMethod/CurveEx.cs | 6 ++---- .../IFox.CAD.Shared/ExtensionMethod/EditorEx.cs | 6 +++--- .../ExtensionMethod/Entity/BlockReferenceEx.cs | 17 +++++++++-------- .../ExtensionMethod/ObjectIdEx.cs | 8 +++++--- .../ExtensionMethod/SelectionSetEx.cs | 1 - .../ExtensionMethod/SymbolTableRecordEx.cs | 2 +- .../ExtensionMethod/TransactionEx.cs | 5 ++--- src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs | 7 +++---- ...\253\345\205\205\344\272\213\344\273\266.cs" | 2 +- tests/TestShared/Copyclip.cs | 2 +- tests/TestShared/TestHatchinfo.cs | 2 +- 13 files changed, 29 insertions(+), 31 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/Algorithms/Graph/Graph.cs b/src/CAD/IFox.CAD.Shared/Algorithms/Graph/Graph.cs index 30a76f8..ee6e059 100644 --- a/src/CAD/IFox.CAD.Shared/Algorithms/Graph/Graph.cs +++ b/src/CAD/IFox.CAD.Shared/Algorithms/Graph/Graph.cs @@ -598,6 +598,7 @@ public void FindAll(IGraph graph) /// /// 图 /// 已经遍历的路径 + /// #if true void Dfs(IGraph graph, LinkedHashSet visited, HashSet totalVisited) { diff --git a/src/CAD/IFox.CAD.Shared/Algorithms/Graph/IGraph.cs b/src/CAD/IFox.CAD.Shared/Algorithms/Graph/IGraph.cs index 3a7eec4..a3a5aec 100644 --- a/src/CAD/IFox.CAD.Shared/Algorithms/Graph/IGraph.cs +++ b/src/CAD/IFox.CAD.Shared/Algorithms/Graph/IGraph.cs @@ -75,7 +75,6 @@ public interface IGraph /// /// 无向图顶点 /// -/// 顶点数据类型 public interface IGraphVertex : IComparable { /// diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/CurveEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/CurveEx.cs index 47b42ad..7b121f2 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/CurveEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/CurveEx.cs @@ -625,8 +625,7 @@ public static PolylineCurve3d ToPolylineCurve3d(this Polyline3d pl) using Point3dCollection pnts = new(); foreach (ObjectId id in pl) { - var ver = id.GetObject(OpenMode.ForRead); - if (ver != null) + if (id.GetObject(OpenMode.ForRead) is PolylineVertex3d ver) pnts.Add(ver.Position); } return new PolylineCurve3d(pnts); @@ -777,8 +776,7 @@ public static void ChamferAt(this Polyline polyline, int index, double radius, b ); // 将结果Ge曲线转为Db曲线,并将相关的数值反映到原曲线 - var plTemp = c3ds[0].ToCurve() as Polyline; - if (plTemp is null) + if (c3ds[0].ToCurve() is not Polyline plTemp) return; polyline.RemoveVertexAt(index); polyline.AddVertexAt(index, plTemp.GetPoint2dAt(1), plTemp.GetBulgeAt(1), 0, 0); diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs index bf142b2..b816e29 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs @@ -175,13 +175,13 @@ public static void SsgetAddKeys(this PromptSelectionOptions pso, var item = keySp[j]; // 防止多个后缀通过|符越过词典约束同名 // 后缀(key)含有,而且Action(value)不同,就把Action(value)累加到后面. - if (dicActions.ContainsKey(item)) + if (dicActions.TryGetValue(item, out Action value)) { if (dicActions[item] != dicActions[key]) dicActions[item] += dicActions[key]; } else - tmp.Add(item, dicActions[key]); + tmp.Add(item, value); } dicActions.Remove(key); } @@ -1045,7 +1045,7 @@ public static void ComExportWMF(this Editor editor, string saveFile, // 因为文件名可以有.所以后缀点必须是最后\的后面 int s = saveFile.LastIndexOf('\\'); if (s < dot) - saveFile = saveFile.Substring(0, dot); + saveFile = saveFile[..dot]; } // ActiveSelectionSet: diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs index 7ce17d2..4d7631b 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs @@ -74,8 +74,8 @@ private static void ChangeDynamicBlockProperty(BlockReference blockReference, using (blockReference.ForWrite()) { foreach (DynamicBlockReferenceProperty item in blockReference.DynamicBlockReferencePropertyCollection) - if (propertyNameValues.ContainsKey(item.PropertyName)) - item.Value = propertyNameValues[item.PropertyName]; + if (propertyNameValues.TryGetValue(item.PropertyName, out T? value)) + item.Value = value; } } /// @@ -90,7 +90,7 @@ private static void ChangePureBlockProperty(BlockReference blockReference, Di if (item is ObjectId id) { // 通常情况下返回的都是 ObjectId - att = tr.GetObject(id); + att = (AttributeReference)tr.GetObject(id); } else { @@ -98,9 +98,9 @@ private static void ChangePureBlockProperty(BlockReference blockReference, Di att = (AttributeReference)item; } att.ForWrite(obj => { - if (propertyNameValues.ContainsKey(obj.Tag)) + if (propertyNameValues.TryGetValue(obj.Tag, out T? value)) { - obj.TextString = propertyNameValues[obj.Tag]?.ToString(); + obj.TextString = value?.ToString(); } }); } @@ -128,23 +128,24 @@ public static void ChangeBlockProperty(this BlockReference blockReference, Di /// 子块名 /// 子块的位置 /// - public static Point3d GetNestedBlockPosition(this BlockReference parentBlockRef, string nestedBlockName) + public static Point3d? GetNestedBlockPosition(this BlockReference parentBlockRef, string nestedBlockName) { var tr = DBTrans.GetTopTransaction(parentBlockRef.Database); var btr = tr.GetObject(parentBlockRef.BlockTableRecord); + if (btr == null) return null; foreach (ObjectId id in btr) { if (id.ObjectClass.Name == "AcDbBlockReference") { var nestedBlockRef = tr.GetObject(id); - if (nestedBlockRef.Name == nestedBlockName) + if (nestedBlockRef?.Name == nestedBlockName) { return nestedBlockRef.Position.TransformBy(parentBlockRef.BlockTransform); } } } - throw new ArgumentException($"Block {nestedBlockName} not found."); + return null; } /// /// 获取普通块参照的属性集合 diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs index 548a724..171d110 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs @@ -15,7 +15,7 @@ public static class ObjectIdEx /// 是否打开已删除对象,默认为不打开 /// 是否打开锁定图层对象,默认为不打开 /// 指定类型对象 - public static T GetObject(this ObjectId id, + public static T? GetObject(this ObjectId id, OpenMode openMode = OpenMode.ForRead, bool openErased = false, bool openLockedLayer = false) where T : DBObject @@ -34,12 +34,14 @@ public static T GetObject(this ObjectId id, /// 是否打开锁定图层对象,默认为不打开 /// 指定类型对象集合 [System.Diagnostics.DebuggerStepThrough] - public static IEnumerable GetObject(this IEnumerable ids, + public static IEnumerable GetObject(this IEnumerable ids, OpenMode openMode = OpenMode.ForRead, bool openErased = false, bool openLockedLayer = false) where T : DBObject { - return ids.Select(id => id.GetObject(openMode, openErased, openLockedLayer)); + return ids.Select(id => + id.GetObject(openMode, openErased, openLockedLayer)) + .OfType(); } /// diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SelectionSetEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SelectionSetEx.cs index faee9ef..31733f0 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SelectionSetEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SelectionSetEx.cs @@ -84,7 +84,6 @@ public static IEnumerable GetEntities(this SelectionSet ss, ss.NotNull(nameof(ss)); return ss.GetObjectIds() .Select(id => id.GetObject(openMode, openErased, openLockedLayer)) - .Where(ent => ent != null) .OfType(); } #endregion diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs index 3884bfc..e40a5a2 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs @@ -159,7 +159,7 @@ public static IEnumerable> GetObjectIds(this BlockTa /// 是否打开已删除对象,默认为不打开 /// 是否打开锁定图层对象,默认为不打开 /// 绘制顺序表 - public static DrawOrderTable GetDrawOrderTable(this BlockTableRecord btr, + public static DrawOrderTable? GetDrawOrderTable(this BlockTableRecord btr, Transaction? trans = null, bool openErased = false, bool openLockedLayer = false) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/TransactionEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/TransactionEx.cs index bafd5d1..a9e2d71 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/TransactionEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/TransactionEx.cs @@ -33,13 +33,12 @@ public static DBObject GetObject([DisallowNull] this Transaction tr, ObjectId id /// 是否打开已删除对象,默认为不打开 /// 是否打开锁定图层对象,默认为不打开 /// 图元对象,类型不匹配时抛异常 - public static T GetObject([DisallowNull] this Transaction tr, ObjectId id, + public static T? GetObject([DisallowNull] this Transaction tr, ObjectId id, OpenMode openMode = OpenMode.ForRead, bool openErased = false, bool openLockedLayer = false) where T : DBObject { - return tr.GetObject(id, openMode, openErased, openLockedLayer) as T - ?? throw new ArgumentNullException(nameof(T), $"你传入的 id 不能转换为 {nameof(T)} 类型"); + return tr.GetObject(id, openMode, openErased, openLockedLayer) as T; } } } diff --git a/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs b/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs index ac45666..9288fd1 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs @@ -430,14 +430,13 @@ public DBObject GetObject(ObjectId id, /// 打开模式,默认为只读 /// 是否打开已删除对象,默认为不打开 /// 是否打开锁定图层对象,默认为不打开 - /// 图元对象,类型不匹配时抛异常 - public T GetObject(ObjectId id, + /// 图元对象 + public T? GetObject(ObjectId id, OpenMode openMode = OpenMode.ForRead, bool openErased = false, bool openLockedLayer = false) where T : DBObject { - return Transaction.GetObject(id, openMode, openErased, openLockedLayer) as T - ?? throw new ArgumentNullException(nameof(T), $"你传入的 id 不能转换为 {nameof(T)} 类型"); + return Transaction.GetObject(id, openMode, openErased, openLockedLayer) as T; } /// diff --git "a/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/02.\346\213\211\344\274\270\345\241\253\345\205\205\344\272\213\344\273\266.cs" "b/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/02.\346\213\211\344\274\270\345\241\253\345\205\205\344\272\213\344\273\266.cs" index 8da9e57..2d0bfc1 100644 --- "a/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/02.\346\213\211\344\274\270\345\241\253\345\205\205\344\272\213\344\273\266.cs" +++ "b/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/02.\346\213\211\344\274\270\345\241\253\345\205\205\344\272\213\344\273\266.cs" @@ -14,7 +14,7 @@ public class HatchPickEvent : IDisposable // 临时标记(重设选择集会触发一次选择集反应器) static bool _selectChangedStop = false; // 临时选择集用 - static List _hatchIds = new(); + static readonly List _hatchIds = new(); // 获取夹点在哪个图元边界上面,是为true static bool _pickInBo = false; static bool _vetoProperties = false; diff --git a/tests/TestShared/Copyclip.cs b/tests/TestShared/Copyclip.cs index ac4b591..bcdb912 100644 --- a/tests/TestShared/Copyclip.cs +++ b/tests/TestShared/Copyclip.cs @@ -185,7 +185,7 @@ public void Terminate() /// 其他线程写入需要等待本次写入结束之后才能继续写入 /// 参考链接 /// - static ReaderWriterLockSlim _rwLock = new(); + static readonly ReaderWriterLockSlim _rwLock = new(); /// /// 储存准备删除的文件 diff --git a/tests/TestShared/TestHatchinfo.cs b/tests/TestShared/TestHatchinfo.cs index 52dbfaf..1b765e5 100644 --- a/tests/TestShared/TestHatchinfo.cs +++ b/tests/TestShared/TestHatchinfo.cs @@ -10,7 +10,7 @@ public void TestHatchInfo() var ids = Env.Editor.SSGet(null, sf).Value?.GetObjectIds(); if (ids.Count() > 0) { - HatchInfo hf = new HatchInfo(ids, false, null, 1, 0).Mode2UserDefined(); + HatchInfo hf = new HatchInfo(ids!, false, null, 1, 0).Mode2UserDefined(); hf.Build(tr.CurrentSpace); } } -- Gitee From 1c041d1dbdeab6df9d8c9855e013c87eb1de5e12 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Sat, 15 Apr 2023 16:46:51 +0800 Subject: [PATCH 048/453] =?UTF-8?q?=E5=88=A0=E6=8E=89net35=E7=9A=84?= =?UTF-8?q?=E5=90=8E=E7=BB=91=E5=AE=9A=E4=BB=A3=E7=A0=81=EF=BC=8Cnet40?= =?UTF-8?q?=E4=BB=A5=E4=B8=8A=E5=8F=AF=E4=BB=A5=E7=9B=B4=E6=8E=A5=E7=94=A8?= =?UTF-8?q?dynamic=20=E3=80=82fixed=20#I6VZ3L?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.ACAD/IFox.CAD.ACAD.csproj | 1 + .../ExtensionMethod/EditorEx.cs | 25 ++++++------------- tests/TestShared/TestEditor.cs | 2 +- 3 files changed, 10 insertions(+), 18 deletions(-) diff --git a/src/CAD/IFox.CAD.ACAD/IFox.CAD.ACAD.csproj b/src/CAD/IFox.CAD.ACAD/IFox.CAD.ACAD.csproj index f8a92bb..a7365ec 100644 --- a/src/CAD/IFox.CAD.ACAD/IFox.CAD.ACAD.csproj +++ b/src/CAD/IFox.CAD.ACAD/IFox.CAD.ACAD.csproj @@ -47,6 +47,7 @@ + diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs index b816e29..1db3b77 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs @@ -1029,7 +1029,7 @@ public enum RunLispFlag : byte public static void ComExportWMF(this Editor editor, string saveFile, ObjectId[]? ids = null, bool wmfSetDel = false) { - if (string.IsNullOrEmpty(saveFile)) + if (string.IsNullOrWhiteSpace(saveFile)) throw new ArgumentNullException(nameof(saveFile)); if (File.Exists(saveFile)) throw new FileFormatException("文件重复:" + saveFile); @@ -1039,15 +1039,7 @@ public static void ComExportWMF(this Editor editor, string saveFile, return; // 剔除后缀 - int dot = saveFile.LastIndexOf('.'); - if (dot != -1) - { - // 因为文件名可以有.所以后缀点必须是最后\的后面 - int s = saveFile.LastIndexOf('\\'); - if (s < dot) - saveFile = saveFile[..dot]; - } - + saveFile = Path.Combine(Path.GetDirectoryName(saveFile), Path.GetFileNameWithoutExtension(saveFile)); // ActiveSelectionSet: // 第一次执行会触发选择,再次重复命令执行的时候,它会无法再选择(即使清空选择集). // 因此此处netAPI进行选择,它就能读取当前选择集缓冲区的对象 @@ -1063,19 +1055,18 @@ public static void ComExportWMF(this Editor editor, string saveFile, editor.SetImpliedSelection(ids); #if zcad - var com = Acap.ZcadApplication; + dynamic com = Acap.ZcadApplication; #else - var com = Acap.AcadApplication; + dynamic com = Acap.AcadApplication; #endif - var doc = com.GetProperty("ActiveDocument"); - var wmfSet = doc.GetProperty("ActiveSelectionSet"); - + dynamic doc = com.ActiveDocument; + dynamic wmfSet = doc.ActiveSelectionSet; // TODO 20221007 导出wmf的bug // cad21 先net选择,再进行,此处再选择一次? // cad21 调试期间无法选择性粘贴? - var exp = doc.Invoke("Export", saveFile, "wmf", wmfSet); // JPGOUT,PNGOUT + doc.Export(saveFile, "wmf", wmfSet); if (wmfSetDel) - wmfSet.Invoke("Delete"); + wmfSet.Delete(); } #endregion diff --git a/tests/TestShared/TestEditor.cs b/tests/TestShared/TestEditor.cs index ed45db3..2c368f1 100644 --- a/tests/TestShared/TestEditor.cs +++ b/tests/TestShared/TestEditor.cs @@ -73,6 +73,6 @@ public void Test_ExportWMF() var ids = psr.Value.GetObjectIds(); // acad21(acad08没有)先选择再执行..会让你再选择一次 // 而且只发生在启动cad之后第一次执行. - Env.Editor.ComExportWMF("D:\\桌面\\aaa.dwg", ids); + Env.Editor.ComExportWMF(@"C:\Users\vic\Desktop\aaa.dwg", ids); } } \ No newline at end of file -- Gitee From d7f54f3e293fddb954f07e8b6bd2543928b2f8bc Mon Sep 17 00:00:00 2001 From: vicwjb Date: Sat, 15 Apr 2023 16:46:51 +0800 Subject: [PATCH 049/453] =?UTF-8?q?=E5=88=A0=E6=8E=89net35=E7=9A=84?= =?UTF-8?q?=E5=90=8E=E7=BB=91=E5=AE=9A=E4=BB=A3=E7=A0=81=EF=BC=8Cnet40?= =?UTF-8?q?=E4=BB=A5=E4=B8=8A=E5=8F=AF=E4=BB=A5=E7=9B=B4=E6=8E=A5=E7=94=A8?= =?UTF-8?q?dynamic=20=E3=80=82fixed=20#I6VZ3L?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../IFox.Basal.Shared/General/LateBinding.cs | 83 ------------------- .../IFox.Basal.Shared.projitems | 1 - 2 files changed, 84 deletions(-) delete mode 100644 src/Basal/IFox.Basal.Shared/General/LateBinding.cs diff --git a/src/Basal/IFox.Basal.Shared/General/LateBinding.cs b/src/Basal/IFox.Basal.Shared/General/LateBinding.cs deleted file mode 100644 index c72d4b4..0000000 --- a/src/Basal/IFox.Basal.Shared/General/LateBinding.cs +++ /dev/null @@ -1,83 +0,0 @@ -namespace IFoxCAD.Basal; - -/// -/// 后绑代码工具 -/// -public static class LateBinding -{ - /// - /// 从运行对象表 (ROT) 获取指定对象的运行实例 - /// - /// - /// - public static object GetInstance(string appName) - { - return Marshal.GetActiveObject(appName); - } - /// - /// 创建实例 - /// - /// - /// - public static object CreateInstance(string appName) - { - return Activator.CreateInstance(Type.GetTypeFromProgID(appName)); - } - /// - /// 获取或创建实例 - /// - /// - /// - public static object GetOrCreateInstance(string appName) - { - try { return GetInstance(appName); } - catch { return CreateInstance(appName); } - } - /// - /// 释放实例 - /// - /// - public static void ReleaseInstance(this object obj) - { - Marshal.ReleaseComObject(obj); - } - - /// - /// 获取属性 - /// - /// - /// - /// - /// - public static object GetProperty(this object obj, string propName, params object[] parameter) - { - return obj.GetType().InvokeMember(propName, - BindingFlags.GetProperty, - null, obj, parameter); - } - /// - /// 设置属性 - /// - /// - /// - /// - public static void SetProperty(this object obj, string propName, params object[] parameter) - { - obj.GetType().InvokeMember(propName, - BindingFlags.SetProperty, - null, obj, parameter); - } - /// - /// 执行函数 - /// - /// - /// - /// - /// - public static object Invoke(this object obj, string memberName, params object[] parameter) - { - return obj.GetType().InvokeMember(memberName, - BindingFlags.Public | BindingFlags.InvokeMethod, - null, obj, parameter); - } -} \ No newline at end of file diff --git a/src/Basal/IFox.Basal.Shared/IFox.Basal.Shared.projitems b/src/Basal/IFox.Basal.Shared/IFox.Basal.Shared.projitems index b5a563a..05ab2a7 100644 --- a/src/Basal/IFox.Basal.Shared/IFox.Basal.Shared.projitems +++ b/src/Basal/IFox.Basal.Shared/IFox.Basal.Shared.projitems @@ -22,7 +22,6 @@ - -- Gitee From 76c3f67e3fc4ee29856a905f17d5a61150a31666 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sat, 15 Apr 2023 14:47:44 +0800 Subject: [PATCH 050/453] =?UTF-8?q?=E5=AF=B9=E8=B1=A1=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E5=87=BD=E6=95=B0=E9=87=8C=E8=87=AA=E5=8A=A8=E5=88=87=E6=8D=A2?= =?UTF-8?q?=E8=AF=BB=E5=86=99=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/Entity/EntityEx.cs | 39 ++++++++++++++----- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityEx.cs index 9186a1c..d0de5ca 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityEx.cs @@ -6,7 +6,7 @@ /// public static class EntityEx { - + #region 实体线性变换 @@ -18,7 +18,10 @@ public static class EntityEx /// 目标点 public static void Move(this Entity ent, Point3d from, Point3d to) { - ent.TransformBy(Matrix3d.Displacement(to - from)); + using (ent.ForWrite()) + { + ent.TransformBy(Matrix3d.Displacement(to - from)); + } } /// @@ -29,7 +32,10 @@ public static void Move(this Entity ent, Point3d from, Point3d to) /// 缩放比例 public static void Scale(this Entity ent, Point3d center, double scaleValue) { - ent.TransformBy(Matrix3d.Scaling(scaleValue, center)); + using (ent.ForWrite()) + { + ent.TransformBy(Matrix3d.Scaling(scaleValue, center)); + } } /// @@ -41,7 +47,10 @@ public static void Scale(this Entity ent, Point3d center, double scaleValue) /// 旋转平面的法向矢量 public static void Rotation(this Entity ent, Point3d center, double angle, Vector3d normal) { - ent.TransformBy(Matrix3d.Rotation(angle, normal, center)); + using (ent.ForWrite()) + { + ent.TransformBy(Matrix3d.Rotation(angle, normal, center)); + } } /// @@ -52,7 +61,10 @@ public static void Rotation(this Entity ent, Point3d center, double angle, Vecto /// 转角,弧度制,正数为顺时针 public static void Rotation(this Entity ent, Point3d center, double angle) { - ent.TransformBy(Matrix3d.Rotation(angle, Vector3d.ZAxis.TransformBy(ent.Ecs), center)); + using (ent.ForWrite()) + { + ent.TransformBy(Matrix3d.Rotation(angle, Vector3d.ZAxis.TransformBy(ent.Ecs), center)); + } } /// @@ -63,7 +75,10 @@ public static void Rotation(this Entity ent, Point3d center, double angle) /// 对称轴终点 public static void Mirror(this Entity ent, Point3d startPoint, Point3d endPoint) { - ent.TransformBy(Matrix3d.Mirroring(new Line3d(startPoint, endPoint))); + using (ent.ForWrite()) + { + ent.TransformBy(Matrix3d.Mirroring(new Line3d(startPoint, endPoint))); + } } /// @@ -73,7 +88,10 @@ public static void Mirror(this Entity ent, Point3d startPoint, Point3d endPoint) /// 对称平面 public static void Mirror(this Entity ent, Plane plane) { - ent.TransformBy(Matrix3d.Mirroring(plane)); + using (ent.ForWrite()) + { + ent.TransformBy(Matrix3d.Mirroring(plane)); + } } /// @@ -83,7 +101,10 @@ public static void Mirror(this Entity ent, Plane plane) /// 对称点 public static void Mirror(this Entity ent, Point3d basePoint) { - ent.TransformBy(Matrix3d.Mirroring(basePoint)); + using (ent.ForWrite()) + { + ent.TransformBy(Matrix3d.Mirroring(basePoint)); + } } #endregion @@ -106,7 +127,7 @@ public static Extents3d GetExtents(this IEnumerable ents) } #endregion - + /// /// 获取图元包围盒 -- Gitee From 1602c1f5f6900f37b72f75f4dba276ed75e946b1 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sun, 16 Apr 2023 12:12:50 +0800 Subject: [PATCH 051/453] =?UTF-8?q?=E5=AF=B9=E8=B1=A1=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E5=87=BD=E6=95=B0=E9=87=8C=E8=87=AA=E5=8A=A8=E5=88=87=E6=8D=A2?= =?UTF-8?q?=E8=AF=BB=E5=86=99=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/RedrawEx.cs | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/RedrawEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/RedrawEx.cs index c42ec5c..f58f51d 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/RedrawEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/RedrawEx.cs @@ -68,16 +68,20 @@ public static class RedrawEx /// 刷新屏幕 /// /// 编辑器 - /// 图元,调用时候图元必须提权 + /// 图元 public static void Redraw(this Editor ed, Entity? ent = null) { - // 刷新图元 - ent?.Redraw(BrightEntity.Draw | - BrightEntity.RecordGraphicsModified | - BrightEntity.RecomputeDimensionBlock | - BrightEntity.MoveZero); - // 刷新 - ed.Redraw(BrightEditor.UpdateScreen); + using (ent?.ForWrite()) + { + // 刷新图元 + ent?.Redraw(BrightEntity.Draw | + BrightEntity.RecordGraphicsModified | + BrightEntity.RecomputeDimensionBlock | + BrightEntity.MoveZero); + // 刷新 + ed.Redraw(BrightEditor.UpdateScreen); + } + /* * 我发现命令加 CommandFlags.Redraw 就不需要以下处理了: -- Gitee From 99484d7f6311ef318b4c4b7eb03146d55b20507b Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Wed, 26 Apr 2023 21:36:17 +0800 Subject: [PATCH 052/453] =?UTF-8?q?=E6=8B=BC=E5=86=99=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs index 171d110..d0d5105 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs @@ -76,8 +76,8 @@ public static ObjectId GetObjectId(this Database db, string handleString) { if (long.TryParse(handleString, System.Globalization.NumberStyles.HexNumber, null, out long l)) { - var hanle = new Handle(l); - if (db.TryGetObjectId(hanle, out ObjectId id)) + var handle = new Handle(l); + if (db.TryGetObjectId(handle, out ObjectId id)) { return id; } -- Gitee From 21c2a65eada7c077b73338e9c9cfcfa79934f985 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Thu, 20 Apr 2023 23:10:56 +0800 Subject: [PATCH 053/453] =?UTF-8?q?=E6=81=A2=E5=A4=8D=E5=9D=97=E5=B1=9E?= =?UTF-8?q?=E6=80=A7=E5=87=BD=E6=95=B0=E4=B8=BA=E5=B1=9E=E6=80=A7=E5=9D=97?= =?UTF-8?q?=E5=92=8C=E5=8A=A8=E6=80=81=E5=9D=97=E4=B8=A4=E4=B8=AA=E5=87=BD?= =?UTF-8?q?=E6=95=B0=20=E3=80=82fixed=20#I6XHI6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Entity/BlockReferenceEx.cs | 25 ++++--------------- tests/TestShared/TestBlock.cs | 4 +-- 2 files changed, 7 insertions(+), 22 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs index 4d7631b..32f1ad6 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs @@ -68,7 +68,7 @@ public static void ClipBlockRef(this BlockReference bref, Point3d pt1, Point3d p /// /// 更新动态块属性值 /// - private static void ChangeDynamicBlockProperty(BlockReference blockReference, + public static void ChangeDynamicBlockProperty(this BlockReference blockReference, Dictionary propertyNameValues) { using (blockReference.ForWrite()) @@ -81,7 +81,7 @@ private static void ChangeDynamicBlockProperty(BlockReference blockReference, /// /// 更新普通块的属性值 /// - private static void ChangePureBlockProperty(BlockReference blockReference, Dictionary propertyNameValues) + public static void ChangeBlockProperty(this BlockReference blockReference, Dictionary propertyNameValues) { var tr = DBTrans.GetTopTransaction(blockReference.Database); AttributeReference att; @@ -98,29 +98,14 @@ private static void ChangePureBlockProperty(BlockReference blockReference, Di att = (AttributeReference)item; } att.ForWrite(obj => { - if (propertyNameValues.TryGetValue(obj.Tag, out T? value)) + if (propertyNameValues.TryGetValue(obj.Tag, out string value)) { - obj.TextString = value?.ToString(); + obj.TextString = value; } }); } } - /// - /// 更新块属性值 - /// - /// 块 - /// 属性值字典 - public static void ChangeBlockProperty(this BlockReference blockReference, Dictionary propertyNameValues) - { - if (blockReference.IsDynamicBlock) - { - ChangeDynamicBlockProperty(blockReference, propertyNameValues); - } - else - { - ChangePureBlockProperty(blockReference, propertyNameValues); - } - } + /// /// 获取嵌套块的位置(wcs) /// diff --git a/tests/TestShared/TestBlock.cs b/tests/TestShared/TestBlock.cs index cb45f67..d2ccad6 100644 --- a/tests/TestShared/TestBlock.cs +++ b/tests/TestShared/TestBlock.cs @@ -525,13 +525,13 @@ public void ChangeDynameicBlock() var blockid = Env.Editor.GetEntity("选择个块").ObjectId; using DBTrans tr = new(); var brf = tr.GetObject(blockid)!; - brf.ChangeBlockProperty(pro); + brf.ChangeDynamicBlockProperty(pro); // 这是第一个函数的用法 } [CommandMethod(nameof(ChangeBlockProperty))] public void ChangeBlockProperty() { - Dictionary? pro = new Dictionary + Dictionary? pro = new() { { "haha", "1" } }; -- Gitee From 25b1c0fa877adf9ba5e5bc14d1c25305e614a072 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Thu, 20 Apr 2023 23:45:45 +0800 Subject: [PATCH 054/453] =?UTF-8?q?=E6=B5=8B=E8=AF=95=E6=8F=90=E6=9D=83?= =?UTF-8?q?=E5=87=BD=E6=95=B0=E7=9A=84=E9=80=9F=E5=BA=A6=EF=BC=8Cusing?= =?UTF-8?q?=E6=A8=A1=E5=BC=8F=E6=AF=94=E5=A7=94=E6=89=98=E6=A8=A1=E5=BC=8F?= =?UTF-8?q?=E5=BF=AB=E4=B8=80=E5=80=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/DBObjectEx.cs | 2 +- .../IFox.CAD.Shared/ExtensionMethod/Tools.cs | 26 +++++++++++++++++- tests/TestShared/TestDBobject.cs | 27 +++++++++++++++++++ tests/TestShared/TestShared.projitems | 1 + 4 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 tests/TestShared/TestDBobject.cs diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBObjectEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBObjectEx.cs index 711c270..f535937 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBObjectEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBObjectEx.cs @@ -90,7 +90,7 @@ public static void ChangeXData(this DBObject obj, string appName, DxfCode dxfCod #line hidden // 调试的时候跳过它 /// - /// 实体自动管理读写函数 + /// 实体自动管理读写函数,此函数性能比using模式低一倍 /// /// 实体类型 /// 实体对象 diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Tools.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Tools.cs index 1127722..b5b8f2c 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Tools.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Tools.cs @@ -26,6 +26,30 @@ public static void TestTimes2(int count, string message, Action action) Env.Print($"{message} 代码执行 {count} 次的时间:{time} ({name})"); // 总毫秒数 } + /// + /// 计时器 + /// + [System.Diagnostics.DebuggerStepThrough] + public static void TestTimes3(int count, string message, Action action) + { + System.Diagnostics.Stopwatch watch = new(); + watch.Start(); // 开始监视代码运行时间 + for (int i = 0; i < count; i++) + action.Invoke(i);// 需要测试的代码 + watch.Stop(); // 停止监视 + TimeSpan timespan = watch.Elapsed; // 获取当前实例测量得出的总时间 + double time = timespan.TotalMilliseconds; + string name = "毫秒"; + if (timespan.TotalMilliseconds > 1000) + { + time = timespan.TotalSeconds; + name = "秒"; + } + Env.Print($"{message} 代码执行 {count} 次的时间:{time} ({name})"); // 总毫秒数 + } + + + /// /// 纳秒计时器 /// @@ -35,7 +59,7 @@ public static void TestTimes(int count, string message, Action action, { var time = RunTime(() => { for (int i = 0; i < count; i++) - action(); + action.Invoke(); }, timeEnum); string timeNameZn = ""; diff --git a/tests/TestShared/TestDBobject.cs b/tests/TestShared/TestDBobject.cs new file mode 100644 index 0000000..f0cb142 --- /dev/null +++ b/tests/TestShared/TestDBobject.cs @@ -0,0 +1,27 @@ + + +namespace TestShared +{ + public static class TestDBobject + { + [CommandMethod(nameof(TestForWrite))] + public static void TestForWrite() + { + using var tr = new DBTrans(); + var ent = Env.Editor.GetEntity("\npick entity"); + if (ent.Status is not PromptStatus.OK) return; + var entid = ent.ObjectId.GetObject()!; + Tools.TestTimes3(100000, "using:", i => { + using (entid.ForWrite()) + { + entid.ColorIndex = i % 7; + } + }); + Tools.TestTimes3(100000, "action:", i => { + entid.ForWrite(e => { + e.ColorIndex = i % 7; + }); + }); + } + } +} diff --git a/tests/TestShared/TestShared.projitems b/tests/TestShared/TestShared.projitems index 0581627..105f637 100644 --- a/tests/TestShared/TestShared.projitems +++ b/tests/TestShared/TestShared.projitems @@ -16,6 +16,7 @@ + -- Gitee From eebc0564e4e1fa8653d722a1f29149aa2e015925 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Thu, 20 Apr 2023 23:50:04 +0800 Subject: [PATCH 055/453] =?UTF-8?q?=E6=9B=B4=E6=94=B9forwrite=E5=A7=94?= =?UTF-8?q?=E6=89=98=E8=B0=83=E7=94=A8=E4=B8=BAusing=E8=B0=83=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/Entity/BlockReferenceEx.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs index 32f1ad6..f3dac76 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs @@ -97,12 +97,13 @@ public static void ChangeBlockProperty(this BlockReference blockReference, Dicti // 某些情况下,比如你exploded炸开块后的子块块参照是没有在数据库里的,这时候返回的结果就是 AttributeReference att = (AttributeReference)item; } - att.ForWrite(obj => { - if (propertyNameValues.TryGetValue(obj.Tag, out string value)) + using (att.ForWrite()) + { + if (propertyNameValues.TryGetValue(att.Tag, out string value)) { - obj.TextString = value; + att.TextString = value; } - }); + } } } -- Gitee From c7e42322aaf1faff674d2741af66dd6827198793 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Wed, 26 Apr 2023 21:41:20 +0800 Subject: [PATCH 056/453] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E8=AF=AD=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs index d0d5105..9c2a359 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs @@ -92,7 +92,7 @@ public static ObjectId GetObjectId(this Database db, string handleString) /// id有效返回 ,反之返回 public static bool IsOk(this ObjectId id) { - return !id.IsNull && id.IsValid && !id.IsErased && !id.IsEffectivelyErased && id.IsResident; + return id is { IsNull: false, IsValid: true, IsErased: false, IsEffectivelyErased: false, IsResident: true }; } /// -- Gitee From 4d81f5af6c9ee7e27916e7552cb08e2a347fbb79 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Wed, 26 Apr 2023 21:45:58 +0800 Subject: [PATCH 057/453] =?UTF-8?q?=E7=9E=AC=E6=80=81=E5=9C=A8=E4=B8=AD?= =?UTF-8?q?=E6=9C=9Bcad=E7=9A=84=E5=8F=AF=E4=BB=A5=E7=94=A8=E7=9A=84?= =?UTF-8?q?=E4=B8=8D=E9=9C=80=E8=A6=81=E9=99=90=E5=88=B6acad?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../IFox.CAD.Shared/ExtensionMethod/Jig/JigExTransient.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigExTransient.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigExTransient.cs index 55f9e8e..6dc7efc 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigExTransient.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigExTransient.cs @@ -1,5 +1,4 @@ -#if acad -namespace IFoxCAD.Cad; +namespace IFoxCAD.Cad; /// /// 瞬态容器 @@ -139,5 +138,4 @@ protected virtual void Dispose(bool disposing) Clear();// 清空瞬态容器并移除对象在图纸上的显示 } #endregion -} -#endif \ No newline at end of file +} \ No newline at end of file -- Gitee From 95c658bd1e074fe64c981d7db9a4ff27c697b756 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Wed, 26 Apr 2023 22:50:32 +0800 Subject: [PATCH 058/453] =?UTF-8?q?2d=E7=82=B9=E7=9A=84GetMidPointTo?= =?UTF-8?q?=E6=96=B9=E6=B3=95=E5=90=8D=E9=87=8D=E5=A4=8D=EF=BC=8C=E5=88=A0?= =?UTF-8?q?=E9=99=A4=E4=B8=80=E4=B8=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs index 58e9da3..12355c0 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs @@ -617,18 +617,6 @@ public static Point3d GetMidPointTo(this Point3d pt1, Point3d pt2) pt1.Z * 0.5 + pt2.Z * 0.5); } - /// - /// 获取两个点之间的中点 - /// - /// 第一点 - /// 第二点 - /// 返回两个点之间的中点 - public static Point2d GetMidPointTo(this Point2d pt1, Point2d pt2) - { - // (pt1 + pt2) / 2; // 溢出风险 - return new(pt1.X * 0.5 + pt2.X * 0.5, - pt1.Y * 0.5 + pt2.Y * 0.5); - } /// /// 根据世界坐标计算用户坐标 -- Gitee From 1fdd3805d3cb183d3f65d4e3e153e83f193a2574 Mon Sep 17 00:00:00 2001 From: Music_Die Date: Tue, 25 Apr 2023 16:15:34 +0800 Subject: [PATCH 059/453] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E4=B8=BAdwg=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E6=B7=BB=E5=8A=A0=E6=A0=87=E8=AE=B0=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/DwgMark.cs | 63 +++++++++++++++++++ .../IFox.CAD.Shared/IFox.CAD.Shared.projitems | 1 + tests/TestShared/TestDwgMark.cs | 11 ++++ tests/TestShared/TestShared.projitems | 1 + 4 files changed, 76 insertions(+) create mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/DwgMark.cs create mode 100644 tests/TestShared/TestDwgMark.cs diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/DwgMark.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/DwgMark.cs new file mode 100644 index 0000000..c82ed23 --- /dev/null +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/DwgMark.cs @@ -0,0 +1,63 @@ +namespace IFoxCAD.Cad; +/// +/// Ϊdwgļӱ +/// +public static class DwgMark +{ + + private const int FREESPACE = 0x15; + private const int FREESPACEDEFAULT = 0x00; + /// + /// Ϊdwgļӱʶ + /// + /// DWGļ + /// ASCIIʶֽ0X00~0X7F + /// dwgļᱨbiteҲ + public static void AddMark(FileInfo file, int bite) + { + if (file.Extension.ToLower() != ".dwg") + { + throw new ArgumentException("dwgļ"); + } + if (bite > 0x7F || bite < 0x00) + { + throw new ArgumentException("ַASCIIΧ"); + } + using BinaryWriter bw = new BinaryWriter(File.Open(file.FullName, FileMode.Open)); + bw.BaseStream.Position = FREESPACE;//ļͷ21ֽ + bw.Write(bite); //дݣһֽ + } + /// + /// dwgļǻָΪĬֵ + /// + /// ļ + /// dwgļᱨ + public static void RemoveMark(FileInfo file) + { + if (file.Extension.ToLower() != ".dwg") + { + throw new ArgumentException("dwgļ"); + } + using BinaryWriter bw = new BinaryWriter(File.Open(file.FullName, FileMode.Open)); + bw.BaseStream.Position = FREESPACE;//ļͷ21ֽ + bw.Write(FREESPACEDEFAULT); //дݣһֽ + } + /// + /// ȡõdwgļ + /// + /// ļ + /// + /// dwgļᱨ + public static int GetMark(FileInfo file) + { + if (file.Extension.ToLower() != ".dwg") + { + throw new ArgumentException("dwgļ"); + } + using FileStream fs = File.OpenRead(file.FullName); + fs.Seek(FREESPACE, SeekOrigin.Begin); + byte[] mark = new byte[1]; + fs.Read(mark, 0, mark.Length); + return mark[0]; + } +} diff --git a/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems b/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems index 13b7df2..c77cbc0 100644 --- a/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems +++ b/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems @@ -28,6 +28,7 @@ + diff --git a/tests/TestShared/TestDwgMark.cs b/tests/TestShared/TestDwgMark.cs new file mode 100644 index 0000000..cf0d712 --- /dev/null +++ b/tests/TestShared/TestDwgMark.cs @@ -0,0 +1,11 @@ +namespace Test; +using IFoxCAD.Cad; +public class TestDwgMark { + [CommandMethod(nameof(DwgMarktest))] + public void DwgMarktest() { + FileInfo file = new FileInfo(@"D:\TEST\1.dwg"); + DwgMark.AddMark(file, 0x4D); + DwgMark.RemoveMark(file); + int A = DwgMark.GetMark(file); + } +} \ No newline at end of file diff --git a/tests/TestShared/TestShared.projitems b/tests/TestShared/TestShared.projitems index 105f637..dd9a61c 100644 --- a/tests/TestShared/TestShared.projitems +++ b/tests/TestShared/TestShared.projitems @@ -19,6 +19,7 @@ + -- Gitee From d12b50522c30cd0baa53033817263f18b735337b Mon Sep 17 00:00:00 2001 From: vicwjb Date: Sat, 29 Apr 2023 00:00:45 +0800 Subject: [PATCH 060/453] =?UTF-8?q?=E7=9E=AC=E6=80=81=E4=B8=8D=E8=83=BD?= =?UTF-8?q?=E5=9C=A8=E6=B5=A9=E8=BE=B0=E9=87=8C=E4=BD=BF=E7=94=A8=EF=BC=8C?= =?UTF-8?q?=E8=BF=9B=E8=A1=8C=E5=B1=8F=E8=94=BD=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/Jig/JigExTransient.cs | 11 ++- src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs | 78 ++++++++++--------- 2 files changed, 49 insertions(+), 40 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigExTransient.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigExTransient.cs index 6dc7efc..9ac679a 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigExTransient.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigExTransient.cs @@ -1,4 +1,5 @@ -namespace IFoxCAD.Cad; +#if !gcad +namespace IFoxCAD.Cad; /// /// 瞬态容器 @@ -108,7 +109,10 @@ public void UpdateAll() #endregion #region IDisposable接口相关函数 - public bool IsDisposed { get; private set; } = false; + /// + /// 是否注销 + /// + public bool IsDisposed { get; private set; } /// /// 手动释放 @@ -138,4 +142,5 @@ protected virtual void Dispose(bool disposing) Clear();// 清空瞬态容器并移除对象在图纸上的显示 } #endregion -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs b/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs index 9288fd1..bb4fe6b 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs @@ -2,7 +2,6 @@ namespace IFoxCAD.Cad; using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; using System.IO; using System.Threading; using System.Windows.Forms; @@ -16,7 +15,7 @@ namespace IFoxCAD.Cad; public class DBTrans : IDisposable { [DebuggerBrowsable(DebuggerBrowsableState.Never)] - string DebuggerDisplay => ToString(" | "); + private string DebuggerDisplay => ToString(" | "); #region 静态函数 /// @@ -24,11 +23,11 @@ public class DBTrans : IDisposable /// /// 数据库 /// 事务对象 - public static Transaction GetTopTransaction([DisallowNull] Database database) + public static Transaction GetTopTransaction(Database database) { return database.TransactionManager.TopTransaction switch { - Transaction tr => tr, + { } tr => tr, _ => throw new Exception("没有顶层事务!") }; } @@ -63,19 +62,19 @@ public static DBTrans GetTop(Database database) /// /// 事务栈 /// - static readonly Stack _dBTrans = new(); + private static readonly Stack _dBTrans = new(); /// /// 文档锁 /// - readonly DocumentLock? _documentLock; + private readonly DocumentLock? _documentLock; /// /// 是否提交事务 /// - bool _commit; + private bool _commit; /// /// 文件名 /// - readonly string? _fileName; + private readonly string? _fileName; #endregion #region 公开属性 @@ -285,8 +284,9 @@ public static implicit operator Transaction(DBTrans tr) /// /// 块表 /// - public SymbolTable BlockTable => _BlockTable ??= new(this, Database.BlockTableId); - SymbolTable? _BlockTable; + public SymbolTable BlockTable => _blockTable ??= new(this, Database.BlockTableId); + + private SymbolTable? _blockTable; /// /// 当前绘图空间 /// @@ -302,43 +302,51 @@ public static implicit operator Transaction(DBTrans tr) /// /// 层表 /// - public SymbolTable LayerTable => _LayerTable ??= new(this, Database.LayerTableId); - SymbolTable? _LayerTable; + public SymbolTable LayerTable => _layerTable ??= new(this, Database.LayerTableId); + + private SymbolTable? _layerTable; /// /// 文字样式表 /// - public SymbolTable TextStyleTable => _TextStyleTable ??= new(this, Database.TextStyleTableId); - SymbolTable? _TextStyleTable; + public SymbolTable TextStyleTable => _textStyleTable ??= new(this, Database.TextStyleTableId); + + private SymbolTable? _textStyleTable; /// /// 注册应用程序表 /// - public SymbolTable RegAppTable => _RegAppTable ??= new(this, Database.RegAppTableId); - SymbolTable? _RegAppTable; + public SymbolTable RegAppTable => _regAppTable ??= new(this, Database.RegAppTableId); + + private SymbolTable? _regAppTable; /// /// 标注样式表 /// - public SymbolTable DimStyleTable => _DimStyleTable ??= new(this, Database.DimStyleTableId); - SymbolTable? _DimStyleTable; + public SymbolTable DimStyleTable => _dimStyleTable ??= new(this, Database.DimStyleTableId); + + private SymbolTable? _dimStyleTable; /// /// 线型表 /// - public SymbolTable LinetypeTable => _LinetypeTable ??= new(this, Database.LinetypeTableId); - SymbolTable? _LinetypeTable; + public SymbolTable LinetypeTable => _linetypeTable ??= new(this, Database.LinetypeTableId); + + private SymbolTable? _linetypeTable; /// /// 用户坐标系表 /// - public SymbolTable UcsTable => _UcsTable ??= new(this, Database.UcsTableId); - SymbolTable? _UcsTable; + public SymbolTable UcsTable => _ucsTable ??= new(this, Database.UcsTableId); + + private SymbolTable? _ucsTable; /// /// 视图表 /// - public SymbolTable ViewTable => _ViewTable ??= new(this, Database.ViewTableId); - SymbolTable? _ViewTable; + public SymbolTable ViewTable => _viewTable ??= new(this, Database.ViewTableId); + + private SymbolTable? _viewTable; /// /// 视口表 /// - public SymbolTable ViewportTable => _ViewportTable ??= new(this, Database.ViewportTableId); - SymbolTable? _ViewportTable; + public SymbolTable ViewportTable => _viewportTable ??= new(this, Database.ViewportTableId); + + private SymbolTable? _viewportTable; #endregion #region 字典 @@ -357,6 +365,7 @@ public static implicit operator Transaction(DBTrans tr) /// /// 多线样式字典 /// + // ReSharper disable once InconsistentNaming public DBDictionary MLStyleDict => GetObject(Database.MLStyleDictionaryId)!; /// /// 材质字典 @@ -494,11 +503,8 @@ public void SaveFile(DwgVersion version = DwgVersion.AC1800, // 前台开图,使用命令保存;不需要切换文档 if (doc != null) { - if (saveAsFile == null) - doc.SendStringToExecute("_qsave\n", false, true, true); - else - // 无法把 给这个面板 - doc.SendStringToExecute($"_Saveas\n", false, true, true); + // 无法把 给这个面板 + doc.SendStringToExecute(saveAsFile == null ? "_qsave\n" : $"_Saveas\n", false, true, true); return; } @@ -579,7 +585,7 @@ public void SaveFile(DwgVersion version = DwgVersion.AC1800, /// 获取文件名,无效的话就制造 /// /// - (bool error, string path) GetOrCreateSaveAsFile() + private (bool error, string path) GetOrCreateSaveAsFile() { var file = Database.Filename; if (!string.IsNullOrWhiteSpace(file)) @@ -630,6 +636,7 @@ public void SaveFile(DwgVersion version = DwgVersion.AC1800, /// /// 委托 /// 开启单行文字偏移处理 + // ReSharper disable once InconsistentNaming public void Task(Action action, bool handlingDBTextDeviation = true) { //if (action == null) @@ -683,7 +690,7 @@ public void Commit() /// /// 是否释放事务 /// - public bool IsDisposed { get; private set; } = false; + public bool IsDisposed { get; private set; } /// /// 手动调用释放 @@ -777,10 +784,7 @@ public string ToString(string? format = null, IFormatProvider? formatProvider = $"Database = {Database != null}" }; - if (!string.IsNullOrWhiteSpace(format)) - return string.Join(format, lines.ToArray()); - - return string.Join("\n", lines.ToArray()); + return string.Join(!string.IsNullOrWhiteSpace(format) ? format : "\n", lines.ToArray()); } #endregion } \ No newline at end of file -- Gitee From 19d51d3dbc5afa6eadae22b072015bbae15f7ff5 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Tue, 2 May 2023 17:20:33 +0800 Subject: [PATCH 061/453] =?UTF-8?q?=E6=B6=88=E9=99=A4=E8=AD=A6=E5=91=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/Entity/EntityBoundingInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs index fb3d5fa..a9227a0 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs @@ -124,7 +124,7 @@ public static BoundingInfo GetBoundingInfo(Entity ent) { return new(ent.GeometricExtents.MinPoint, ent.GeometricExtents.MaxPoint, true); } - catch (Exception e) { } + catch { } return new(Point3d.Origin, Point3d.Origin, false); } -- Gitee From bd708c9ed5ceb23edef57fe9472b32b4331abea0 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Tue, 2 May 2023 17:21:54 +0800 Subject: [PATCH 062/453] =?UTF-8?q?=E6=B6=88=E9=99=A4=E8=AD=A6=E5=91=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs index e40a5a2..4cf0436 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs @@ -40,7 +40,7 @@ public static void DeepCloneEx(this BlockTableRecord btr, ObjectIdCollection obj // foreach (ObjectId item in blockIds) // result.Add(mapping[item].Value); } - catch (System.Exception e) + catch { } -- Gitee From d3f5747279fcd94b0ac24283f61af0d7f78eb441 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Wed, 3 May 2023 23:16:34 +0800 Subject: [PATCH 063/453] =?UTF-8?q?=E5=8F=91=E5=B8=830.6.1=E7=89=88?= =?UTF-8?q?=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Basal/Directory.Build.props | 4 ++-- src/CAD/Directory.Build.props | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Basal/Directory.Build.props b/src/Basal/Directory.Build.props index 0b335fd..7ed6b54 100644 --- a/src/Basal/Directory.Build.props +++ b/src/Basal/Directory.Build.props @@ -1,8 +1,8 @@  - 0.6.0-alpha2 - 发布个alpha版 + 0.6.1 + 发布0.6.1版 diff --git a/src/CAD/Directory.Build.props b/src/CAD/Directory.Build.props index 3460c56..90de1e7 100644 --- a/src/CAD/Directory.Build.props +++ b/src/CAD/Directory.Build.props @@ -1,8 +1,8 @@  - 0.6.0-alpha2 - 发布个alpha版 + 0.6.1 + 发布0.6.1版 -- Gitee From 90de7e11b71fbb755ce94b3d4b698b40b7b2f20f Mon Sep 17 00:00:00 2001 From: vicwjb Date: Wed, 3 May 2023 23:54:44 +0800 Subject: [PATCH 064/453] =?UTF-8?q?=E6=9B=B4=E6=96=B0net=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E4=B8=BAnet48=EF=BC=8C=E5=88=A0=E9=99=A4=E5=85=83=E7=BB=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Basal/Directory.Build.props | 4 +- .../IFox.Basal.Shared/CLS/RuntimeHelpers.cs | 3 +- .../CLS/TupleElementNamesAttribute.cs | 7 +- src/Basal/IFox.Basal.Shared/CLS/ValueTuple.cs | 2123 ----------------- .../IFox.Basal.Shared.projitems | 1 - src/Basal/IFox.Basal/GlobalUsings.cs | 4 - src/Basal/IFox.Basal/IFox.Basal.csproj | 11 +- src/CAD/IFox.CAD.ACAD/IFox.CAD.ACAD.csproj | 18 +- tests/TestAcad09plus/TestAcad09plus.csproj | 6 +- 9 files changed, 23 insertions(+), 2154 deletions(-) delete mode 100644 src/Basal/IFox.Basal.Shared/CLS/ValueTuple.cs diff --git a/src/Basal/Directory.Build.props b/src/Basal/Directory.Build.props index 7ed6b54..375e114 100644 --- a/src/Basal/Directory.Build.props +++ b/src/Basal/Directory.Build.props @@ -1,8 +1,8 @@  - 0.6.1 - 发布0.6.1版 + 0.7.0-alpha1 + 发布0.7.0-alpha1版 diff --git a/src/Basal/IFox.Basal.Shared/CLS/RuntimeHelpers.cs b/src/Basal/IFox.Basal.Shared/CLS/RuntimeHelpers.cs index 841c0d5..6dcdb89 100644 --- a/src/Basal/IFox.Basal.Shared/CLS/RuntimeHelpers.cs +++ b/src/Basal/IFox.Basal.Shared/CLS/RuntimeHelpers.cs @@ -1,4 +1,4 @@ - +#if false // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. @@ -55,3 +55,4 @@ public static T[] GetSubArray(T[] array, Range range) } } #endif +#endif \ No newline at end of file diff --git a/src/Basal/IFox.Basal.Shared/CLS/TupleElementNamesAttribute.cs b/src/Basal/IFox.Basal.Shared/CLS/TupleElementNamesAttribute.cs index 93e6193..747ae51 100644 --- a/src/Basal/IFox.Basal.Shared/CLS/TupleElementNamesAttribute.cs +++ b/src/Basal/IFox.Basal.Shared/CLS/TupleElementNamesAttribute.cs @@ -1,4 +1,5 @@ -// Licensed to the .NET Foundation under one or more agreements. +#if false +// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. @@ -45,4 +46,6 @@ public TupleElementNamesAttribute(string[] transformNames) /// meant to carry element names. /// public IList TransformNames => _transformNames; -} \ No newline at end of file +} + +#endif \ No newline at end of file diff --git a/src/Basal/IFox.Basal.Shared/CLS/ValueTuple.cs b/src/Basal/IFox.Basal.Shared/CLS/ValueTuple.cs deleted file mode 100644 index 3ce158c..0000000 --- a/src/Basal/IFox.Basal.Shared/CLS/ValueTuple.cs +++ /dev/null @@ -1,2123 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -// #pragma warning disable SA1141 // explicitly not using tuple syntax in tuple implementation -#if !NOVALUETUPLE - -using System.Numerics.Hashing; - -/* - * 1. 元组是net47之后提供的特性,所以net47之前的版本是都没有的 - * 2. 通过定义常量的办法将元组屏蔽,很奇怪的是源码包可以,但是普通包不行,所以推荐使用源码包 index和range的情况类似 - * 这种问题就没有很好的解决方式,因为用了ifox就不能用其他的index,range,valuetuple类库,但是其他的三方库却依赖 - * 这些类库,所以还是使用源码包吧。 -*/ - -namespace System.Numerics.Hashing -{ - internal static class HashHelpers - { - public static readonly int RandomSeed = Guid.NewGuid().GetHashCode(); - - public static int Combine(int h1, int h2) - { - unchecked - { - // RyuJIT optimizes this to use the ROL instruction - // Related GitHub pull request: dotnet/coreclr#1830 - - // RyuJIT 对此进行了优化以使用 ROL 指令 - // 相关 GitHub 拉取请求:dotnet/coreclr#1830 - uint rol5 = ((uint)h1 << 5) | ((uint)h1 >> 27); - return ((int)rol5 + h1) ^ h2; - } - } - } -} - - - - -namespace System -{ - - // internal static class SR - internal sealed partial class SR - { - // public const string ArgumentException_ValueTupleIncorrectType = "The parameter should be a ValueTuple type of appropriate arity."; - // public const string ArgumentException_ValueTupleLastArgumentNotAValueTuple = "The TRest type argument of ValueTuple`8 must be a ValueTuple."; - public const string ArgumentException_ValueTupleIncorrectType = "该参数应该是适当数量的 ValueTuple 类型."; - public const string ArgumentException_ValueTupleLastArgumentNotAValueTuple = "ValueTuple`8 的 TREST 类型参数必须是 ValueTuple."; - } - - // Helper so we can call some tuple methods recursively without knowing the underlying types. - /// - /// 帮助器,因此我们可以在不知道底层类型的情况下递归调用一些元组方法. - /// - internal interface ITupleInternal - { - int GetHashCode(IEqualityComparer comparer); - int Size { get; } - string ToStringEnd(); - } - - - // The ValueTuple types (from arity 0 to 8) comprise the runtime implementation that underlies tuples in C# and struct tuples in F#. - // Aside from created via language syntax, they are most easily created via the ValueTuple.Create factory methods. - // The System.ValueTuple types differ from the System.Tuple types in that: - // - they are structs rather than classes, - // - they are mutable rather than readonly, and - // - their members (such as Item1, Item2, etc) are fields rather than properties. - /// - /// ValueTuple 类型(从 arity 0 到 8)包含运行时实现,它是 C# 中的元组和 F# 中的结构元组的基础. - /// 除了通过语言语法创建之外,它们最容易通过 ValueTuple.Create 工厂方法创建. - /// System.ValueTuple 类型与 System.Tuple 类型的不同之处在于: - /// - 它们是结构而不是类, - /// - 它们是可变的而不是只读的,并且 - /// - 它们的成员(例如 Item1、Item2 等)是字段而不是属性. - /// - public struct ValueTuple - : IEquatable, IStructuralEquatable, IStructuralComparable, IComparable, IComparable, ITupleInternal - { - /// - /// Returns a value that indicates whether the current instance is equal to a specified object. - /// - /// The object to compare with this instance. - /// if is a . - public override bool Equals(object obj) - { - return obj is ValueTuple; - } - - /// Returns a value indicating whether this instance is equal to a specified value. - /// An instance to compare to this instance. - /// true if has the same value as this instance; otherwise, false. - public bool Equals(ValueTuple other) - { - return true; - } - - bool IStructuralEquatable.Equals(object? other, IEqualityComparer comparer) - { - return other is ValueTuple; - } - - int IComparable.CompareTo(object other) - { - if (other == null) return 1; - - if (other is not ValueTuple) - { - throw new ArgumentException(SR.ArgumentException_ValueTupleIncorrectType, nameof(other)); - } - - return 0; - } - - /// Compares this instance to a specified instance and returns an indication of their relative values. - /// An instance to compare. - /// - /// A signed number indicating the relative values of this instance and . - /// Returns less than zero if this instance is less than , zero if this - /// instance is equal to , and greater than zero if this instance is greater - /// than . - /// - public int CompareTo(ValueTuple other) - { - return 0; - } - - int IStructuralComparable.CompareTo(object? other, IComparer comparer) - { - if (other == null) return 1; - - if (other is not ValueTuple) - { - throw new ArgumentException(SR.ArgumentException_ValueTupleIncorrectType, nameof(other)); - } - - return 0; - } - - /// Returns the hash code for this instance. - /// A 32-bit signed integer hash code. - public override int GetHashCode() - { - return 0; - } - - int IStructuralEquatable.GetHashCode(IEqualityComparer comparer) - { - return 0; - } - - int ITupleInternal.GetHashCode(IEqualityComparer comparer) - { - return 0; - } - - /// - /// Returns a string that represents the value of this instance. - /// - /// The string representation of this instance. - /// - /// The string returned by this method takes the form (). - /// - public override string ToString() - { - return "()"; - } - - string ITupleInternal.ToStringEnd() - { - return ")"; - } - - int ITupleInternal.Size => 0; - - /// Creates a new struct 0-tuple. - /// A 0-tuple. - public static ValueTuple Create() => new(); - - /// Creates a new struct 1-tuple, or singleton. - /// The type of the first component of the tuple. - /// The value of the first component of the tuple. - /// A 1-tuple (singleton) whose value is (item1). - public static ValueTuple Create(T1 item1) => new(item1); - - /// Creates a new struct 2-tuple, or pair. - /// The type of the first component of the tuple. - /// The type of the second component of the tuple. - /// The value of the first component of the tuple. - /// The value of the second component of the tuple. - /// A 2-tuple (pair) whose value is (item1, item2). - public static ValueTuple Create(T1 item1, T2 item2) => new(item1, item2); - - /// Creates a new struct 3-tuple, or triple. - /// The type of the first component of the tuple. - /// The type of the second component of the tuple. - /// The type of the third component of the tuple. - /// The value of the first component of the tuple. - /// The value of the second component of the tuple. - /// The value of the third component of the tuple. - /// A 3-tuple (triple) whose value is (item1, item2, item3). - public static ValueTuple Create(T1 item1, T2 item2, T3 item3) => - new(item1, item2, item3); - - /// Creates a new struct 4-tuple, or quadruple. - /// The type of the first component of the tuple. - /// The type of the second component of the tuple. - /// The type of the third component of the tuple. - /// The type of the fourth component of the tuple. - /// The value of the first component of the tuple. - /// The value of the second component of the tuple. - /// The value of the third component of the tuple. - /// The value of the fourth component of the tuple. - /// A 4-tuple (quadruple) whose value is (item1, item2, item3, item4). - public static ValueTuple Create(T1 item1, T2 item2, T3 item3, T4 item4) => - new(item1, item2, item3, item4); - - /// Creates a new struct 5-tuple, or quintuple. - /// The type of the first component of the tuple. - /// The type of the second component of the tuple. - /// The type of the third component of the tuple. - /// The type of the fourth component of the tuple. - /// The type of the fifth component of the tuple. - /// The value of the first component of the tuple. - /// The value of the second component of the tuple. - /// The value of the third component of the tuple. - /// The value of the fourth component of the tuple. - /// The value of the fifth component of the tuple. - /// A 5-tuple (quintuple) whose value is (item1, item2, item3, item4, item5). - public static ValueTuple Create(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5) => - new(item1, item2, item3, item4, item5); - - /// Creates a new struct 6-tuple, or sextuple. - /// The type of the first component of the tuple. - /// The type of the second component of the tuple. - /// The type of the third component of the tuple. - /// The type of the fourth component of the tuple. - /// The type of the fifth component of the tuple. - /// The type of the sixth component of the tuple. - /// The value of the first component of the tuple. - /// The value of the second component of the tuple. - /// The value of the third component of the tuple. - /// The value of the fourth component of the tuple. - /// The value of the fifth component of the tuple. - /// The value of the sixth component of the tuple. - /// A 6-tuple (sextuple) whose value is (item1, item2, item3, item4, item5, item6). - public static ValueTuple Create(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6) => - new(item1, item2, item3, item4, item5, item6); - - /// Creates a new struct 7-tuple, or septuple. - /// The type of the first component of the tuple. - /// The type of the second component of the tuple. - /// The type of the third component of the tuple. - /// The type of the fourth component of the tuple. - /// The type of the fifth component of the tuple. - /// The type of the sixth component of the tuple. - /// The type of the seventh component of the tuple. - /// The value of the first component of the tuple. - /// The value of the second component of the tuple. - /// The value of the third component of the tuple. - /// The value of the fourth component of the tuple. - /// The value of the fifth component of the tuple. - /// The value of the sixth component of the tuple. - /// The value of the seventh component of the tuple. - /// A 7-tuple (septuple) whose value is (item1, item2, item3, item4, item5, item6, item7). - public static ValueTuple Create(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7) => - new(item1, item2, item3, item4, item5, item6, item7); - - /// Creates a new struct 8-tuple, or octuple. - /// The type of the first component of the tuple. - /// The type of the second component of the tuple. - /// The type of the third component of the tuple. - /// The type of the fourth component of the tuple. - /// The type of the fifth component of the tuple. - /// The type of the sixth component of the tuple. - /// The type of the seventh component of the tuple. - /// The type of the eighth component of the tuple. - /// The value of the first component of the tuple. - /// The value of the second component of the tuple. - /// The value of the third component of the tuple. - /// The value of the fourth component of the tuple. - /// The value of the fifth component of the tuple. - /// The value of the sixth component of the tuple. - /// The value of the seventh component of the tuple. - /// The value of the eighth component of the tuple. - /// An 8-tuple (octuple) whose value is (item1, item2, item3, item4, item5, item6, item7, item8). - public static ValueTuple> Create(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7, T8 item8) => - new(item1, item2, item3, item4, item5, item6, item7, ValueTuple.Create(item8)); - - internal static int CombineHashCodes(int h1, int h2) - { - return HashHelpers.Combine(HashHelpers.Combine(HashHelpers.RandomSeed, h1), h2); - } - - internal static int CombineHashCodes(int h1, int h2, int h3) - { - return HashHelpers.Combine(CombineHashCodes(h1, h2), h3); - } - - internal static int CombineHashCodes(int h1, int h2, int h3, int h4) - { - return HashHelpers.Combine(CombineHashCodes(h1, h2, h3), h4); - } - - internal static int CombineHashCodes(int h1, int h2, int h3, int h4, int h5) - { - return HashHelpers.Combine(CombineHashCodes(h1, h2, h3, h4), h5); - } - - internal static int CombineHashCodes(int h1, int h2, int h3, int h4, int h5, int h6) - { - return HashHelpers.Combine(CombineHashCodes(h1, h2, h3, h4, h5), h6); - } - - internal static int CombineHashCodes(int h1, int h2, int h3, int h4, int h5, int h6, int h7) - { - return HashHelpers.Combine(CombineHashCodes(h1, h2, h3, h4, h5, h6), h7); - } - - internal static int CombineHashCodes(int h1, int h2, int h3, int h4, int h5, int h6, int h7, int h8) - { - return HashHelpers.Combine(CombineHashCodes(h1, h2, h3, h4, h5, h6, h7), h8); - } - } - - /// Represents a 1-tuple, or singleton, as a value type. - /// The type of the tuple's only component. - public struct ValueTuple - : IEquatable>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable>, ITupleInternal - { - /// - /// The current instance's first component. - /// - public T1 Item1; - - /// - /// Initializes a new instance of the value type. - /// - /// The value of the tuple's first component. - public ValueTuple(T1 item1) - { - Item1 = item1; - } - - /// - /// Returns a value that indicates whether the current instance is equal to a specified object. - /// - /// The object to compare with this instance. - /// if the current instance is equal to the specified object; otherwise, . - /// - /// The parameter is considered to be equal to the current instance under the following conditions: - /// - /// It is a value type. - /// Its components are of the same types as those of the current instance. - /// Its components are equal to those of the current instance. Equality is determined by the default object equality comparer for each component. - /// - /// - public override bool Equals(object obj) - { - return obj is ValueTuple tuple && Equals(tuple); - } - - /// - /// Returns a value that indicates whether the current - /// instance is equal to a specified . - /// - /// The tuple to compare with this instance. - /// if the current instance is equal to the specified tuple; otherwise, . - /// - /// The parameter is considered to be equal to the current instance if each of its field - /// is equal to that of the current instance, using the default comparer for that field's type. - /// - public bool Equals(ValueTuple other) - { - return EqualityComparer.Default.Equals(Item1, other.Item1); - } - - bool IStructuralEquatable.Equals(object? other, IEqualityComparer comparer) - { - if (other == null || other is not ValueTuple) return false; - - var objTuple = (ValueTuple)other; - - return comparer.Equals(Item1, objTuple.Item1); - } - - int IComparable.CompareTo(object other) - { - if (other == null) return 1; - - if (other is not ValueTuple) - { - throw new ArgumentException(SR.ArgumentException_ValueTupleIncorrectType, nameof(other)); - } - - var objTuple = (ValueTuple)other; - - return Comparer.Default.Compare(Item1, objTuple.Item1); - } - - /// Compares this instance to a specified instance and returns an indication of their relative values. - /// An instance to compare. - /// - /// A signed number indicating the relative values of this instance and . - /// Returns less than zero if this instance is less than , zero if this - /// instance is equal to , and greater than zero if this instance is greater - /// than . - /// - public int CompareTo(ValueTuple other) - { - return Comparer.Default.Compare(Item1, other.Item1); - } - - int IStructuralComparable.CompareTo(object? other, IComparer comparer) - { - if (other == null) return 1; - - if (other is not ValueTuple) - { - throw new ArgumentException(SR.ArgumentException_ValueTupleIncorrectType, nameof(other)); - } - - var objTuple = (ValueTuple)other; - - return comparer.Compare(Item1, objTuple.Item1); - } - - /// - /// Returns the hash code for the current instance. - /// - /// A 32-bit signed integer hash code. - public override int GetHashCode() - { - return EqualityComparer.Default.GetHashCode(Item1); - } - - int IStructuralEquatable.GetHashCode(IEqualityComparer comparer) - { - return comparer.GetHashCode(Item1); - } - - int ITupleInternal.GetHashCode(IEqualityComparer comparer) - { - return comparer.GetHashCode(Item1); - } - - /// - /// Returns a string that represents the value of this instance. - /// - /// The string representation of this instance. - /// - /// The string returned by this method takes the form (Item1), - /// where Item1 represents the value of . If the field is , - /// it is represented as . - /// - public override string ToString() - { - return "(" + Item1?.ToString() + ")"; - } - - string ITupleInternal.ToStringEnd() - { - return Item1?.ToString() + ")"; - } - - int ITupleInternal.Size => 1; - } - - /// - /// Represents a 2-tuple, or pair, as a value type. - /// - /// The type of the tuple's first component. - /// The type of the tuple's second component. - public struct ValueTuple - : IEquatable>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable>, ITupleInternal - { - /// - /// The current instance's first component. - /// - public T1 Item1; - - /// - /// The current instance's first component. - /// - public T2 Item2; - - /// - /// Initializes a new instance of the value type. - /// - /// The value of the tuple's first component. - /// The value of the tuple's second component. - public ValueTuple(T1 item1, T2 item2) - { - Item1 = item1; - Item2 = item2; - } - - /// - /// Returns a value that indicates whether the current instance is equal to a specified object. - /// - /// The object to compare with this instance. - /// if the current instance is equal to the specified object; otherwise, . - /// - /// - /// The parameter is considered to be equal to the current instance under the following conditions: - /// - /// It is a value type. - /// Its components are of the same types as those of the current instance. - /// Its components are equal to those of the current instance. Equality is determined by the default object equality comparer for each component. - /// - /// - public override bool Equals(object obj) - { - return obj is ValueTuple tuple && Equals(tuple); - } - - /// - /// Returns a value that indicates whether the current instance is equal to a specified . - /// - /// The tuple to compare with this instance. - /// if the current instance is equal to the specified tuple; otherwise, . - /// - /// The parameter is considered to be equal to the current instance if each of its fields - /// are equal to that of the current instance, using the default comparer for that field's type. - /// - public bool Equals(ValueTuple other) - { - return EqualityComparer.Default.Equals(Item1, other.Item1) - && EqualityComparer.Default.Equals(Item2, other.Item2); - } - - /// - /// Returns a value that indicates whether the current instance is equal to a specified object based on a specified comparison method. - /// - /// The object to compare with this instance. - /// An object that defines the method to use to evaluate whether the two objects are equal. - /// if the current instance is equal to the specified object; otherwise, . - /// - /// - /// This member is an explicit interface member implementation. It can be used only when the - /// instance is cast to an interface. - /// - /// The implementation is called only if other is not , - /// and if it can be successfully cast (in C#) or converted (in Visual Basic) to a - /// whose components are of the same types as those of the current instance. The IStructuralEquatable.Equals(Object, IEqualityComparer) method - /// first passes the values of the objects to be compared to the - /// implementation. If this method call returns , the method is - /// called again and passed the values of the two instances. - /// - bool IStructuralEquatable.Equals(object? other, IEqualityComparer comparer) - { - if (other is null or not ValueTuple) return false; - - var objTuple = (ValueTuple)other; - - return comparer.Equals(Item1, objTuple.Item1) - && comparer.Equals(Item2, objTuple.Item2); - } - - int IComparable.CompareTo(object other) - { - if (other == null) return 1; - - if (other is not ValueTuple) - { - throw new ArgumentException(SR.ArgumentException_ValueTupleIncorrectType, nameof(other)); - } - - return CompareTo((ValueTuple)other); - } - - /// Compares this instance to a specified instance and returns an indication of their relative values. - /// An instance to compare. - /// - /// A signed number indicating the relative values of this instance and . - /// Returns less than zero if this instance is less than , zero if this - /// instance is equal to , and greater than zero if this instance is greater - /// than . - /// - public int CompareTo(ValueTuple other) - { - int c = Comparer.Default.Compare(Item1, other.Item1); - if (c != 0) return c; - - return Comparer.Default.Compare(Item2, other.Item2); - } - - int IStructuralComparable.CompareTo(object? other, IComparer comparer) - { - if (other == null) return 1; - - if (other is not ValueTuple) - { - throw new ArgumentException(SR.ArgumentException_ValueTupleIncorrectType, nameof(other)); - } - - var objTuple = (ValueTuple)other; - - int c = comparer.Compare(Item1, objTuple.Item1); - if (c != 0) return c; - - return comparer.Compare(Item2, objTuple.Item2); - } - - /// - /// Returns the hash code for the current instance. - /// - /// A 32-bit signed integer hash code. - public override int GetHashCode() - { - return ValueTuple.CombineHashCodes(EqualityComparer.Default.GetHashCode(Item1), - EqualityComparer.Default.GetHashCode(Item2)); - } - - int IStructuralEquatable.GetHashCode(IEqualityComparer comparer) - { - return GetHashCodeCore(comparer); - } - - private int GetHashCodeCore(IEqualityComparer comparer) - { - return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item1), - comparer.GetHashCode(Item2)); - } - - int ITupleInternal.GetHashCode(IEqualityComparer comparer) - { - return GetHashCodeCore(comparer); - } - - /// - /// Returns a string that represents the value of this instance. - /// - /// The string representation of this instance. - /// - /// The string returned by this method takes the form (Item1, Item2), - /// where Item1 and Item2 represent the values of the - /// and fields. If either field value is , - /// it is represented as . - /// - public override string ToString() - { - return "(" + Item1?.ToString() + ", " + Item2?.ToString() + ")"; - } - - string ITupleInternal.ToStringEnd() - { - return Item1?.ToString() + ", " + Item2?.ToString() + ")"; - } - - int ITupleInternal.Size => 2; - } - - /// - /// Represents a 3-tuple, or triple, as a value type. - /// - /// The type of the tuple's first component. - /// The type of the tuple's second component. - /// The type of the tuple's third component. - public struct ValueTuple - : IEquatable>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable>, ITupleInternal - { - /// - /// The current instance's first component. - /// - public T1 Item1; - /// - /// The current instance's second component. - /// - public T2 Item2; - /// - /// The current instance's third component. - /// - public T3 Item3; - - /// - /// Initializes a new instance of the value type. - /// - /// The value of the tuple's first component. - /// The value of the tuple's second component. - /// The value of the tuple's third component. - public ValueTuple(T1 item1, T2 item2, T3 item3) - { - Item1 = item1; - Item2 = item2; - Item3 = item3; - } - - /// - /// Returns a value that indicates whether the current instance is equal to a specified object. - /// - /// The object to compare with this instance. - /// if the current instance is equal to the specified object; otherwise, . - /// - /// The parameter is considered to be equal to the current instance under the following conditions: - /// - /// It is a value type. - /// Its components are of the same types as those of the current instance. - /// Its components are equal to those of the current instance. Equality is determined by the default object equality comparer for each component. - /// - /// - public override bool Equals(object obj) - { - return obj is ValueTuple tuple && Equals(tuple); - } - - /// - /// Returns a value that indicates whether the current - /// instance is equal to a specified . - /// - /// The tuple to compare with this instance. - /// if the current instance is equal to the specified tuple; otherwise, . - /// - /// The parameter is considered to be equal to the current instance if each of its fields - /// are equal to that of the current instance, using the default comparer for that field's type. - /// - public bool Equals(ValueTuple other) - { - return EqualityComparer.Default.Equals(Item1, other.Item1) - && EqualityComparer.Default.Equals(Item2, other.Item2) - && EqualityComparer.Default.Equals(Item3, other.Item3); - } - - bool IStructuralEquatable.Equals(object? other, IEqualityComparer comparer) - { - if (other == null || other is not ValueTuple) return false; - - var objTuple = (ValueTuple)other; - - return comparer.Equals(Item1, objTuple.Item1) - && comparer.Equals(Item2, objTuple.Item2) - && comparer.Equals(Item3, objTuple.Item3); - } - - int IComparable.CompareTo(object other) - { - if (other == null) return 1; - - if (other is not ValueTuple) - { - throw new ArgumentException(SR.ArgumentException_ValueTupleIncorrectType, nameof(other)); - } - - return CompareTo((ValueTuple)other); - } - - /// Compares this instance to a specified instance and returns an indication of their relative values. - /// An instance to compare. - /// - /// A signed number indicating the relative values of this instance and . - /// Returns less than zero if this instance is less than , zero if this - /// instance is equal to , and greater than zero if this instance is greater - /// than . - /// - public int CompareTo(ValueTuple other) - { - int c = Comparer.Default.Compare(Item1, other.Item1); - if (c != 0) return c; - - c = Comparer.Default.Compare(Item2, other.Item2); - if (c != 0) return c; - - return Comparer.Default.Compare(Item3, other.Item3); - } - - int IStructuralComparable.CompareTo(object? other, IComparer comparer) - { - if (other == null) return 1; - - if (other is not ValueTuple) - { - throw new ArgumentException(SR.ArgumentException_ValueTupleIncorrectType, nameof(other)); - } - - var objTuple = (ValueTuple)other; - - int c = comparer.Compare(Item1, objTuple.Item1); - if (c != 0) return c; - - c = comparer.Compare(Item2, objTuple.Item2); - if (c != 0) return c; - - return comparer.Compare(Item3, objTuple.Item3); - } - - /// - /// Returns the hash code for the current instance. - /// - /// A 32-bit signed integer hash code. - public override int GetHashCode() - { - return ValueTuple.CombineHashCodes(EqualityComparer.Default.GetHashCode(Item1), - EqualityComparer.Default.GetHashCode(Item2), - EqualityComparer.Default.GetHashCode(Item3)); - } - - int IStructuralEquatable.GetHashCode(IEqualityComparer comparer) - { - return GetHashCodeCore(comparer); - } - - private int GetHashCodeCore(IEqualityComparer comparer) - { - return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item1), - comparer.GetHashCode(Item2), - comparer.GetHashCode(Item3)); - } - - int ITupleInternal.GetHashCode(IEqualityComparer comparer) - { - return GetHashCodeCore(comparer); - } - - /// - /// Returns a string that represents the value of this instance. - /// - /// The string representation of this instance. - /// - /// The string returned by this method takes the form (Item1, Item2, Item3). - /// If any field value is , it is represented as . - /// - public override string ToString() - { - return "(" + Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ")"; - } - - string ITupleInternal.ToStringEnd() - { - return Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ")"; - } - - int ITupleInternal.Size => 3; - } - - /// - /// Represents a 4-tuple, or quadruple, as a value type. - /// - /// The type of the tuple's first component. - /// The type of the tuple's second component. - /// The type of the tuple's third component. - /// The type of the tuple's fourth component. - public struct ValueTuple - : IEquatable>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable>, ITupleInternal - { - /// - /// The current instance's first component. - /// - public T1 Item1; - /// - /// The current instance's second component. - /// - public T2 Item2; - /// - /// The current instance's third component. - /// - public T3 Item3; - /// - /// The current instance's fourth component. - /// - public T4 Item4; - - /// - /// Initializes a new instance of the value type. - /// - /// The value of the tuple's first component. - /// The value of the tuple's second component. - /// The value of the tuple's third component. - /// The value of the tuple's fourth component. - public ValueTuple(T1 item1, T2 item2, T3 item3, T4 item4) - { - Item1 = item1; - Item2 = item2; - Item3 = item3; - Item4 = item4; - } - - /// - /// Returns a value that indicates whether the current instance is equal to a specified object. - /// - /// The object to compare with this instance. - /// if the current instance is equal to the specified object; otherwise, . - /// - /// The parameter is considered to be equal to the current instance under the following conditions: - /// - /// It is a value type. - /// Its components are of the same types as those of the current instance. - /// Its components are equal to those of the current instance. Equality is determined by the default object equality comparer for each component. - /// - /// - public override bool Equals(object obj) - { - return obj is ValueTuple tuple && Equals(tuple); - } - - /// - /// Returns a value that indicates whether the current - /// instance is equal to a specified . - /// - /// The tuple to compare with this instance. - /// if the current instance is equal to the specified tuple; otherwise, . - /// - /// The parameter is considered to be equal to the current instance if each of its fields - /// are equal to that of the current instance, using the default comparer for that field's type. - /// - public bool Equals(ValueTuple other) - { - return EqualityComparer.Default.Equals(Item1, other.Item1) - && EqualityComparer.Default.Equals(Item2, other.Item2) - && EqualityComparer.Default.Equals(Item3, other.Item3) - && EqualityComparer.Default.Equals(Item4, other.Item4); - } - - bool IStructuralEquatable.Equals(object? other, IEqualityComparer comparer) - { - if (other == null || other is not ValueTuple) return false; - - var objTuple = (ValueTuple)other; - - return comparer.Equals(Item1, objTuple.Item1) - && comparer.Equals(Item2, objTuple.Item2) - && comparer.Equals(Item3, objTuple.Item3) - && comparer.Equals(Item4, objTuple.Item4); - } - - int IComparable.CompareTo(object other) - { - if (other == null) return 1; - - if (other is not ValueTuple) - { - throw new ArgumentException(SR.ArgumentException_ValueTupleIncorrectType, nameof(other)); - } - - return CompareTo((ValueTuple)other); - } - - /// Compares this instance to a specified instance and returns an indication of their relative values. - /// An instance to compare. - /// - /// A signed number indicating the relative values of this instance and . - /// Returns less than zero if this instance is less than , zero if this - /// instance is equal to , and greater than zero if this instance is greater - /// than . - /// - public int CompareTo(ValueTuple other) - { - int c = Comparer.Default.Compare(Item1, other.Item1); - if (c != 0) return c; - - c = Comparer.Default.Compare(Item2, other.Item2); - if (c != 0) return c; - - c = Comparer.Default.Compare(Item3, other.Item3); - if (c != 0) return c; - - return Comparer.Default.Compare(Item4, other.Item4); - } - - int IStructuralComparable.CompareTo(object? other, IComparer comparer) - { - if (other == null) return 1; - - if (other is not ValueTuple) - { - throw new ArgumentException(SR.ArgumentException_ValueTupleIncorrectType, nameof(other)); - } - - var objTuple = (ValueTuple)other; - - int c = comparer.Compare(Item1, objTuple.Item1); - if (c != 0) return c; - - c = comparer.Compare(Item2, objTuple.Item2); - if (c != 0) return c; - - c = comparer.Compare(Item3, objTuple.Item3); - if (c != 0) return c; - - return comparer.Compare(Item4, objTuple.Item4); - } - - /// - /// Returns the hash code for the current instance. - /// - /// A 32-bit signed integer hash code. - public override int GetHashCode() - { - return ValueTuple.CombineHashCodes(EqualityComparer.Default.GetHashCode(Item1), - EqualityComparer.Default.GetHashCode(Item2), - EqualityComparer.Default.GetHashCode(Item3), - EqualityComparer.Default.GetHashCode(Item4)); - } - - int IStructuralEquatable.GetHashCode(IEqualityComparer comparer) - { - return GetHashCodeCore(comparer); - } - - private int GetHashCodeCore(IEqualityComparer comparer) - { - return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item1), - comparer.GetHashCode(Item2), - comparer.GetHashCode(Item3), - comparer.GetHashCode(Item4)); - } - - int ITupleInternal.GetHashCode(IEqualityComparer comparer) - { - return GetHashCodeCore(comparer); - } - - /// - /// Returns a string that represents the value of this instance. - /// - /// The string representation of this instance. - /// - /// The string returned by this method takes the form (Item1, Item2, Item3, Item4). - /// If any field value is , it is represented as . - /// - public override string ToString() - { - return "(" + Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ")"; - } - - string ITupleInternal.ToStringEnd() - { - return Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ")"; - } - - int ITupleInternal.Size => 4; - } - - /// - /// Represents a 5-tuple, or quintuple, as a value type. - /// - /// The type of the tuple's first component. - /// The type of the tuple's second component. - /// The type of the tuple's third component. - /// The type of the tuple's fourth component. - /// The type of the tuple's fifth component. - public struct ValueTuple - : IEquatable>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable>, ITupleInternal - { - /// - /// The current instance's first component. - /// - public T1 Item1; - /// - /// The current instance's second component. - /// - public T2 Item2; - /// - /// The current instance's third component. - /// - public T3 Item3; - /// - /// The current instance's fourth component. - /// - public T4 Item4; - /// - /// The current instance's fifth component. - /// - public T5 Item5; - - /// - /// Initializes a new instance of the value type. - /// - /// The value of the tuple's first component. - /// The value of the tuple's second component. - /// The value of the tuple's third component. - /// The value of the tuple's fourth component. - /// The value of the tuple's fifth component. - public ValueTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5) - { - Item1 = item1; - Item2 = item2; - Item3 = item3; - Item4 = item4; - Item5 = item5; - } - - /// - /// Returns a value that indicates whether the current instance is equal to a specified object. - /// - /// The object to compare with this instance. - /// if the current instance is equal to the specified object; otherwise, . - /// - /// The parameter is considered to be equal to the current instance under the following conditions: - /// - /// It is a value type. - /// Its components are of the same types as those of the current instance. - /// Its components are equal to those of the current instance. Equality is determined by the default object equality comparer for each component. - /// - /// - public override bool Equals(object obj) - { - return obj is ValueTuple tuple && Equals(tuple); - } - - /// - /// Returns a value that indicates whether the current - /// instance is equal to a specified . - /// - /// The tuple to compare with this instance. - /// if the current instance is equal to the specified tuple; otherwise, . - /// - /// The parameter is considered to be equal to the current instance if each of its fields - /// are equal to that of the current instance, using the default comparer for that field's type. - /// - public bool Equals(ValueTuple other) - { - return EqualityComparer.Default.Equals(Item1, other.Item1) - && EqualityComparer.Default.Equals(Item2, other.Item2) - && EqualityComparer.Default.Equals(Item3, other.Item3) - && EqualityComparer.Default.Equals(Item4, other.Item4) - && EqualityComparer.Default.Equals(Item5, other.Item5); - } - - bool IStructuralEquatable.Equals(object? other, IEqualityComparer comparer) - { - if (other == null || other is not ValueTuple) return false; - - var objTuple = (ValueTuple)other; - - return comparer.Equals(Item1, objTuple.Item1) - && comparer.Equals(Item2, objTuple.Item2) - && comparer.Equals(Item3, objTuple.Item3) - && comparer.Equals(Item4, objTuple.Item4) - && comparer.Equals(Item5, objTuple.Item5); - } - - int IComparable.CompareTo(object other) - { - if (other == null) return 1; - - if (other is not ValueTuple) - { - throw new ArgumentException(SR.ArgumentException_ValueTupleIncorrectType, nameof(other)); - } - - return CompareTo((ValueTuple)other); - } - - /// Compares this instance to a specified instance and returns an indication of their relative values. - /// An instance to compare. - /// - /// A signed number indicating the relative values of this instance and . - /// Returns less than zero if this instance is less than , zero if this - /// instance is equal to , and greater than zero if this instance is greater - /// than . - /// - public int CompareTo(ValueTuple other) - { - int c = Comparer.Default.Compare(Item1, other.Item1); - if (c != 0) return c; - - c = Comparer.Default.Compare(Item2, other.Item2); - if (c != 0) return c; - - c = Comparer.Default.Compare(Item3, other.Item3); - if (c != 0) return c; - - c = Comparer.Default.Compare(Item4, other.Item4); - if (c != 0) return c; - - return Comparer.Default.Compare(Item5, other.Item5); - } - - int IStructuralComparable.CompareTo(object? other, IComparer comparer) - { - if (other == null) return 1; - - if (other is not ValueTuple) - { - throw new ArgumentException(SR.ArgumentException_ValueTupleIncorrectType, nameof(other)); - } - - var objTuple = (ValueTuple)other; - - int c = comparer.Compare(Item1, objTuple.Item1); - if (c != 0) return c; - - c = comparer.Compare(Item2, objTuple.Item2); - if (c != 0) return c; - - c = comparer.Compare(Item3, objTuple.Item3); - if (c != 0) return c; - - c = comparer.Compare(Item4, objTuple.Item4); - if (c != 0) return c; - - return comparer.Compare(Item5, objTuple.Item5); - } - - /// - /// Returns the hash code for the current instance. - /// - /// A 32-bit signed integer hash code. - public override int GetHashCode() - { - return ValueTuple.CombineHashCodes(EqualityComparer.Default.GetHashCode(Item1), - EqualityComparer.Default.GetHashCode(Item2), - EqualityComparer.Default.GetHashCode(Item3), - EqualityComparer.Default.GetHashCode(Item4), - EqualityComparer.Default.GetHashCode(Item5)); - } - - int IStructuralEquatable.GetHashCode(IEqualityComparer comparer) - { - return GetHashCodeCore(comparer); - } - - private int GetHashCodeCore(IEqualityComparer comparer) - { - return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item1), - comparer.GetHashCode(Item2), - comparer.GetHashCode(Item3), - comparer.GetHashCode(Item4), - comparer.GetHashCode(Item5)); - } - - int ITupleInternal.GetHashCode(IEqualityComparer comparer) - { - return GetHashCodeCore(comparer); - } - - /// - /// Returns a string that represents the value of this instance. - /// - /// The string representation of this instance. - /// - /// The string returned by this method takes the form (Item1, Item2, Item3, Item4, Item5). - /// If any field value is , it is represented as . - /// - public override string ToString() - { - return "(" + Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ", " + Item5?.ToString() + ")"; - } - - string ITupleInternal.ToStringEnd() - { - return Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ", " + Item5?.ToString() + ")"; - } - - int ITupleInternal.Size => 5; - } - - /// - /// Represents a 6-tuple, or sixtuple, as a value type. - /// - /// The type of the tuple's first component. - /// The type of the tuple's second component. - /// The type of the tuple's third component. - /// The type of the tuple's fourth component. - /// The type of the tuple's fifth component. - /// The type of the tuple's sixth component. - public struct ValueTuple - : IEquatable>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable>, ITupleInternal - { - /// - /// The current instance's first component. - /// - public T1 Item1; - /// - /// The current instance's second component. - /// - public T2 Item2; - /// - /// The current instance's third component. - /// - public T3 Item3; - /// - /// The current instance's fourth component. - /// - public T4 Item4; - /// - /// The current instance's fifth component. - /// - public T5 Item5; - /// - /// The current instance's sixth component. - /// - public T6 Item6; - - /// - /// Initializes a new instance of the value type. - /// - /// The value of the tuple's first component. - /// The value of the tuple's second component. - /// The value of the tuple's third component. - /// The value of the tuple's fourth component. - /// The value of the tuple's fifth component. - /// The value of the tuple's sixth component. - public ValueTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6) - { - Item1 = item1; - Item2 = item2; - Item3 = item3; - Item4 = item4; - Item5 = item5; - Item6 = item6; - } - - /// - /// Returns a value that indicates whether the current instance is equal to a specified object. - /// - /// The object to compare with this instance. - /// if the current instance is equal to the specified object; otherwise, . - /// - /// The parameter is considered to be equal to the current instance under the following conditions: - /// - /// It is a value type. - /// Its components are of the same types as those of the current instance. - /// Its components are equal to those of the current instance. Equality is determined by the default object equality comparer for each component. - /// - /// - public override bool Equals(object obj) - { - return obj is ValueTuple tuple && Equals(tuple); - } - - /// - /// Returns a value that indicates whether the current - /// instance is equal to a specified . - /// - /// The tuple to compare with this instance. - /// if the current instance is equal to the specified tuple; otherwise, . - /// - /// The parameter is considered to be equal to the current instance if each of its fields - /// are equal to that of the current instance, using the default comparer for that field's type. - /// - public bool Equals(ValueTuple other) - { - return EqualityComparer.Default.Equals(Item1, other.Item1) - && EqualityComparer.Default.Equals(Item2, other.Item2) - && EqualityComparer.Default.Equals(Item3, other.Item3) - && EqualityComparer.Default.Equals(Item4, other.Item4) - && EqualityComparer.Default.Equals(Item5, other.Item5) - && EqualityComparer.Default.Equals(Item6, other.Item6); - } - - bool IStructuralEquatable.Equals(object? other, IEqualityComparer comparer) - { - if (other == null || other is not ValueTuple) return false; - - var objTuple = (ValueTuple)other; - - return comparer.Equals(Item1, objTuple.Item1) - && comparer.Equals(Item2, objTuple.Item2) - && comparer.Equals(Item3, objTuple.Item3) - && comparer.Equals(Item4, objTuple.Item4) - && comparer.Equals(Item5, objTuple.Item5) - && comparer.Equals(Item6, objTuple.Item6); - } - - int IComparable.CompareTo(object other) - { - if (other == null) return 1; - - if (other is not ValueTuple) - { - throw new ArgumentException(SR.ArgumentException_ValueTupleIncorrectType, nameof(other)); - } - - return CompareTo((ValueTuple)other); - } - - /// Compares this instance to a specified instance and returns an indication of their relative values. - /// An instance to compare. - /// - /// A signed number indicating the relative values of this instance and . - /// Returns less than zero if this instance is less than , zero if this - /// instance is equal to , and greater than zero if this instance is greater - /// than . - /// - public int CompareTo(ValueTuple other) - { - int c = Comparer.Default.Compare(Item1, other.Item1); - if (c != 0) return c; - - c = Comparer.Default.Compare(Item2, other.Item2); - if (c != 0) return c; - - c = Comparer.Default.Compare(Item3, other.Item3); - if (c != 0) return c; - - c = Comparer.Default.Compare(Item4, other.Item4); - if (c != 0) return c; - - c = Comparer.Default.Compare(Item5, other.Item5); - if (c != 0) return c; - - return Comparer.Default.Compare(Item6, other.Item6); - } - - int IStructuralComparable.CompareTo(object? other, IComparer comparer) - { - if (other == null) return 1; - - if (other is not ValueTuple) - { - throw new ArgumentException(SR.ArgumentException_ValueTupleIncorrectType, nameof(other)); - } - - var objTuple = (ValueTuple)other; - - int c = comparer.Compare(Item1, objTuple.Item1); - if (c != 0) return c; - - c = comparer.Compare(Item2, objTuple.Item2); - if (c != 0) return c; - - c = comparer.Compare(Item3, objTuple.Item3); - if (c != 0) return c; - - c = comparer.Compare(Item4, objTuple.Item4); - if (c != 0) return c; - - c = comparer.Compare(Item5, objTuple.Item5); - if (c != 0) return c; - - return comparer.Compare(Item6, objTuple.Item6); - } - - /// - /// Returns the hash code for the current instance. - /// - /// A 32-bit signed integer hash code. - public override int GetHashCode() - { - return ValueTuple.CombineHashCodes(EqualityComparer.Default.GetHashCode(Item1), - EqualityComparer.Default.GetHashCode(Item2), - EqualityComparer.Default.GetHashCode(Item3), - EqualityComparer.Default.GetHashCode(Item4), - EqualityComparer.Default.GetHashCode(Item5), - EqualityComparer.Default.GetHashCode(Item6)); - } - - int IStructuralEquatable.GetHashCode(IEqualityComparer comparer) - { - return GetHashCodeCore(comparer); - } - - private int GetHashCodeCore(IEqualityComparer comparer) - { - return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item1), - comparer.GetHashCode(Item2), - comparer.GetHashCode(Item3), - comparer.GetHashCode(Item4), - comparer.GetHashCode(Item5), - comparer.GetHashCode(Item6)); - } - - int ITupleInternal.GetHashCode(IEqualityComparer comparer) - { - return GetHashCodeCore(comparer); - } - - /// - /// Returns a string that represents the value of this instance. - /// - /// The string representation of this instance. - /// - /// The string returned by this method takes the form (Item1, Item2, Item3, Item4, Item5, Item6). - /// If any field value is , it is represented as . - /// - public override string ToString() - { - return "(" + Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ", " + Item5?.ToString() + ", " + Item6?.ToString() + ")"; - } - - string ITupleInternal.ToStringEnd() - { - return Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ", " + Item5?.ToString() + ", " + Item6?.ToString() + ")"; - } - - int ITupleInternal.Size => 6; - } - - /// - /// Represents a 7-tuple, or sentuple, as a value type. - /// - /// The type of the tuple's first component. - /// The type of the tuple's second component. - /// The type of the tuple's third component. - /// The type of the tuple's fourth component. - /// The type of the tuple's fifth component. - /// The type of the tuple's sixth component. - /// The type of the tuple's seventh component. - public struct ValueTuple - : IEquatable>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable>, ITupleInternal - { - /// - /// The current instance's first component. - /// - public T1 Item1; - /// - /// The current instance's second component. - /// - public T2 Item2; - /// - /// The current instance's third component. - /// - public T3 Item3; - /// - /// The current instance's fourth component. - /// - public T4 Item4; - /// - /// The current instance's fifth component. - /// - public T5 Item5; - /// - /// The current instance's sixth component. - /// - public T6 Item6; - /// - /// The current instance's seventh component. - /// - public T7 Item7; - - /// - /// Initializes a new instance of the value type. - /// - /// The value of the tuple's first component. - /// The value of the tuple's second component. - /// The value of the tuple's third component. - /// The value of the tuple's fourth component. - /// The value of the tuple's fifth component. - /// The value of the tuple's sixth component. - /// The value of the tuple's seventh component. - public ValueTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7) - { - Item1 = item1; - Item2 = item2; - Item3 = item3; - Item4 = item4; - Item5 = item5; - Item6 = item6; - Item7 = item7; - } - - /// - /// Returns a value that indicates whether the current instance is equal to a specified object. - /// - /// The object to compare with this instance. - /// if the current instance is equal to the specified object; otherwise, . - /// - /// The parameter is considered to be equal to the current instance under the following conditions: - /// - /// It is a value type. - /// Its components are of the same types as those of the current instance. - /// Its components are equal to those of the current instance. Equality is determined by the default object equality comparer for each component. - /// - /// - public override bool Equals(object obj) - { - return obj is ValueTuple tuple && Equals(tuple); - } - - /// - /// Returns a value that indicates whether the current - /// instance is equal to a specified . - /// - /// The tuple to compare with this instance. - /// if the current instance is equal to the specified tuple; otherwise, . - /// - /// The parameter is considered to be equal to the current instance if each of its fields - /// are equal to that of the current instance, using the default comparer for that field's type. - /// - public bool Equals(ValueTuple other) - { - return EqualityComparer.Default.Equals(Item1, other.Item1) - && EqualityComparer.Default.Equals(Item2, other.Item2) - && EqualityComparer.Default.Equals(Item3, other.Item3) - && EqualityComparer.Default.Equals(Item4, other.Item4) - && EqualityComparer.Default.Equals(Item5, other.Item5) - && EqualityComparer.Default.Equals(Item6, other.Item6) - && EqualityComparer.Default.Equals(Item7, other.Item7); - } - - bool IStructuralEquatable.Equals(object? other, IEqualityComparer comparer) - { - if (other == null || other is not ValueTuple) return false; - - var objTuple = (ValueTuple)other; - - return comparer.Equals(Item1, objTuple.Item1) - && comparer.Equals(Item2, objTuple.Item2) - && comparer.Equals(Item3, objTuple.Item3) - && comparer.Equals(Item4, objTuple.Item4) - && comparer.Equals(Item5, objTuple.Item5) - && comparer.Equals(Item6, objTuple.Item6) - && comparer.Equals(Item7, objTuple.Item7); - } - - int IComparable.CompareTo(object other) - { - if (other == null) return 1; - - if (other is not ValueTuple) - { - throw new ArgumentException(SR.ArgumentException_ValueTupleIncorrectType, nameof(other)); - } - - return CompareTo((ValueTuple)other); - } - - /// Compares this instance to a specified instance and returns an indication of their relative values. - /// An instance to compare. - /// - /// A signed number indicating the relative values of this instance and . - /// Returns less than zero if this instance is less than , zero if this - /// instance is equal to , and greater than zero if this instance is greater - /// than . - /// - public int CompareTo(ValueTuple other) - { - int c = Comparer.Default.Compare(Item1, other.Item1); - if (c != 0) return c; - - c = Comparer.Default.Compare(Item2, other.Item2); - if (c != 0) return c; - - c = Comparer.Default.Compare(Item3, other.Item3); - if (c != 0) return c; - - c = Comparer.Default.Compare(Item4, other.Item4); - if (c != 0) return c; - - c = Comparer.Default.Compare(Item5, other.Item5); - if (c != 0) return c; - - c = Comparer.Default.Compare(Item6, other.Item6); - if (c != 0) return c; - - return Comparer.Default.Compare(Item7, other.Item7); - } - - int IStructuralComparable.CompareTo(object? other, IComparer comparer) - { - if (other == null) return 1; - - if (other is not ValueTuple) - { - throw new ArgumentException(SR.ArgumentException_ValueTupleIncorrectType, nameof(other)); - } - - var objTuple = (ValueTuple)other; - - int c = comparer.Compare(Item1, objTuple.Item1); - if (c != 0) return c; - - c = comparer.Compare(Item2, objTuple.Item2); - if (c != 0) return c; - - c = comparer.Compare(Item3, objTuple.Item3); - if (c != 0) return c; - - c = comparer.Compare(Item4, objTuple.Item4); - if (c != 0) return c; - - c = comparer.Compare(Item5, objTuple.Item5); - if (c != 0) return c; - - c = comparer.Compare(Item6, objTuple.Item6); - if (c != 0) return c; - - return comparer.Compare(Item7, objTuple.Item7); - } - - /// - /// Returns the hash code for the current instance. - /// - /// A 32-bit signed integer hash code. - public override int GetHashCode() - { - return ValueTuple.CombineHashCodes(EqualityComparer.Default.GetHashCode(Item1), - EqualityComparer.Default.GetHashCode(Item2), - EqualityComparer.Default.GetHashCode(Item3), - EqualityComparer.Default.GetHashCode(Item4), - EqualityComparer.Default.GetHashCode(Item5), - EqualityComparer.Default.GetHashCode(Item6), - EqualityComparer.Default.GetHashCode(Item7)); - } - - int IStructuralEquatable.GetHashCode(IEqualityComparer comparer) - { - return GetHashCodeCore(comparer); - } - - private int GetHashCodeCore(IEqualityComparer comparer) - { - return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item1), - comparer.GetHashCode(Item2), - comparer.GetHashCode(Item3), - comparer.GetHashCode(Item4), - comparer.GetHashCode(Item5), - comparer.GetHashCode(Item6), - comparer.GetHashCode(Item7)); - } - - int ITupleInternal.GetHashCode(IEqualityComparer comparer) - { - return GetHashCodeCore(comparer); - } - - /// - /// Returns a string that represents the value of this instance. - /// - /// The string representation of this instance. - /// - /// The string returned by this method takes the form (Item1, Item2, Item3, Item4, Item5, Item6, Item7). - /// If any field value is , it is represented as . - /// - public override string ToString() - { - return "(" + Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ", " + Item5?.ToString() + ", " + Item6?.ToString() + ", " + Item7?.ToString() + ")"; - } - - string ITupleInternal.ToStringEnd() - { - return Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ", " + Item5?.ToString() + ", " + Item6?.ToString() + ", " + Item7?.ToString() + ")"; - } - - int ITupleInternal.Size => 7; - } - - /// - /// Represents an 8-tuple, or octuple, as a value type. - /// - /// The type of the tuple's first component. - /// The type of the tuple's second component. - /// The type of the tuple's third component. - /// The type of the tuple's fourth component. - /// The type of the tuple's fifth component. - /// The type of the tuple's sixth component. - /// The type of the tuple's seventh component. - /// The type of the tuple's eighth component. - public struct ValueTuple - : IEquatable>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable>, ITupleInternal - where TRest : struct - { - /// - /// The current instance's first component. - /// - public T1 Item1; - /// - /// The current instance's second component. - /// - public T2 Item2; - /// - /// The current instance's third component. - /// - public T3 Item3; - /// - /// The current instance's fourth component. - /// - public T4 Item4; - /// - /// The current instance's fifth component. - /// - public T5 Item5; - /// - /// The current instance's sixth component. - /// - public T6 Item6; - /// - /// The current instance's seventh component. - /// - public T7 Item7; - /// - /// The current instance's eighth component. - /// - public TRest Rest; - - /// - /// Initializes a new instance of the value type. - /// - /// The value of the tuple's first component. - /// The value of the tuple's second component. - /// The value of the tuple's third component. - /// The value of the tuple's fourth component. - /// The value of the tuple's fifth component. - /// The value of the tuple's sixth component. - /// The value of the tuple's seventh component. - /// The value of the tuple's eight component. - public ValueTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7, TRest rest) - { - if (rest is not ITupleInternal) - { - throw new ArgumentException(SR.ArgumentException_ValueTupleLastArgumentNotAValueTuple); - } - - Item1 = item1; - Item2 = item2; - Item3 = item3; - Item4 = item4; - Item5 = item5; - Item6 = item6; - Item7 = item7; - Rest = rest; - } - - /// - /// Returns a value that indicates whether the current instance is equal to a specified object. - /// - /// The object to compare with this instance. - /// if the current instance is equal to the specified object; otherwise, . - /// - /// The parameter is considered to be equal to the current instance under the following conditions: - /// - /// It is a value type. - /// Its components are of the same types as those of the current instance. - /// Its components are equal to those of the current instance. Equality is determined by the default object equality comparer for each component. - /// - /// - public override bool Equals(object obj) - { - return obj is ValueTuple tuple && Equals(tuple); - } - - /// - /// Returns a value that indicates whether the current - /// instance is equal to a specified . - /// - /// The tuple to compare with this instance. - /// if the current instance is equal to the specified tuple; otherwise, . - /// - /// The parameter is considered to be equal to the current instance if each of its fields - /// are equal to that of the current instance, using the default comparer for that field's type. - /// - public bool Equals(ValueTuple other) - { - return EqualityComparer.Default.Equals(Item1, other.Item1) - && EqualityComparer.Default.Equals(Item2, other.Item2) - && EqualityComparer.Default.Equals(Item3, other.Item3) - && EqualityComparer.Default.Equals(Item4, other.Item4) - && EqualityComparer.Default.Equals(Item5, other.Item5) - && EqualityComparer.Default.Equals(Item6, other.Item6) - && EqualityComparer.Default.Equals(Item7, other.Item7) - && EqualityComparer.Default.Equals(Rest, other.Rest); - } - - bool IStructuralEquatable.Equals(object? other, IEqualityComparer comparer) - { - if (other == null || other is not ValueTuple) return false; - - var objTuple = (ValueTuple)other; - - return comparer.Equals(Item1, objTuple.Item1) - && comparer.Equals(Item2, objTuple.Item2) - && comparer.Equals(Item3, objTuple.Item3) - && comparer.Equals(Item4, objTuple.Item4) - && comparer.Equals(Item5, objTuple.Item5) - && comparer.Equals(Item6, objTuple.Item6) - && comparer.Equals(Item7, objTuple.Item7) - && comparer.Equals(Rest, objTuple.Rest); - } - - int IComparable.CompareTo(object other) - { - if (other == null) return 1; - - if (other is not ValueTuple) - { - throw new ArgumentException(SR.ArgumentException_ValueTupleIncorrectType, nameof(other)); - } - - return CompareTo((ValueTuple)other); - } - - /// Compares this instance to a specified instance and returns an indication of their relative values. - /// An instance to compare. - /// - /// A signed number indicating the relative values of this instance and . - /// Returns less than zero if this instance is less than , zero if this - /// instance is equal to , and greater than zero if this instance is greater - /// than . - /// - public int CompareTo(ValueTuple other) - { - int c = Comparer.Default.Compare(Item1, other.Item1); - if (c != 0) return c; - - c = Comparer.Default.Compare(Item2, other.Item2); - if (c != 0) return c; - - c = Comparer.Default.Compare(Item3, other.Item3); - if (c != 0) return c; - - c = Comparer.Default.Compare(Item4, other.Item4); - if (c != 0) return c; - - c = Comparer.Default.Compare(Item5, other.Item5); - if (c != 0) return c; - - c = Comparer.Default.Compare(Item6, other.Item6); - if (c != 0) return c; - - c = Comparer.Default.Compare(Item7, other.Item7); - if (c != 0) return c; - - return Comparer.Default.Compare(Rest, other.Rest); - } - - int IStructuralComparable.CompareTo(object? other, IComparer comparer) - { - if (other == null) return 1; - - if (other is not ValueTuple) - { - throw new ArgumentException(SR.ArgumentException_ValueTupleIncorrectType, nameof(other)); - } - - var objTuple = (ValueTuple)other; - - int c = comparer.Compare(Item1, objTuple.Item1); - if (c != 0) return c; - - c = comparer.Compare(Item2, objTuple.Item2); - if (c != 0) return c; - - c = comparer.Compare(Item3, objTuple.Item3); - if (c != 0) return c; - - c = comparer.Compare(Item4, objTuple.Item4); - if (c != 0) return c; - - c = comparer.Compare(Item5, objTuple.Item5); - if (c != 0) return c; - - c = comparer.Compare(Item6, objTuple.Item6); - if (c != 0) return c; - - c = comparer.Compare(Item7, objTuple.Item7); - if (c != 0) return c; - - return comparer.Compare(Rest, objTuple.Rest); - } - - /// - /// Returns the hash code for the current instance. - /// - /// A 32-bit signed integer hash code. - public override int GetHashCode() - { - // We want to have a limited hash in this case. We'll use the last 8 elements of the tuple - if (Rest is not ITupleInternal rest) - { - return ValueTuple.CombineHashCodes(EqualityComparer.Default.GetHashCode(Item1), - EqualityComparer.Default.GetHashCode(Item2), - EqualityComparer.Default.GetHashCode(Item3), - EqualityComparer.Default.GetHashCode(Item4), - EqualityComparer.Default.GetHashCode(Item5), - EqualityComparer.Default.GetHashCode(Item6), - EqualityComparer.Default.GetHashCode(Item7)); - } - - int size = rest.Size; - if (size >= 8) { return rest.GetHashCode(); } - - // In this case, the rest member has less than 8 elements so we need to combine some our elements with the elements in rest - int k = 8 - size; - switch (k) - { - case 1: - return ValueTuple.CombineHashCodes(EqualityComparer.Default.GetHashCode(Item7), - rest.GetHashCode()); - case 2: - return ValueTuple.CombineHashCodes(EqualityComparer.Default.GetHashCode(Item6), - EqualityComparer.Default.GetHashCode(Item7), - rest.GetHashCode()); - case 3: - return ValueTuple.CombineHashCodes(EqualityComparer.Default.GetHashCode(Item5), - EqualityComparer.Default.GetHashCode(Item6), - EqualityComparer.Default.GetHashCode(Item7), - rest.GetHashCode()); - case 4: - return ValueTuple.CombineHashCodes(EqualityComparer.Default.GetHashCode(Item4), - EqualityComparer.Default.GetHashCode(Item5), - EqualityComparer.Default.GetHashCode(Item6), - EqualityComparer.Default.GetHashCode(Item7), - rest.GetHashCode()); - case 5: - return ValueTuple.CombineHashCodes(EqualityComparer.Default.GetHashCode(Item3), - EqualityComparer.Default.GetHashCode(Item4), - EqualityComparer.Default.GetHashCode(Item5), - EqualityComparer.Default.GetHashCode(Item6), - EqualityComparer.Default.GetHashCode(Item7), - rest.GetHashCode()); - case 6: - return ValueTuple.CombineHashCodes(EqualityComparer.Default.GetHashCode(Item2), - EqualityComparer.Default.GetHashCode(Item3), - EqualityComparer.Default.GetHashCode(Item4), - EqualityComparer.Default.GetHashCode(Item5), - EqualityComparer.Default.GetHashCode(Item6), - EqualityComparer.Default.GetHashCode(Item7), - rest.GetHashCode()); - case 7: - case 8: - return ValueTuple.CombineHashCodes(EqualityComparer.Default.GetHashCode(Item1), - EqualityComparer.Default.GetHashCode(Item2), - EqualityComparer.Default.GetHashCode(Item3), - EqualityComparer.Default.GetHashCode(Item4), - EqualityComparer.Default.GetHashCode(Item5), - EqualityComparer.Default.GetHashCode(Item6), - EqualityComparer.Default.GetHashCode(Item7), - rest.GetHashCode()); - } - - Debug.Assert(false, "Missed all cases for computing ValueTuple hash code"); - return -1; - } - - int IStructuralEquatable.GetHashCode(IEqualityComparer comparer) - { - return GetHashCodeCore(comparer); - } - - private int GetHashCodeCore(IEqualityComparer comparer) - { - // We want to have a limited hash in this case. We'll use the last 8 elements of the tuple - if (Rest is not ITupleInternal rest) - { - return ValueTuple.CombineHashCodes( - comparer.GetHashCode(Item1), - comparer.GetHashCode(Item2), - comparer.GetHashCode(Item3), - comparer.GetHashCode(Item4), - comparer.GetHashCode(Item5), - comparer.GetHashCode(Item6), - comparer.GetHashCode(Item7)); - } - - int size = rest.Size; - if (size >= 8) { return rest.GetHashCode(comparer); } - - // In this case, the rest member has less than 8 elements so we need to combine some our elements with the elements in rest - int k = 8 - size; - switch (k) - { - case 1: - return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item7), rest.GetHashCode(comparer)); - case 2: - return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item6), comparer.GetHashCode(Item7), rest.GetHashCode(comparer)); - case 3: - return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item5), comparer.GetHashCode(Item6), comparer.GetHashCode(Item7), - rest.GetHashCode(comparer)); - case 4: - return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item4), comparer.GetHashCode(Item5), comparer.GetHashCode(Item6), - comparer.GetHashCode(Item7), rest.GetHashCode(comparer)); - case 5: - return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item3), comparer.GetHashCode(Item4), comparer.GetHashCode(Item5), - comparer.GetHashCode(Item6), comparer.GetHashCode(Item7), rest.GetHashCode(comparer)); - case 6: - return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item2), comparer.GetHashCode(Item3), comparer.GetHashCode(Item4), - comparer.GetHashCode(Item5), comparer.GetHashCode(Item6), comparer.GetHashCode(Item7), - rest.GetHashCode(comparer)); - case 7: - case 8: - return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item1), comparer.GetHashCode(Item2), comparer.GetHashCode(Item3), - comparer.GetHashCode(Item4), comparer.GetHashCode(Item5), comparer.GetHashCode(Item6), - comparer.GetHashCode(Item7), rest.GetHashCode(comparer)); - } - - Debug.Assert(false, "Missed all cases for computing ValueTuple hash code"); - return -1; - } - - int ITupleInternal.GetHashCode(IEqualityComparer comparer) - { - return GetHashCodeCore(comparer); - } - - /// - /// Returns a string that represents the value of this instance. - /// - /// The string representation of this instance. - /// - /// The string returned by this method takes the form (Item1, Item2, Item3, Item4, Item5, Item6, Item7, Rest). - /// If any field value is , it is represented as . - /// - public override string ToString() - { - if (Rest is not ITupleInternal rest) - { - return "(" + Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ", " + Item5?.ToString() + ", " + Item6?.ToString() + ", " + Item7?.ToString() + ", " + Rest.ToString() + ")"; - } - else - { - return "(" + Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ", " + Item5?.ToString() + ", " + Item6?.ToString() + ", " + Item7?.ToString() + ", " + rest.ToStringEnd(); - } - } - - string ITupleInternal.ToStringEnd() - { - if (Rest is not ITupleInternal rest) - { - return Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ", " + Item5?.ToString() + ", " + Item6?.ToString() + ", " + Item7?.ToString() + ", " + Rest.ToString() + ")"; - } - else - { - return Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ", " + Item5?.ToString() + ", " + Item6?.ToString() + ", " + Item7?.ToString() + ", " + rest.ToStringEnd(); - } - } - - int ITupleInternal.Size - { - get - { - // ITupleInternal? rest = Rest as ITupleInternal; - // return rest == null ? 8 : 7 + rest.Size; - return Rest is not ITupleInternal rest ? 8 : 7 + rest.Size; - } - } - } - -} - -#endif \ No newline at end of file diff --git a/src/Basal/IFox.Basal.Shared/IFox.Basal.Shared.projitems b/src/Basal/IFox.Basal.Shared/IFox.Basal.Shared.projitems index 05ab2a7..ace7153 100644 --- a/src/Basal/IFox.Basal.Shared/IFox.Basal.Shared.projitems +++ b/src/Basal/IFox.Basal.Shared/IFox.Basal.Shared.projitems @@ -13,7 +13,6 @@ - diff --git a/src/Basal/IFox.Basal/GlobalUsings.cs b/src/Basal/IFox.Basal/GlobalUsings.cs index d75b153..7625f18 100644 --- a/src/Basal/IFox.Basal/GlobalUsings.cs +++ b/src/Basal/IFox.Basal/GlobalUsings.cs @@ -14,8 +14,4 @@ global using System.Threading; global using System.Linq.Expressions; global using System.Collections.ObjectModel; - - -#if NET45_OR_GREATER global using Microsoft.CSharp.RuntimeBinder; -#endif \ No newline at end of file diff --git a/src/Basal/IFox.Basal/IFox.Basal.csproj b/src/Basal/IFox.Basal/IFox.Basal.csproj index f5542ed..aef25cf 100644 --- a/src/Basal/IFox.Basal/IFox.Basal.csproj +++ b/src/Basal/IFox.Basal/IFox.Basal.csproj @@ -1,23 +1,22 @@  - NET40;NET45 + NET48 true true MSB3270 - - - 4.7.0 - - + all runtime; build; native; contentfiles; analyzers; buildtransitive + + 4.7.0 + diff --git a/src/CAD/IFox.CAD.ACAD/IFox.CAD.ACAD.csproj b/src/CAD/IFox.CAD.ACAD/IFox.CAD.ACAD.csproj index a7365ec..5f218ef 100644 --- a/src/CAD/IFox.CAD.ACAD/IFox.CAD.ACAD.csproj +++ b/src/CAD/IFox.CAD.ACAD/IFox.CAD.ACAD.csproj @@ -1,7 +1,7 @@  - NET40;NET45 + NET48 true true MSB3270 @@ -10,19 +10,13 @@ DEBUG - - $(Configuration);acad;ac2013 - - - $(Configuration);acad;ac2015 + + $(Configuration);acad - - - - - - + + + diff --git a/tests/TestAcad09plus/TestAcad09plus.csproj b/tests/TestAcad09plus/TestAcad09plus.csproj index 35a0636..2a47f2c 100644 --- a/tests/TestAcad09plus/TestAcad09plus.csproj +++ b/tests/TestAcad09plus/TestAcad09plus.csproj @@ -3,15 +3,15 @@ preview enable - NET45 + NET48 true true x64 True - - $(Configuration);acad;ac2015 + + $(Configuration);acad -- Gitee From 934d1faecb6875af97bdf1877ab5d877703f6c93 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sat, 6 May 2023 23:10:29 +0800 Subject: [PATCH 065/453] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E5=8F=98=E9=87=8FLastPoint=E7=9A=84=E5=9D=90?= =?UTF-8?q?=E6=A0=87(UCS)=E7=9A=84=E9=9D=99=E6=80=81=E5=B1=9E=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/Runtime/Env.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/CAD/IFox.CAD.Shared/Runtime/Env.cs b/src/CAD/IFox.CAD.Shared/Runtime/Env.cs index 7e8085a..0c23f66 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/Env.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/Env.cs @@ -102,6 +102,10 @@ public static bool OrthoMode get => Convert.ToInt16(Acap.GetSystemVariable("ORTHOMODE")) == 1; set => Acap.SetSystemVariable("ORTHOMODE", Convert.ToInt16(value)); } + /// + /// 获取系统变量LastPoint的坐标(UCS) + /// + public static Point3d LastPoint => (Point3d)Acap.GetSystemVariable("LASTPOINT"); #region Dimblk -- Gitee From e3181922a081cc99cfca829911f5999926e7322f Mon Sep 17 00:00:00 2001 From: vicwjb Date: Thu, 4 May 2023 23:09:34 +0800 Subject: [PATCH 066/453] =?UTF-8?q?=E5=88=A0=E9=99=A4=E5=BA=8F=E5=88=97?= =?UTF-8?q?=E5=8C=96=E5=8F=8Adwgfiler=E7=9B=B8=E5=85=B3=E5=86=85=E5=AE=B9?= =?UTF-8?q?=E3=80=82fixed=20#I70C67?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Basal/IFox.Basal/GlobalUsings.cs | 2 - src/Basal/IFox.Basal/IFox.Basal.csproj | 10 +-- src/CAD/Directory.Build.props | 4 +- src/CAD/IFox.CAD.ACAD/GlobalUsings.cs | 10 --- src/CAD/IFox.CAD.ACAD/IFox.CAD.ACAD.csproj | 2 +- .../ExtensionMethod/Filer/DwgFiler.cs | 7 ++- .../ExtensionMethod/Filer/DwgFilerEx.cs | 8 ++- .../ExtensionMethod/Filer/DxfFiler.cs | 6 +- .../ExtensionMethod/JsonConverter.cs | 4 +- tests/TestAcad09plus/GlobalUsings.cs | 5 -- tests/TestAcad09plus/TestAcad09plus.csproj | 62 +++++++++---------- tests/TestShared/TestDwgFilerEx.cs | 7 ++- 12 files changed, 63 insertions(+), 64 deletions(-) diff --git a/src/Basal/IFox.Basal/GlobalUsings.cs b/src/Basal/IFox.Basal/GlobalUsings.cs index 7625f18..379fbde 100644 --- a/src/Basal/IFox.Basal/GlobalUsings.cs +++ b/src/Basal/IFox.Basal/GlobalUsings.cs @@ -2,10 +2,8 @@ global using System; global using System.Collections; global using System.Collections.Generic; -global using System.IO; global using System.Linq; global using System.Text; -global using System.Reflection; global using System.ComponentModel; global using System.Runtime.InteropServices; global using System.Diagnostics; diff --git a/src/Basal/IFox.Basal/IFox.Basal.csproj b/src/Basal/IFox.Basal/IFox.Basal.csproj index aef25cf..ad2622c 100644 --- a/src/Basal/IFox.Basal/IFox.Basal.csproj +++ b/src/Basal/IFox.Basal/IFox.Basal.csproj @@ -10,16 +10,16 @@ - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + 4.7.0 - + diff --git a/src/CAD/Directory.Build.props b/src/CAD/Directory.Build.props index 90de1e7..795781f 100644 --- a/src/CAD/Directory.Build.props +++ b/src/CAD/Directory.Build.props @@ -1,8 +1,8 @@  - 0.6.1 - 发布0.6.1版 + 0.7.0-alpha1 + 发布0.7.0-alpha1版 diff --git a/src/CAD/IFox.CAD.ACAD/GlobalUsings.cs b/src/CAD/IFox.CAD.ACAD/GlobalUsings.cs index dadfe53..afce80c 100644 --- a/src/CAD/IFox.CAD.ACAD/GlobalUsings.cs +++ b/src/CAD/IFox.CAD.ACAD/GlobalUsings.cs @@ -10,7 +10,6 @@ global using Microsoft.Win32; global using System.ComponentModel; global using System.Runtime.InteropServices; -global using System.Collections.Specialized; global using Exception = System.Exception; @@ -25,10 +24,8 @@ global using Autodesk.AutoCAD.Geometry; global using Autodesk.AutoCAD.Runtime; global using Acap = Autodesk.AutoCAD.ApplicationServices.Application; -global using Acgi = Autodesk.AutoCAD.GraphicsInterface; global using Autodesk.AutoCAD.DatabaseServices.Filters; -global using Autodesk.AutoCAD; // jig命名空间会引起Viewport/Polyline等等重义,最好逐个引入 using Autodesk.AutoCAD.GraphicsInterface global using Autodesk.AutoCAD.GraphicsInterface; @@ -37,13 +34,6 @@ global using Group = Autodesk.AutoCAD.DatabaseServices.Group; global using Viewport = Autodesk.AutoCAD.DatabaseServices.Viewport; global using Polyline = Autodesk.AutoCAD.DatabaseServices.Polyline; -global using Cad_DwgFiler = Autodesk.AutoCAD.DatabaseServices.DwgFiler; -global using Cad_DxfFiler = Autodesk.AutoCAD.DatabaseServices.DxfFiler; -global using Cad_ErrorStatus = Autodesk.AutoCAD.Runtime.ErrorStatus; // ifoxcad.basal 引用 global using IFoxCAD.Basal; - -#if !NewtonsoftJson -global using System.Web.Script.Serialization; -#endif \ No newline at end of file diff --git a/src/CAD/IFox.CAD.ACAD/IFox.CAD.ACAD.csproj b/src/CAD/IFox.CAD.ACAD/IFox.CAD.ACAD.csproj index 5f218ef..64082ed 100644 --- a/src/CAD/IFox.CAD.ACAD/IFox.CAD.ACAD.csproj +++ b/src/CAD/IFox.CAD.ACAD/IFox.CAD.ACAD.csproj @@ -41,7 +41,7 @@ - + diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Filer/DwgFiler.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Filer/DwgFiler.cs index d40f7a3..7f9c07c 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Filer/DwgFiler.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Filer/DwgFiler.cs @@ -1,4 +1,5 @@ -namespace IFoxCAD.Cad; +#if false +namespace IFoxCAD.Cad; /* Arx自定义实体类,加 读函数(assertReadEnabled)和写函数(assertWriteEnabled) @@ -490,4 +491,6 @@ public override string ToString() return serializer.Serialize(this); #endif } -} \ No newline at end of file +} + +#endif \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Filer/DwgFilerEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Filer/DwgFilerEx.cs index f91fb4c..28526d8 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Filer/DwgFilerEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Filer/DwgFilerEx.cs @@ -1,4 +1,6 @@ -namespace IFoxCAD.Cad; +#if false + +namespace IFoxCAD.Cad; /// /// Dwg序列化 @@ -84,4 +86,6 @@ public static implicit operator Cad_DwgFiler(DwgFilerEx df) return df.DwgFiler; } #endregion -} \ No newline at end of file +} + +#endif \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Filer/DxfFiler.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Filer/DxfFiler.cs index 975c505..7956a4a 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Filer/DxfFiler.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Filer/DxfFiler.cs @@ -1,4 +1,6 @@ -#if acad +#if false + +#if acad namespace IFoxCAD.Cad; /* 此处暂未完成,无任何测试,尚且不知道怎么用 */ @@ -218,4 +220,6 @@ protected override void Dispose(bool disposing) base.Dispose(disposing); } } +#endif + #endif \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/JsonConverter.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/JsonConverter.cs index 975e511..59daa7b 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/JsonConverter.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/JsonConverter.cs @@ -1,4 +1,4 @@ - +#if false namespace IFoxCAD.Cad; @@ -115,4 +115,6 @@ public override object Deserialize(IDictionary dictionary, Type return id; } } +#endif + #endif \ No newline at end of file diff --git a/tests/TestAcad09plus/GlobalUsings.cs b/tests/TestAcad09plus/GlobalUsings.cs index 1bede1f..c28a4bf 100644 --- a/tests/TestAcad09plus/GlobalUsings.cs +++ b/tests/TestAcad09plus/GlobalUsings.cs @@ -47,8 +47,3 @@ global using IFoxCAD.Basal; global using IFoxCAD.WPF; - - -#if !NewtonsoftJson -global using System.Web.Script.Serialization; -#endif \ No newline at end of file diff --git a/tests/TestAcad09plus/TestAcad09plus.csproj b/tests/TestAcad09plus/TestAcad09plus.csproj index 2a47f2c..c12c96c 100644 --- a/tests/TestAcad09plus/TestAcad09plus.csproj +++ b/tests/TestAcad09plus/TestAcad09plus.csproj @@ -1,40 +1,40 @@  - - preview - enable + + preview + enable - NET48 - true - true - x64 - True - + NET48 + true + true + x64 + True + - - $(Configuration);acad - + + $(Configuration);acad + - - - - + + + + - - - TestView.xaml - - + + + TestView.xaml + + - - - Designer - - + + + Designer + + - + - - - - + + + + \ No newline at end of file diff --git a/tests/TestShared/TestDwgFilerEx.cs b/tests/TestShared/TestDwgFilerEx.cs index d2267af..6513cda 100644 --- a/tests/TestShared/TestDwgFilerEx.cs +++ b/tests/TestShared/TestDwgFilerEx.cs @@ -1,4 +1,5 @@ -namespace Test; +#if false +namespace Test; using DxfFiler = IFoxCAD.Cad.DxfFiler; @@ -155,4 +156,6 @@ public static void CmdTest_TextOut() tr.CurrentSpace.AddEntity(nText); } } -} \ No newline at end of file +} + +#endif \ No newline at end of file -- Gitee From 4d07cf1f74e87ea6cd62ec9e202241a7da3a7649 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Fri, 5 May 2023 22:49:15 +0800 Subject: [PATCH 067/453] =?UTF-8?q?=E4=BC=98=E5=8C=96using=E5=BC=95?= =?UTF-8?q?=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Basal/IFox.Basal.Shared/General/ArgumentNullEx.cs | 4 +--- src/Basal/IFox.Basal/GlobalUsings.cs | 1 + 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Basal/IFox.Basal.Shared/General/ArgumentNullEx.cs b/src/Basal/IFox.Basal.Shared/General/ArgumentNullEx.cs index bb24c23..198b237 100644 --- a/src/Basal/IFox.Basal.Shared/General/ArgumentNullEx.cs +++ b/src/Basal/IFox.Basal.Shared/General/ArgumentNullEx.cs @@ -1,6 +1,4 @@ -using System.Diagnostics.CodeAnalysis; - -namespace IFoxCAD.Basal +namespace IFoxCAD.Basal { /// /// 参数null检查类 diff --git a/src/Basal/IFox.Basal/GlobalUsings.cs b/src/Basal/IFox.Basal/GlobalUsings.cs index 379fbde..adaece7 100644 --- a/src/Basal/IFox.Basal/GlobalUsings.cs +++ b/src/Basal/IFox.Basal/GlobalUsings.cs @@ -13,3 +13,4 @@ global using System.Linq.Expressions; global using System.Collections.ObjectModel; global using Microsoft.CSharp.RuntimeBinder; +global using System.Diagnostics.CodeAnalysis; -- Gitee From d10be932806d7aee906b1c7d287caa65e2bf3ae2 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Fri, 5 May 2023 23:01:56 +0800 Subject: [PATCH 068/453] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=97=A0=E7=94=A8?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/TransactionEx.cs | 73 +++++++++---------- 1 file changed, 35 insertions(+), 38 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/TransactionEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/TransactionEx.cs index a9e2d71..698f503 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/TransactionEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/TransactionEx.cs @@ -1,44 +1,41 @@ -using System.Diagnostics.CodeAnalysis; +namespace IFoxCAD.Cad; -namespace IFoxCAD.Cad +/// +/// cad的事务的扩展类 +/// +public static class TransactionEx { /// - /// cad的事务的扩展类 + /// 根据对象id获取对象 /// - public static class TransactionEx + /// + /// 对象id + /// 打开模式,默认为只读 + /// 是否打开已删除对象,默认为不打开 + /// 是否打开锁定图层对象,默认为不打开 + /// 数据库DBObject对象 + public static DBObject GetObject(this Transaction tr, ObjectId id, + OpenMode openMode = OpenMode.ForRead, + bool openErased = false, + bool openLockedLayer = false) { - /// - /// 根据对象id获取对象 - /// - /// - /// 对象id - /// 打开模式,默认为只读 - /// 是否打开已删除对象,默认为不打开 - /// 是否打开锁定图层对象,默认为不打开 - /// 数据库DBObject对象 - public static DBObject GetObject([DisallowNull] this Transaction tr, ObjectId id, - OpenMode openMode = OpenMode.ForRead, - bool openErased = false, - bool openLockedLayer = false) - { - return tr.GetObject(id, openMode, openErased, openLockedLayer); - } - /// - /// 根据对象id获取图元对象 - /// - /// 要获取的图元对象的类型 - /// - /// 对象id - /// 打开模式,默认为只读 - /// 是否打开已删除对象,默认为不打开 - /// 是否打开锁定图层对象,默认为不打开 - /// 图元对象,类型不匹配时抛异常 - public static T? GetObject([DisallowNull] this Transaction tr, ObjectId id, - OpenMode openMode = OpenMode.ForRead, - bool openErased = false, - bool openLockedLayer = false) where T : DBObject - { - return tr.GetObject(id, openMode, openErased, openLockedLayer) as T; - } + return tr.GetObject(id, openMode, openErased, openLockedLayer); } -} + /// + /// 根据对象id获取图元对象 + /// + /// 要获取的图元对象的类型 + /// + /// 对象id + /// 打开模式,默认为只读 + /// 是否打开已删除对象,默认为不打开 + /// 是否打开锁定图层对象,默认为不打开 + /// 图元对象,类型不匹配时抛异常 + public static T? GetObject(this Transaction tr, ObjectId id, + OpenMode openMode = OpenMode.ForRead, + bool openErased = false, + bool openLockedLayer = false) where T : DBObject + { + return tr.GetObject(id, openMode, openErased, openLockedLayer) as T; + } +} \ No newline at end of file -- Gitee From 16a62403f11f23541dd44e9fbad9b1a4d9b27e4b Mon Sep 17 00:00:00 2001 From: vicwjb Date: Sun, 7 May 2023 00:49:58 +0800 Subject: [PATCH 069/453] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.ACAD/GlobalUsings.cs | 1 + src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs | 25 ++++++++-------------- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/src/CAD/IFox.CAD.ACAD/GlobalUsings.cs b/src/CAD/IFox.CAD.ACAD/GlobalUsings.cs index afce80c..2e27cbf 100644 --- a/src/CAD/IFox.CAD.ACAD/GlobalUsings.cs +++ b/src/CAD/IFox.CAD.ACAD/GlobalUsings.cs @@ -24,6 +24,7 @@ global using Autodesk.AutoCAD.Geometry; global using Autodesk.AutoCAD.Runtime; global using Acap = Autodesk.AutoCAD.ApplicationServices.Application; +global using Acaop = Autodesk.AutoCAD.ApplicationServices.Core.Application; global using Autodesk.AutoCAD.DatabaseServices.Filters; diff --git a/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs b/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs index bb4fe6b..e5e8ff7 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs @@ -12,7 +12,7 @@ namespace IFoxCAD.Cad; /// [DebuggerDisplay("{DebuggerDisplay,nq}")] [DebuggerTypeProxy(typeof(DBTrans))] -public class DBTrans : IDisposable +public sealed class DBTrans : IDisposable { [DebuggerBrowsable(DebuggerBrowsableState.Never)] private string DebuggerDisplay => ToString(" | "); @@ -142,7 +142,7 @@ public static DBTrans Top /// 是否锁文档 public DBTrans(Document? doc = null, bool commit = true, bool doclock = false) { - Document = doc ?? Acap.DocumentManager.MdiActiveDocument; + Document = doc ?? Acaop.DocumentManager.MdiActiveDocument; Database = Document.Database; Editor = Document.Editor; Transaction = Database.TransactionManager.StartTransaction(); @@ -205,7 +205,7 @@ public DBTrans(string fileName, } else { - var doc = Acap.DocumentManager + var doc = Acaop.DocumentManager .Cast() .FirstOrDefault(doc => !doc.IsDisposed && doc.Name == _fileName); @@ -217,7 +217,7 @@ public DBTrans(string fileName, { // 设置命令标记: CommandFlags.Session // 若没有设置: Open()之后的会进入中断状态(不会执行,直到切换文档ctrl+tab或者关闭文档) - doc = Acap.DocumentManager.Open(fileName, fileOpenMode == FileOpenMode.OpenForReadAndReadShare, password); + doc = Acaop.DocumentManager.Open(fileName, fileOpenMode == FileOpenMode.OpenForReadAndReadShare, password); } catch (Exception e) { @@ -227,7 +227,7 @@ public DBTrans(string fileName, // 设置命令标记: CommandFlags.Session // 若没有设置: doc.IsActive 会异常 if (!doc.IsActive) - Acap.DocumentManager.MdiActiveDocument = doc; + Acaop.DocumentManager.MdiActiveDocument = doc; // Open()是跨文档,所以必须要锁文档 // 否则 Editor?.Redraw() 的 tm.QueueForGraphicsFlush() 将报错提示文档锁 @@ -457,14 +457,7 @@ public ObjectId GetObjectId(string handleString) { var hanle = new Handle(Convert.ToInt64(handleString, 16)); // return Database.GetObjectId(false, hanle, 0); - if(Database.TryGetObjectId(hanle, out ObjectId id)) - { - return id; - } - else - { - return ObjectId.Null; - } + return Database.TryGetObjectId(hanle, out ObjectId id) ? id : ObjectId.Null; } #endregion @@ -492,7 +485,7 @@ public void SaveFile(DwgVersion version = DwgVersion.AC1800, { // 遍历当前所有文档,文档必然是前台的 Document? doc = null; - foreach (Document docItem in Acap.DocumentManager) + foreach (Document docItem in Acaop.DocumentManager) { if (docItem.Database.Filename == this.Database.Filename) { @@ -652,7 +645,7 @@ public void Task(Action action, bool handlingDBTextDeviation = true) // 后台 // 这种情况发生在关闭了所有文档之后,进行跨进程通讯 // 此处要先获取激活的文档,不能直接获取当前数据库否则异常 - var dm = Acap.DocumentManager; + var dm = Acaop.DocumentManager; var doc = dm.MdiActiveDocument; if (doc == null) { @@ -712,7 +705,7 @@ public void Dispose() /// 释放函数 /// /// - protected virtual void Dispose(bool disposing) + private void Dispose(bool disposing) { /* 事务dispose流程: * 1. 根据传入的参数确定是否提交,true为提交,false为不提交 -- Gitee From 611955a488d70aa260f5bece88fb84bd0e76c9cf Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Mon, 8 May 2023 09:23:53 +0800 Subject: [PATCH 070/453] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=8E=92=E5=88=97?= =?UTF-8?q?=E9=A1=BA=E5=BA=8F=EF=BC=8C=E4=BE=BF=E4=BA=8E=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems b/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems index c77cbc0..fefa9b7 100644 --- a/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems +++ b/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems @@ -59,28 +59,29 @@ + + - + + - - - - + + + + - - -- Gitee From 61a86ae54422d50ce8334c10a8a66e1292dd9bac Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Mon, 8 May 2023 09:24:45 +0800 Subject: [PATCH 071/453] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=8D=95=E5=AD=97?= =?UTF-8?q?=E6=AF=8D=E5=85=B3=E9=94=AE=E5=AD=97=E9=92=A9=E5=AD=90=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Runtime/SingleKeyWordHook.cs | 165 ++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 src/CAD/IFox.CAD.Shared/Runtime/SingleKeyWordHook.cs diff --git a/src/CAD/IFox.CAD.Shared/Runtime/SingleKeyWordHook.cs b/src/CAD/IFox.CAD.Shared/Runtime/SingleKeyWordHook.cs new file mode 100644 index 0000000..9728e26 --- /dev/null +++ b/src/CAD/IFox.CAD.Shared/Runtime/SingleKeyWordHook.cs @@ -0,0 +1,165 @@ +namespace IFoxCAD.Cad; +/// +/// 关键字不需要空格钩子 +/// By DYH 20230508 +/// +public class SingleKeyWordHook : IDisposable +{ + #region 私有字段 + /// + /// 关键字合集 + /// + private readonly HashSet keyWords; + private bool isResponsed; + private bool working; + private Keys key; + #endregion + + #region 公共属性 + /// + /// 上一个触发的关键字 + /// + public Keys Key => key; + /// + /// 上一个触发的关键字字符串 + /// + public string StringResult => key.ToString().ToUpper(); + /// + /// 是否响应了 + /// + public bool IsResponsed => isResponsed && working; + #endregion + + #region 构造 + /// + /// 单字母关键字免输回车钩子 + /// + public SingleKeyWordHook() + { + isDisposed = false; + isResponsed = false; + keyWords = new HashSet(); + key = Keys.None; + working = true; + Acap.PreTranslateMessage += Acap_PreTranslateMessage; + } + #endregion + + #region 方法 + /// + /// 添加Keys + /// + /// Keys集合 + public void AddKeys(params Keys[] values) => values.ForEach(value => keyWords.Add(value)); + /// + /// 添加Keys + /// + /// 关键字集合 + public void AddKeys(KeywordCollection keywordCollection) + { + foreach (Keyword item in keywordCollection) + { + if (item.LocalName.Length == 1) + { + Keys k = (Keys)item.LocalName.ToCharArray()[0]; + keyWords.Add(k); + } + } + } + /// + /// 移除Keys + /// + /// Keys集合 + public void Remove(params Keys[] values) => values.ForEach(value => keyWords.Remove(value)); + /// + /// 清空Keys + /// + public void Clear() => keyWords.Clear(); + /// + /// 复位响应状态,每个循环开始时使用 + /// + public void Reset() + { + isResponsed = false; + } + /// + /// 暂停工作 + /// + public void Pause() + { + working = false; + } + /// + /// 开始工作 + /// + public void Working() + { + working = true; + } + #endregion + + #region 事件 + private void Acap_PreTranslateMessage(object sender, PreTranslateMessageEventArgs e) + { + if (!working || e.Message.message != 256) return; + var tempKey = IntPtr.Size == 4 ? (Keys)e.Message.wParam.ToInt32() : (Keys)e.Message.wParam.ToInt64(); + bool contains = keyWords.Contains(tempKey); + if (contains || tempKey == Keys.ProcessKey) + { + // 标记为true,表示此按键已经被处理,Windows不会再进行处理 + e.Handled = true; + if (contains) + key = tempKey; + if (!isResponsed) + { + // 此bool是防止按键被长按时出错 + isResponsed = true; + // 这里选择发送回车或者ESC//ESC稳妥一些,但是要promptResult的判断顺序 + SingleKeyWordHook.KeyBoardSendKey(Keys.Escape); + } + } + } + #endregion + + #region Dispose + private bool isDisposed; + /// + /// 已经销毁 + /// + public bool IsDisposed => isDisposed; + protected virtual void Dispose(bool disposing) + { + if (!isDisposed) + { + if (disposing) + { + Acap.PreTranslateMessage -= Acap_PreTranslateMessage; + keyWords.Clear(); + } + isDisposed = true; + } + } + public void Dispose() + { + Dispose(disposing: true); + GC.SuppressFinalize(this); + } + #endregion + + #region 静态方法 + /// + /// 发送按键 + /// + /// + /// + /// + /// + private static void KeyBoardSendKey(Keys key, byte bScan = 0, uint dwFlags = 0, uint dwExtraInfo = 0) + { + keybd_event(key, bScan, dwFlags, dwExtraInfo); + keybd_event(key, bScan, 2, dwExtraInfo); + } + [DllImport("user32.dll", EntryPoint = "keybd_event", SetLastError = true)] + private static extern void keybd_event(Keys bVk, byte bScan, uint dwFlags, uint dwExtraInfo); + #endregion +} \ No newline at end of file -- Gitee From d0e1c59f09f4daa5303df47e8965f3dd87a03c44 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Mon, 8 May 2023 09:35:37 +0800 Subject: [PATCH 072/453] =?UTF-8?q?=E5=AF=B9Keys=E7=B1=BB=E8=BF=9B?= =?UTF-8?q?=E8=A1=8C=E7=BA=A6=E6=9D=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/Runtime/SingleKeyWordHook.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/CAD/IFox.CAD.Shared/Runtime/SingleKeyWordHook.cs b/src/CAD/IFox.CAD.Shared/Runtime/SingleKeyWordHook.cs index 9728e26..a0b3f7f 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/SingleKeyWordHook.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/SingleKeyWordHook.cs @@ -1,4 +1,5 @@ -namespace IFoxCAD.Cad; +using Keys = System.Windows.Forms.Keys; +namespace IFoxCAD.Cad; /// /// 关键字不需要空格钩子 /// By DYH 20230508 -- Gitee From db37e0fe678dbdae5e372c6cb410900669814db0 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Mon, 8 May 2023 09:58:18 +0800 Subject: [PATCH 073/453] =?UTF-8?q?=E5=A2=9E=E5=8A=A0SingleKeyWordHook?= =?UTF-8?q?=E7=9A=84=E6=B5=8B=E8=AF=95=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/TestShared/TestSingleKeyWordHook.cs | 48 +++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 tests/TestShared/TestSingleKeyWordHook.cs diff --git a/tests/TestShared/TestSingleKeyWordHook.cs b/tests/TestShared/TestSingleKeyWordHook.cs new file mode 100644 index 0000000..73fe216 --- /dev/null +++ b/tests/TestShared/TestSingleKeyWordHook.cs @@ -0,0 +1,48 @@ +namespace TestShared; +public static class TestSingleKeyWordHook +{ + [CommandMethod(nameof(TestSingleKeyWordHookDemo))] + public static void TestSingleKeyWordHookDemo() + { + var line1 = new Line(Point3d.Origin, new Point3d(100, 100, 0)); + line1.SetDatabaseDefaults(); + using var j1 = new JigEx((mpw, _) => { + line1.Move(line1.StartPoint, mpw); + }); + j1.DatabaseEntityDraw(wd => wd.Geometry.Draw(line1)); + var jppo = j1.SetOptions("\n选择位置或"); + jppo.Keywords.Add("A", "A", "旋转90°(A)"); + jppo.Keywords.Add("D", "D", "旋转45°(D)"); + // 创建关键字钩子 + using var skwh = new SingleKeyWordHook(); + // 添加关键字 + skwh.AddKeys(jppo.Keywords); + while (true) + { + // 循环开始时复位 + skwh.Reset(); + var r1 = Env.Editor.Drag(j1); + if (skwh.IsResponsed || r1.Status == PromptStatus.Keyword) + { + // 此钩子完整保留了原关键字的鼠标点击功能,所以要同时支持两种情况,也方便在已经写好的关键字功能上扩展 + // 如果响应了关键字 + switch (skwh.IsResponsed ? skwh.StringResult : r1.StringResult.ToUpper()) + { + case "A": + line1.Rotation(line1.StartPoint, Math.PI * 0.5, Vector3d.ZAxis); + break; + case "D": + line1.Rotation(line1.StartPoint, Math.PI * 0.25, Vector3d.ZAxis); + break; + } + continue; + } + if (r1.Status == PromptStatus.OK) + { + using var tr = new DBTrans(); + tr.CurrentSpace.AddEntity(line1); + } + return; + } + } +} -- Gitee From ddfb046faf19c52fcf4141f896fc84f81bb6de37 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Mon, 8 May 2023 18:01:20 +0800 Subject: [PATCH 074/453] =?UTF-8?q?Env.LastPoint=E5=B1=9E=E6=80=A7?= =?UTF-8?q?=E7=94=B1=E5=8F=AA=E8=AF=BB=E5=8F=98=E4=B8=BA=E5=8F=AF=E5=86=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/Runtime/Env.cs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/Runtime/Env.cs b/src/CAD/IFox.CAD.Shared/Runtime/Env.cs index 0c23f66..f294941 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/Env.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/Env.cs @@ -103,9 +103,19 @@ public static bool OrthoMode set => Acap.SetSystemVariable("ORTHOMODE", Convert.ToInt16(value)); } /// - /// 获取系统变量LastPoint的坐标(UCS) + /// 读写系统变量LastPoint的坐标(UCS) /// - public static Point3d LastPoint => (Point3d)Acap.GetSystemVariable("LASTPOINT"); + public static Point3d LastPoint + { + get + { + return (Point3d)Acap.GetSystemVariable("LASTPOINT"); + } + set + { + Acap.SetSystemVariable("LASTPOINT", value); + } + } #region Dimblk -- Gitee From d3ff03b5e5a49d1c3c59000f5d4ac02f7f55c470 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 11 May 2023 21:17:14 +0800 Subject: [PATCH 075/453] =?UTF-8?q?=E5=A2=9E=E5=8A=A0Editor.PrepareForJig?= =?UTF-8?q?=E5=87=BD=E6=95=B0=EF=BC=8C=E4=BD=9C=E7=94=A8=E4=B8=BAjig?= =?UTF-8?q?=E5=89=8D=E7=9A=84=E5=87=86=E5=A4=87=E5=B7=A5=E4=BD=9C=EF=BC=8C?= =?UTF-8?q?=E4=BD=BF=E5=9B=BE=E5=85=83=E6=9A=97=E6=98=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/EditorEx.cs | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs index 1db3b77..dbeceab 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs @@ -1070,4 +1070,37 @@ public static void ComExportWMF(this Editor editor, string saveFile, } #endregion + #region JigEx + /// + /// jig前的准备工作,使图元暗显 + /// + /// 命令栏 + /// 实体(已存在数据库中) + public static void PrepareForJig(this Editor ed, params Entity[] ents) + { + ed.PrepareForJig(ents.ToList()); + } + /// + /// jig前的准备工作,使图元暗显 + /// + /// 命令栏 + /// 实体(已存在数据库中) + public static void PrepareForJig(this Editor ed, IEnumerable ents) + { + var dic = new Dictionary(); + foreach (var ent in ents) + { + if (ent.IsNewObject) + continue; + dic.Add(ent, ent.ColorIndex); + ent.ColorIndex = 250; + ent.Draw(); + } + ed.Redraw(); + foreach (var kvp in dic) + { + kvp.Key.ColorIndex = kvp.Value; + } + } + #endregion } \ No newline at end of file -- Gitee From 4db938f7794b3d97da6b756acac464a49b7c8d51 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 11 May 2023 21:25:47 +0800 Subject: [PATCH 076/453] =?UTF-8?q?=E4=B8=BAGeometry.Draw=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E5=A4=8D=E6=95=B0=E5=87=BD=E6=95=B0=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs index 12355c0..869fc3a 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs @@ -656,4 +656,13 @@ public static Point2d Polar(this Point2d pt, double ang, double len) { return pt + Vector2d.XAxis.RotateBy(ang) * len; } + /// + /// 重绘 + /// + /// 图形界面几何 + /// 可绘制的对象列表 + public static void Draw(this Geometry geometry, IEnumerable drawables) + { + drawables.ForEach(d => geometry.Draw(d)); + } } \ No newline at end of file -- Gitee From cbdd5cc90249fc4c05ad7428419e56d14630a36c Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 11 May 2023 21:26:22 +0800 Subject: [PATCH 077/453] =?UTF-8?q?=E4=B8=BAGeometry.Draw=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E5=A4=8D=E6=95=B0=E5=87=BD=E6=95=B0=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs index 869fc3a..2f4f32d 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs @@ -665,4 +665,13 @@ public static void Draw(this Geometry geometry, IEnumerable drawables) { drawables.ForEach(d => geometry.Draw(d)); } + /// + /// 重绘 + /// + /// 图形界面几何 + /// 可绘制的对象列表 + public static void Draw(this Geometry geometry, params Drawable[] drawables) + { + drawables.ForEach(d => geometry.Draw(d)); + } } \ No newline at end of file -- Gitee From 4671a8671f8c4af493abd00c636822e8d87ba625 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 11 May 2023 22:10:39 +0800 Subject: [PATCH 078/453] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=AD=97=E6=AE=B5?= =?UTF-8?q?=E5=91=BD=E5=90=8D=E8=A7=84=E5=88=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Runtime/SingleKeyWordHook.cs | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/Runtime/SingleKeyWordHook.cs b/src/CAD/IFox.CAD.Shared/Runtime/SingleKeyWordHook.cs index a0b3f7f..ed843c5 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/SingleKeyWordHook.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/SingleKeyWordHook.cs @@ -10,25 +10,25 @@ public class SingleKeyWordHook : IDisposable /// /// 关键字合集 /// - private readonly HashSet keyWords; - private bool isResponsed; - private bool working; - private Keys key; + private readonly HashSet _keyWords; + private bool _isResponsed; + private bool _working; + private Keys _key; #endregion #region 公共属性 /// /// 上一个触发的关键字 /// - public Keys Key => key; + public Keys Key => _key; /// /// 上一个触发的关键字字符串 /// - public string StringResult => key.ToString().ToUpper(); + public string StringResult => _key.ToString().ToUpper(); /// /// 是否响应了 /// - public bool IsResponsed => isResponsed && working; + public bool IsResponsed => _isResponsed && _working; #endregion #region 构造 @@ -38,10 +38,10 @@ public class SingleKeyWordHook : IDisposable public SingleKeyWordHook() { isDisposed = false; - isResponsed = false; - keyWords = new HashSet(); - key = Keys.None; - working = true; + _isResponsed = false; + _keyWords = new HashSet(); + _key = Keys.None; + _working = true; Acap.PreTranslateMessage += Acap_PreTranslateMessage; } #endregion @@ -51,7 +51,7 @@ public SingleKeyWordHook() /// 添加Keys /// /// Keys集合 - public void AddKeys(params Keys[] values) => values.ForEach(value => keyWords.Add(value)); + public void AddKeys(params Keys[] values) => values.ForEach(value => _keyWords.Add(value)); /// /// 添加Keys /// @@ -63,7 +63,7 @@ public void AddKeys(KeywordCollection keywordCollection) if (item.LocalName.Length == 1) { Keys k = (Keys)item.LocalName.ToCharArray()[0]; - keyWords.Add(k); + _keyWords.Add(k); } } } @@ -71,50 +71,50 @@ public void AddKeys(KeywordCollection keywordCollection) /// 移除Keys /// /// Keys集合 - public void Remove(params Keys[] values) => values.ForEach(value => keyWords.Remove(value)); + public void Remove(params Keys[] values) => values.ForEach(value => _keyWords.Remove(value)); /// /// 清空Keys /// - public void Clear() => keyWords.Clear(); + public void Clear() => _keyWords.Clear(); /// /// 复位响应状态,每个循环开始时使用 /// public void Reset() { - isResponsed = false; + _isResponsed = false; } /// /// 暂停工作 /// public void Pause() { - working = false; + _working = false; } /// /// 开始工作 /// public void Working() { - working = true; + _working = true; } #endregion #region 事件 private void Acap_PreTranslateMessage(object sender, PreTranslateMessageEventArgs e) { - if (!working || e.Message.message != 256) return; + if (!_working || e.Message.message != 256) return; var tempKey = IntPtr.Size == 4 ? (Keys)e.Message.wParam.ToInt32() : (Keys)e.Message.wParam.ToInt64(); - bool contains = keyWords.Contains(tempKey); + bool contains = _keyWords.Contains(tempKey); if (contains || tempKey == Keys.ProcessKey) { // 标记为true,表示此按键已经被处理,Windows不会再进行处理 e.Handled = true; if (contains) - key = tempKey; - if (!isResponsed) + _key = tempKey; + if (!_isResponsed) { // 此bool是防止按键被长按时出错 - isResponsed = true; + _isResponsed = true; // 这里选择发送回车或者ESC//ESC稳妥一些,但是要promptResult的判断顺序 SingleKeyWordHook.KeyBoardSendKey(Keys.Escape); } @@ -135,7 +135,7 @@ protected virtual void Dispose(bool disposing) if (disposing) { Acap.PreTranslateMessage -= Acap_PreTranslateMessage; - keyWords.Clear(); + _keyWords.Clear(); } isDisposed = true; } -- Gitee From 61614c266a3753029300fa21aacccfed12e5d05a Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 11 May 2023 22:13:10 +0800 Subject: [PATCH 079/453] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=AD=97=E6=AE=B5?= =?UTF-8?q?=E5=91=BD=E5=90=8D=E8=A7=84=E5=88=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/Runtime/SingleKeyWordHook.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/Runtime/SingleKeyWordHook.cs b/src/CAD/IFox.CAD.Shared/Runtime/SingleKeyWordHook.cs index ed843c5..8c7a230 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/SingleKeyWordHook.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/SingleKeyWordHook.cs @@ -37,7 +37,7 @@ public class SingleKeyWordHook : IDisposable /// public SingleKeyWordHook() { - isDisposed = false; + _isDisposed = false; _isResponsed = false; _keyWords = new HashSet(); _key = Keys.None; @@ -123,21 +123,21 @@ private void Acap_PreTranslateMessage(object sender, PreTranslateMessageEventArg #endregion #region Dispose - private bool isDisposed; + private bool _isDisposed; /// /// 已经销毁 /// - public bool IsDisposed => isDisposed; + public bool IsDisposed => _isDisposed; protected virtual void Dispose(bool disposing) { - if (!isDisposed) + if (!_isDisposed) { if (disposing) { Acap.PreTranslateMessage -= Acap_PreTranslateMessage; _keyWords.Clear(); } - isDisposed = true; + _isDisposed = true; } } public void Dispose() -- Gitee From b6946d9c8a4e5dea48932028e5fcf72872feff5a Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Fri, 12 May 2023 20:22:21 +0800 Subject: [PATCH 080/453] =?UTF-8?q?=E5=88=A0=E9=99=A4=E5=BC=95=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/TestShared/Copyclip.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/TestShared/Copyclip.cs b/tests/TestShared/Copyclip.cs index bcdb912..61c4cbf 100644 --- a/tests/TestShared/Copyclip.cs +++ b/tests/TestShared/Copyclip.cs @@ -3,7 +3,6 @@ #define PASTECLIP namespace Test; -using Autodesk.AutoCAD.DatabaseServices; using System; using System.Diagnostics; using System.Drawing.Imaging; -- Gitee From f001b7ab76761a05fc31ce44872ef47b46f04760 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Fri, 12 May 2023 20:23:03 +0800 Subject: [PATCH 081/453] =?UTF-8?q?=E6=B7=BB=E5=8A=A0test=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E7=9A=84=E5=85=B1=E4=BA=AB=E9=A1=B9=E7=9B=AE=E5=BC=95?= =?UTF-8?q?=E7=94=A8=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/TestShared/TestShared.projitems | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/TestShared/TestShared.projitems b/tests/TestShared/TestShared.projitems index dd9a61c..e6dfbbe 100644 --- a/tests/TestShared/TestShared.projitems +++ b/tests/TestShared/TestShared.projitems @@ -36,6 +36,7 @@ + -- Gitee From 9dd03e00bb4e5b092748c470bbb460527acec6fd Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Fri, 12 May 2023 20:23:31 +0800 Subject: [PATCH 082/453] =?UTF-8?q?=E4=BF=AE=E6=94=B9test=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=20=E7=9A=84globalusing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/TestAcad09plus/GlobalUsings.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/TestAcad09plus/GlobalUsings.cs b/tests/TestAcad09plus/GlobalUsings.cs index c28a4bf..d32580b 100644 --- a/tests/TestAcad09plus/GlobalUsings.cs +++ b/tests/TestAcad09plus/GlobalUsings.cs @@ -25,6 +25,7 @@ global using Autodesk.AutoCAD.Geometry; global using Autodesk.AutoCAD.Runtime; global using Acap = Autodesk.AutoCAD.ApplicationServices.Application; +global using Acaop = Autodesk.AutoCAD.ApplicationServices.Core.Application; global using Acgi = Autodesk.AutoCAD.GraphicsInterface; global using Autodesk.AutoCAD.DatabaseServices.Filters; -- Gitee From 9117a150b68b4c055aedd928f780f2e1deb004e2 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Fri, 12 May 2023 20:26:14 +0800 Subject: [PATCH 083/453] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E6=8B=89=E4=BC=B8=E7=82=B9=E9=87=8D=E8=BD=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/Entity/EntityEx.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityEx.cs index d0de5ca..870cc09 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityEx.cs @@ -140,6 +140,15 @@ public static BoundingInfo GetBoundingBoxEx(this Entity ent) { return EntityBoundingInfo.GetBoundingInfo(ent); } - - + /// + /// 获取拉伸点 + /// + /// 实体 + /// 点集 + public static IEnumerable GetStretchPoints(this Entity ent) + { + var p3dc = new Point3dCollection(); + ent.GetStretchPoints(p3dc); + return p3dc.Cast(); + } } \ No newline at end of file -- Gitee From 360d7ee21ddaf073bc5dfe603ad6678f6ee4a65d Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Fri, 12 May 2023 20:31:20 +0800 Subject: [PATCH 084/453] =?UTF-8?q?=E6=B7=BB=E5=8A=A03d=E5=90=91=E9=87=8F?= =?UTF-8?q?=E8=BD=AC=E4=B8=BA2d=E7=9A=84=E6=97=A0=E5=8F=82=E6=95=B0?= =?UTF-8?q?=E9=87=8D=E8=BD=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs index 2f4f32d..6112fff 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs @@ -574,7 +574,15 @@ public static Size GetSize(this Extents3d ext) int height = (int)Math.Ceiling(ext.MaxPoint.Y - ext.MinPoint.Y); return new(width, height); } - + /// + /// 转换为2d向量 + /// + /// 3d向量 + /// 2d向量 + public static Vector2d Convert2d(this Vector3d vector3d) + { + return new Vector2d(vector3d.X, vector3d.Y); + } /// /// 将三维点转换为二维点 /// -- Gitee From 32da5187053d7dc4b8046eda5664978d21e2d614 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Fri, 12 May 2023 20:33:45 +0800 Subject: [PATCH 085/453] =?UTF-8?q?VectorEx=E5=BD=92=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/GeometryEx.cs | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs index 6112fff..0fca4a2 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs @@ -574,15 +574,7 @@ public static Size GetSize(this Extents3d ext) int height = (int)Math.Ceiling(ext.MaxPoint.Y - ext.MinPoint.Y); return new(width, height); } - /// - /// 转换为2d向量 - /// - /// 3d向量 - /// 2d向量 - public static Vector2d Convert2d(this Vector3d vector3d) - { - return new Vector2d(vector3d.X, vector3d.Y); - } + /// /// 将三维点转换为二维点 /// @@ -682,4 +674,16 @@ public static void Draw(this Geometry geometry, params Drawable[] drawables) { drawables.ForEach(d => geometry.Draw(d)); } +} +public static class VectorEx +{ + /// + /// 转换为2d向量 + /// + /// 3d向量 + /// 2d向量 + public static Vector2d Convert2d(this Vector3d vector3d) + { + return new Vector2d(vector3d.X, vector3d.Y); + } } \ No newline at end of file -- Gitee From a3c4b6cace4fcf16192c184a3cecfbf2236e506c Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Fri, 12 May 2023 20:40:24 +0800 Subject: [PATCH 086/453] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=90=91=E9=87=8F?= =?UTF-8?q?=E5=8F=89=E4=B9=98=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs index 0fca4a2..328b207 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs @@ -686,4 +686,14 @@ public static Vector2d Convert2d(this Vector3d vector3d) { return new Vector2d(vector3d.X, vector3d.Y); } + /// + /// 叉乘 + /// + /// 向量a + /// 向量b + /// 叉乘值 + public static double Cross2d(this Vector3d a, Vector3d b) + { + return a.X * b.Y - b.X * a.Y; + } } \ No newline at end of file -- Gitee From 6bf90cd42a0b35c7096bc6f346c1b82f62973158 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Fri, 12 May 2023 20:45:54 +0800 Subject: [PATCH 087/453] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=90=91=E9=87=8FZ?= =?UTF-8?q?=E5=80=BC=E5=BD=92=E9=9B=B6=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs index 328b207..6d6dd52 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs @@ -687,7 +687,7 @@ public static Vector2d Convert2d(this Vector3d vector3d) return new Vector2d(vector3d.X, vector3d.Y); } /// - /// 叉乘 + /// 2d叉乘 /// /// 向量a /// 向量b @@ -696,4 +696,14 @@ public static double Cross2d(this Vector3d a, Vector3d b) { return a.X * b.Y - b.X * a.Y; } + /// + /// 2d叉乘 + /// + /// 向量a + /// 向量b + /// 叉乘值 + public static double Cross2d(this Vector2d a, Vector2d b) + { + return a.X * b.Y - b.X * a.Y; + } } \ No newline at end of file -- Gitee From 80806d2d63fda217ae61b2b2becea3cd1d80f1e6 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Fri, 12 May 2023 20:46:05 +0800 Subject: [PATCH 088/453] =?UTF-8?q?=E5=90=91=E9=87=8FZ=E5=80=BC=E5=BD=92?= =?UTF-8?q?=E9=9B=B6=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs index 6d6dd52..1639beb 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs @@ -706,4 +706,13 @@ public static double Cross2d(this Vector2d a, Vector2d b) { return a.X * b.Y - b.X * a.Y; } + /// + /// 向量Z值归零 + /// + /// 向量 + /// + public static Vector3d Z20(this Vector3d vector3d) + { + return new Vector3d(vector3d.X,vector3d.Y,0); + } } \ No newline at end of file -- Gitee From d0c261d3ac1312f8274cda6639aca30e9d87b2bf Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Fri, 12 May 2023 20:47:20 +0800 Subject: [PATCH 089/453] =?UTF-8?q?=E5=A2=9E=E5=8A=A02d=E8=BD=AC3d?= =?UTF-8?q?=E5=90=91=E9=87=8F=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs index 1639beb..789c03a 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs @@ -574,7 +574,7 @@ public static Size GetSize(this Extents3d ext) int height = (int)Math.Ceiling(ext.MaxPoint.Y - ext.MinPoint.Y); return new(width, height); } - + /// /// 将三维点转换为二维点 /// @@ -687,6 +687,15 @@ public static Vector2d Convert2d(this Vector3d vector3d) return new Vector2d(vector3d.X, vector3d.Y); } /// + /// 转换为3d向量 + /// + /// 2d向量 + /// 3d向量 + public static Vector3d Convert3d(this Vector2d vector2d, double z = 0) + { + return new Vector3d(vector2d.X, vector2d.Y, z); + } + /// /// 2d叉乘 /// /// 向量a @@ -713,6 +722,6 @@ public static double Cross2d(this Vector2d a, Vector2d b) /// public static Vector3d Z20(this Vector3d vector3d) { - return new Vector3d(vector3d.X,vector3d.Y,0); + return new Vector3d(vector3d.X, vector3d.Y, 0); } } \ No newline at end of file -- Gitee From 462d3dffbe09463f12ddfff128f6e94ff24339fc Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Fri, 12 May 2023 20:51:42 +0800 Subject: [PATCH 090/453] =?UTF-8?q?=E7=A7=BB=E5=8A=A8=E5=AE=9E=E4=BD=93?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=90=91=E9=87=8F=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/Entity/EntityEx.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityEx.cs index 870cc09..bd7c64d 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityEx.cs @@ -23,6 +23,18 @@ public static void Move(this Entity ent, Point3d from, Point3d to) ent.TransformBy(Matrix3d.Displacement(to - from)); } } + /// + /// 移动实体 + /// + /// 实体 + /// 向量 + public static void Move(this Entity ent, Vector3d vector) + { + using (ent.ForWrite()) + { + ent.TransformBy(Matrix3d.Displacement(vector)); + } + } /// /// 缩放实体 -- Gitee From fcda3bdf131a7cc18934372ff5ca082feb77de29 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sat, 13 May 2023 09:29:27 +0800 Subject: [PATCH 091/453] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs index 789c03a..c6ff6dc 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs @@ -686,10 +686,12 @@ public static Vector2d Convert2d(this Vector3d vector3d) { return new Vector2d(vector3d.X, vector3d.Y); } + /// /// 转换为3d向量 /// - /// 2d向量 + /// 2d向量 + /// z值 /// 3d向量 public static Vector3d Convert3d(this Vector2d vector2d, double z = 0) { -- Gitee From 3241817f87833d6c4313c729d51290d5213d2f11 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sat, 13 May 2023 09:31:05 +0800 Subject: [PATCH 092/453] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/PointEx.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/PointEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/PointEx.cs index e059633..21635a2 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/PointEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/PointEx.cs @@ -79,6 +79,7 @@ internal static Point3d Z20(this Point3d point) /// 圆弧起点 /// 圆弧腰点 /// 圆弧尾点 + /// 容差 /// 逆时针为正,顺时针为负 public static double GetArcBulge(this Point2d arc1, Point2d arc2, Point2d arc3, double tol = 1e-10) { -- Gitee From f0720e6c57a3bd44f4dcde5e87dfd757e6b65efa Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sat, 13 May 2023 09:31:33 +0800 Subject: [PATCH 093/453] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=AF=AD=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/PointEx.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/PointEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/PointEx.cs index 21635a2..1f25075 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/PointEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/PointEx.cs @@ -92,9 +92,9 @@ public static double GetArcBulge(this Point2d arc1, Point2d arc2, Point2d arc3, double bulge = Math.Sin(talAngle) / Math.Cos(talAngle); // 处理精度 - if (bulge > 0.9999 && bulge < 1.0001) + if (bulge is > 0.9999 and < 1.0001) bulge = 1; - else if (bulge < -0.9999 && bulge > -1.0001) + else if (bulge is < -0.9999 and > -1.0001) bulge = -1; else if (Math.Abs(bulge) < tol) bulge = 0; -- Gitee From 29f7905bfa9ac131c4c6d2f618f0ddcd1d8501fc Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sat, 13 May 2023 09:36:14 +0800 Subject: [PATCH 094/453] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/PolylineEx.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/PolylineEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/PolylineEx.cs index 6552bb3..da2d650 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/PolylineEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/PolylineEx.cs @@ -31,7 +31,6 @@ public static IEnumerable GetPoints(this Polyline2d pl2d) /// 获取三维多段线的端点坐标 /// /// 三维多段线 - /// 事务 /// 端点坐标集合 public static IEnumerable GetPoints(this Polyline3d pl3d) { -- Gitee From 73ff7d37f5bcdfd93a88963dfd56676c90c17d16 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sat, 13 May 2023 09:42:12 +0800 Subject: [PATCH 095/453] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=89=B9=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/Enums.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Enums.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Enums.cs index d100ded..5043cad 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Enums.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Enums.cs @@ -38,6 +38,7 @@ public enum XrefModes : byte Bind, } +[Flags] public enum SymModes : ushort { /// -- Gitee From 9e9982b5f90dc02672ccf6b66db46ae3439e5990 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sat, 13 May 2023 09:45:03 +0800 Subject: [PATCH 096/453] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E8=AF=AD=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs index dbeceab..ffd5f3e 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs @@ -105,12 +105,9 @@ public static PromptSelectionResult SSGet(this Editor editor, } try { - if (filter is not null) - ss = editor.GetSelection(pso, filter); - else - ss = editor.GetSelection(pso); + ss = filter is not null ? editor.GetSelection(pso, filter) : editor.GetSelection(pso); } - catch (Exception) + catch { //editor.WriteMessage($"\nKey is {e.Message}"); throw; -- Gitee From 8284a3e371e001ce8c8afb33715555f4018d1108 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sat, 13 May 2023 09:58:49 +0800 Subject: [PATCH 097/453] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=AF=AD=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/IdleAction.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/IdleAction.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/IdleAction.cs index 6431391..0d1c78e 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/IdleAction.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/IdleAction.cs @@ -14,18 +14,19 @@ public static class IdleAction /// /// 委托列表 /// - private static readonly List actions = new(); + private static readonly List _actions = new(); /// /// 未处理的委托数量 /// - public static int Count { get { return actions.Count; } } + public static int Count => _actions.Count; + /// /// 添加空闲执行委托 /// /// 委托 public static void Add(Action action) { - actions.Add(action); + _actions.Add(action); if (!alreadyLoad) { Acap.Idle -= Acap_Idle; @@ -48,11 +49,11 @@ private static void Acap_Idle(object sender, EventArgs e) } try { - actions[0]?.Invoke(); + _actions[0]?.Invoke(); } finally { - actions.RemoveAt(0); + _actions.RemoveAt(0); } } } -- Gitee From b1c0dbd683945dcb8a2e94fc834af27a518b6bf2 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sat, 13 May 2023 09:58:56 +0800 Subject: [PATCH 098/453] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=B9=B3=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs index c6ff6dc..95009df 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs @@ -726,4 +726,13 @@ public static Vector3d Z20(this Vector3d vector3d) { return new Vector3d(vector3d.X, vector3d.Y, 0); } +} +/// +/// 平面 +/// +public static class PlaneEx +{ + public static readonly Plane X = new Plane(Point3d.Origin, Vector3d.XAxis); + public static readonly Plane Y = new Plane(Point3d.Origin, Vector3d.YAxis); + public static readonly Plane Z = new Plane(Point3d.Origin, Vector3d.ZAxis); } \ No newline at end of file -- Gitee From 2544eb2d117ff056f195e3468f57ddba54a95d46 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sat, 13 May 2023 10:04:48 +0800 Subject: [PATCH 099/453] =?UTF-8?q?=E5=90=91=E9=87=8F=E5=9C=A8=E5=B9=B3?= =?UTF-8?q?=E9=9D=A2=E4=B8=8A=E7=9A=84=E5=BC=A7=E5=BA=A6=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E9=BB=98=E8=AE=A4=E5=8F=82=E6=95=B0=E9=87=8D=E8=BD=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/GeometryEx.cs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs index 95009df..46abb53 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs @@ -726,13 +726,23 @@ public static Vector3d Z20(this Vector3d vector3d) { return new Vector3d(vector3d.X, vector3d.Y, 0); } + /// + /// 向量在平面上的弧度 + /// + /// 向量 + /// 平面 + /// 弧度 + public static double AngleOnPlane(this Vector3d vector, Plane? plane = null) + { + return vector.AngleOnPlane(plane ?? PlaneEx.Z); + } } /// /// 平面 /// public static class PlaneEx { - public static readonly Plane X = new Plane(Point3d.Origin, Vector3d.XAxis); - public static readonly Plane Y = new Plane(Point3d.Origin, Vector3d.YAxis); - public static readonly Plane Z = new Plane(Point3d.Origin, Vector3d.ZAxis); + public static readonly Plane X = new (Point3d.Origin, Vector3d.XAxis); + public static readonly Plane Y = new (Point3d.Origin, Vector3d.YAxis); + public static readonly Plane Z = new (Point3d.Origin, Vector3d.ZAxis); } \ No newline at end of file -- Gitee From 62dc0d11ee2080ad7efca0a43884a80f7b44f16a Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sat, 13 May 2023 14:43:37 +0800 Subject: [PATCH 100/453] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=A0=B9=E6=8D=AE?= =?UTF-8?q?=E5=AF=B9=E8=B1=A1=E5=8F=A5=E6=9F=84=E8=8E=B7=E5=8F=96=E5=AF=B9?= =?UTF-8?q?=E8=B1=A1Id=E7=9A=84=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/ObjectIdEx.cs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs index 9c2a359..2a9b761 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs @@ -39,7 +39,7 @@ public static IEnumerable GetObject(this IEnumerable ids, bool openErased = false, bool openLockedLayer = false) where T : DBObject { - return ids.Select(id => + return ids.Select(id => id.GetObject(openMode, openErased, openLockedLayer)) .OfType(); } @@ -51,9 +51,9 @@ public static IEnumerable GetObject(this IEnumerable ids, /// 对象id集合 /// 精确匹配 /// 对象id集合 - public static IEnumerable OfType(this IEnumerable ids,bool exactMatch =false) where T : DBObject + public static IEnumerable OfType(this IEnumerable ids, bool exactMatch = false) where T : DBObject { - var rxc = RXClass.GetClass(typeof(T)); + var rxc = RXClass.GetClass(typeof(T)); if (exactMatch) { var dxfName = rxc.DxfName; @@ -84,7 +84,16 @@ public static ObjectId GetObjectId(this Database db, string handleString) } return ObjectId.Null; } - + /// + /// 根据对象句柄获取对象Id + /// + /// 数据库 + /// 句柄 + /// 对象的ObjectId + public static ObjectId GetObjectId(this Database db, Handle handle) + { + return db.TryGetObjectId(handle, out ObjectId id) ? id : ObjectId.Null; + } /// /// id是否有效,未被删除 /// -- Gitee From d158196eb1e67ede3aa64be1ea073a4aa99e4404 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sat, 13 May 2023 14:51:05 +0800 Subject: [PATCH 101/453] =?UTF-8?q?=E5=8F=A5=E6=9F=84=E8=BD=ACobjecid?= =?UTF-8?q?=E5=87=BD=E6=95=B0=E6=8B=86=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/ObjectIdEx.cs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs index 2a9b761..9eb4beb 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs @@ -74,15 +74,7 @@ public static IEnumerable OfType(this IEnumerable ids, bo /// 对象的ObjectId public static ObjectId GetObjectId(this Database db, string handleString) { - if (long.TryParse(handleString, System.Globalization.NumberStyles.HexNumber, null, out long l)) - { - var handle = new Handle(l); - if (db.TryGetObjectId(handle, out ObjectId id)) - { - return id; - } - } - return ObjectId.Null; + return handleString.ToHandle() is { } handle ? db.GetObjectId(handle) : ObjectId.Null; } /// /// 根据对象句柄获取对象Id @@ -95,6 +87,15 @@ public static ObjectId GetObjectId(this Database db, Handle handle) return db.TryGetObjectId(handle, out ObjectId id) ? id : ObjectId.Null; } /// + /// 字符串转句柄 + /// + /// + /// + public static Handle? ToHandle(this string handleString) + { + return long.TryParse(handleString, System.Globalization.NumberStyles.HexNumber, null, out long l) ? new Handle(l) : null; + } + /// /// id是否有效,未被删除 /// /// 对象id -- Gitee From a24616b18048cc561f4ee04b8dfc2662ce2eb162 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sat, 13 May 2023 14:53:12 +0800 Subject: [PATCH 102/453] =?UTF-8?q?=E8=A1=A5=E5=85=85=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs index 9eb4beb..e41fe21 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs @@ -74,10 +74,10 @@ public static IEnumerable OfType(this IEnumerable ids, bo /// 对象的ObjectId public static ObjectId GetObjectId(this Database db, string handleString) { - return handleString.ToHandle() is { } handle ? db.GetObjectId(handle) : ObjectId.Null; + return handleString.ConvertToHandle() is { } handle ? db.GetObjectId(handle) : ObjectId.Null; } /// - /// 根据对象句柄获取对象Id + /// 根据对象句柄获取对象ObjectId /// /// 数据库 /// 句柄 @@ -87,11 +87,11 @@ public static ObjectId GetObjectId(this Database db, Handle handle) return db.TryGetObjectId(handle, out ObjectId id) ? id : ObjectId.Null; } /// - /// 字符串转句柄 + /// 句柄字符串转句柄 /// - /// - /// - public static Handle? ToHandle(this string handleString) + /// 句柄字符串 + /// 句柄 + public static Handle? ConvertToHandle(this string handleString) { return long.TryParse(handleString, System.Globalization.NumberStyles.HexNumber, null, out long l) ? new Handle(l) : null; } -- Gitee From 11139b79d311d62b776fcae6e9d0870c807e1395 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sat, 13 May 2023 15:33:08 +0800 Subject: [PATCH 103/453] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=AF=AD=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs index e41fe21..8980443 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs @@ -74,7 +74,7 @@ public static IEnumerable OfType(this IEnumerable ids, bo /// 对象的ObjectId public static ObjectId GetObjectId(this Database db, string handleString) { - return handleString.ConvertToHandle() is { } handle ? db.GetObjectId(handle) : ObjectId.Null; + return db.GetObjectId(handleString.ConvertToHandle()); } /// /// 根据对象句柄获取对象ObjectId @@ -82,9 +82,9 @@ public static ObjectId GetObjectId(this Database db, string handleString) /// 数据库 /// 句柄 /// 对象的ObjectId - public static ObjectId GetObjectId(this Database db, Handle handle) + public static ObjectId GetObjectId(this Database db, Handle? handle) { - return db.TryGetObjectId(handle, out ObjectId id) ? id : ObjectId.Null; + return handle is not null && db.TryGetObjectId(handle.Value, out ObjectId id) ? id : ObjectId.Null; } /// /// 句柄字符串转句柄 -- Gitee From 051e692b7d1193b85108bc611bfa494f744fa270 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sat, 13 May 2023 16:10:53 +0800 Subject: [PATCH 104/453] =?UTF-8?q?=E4=BD=BF=E7=94=A8rxclass=E6=8F=90?= =?UTF-8?q?=E9=80=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs index 8980443..2b9f915 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs @@ -39,8 +39,9 @@ public static IEnumerable GetObject(this IEnumerable ids, bool openErased = false, bool openLockedLayer = false) where T : DBObject { - return ids.Select(id => - id.GetObject(openMode, openErased, openLockedLayer)) + var rxc = RXObject.GetClass(typeof(T)); + return ids.Where(id => id.ObjectClass.IsDerivedFrom(rxc)) + .Select(id => id.GetObject(openMode, openErased, openLockedLayer)) .OfType(); } -- Gitee From 679b6517fe1a573f5bb1dc9da6dd005302ab8d12 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sun, 14 May 2023 22:24:00 +0800 Subject: [PATCH 105/453] =?UTF-8?q?=E4=BF=AE=E5=A4=8DJigEx=E5=85=B3?= =?UTF-8?q?=E9=94=AE=E5=AD=97=E8=BE=93=E5=85=A5=E4=B9=8B=E5=90=8E=E9=9C=80?= =?UTF-8?q?=E8=A6=81=E7=A7=BB=E5=8A=A8=E9=BC=A0=E6=A0=87=E6=89=8D=E8=83=BD?= =?UTF-8?q?=E9=87=8D=E7=BB=98=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/Jig/JigEx.cs | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigEx.cs index c6f1296..d88a073 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigEx.cs @@ -77,7 +77,10 @@ public JigEx(Action>? action = null, double tolerance = 1 _tolerance = new(tolerance, tolerance); } #endregion - + /// + /// 因为是worldDraw触发sampler不是Sample触发worldDraw,所以要记一次上次的状态 + /// + static bool lastIsKw = false; #region 重写 /// /// 鼠标采样器 @@ -88,15 +91,14 @@ protected override SamplerStatus Sampler(JigPrompts prompts) { if (_worldDrawFlag) return SamplerStatus.NoChange;// OK的时候拖动鼠标与否都不出现图元 - if (_options is null) throw new NullReferenceException(nameof(_options)); - var pro = prompts.AcquirePoint(_options); - if (pro.Status == PromptStatus.Keyword) - return SamplerStatus.OK; - else if (pro.Status != PromptStatus.OK) + if (pro.Status != PromptStatus.OK && pro.Status != PromptStatus.Keyword) return SamplerStatus.Cancel; + // 记上次的状态,因为马上要还原 + bool isOk = !lastIsKw; + lastIsKw = pro.Status == PromptStatus.Keyword; // 上次鼠标点不同(一定要这句,不然图元刷新太快会看到奇怪的边线) var mousePointWcs = pro.Value; @@ -105,9 +107,10 @@ protected override SamplerStatus Sampler(JigPrompts prompts) // IsEqualTo 是方形判断(仅加法),但是cad是距离. // Distance 是圆形判断(会求平方根,使用了牛顿迭代), // 大量数据(十万以上/频繁刷新)面前会显得非常慢. - if (mousePointWcs.IsEqualTo(MousePointWcsLast, _tolerance)) + if (isOk && mousePointWcs.IsEqualTo(MousePointWcsLast, _tolerance)) + { return SamplerStatus.NoChange; - + } // 上次循环的缓冲区图元清理,否则将会在vs输出遗忘 Dispose while (_drawEntitys.Count > 0) _drawEntitys.Dequeue().Dispose(); @@ -169,7 +172,7 @@ protected override bool WorldDraw(WorldDraw draw) _worldDrawFlag = true; WorldDrawEvent?.Invoke(draw); _drawEntitys.ForEach(ent => { - draw.RawGeometry.Draw(ent); + draw.Geometry.Draw(ent); }); _worldDrawFlag = false; return true; @@ -216,16 +219,16 @@ public JigPromptPointOptions SetOptions(string msg, _options = JigPointOptions(); _options.Message = Environment.NewLine + msg; - + if (keywords != null) foreach (var item in keywords) - _options.Keywords.Add(item.Key, item.Key, item.Value); + _options.Keywords.Add(item.Key, item.Key, item.Value); // 因为默认配置函数导致此处空格触发是无效的, // 但是用户如果想触发,就需要在外部减去默认UserInputControls配置 // 要放最后,才能优先触发其他关键字 - + // 外部设置减去配置 // _options.UserInputControls = -- Gitee From 9d88db5f9f728574c07258a73764375f76a94a39 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sun, 14 May 2023 22:47:06 +0800 Subject: [PATCH 106/453] =?UTF-8?q?SingleKeyWordHook=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=8F=AF=E9=80=89=E5=8F=91=E5=9B=9E=E8=BD=A6=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/Runtime/SingleKeyWordHook.cs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/Runtime/SingleKeyWordHook.cs b/src/CAD/IFox.CAD.Shared/Runtime/SingleKeyWordHook.cs index 8c7a230..c08be4c 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/SingleKeyWordHook.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/SingleKeyWordHook.cs @@ -14,6 +14,7 @@ public class SingleKeyWordHook : IDisposable private bool _isResponsed; private bool _working; private Keys _key; + private bool _escapeMode; #endregion #region 公共属性 @@ -35,13 +36,15 @@ public class SingleKeyWordHook : IDisposable /// /// 单字母关键字免输回车钩子 /// - public SingleKeyWordHook() + /// 使用esc(填false则使用回车) + public SingleKeyWordHook(bool escapeMode = true) { _isDisposed = false; _isResponsed = false; _keyWords = new HashSet(); _key = Keys.None; _working = true; + _escapeMode = escapeMode; Acap.PreTranslateMessage += Acap_PreTranslateMessage; } #endregion @@ -108,7 +111,10 @@ private void Acap_PreTranslateMessage(object sender, PreTranslateMessageEventArg if (contains || tempKey == Keys.ProcessKey) { // 标记为true,表示此按键已经被处理,Windows不会再进行处理 - e.Handled = true; + if (_escapeMode) + { + e.Handled = true; + } if (contains) _key = tempKey; if (!_isResponsed) @@ -116,7 +122,7 @@ private void Acap_PreTranslateMessage(object sender, PreTranslateMessageEventArg // 此bool是防止按键被长按时出错 _isResponsed = true; // 这里选择发送回车或者ESC//ESC稳妥一些,但是要promptResult的判断顺序 - SingleKeyWordHook.KeyBoardSendKey(Keys.Escape); + SingleKeyWordHook.KeyBoardSendKey(_escapeMode? Keys.Escape:Keys.Enter); } } } -- Gitee From 48f41cf3cd06777e7e3d164058ab88aba0bfd536 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sun, 14 May 2023 22:51:27 +0800 Subject: [PATCH 107/453] =?UTF-8?q?=E6=B7=BB=E5=8A=A0readonly=E4=BF=AE?= =?UTF-8?q?=E9=A5=B0=E7=AC=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/Runtime/SingleKeyWordHook.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CAD/IFox.CAD.Shared/Runtime/SingleKeyWordHook.cs b/src/CAD/IFox.CAD.Shared/Runtime/SingleKeyWordHook.cs index c08be4c..05b079d 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/SingleKeyWordHook.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/SingleKeyWordHook.cs @@ -14,7 +14,7 @@ public class SingleKeyWordHook : IDisposable private bool _isResponsed; private bool _working; private Keys _key; - private bool _escapeMode; + private readonly bool _escapeMode; #endregion #region 公共属性 -- Gitee From 32f8deb946af79a050755849ba436aec7acd9a2f Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Mon, 15 May 2023 10:17:38 +0800 Subject: [PATCH 108/453] =?UTF-8?q?SymbolUtilityServices.RepairSymbolName?= =?UTF-8?q?=E6=96=B9=E6=B3=95=E5=9C=A8=E4=B8=AD=E6=9C=9B=E4=BC=9A=E6=8A=A5?= =?UTF-8?q?=E9=94=99=EF=BC=8C=E6=9A=82=E6=97=B6=E6=9D=A1=E4=BB=B6=E7=BC=96?= =?UTF-8?q?=E8=AF=91=E8=A7=84=E9=81=BF=E4=B8=80=E4=B8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../IFox.CAD.Shared/ExtensionMethod/SymbolTableEx.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableEx.cs index fc811de..5bef6ab 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableEx.cs @@ -184,10 +184,11 @@ public static void AddAttsToBlocks(this SymbolTable块定义Id public static ObjectId GetBlockFrom(this SymbolTable table, string fileName, bool over) { - - string blkdefname = SymbolUtilityServices.RepairSymbolName( - SymbolUtilityServices.GetSymbolNameFromPathName(fileName, "dwg"), false); + string blkdefname = SymbolUtilityServices.GetSymbolNameFromPathName(fileName, "dwg"); +#if !zcad + blkdefname = SymbolUtilityServices.RepairSymbolName(blkdefname, false); +#endif ObjectId id = table[blkdefname]; bool has = id != ObjectId.Null; if ((has && over) || !has) @@ -284,8 +285,8 @@ public static ObjectId Add(this SymbolTable宽度比例 /// 文字样式Id public static ObjectId Add(this SymbolTable table, - string textStyleName, - FontTTF fontTTF, + string textStyleName, + FontTTF fontTTF, double xscale = 1.0) { return table.Add(textStyleName, fontTTF.GetDesc(), xscale); -- Gitee From 303d4a6c5061bab9321c292438f59fc95c5de716 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Mon, 15 May 2023 20:23:30 +0800 Subject: [PATCH 109/453] =?UTF-8?q?=E9=80=92=E5=BD=92=E5=9D=97=E4=B8=AD?= =?UTF-8?q?=E5=9D=97=E5=9B=BE=E5=85=83=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Entity/BlockReferenceEx.cs | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs index f3dac76..6c33404 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs @@ -203,4 +203,34 @@ public static void ForEach(this BlockReference brf, Action + /// 递归块中块图元 + /// + /// 块参照 + /// 委托 + /// 事务 + public static void Recursion(this BlockReference blockReference, Action action, DBTrans? tr = null) + { + tr ??= DBTrans.GetTop(blockReference.IsNewObject ? Env.Database : blockReference.Database); + var queue = new Queue<(Entity, Matrix3d)>(); + queue.Enqueue((blockReference, Matrix3d.Identity)); + while (queue.Any()) + { + var (ent, mt) = queue.Dequeue(); + action?.Invoke(ent, mt); + if (ent is BlockReference brfTemp) + { + var mtNext = mt * brfTemp.BlockTransform; + tr.BlockTable.Change(brfTemp.BlockTableRecord, btr => { + foreach (var id in btr) + { + if (tr.GetObject(id) is Entity entNext) + { + queue.Enqueue((entNext, mtNext)); + } + } + }); + } + } + } } \ No newline at end of file -- Gitee From d9cd922a585eaa73a1176dbd630c549a6e22aeb2 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Tue, 16 May 2023 11:20:48 +0800 Subject: [PATCH 110/453] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=80=92=E5=BD=92?= =?UTF-8?q?=E5=9D=97=E5=87=BD=E6=95=B0=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/Entity/BlockReferenceEx.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs index 6c33404..23efd3f 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs @@ -204,12 +204,12 @@ public static void ForEach(this BlockReference brf, Action - /// 递归块中块图元 + /// 遍历嵌套块中块图元 /// /// 块参照 /// 委托 /// 事务 - public static void Recursion(this BlockReference blockReference, Action action, DBTrans? tr = null) + public static void NestedForEach(this BlockReference blockReference, Action action, DBTrans? tr = null) { tr ??= DBTrans.GetTop(blockReference.IsNewObject ? Env.Database : blockReference.Database); var queue = new Queue<(Entity, Matrix3d)>(); -- Gitee From 2b3406a1e48a4b81060da2f50336019384251835 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Tue, 16 May 2023 14:18:59 +0800 Subject: [PATCH 111/453] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=A3=80=E6=9F=A5Com?= =?UTF-8?q?mand=E5=91=BD=E4=BB=A4=E9=87=8D=E5=A4=8D=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../IFox.CAD.Shared/IFox.CAD.Shared.projitems | 1 + .../IFox.CAD.Shared/Runtime/CheckFactory.cs | 38 +++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 src/CAD/IFox.CAD.Shared/Runtime/CheckFactory.cs diff --git a/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems b/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems index fefa9b7..74a3fbf 100644 --- a/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems +++ b/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems @@ -74,6 +74,7 @@ + diff --git a/src/CAD/IFox.CAD.Shared/Runtime/CheckFactory.cs b/src/CAD/IFox.CAD.Shared/Runtime/CheckFactory.cs new file mode 100644 index 0000000..3a476de --- /dev/null +++ b/src/CAD/IFox.CAD.Shared/Runtime/CheckFactory.cs @@ -0,0 +1,38 @@ +#if Debug +namespace IFoxCAD.Cad; +public static class CheckFactory +{ + /// + /// 检查Command命令重复 + /// 将此函数添加在IExtensionApplication.Initialize()开头 + /// 2023-05-16 by DYH + /// + public static void CheckDuplicateCommand(Assembly? assembly = null) + { + var dic = new Dictionary>(); + assembly ??= Assembly.GetCallingAssembly(); + var typeArray = assembly.GetTypes(); + foreach (var type in typeArray) + { + foreach (var method in type.GetMethods()) + { + foreach (Attribute add in method.GetCustomAttributes(typeof(CommandMethodAttribute), false)) + { + if (add is CommandMethodAttribute cma) + { + if (!dic.ContainsKey(cma.GlobalName)) + { + dic.Add(cma.GlobalName, new()); + } + dic[cma.GlobalName].Add(type.Name + "." + method.Name); + } + } + } + } + var strings = dic.Where(o => o.Value.Count() > 1).Select(o => o.Key + "命令重复,在类" + string.Join("和", o.Value) + "中"); + string str = string.Join(Environment.NewLine, strings); + if (!string.IsNullOrEmpty(str)) + MessageBox.Show(str, "错误:重复命令!"); + } +} +#endif \ No newline at end of file -- Gitee From b67c1cc4afd5f4b29270b1c07b2f5a7d90a976f6 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Wed, 17 May 2023 19:59:09 +0800 Subject: [PATCH 112/453] =?UTF-8?q?=E5=B0=86CheckFactory=E7=B1=BB=E5=92=8C?= =?UTF-8?q?SingleKeyWordHook=E7=B1=BB=E7=A7=BB=E5=8A=A8=E5=88=B0ExtensionM?= =?UTF-8?q?ethod=E6=96=87=E4=BB=B6=E5=A4=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{Runtime => ExtensionMethod}/CheckFactory.cs | 11 +++++++++-- .../{Runtime => ExtensionMethod}/SingleKeyWordHook.cs | 0 src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems | 4 ++-- 3 files changed, 11 insertions(+), 4 deletions(-) rename src/CAD/IFox.CAD.Shared/{Runtime => ExtensionMethod}/CheckFactory.cs (77%) rename src/CAD/IFox.CAD.Shared/{Runtime => ExtensionMethod}/SingleKeyWordHook.cs (100%) diff --git a/src/CAD/IFox.CAD.Shared/Runtime/CheckFactory.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/CheckFactory.cs similarity index 77% rename from src/CAD/IFox.CAD.Shared/Runtime/CheckFactory.cs rename to src/CAD/IFox.CAD.Shared/ExtensionMethod/CheckFactory.cs index 3a476de..3e5bb4e 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/CheckFactory.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/CheckFactory.cs @@ -2,10 +2,17 @@ namespace IFoxCAD.Cad; public static class CheckFactory { + /* + * 平时command命令的globalName如果重复,加载时会报错 + * 但是并不会告诉你是哪里错了,通常需要花大量时间来查找 + * 将此函数添加在IExtensionApplication.Initialize()函数开头 + * 虽然还会报错,但是至少能知道哪个类下哪个方法导致的报错 + * 聊胜于无吧 + * 2023-05-16 by DYH + */ + /// /// 检查Command命令重复 - /// 将此函数添加在IExtensionApplication.Initialize()开头 - /// 2023-05-16 by DYH /// public static void CheckDuplicateCommand(Assembly? assembly = null) { diff --git a/src/CAD/IFox.CAD.Shared/Runtime/SingleKeyWordHook.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SingleKeyWordHook.cs similarity index 100% rename from src/CAD/IFox.CAD.Shared/Runtime/SingleKeyWordHook.cs rename to src/CAD/IFox.CAD.Shared/ExtensionMethod/SingleKeyWordHook.cs diff --git a/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems b/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems index 74a3fbf..d87bdaf 100644 --- a/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems +++ b/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems @@ -74,11 +74,11 @@ - + - + -- Gitee From 33b1852754fcd584e01ff6e8177362a7d877f04c Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Wed, 17 May 2023 20:03:49 +0800 Subject: [PATCH 113/453] =?UTF-8?q?BlockTableRecord.GetEntities=E5=87=BD?= =?UTF-8?q?=E6=95=B0=E4=BD=BF=E7=94=A8RXClass=E6=8F=90=E9=80=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs index 4cf0436..b93b88a 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs @@ -119,9 +119,11 @@ public static IEnumerable GetEntities(this BlockTableRecord btr, bool openErased = false, bool openLockedLayer = false) where T : Entity { + var rxc = RXObject.GetClass(typeof(T)); return btr .Cast() + .Where(id=>id.ObjectClass.IsDerivedFrom(rxc)) .Select(id => id.GetObject(openMode, openErased, openLockedLayer)) .OfType(); } -- Gitee From 634633ab9f40bd5c37362fae61ab10d5ba264344 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sun, 28 May 2023 13:25:04 +0800 Subject: [PATCH 114/453] =?UTF-8?q?=E8=BF=81=E7=A7=BBEvent=E5=BA=93?= =?UTF-8?q?=EF=BC=8C=E4=BF=AE=E6=94=B9=E5=91=BD=E5=90=8D=E7=A9=BA=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../EventEx/BeginDoubleClickEvent.cs | 108 +++++++++++++++ .../EventEx/DocumentLockModeChangedEvent.cs | 123 ++++++++++++++++++ .../EventEx/SystemVariableChangedEvent.cs | 123 ++++++++++++++++++ .../EventFactory/CadEvent.cs | 26 ++++ .../EventFactory/EventFactory.cs | 88 +++++++++++++ .../EventFactory/EventMethodInfo.cs | 22 ++++ .../EventTemporaryShutdownManager.cs | 40 ++++++ .../IFox.Event.Shared.projitems | 20 +++ .../IFox.Event.Shared.shproj | 13 ++ 9 files changed, 563 insertions(+) create mode 100644 src/Event/IFox.Event.Shared/EventEx/BeginDoubleClickEvent.cs create mode 100644 src/Event/IFox.Event.Shared/EventEx/DocumentLockModeChangedEvent.cs create mode 100644 src/Event/IFox.Event.Shared/EventEx/SystemVariableChangedEvent.cs create mode 100644 src/Event/IFox.Event.Shared/EventFactory/CadEvent.cs create mode 100644 src/Event/IFox.Event.Shared/EventFactory/EventFactory.cs create mode 100644 src/Event/IFox.Event.Shared/EventFactory/EventMethodInfo.cs create mode 100644 src/Event/IFox.Event.Shared/EventFactory/EventTemporaryShutdownManager.cs create mode 100644 src/Event/IFox.Event.Shared/IFox.Event.Shared.projitems create mode 100644 src/Event/IFox.Event.Shared/IFox.Event.Shared.shproj diff --git a/src/Event/IFox.Event.Shared/EventEx/BeginDoubleClickEvent.cs b/src/Event/IFox.Event.Shared/EventEx/BeginDoubleClickEvent.cs new file mode 100644 index 0000000..d800baf --- /dev/null +++ b/src/Event/IFox.Event.Shared/EventEx/BeginDoubleClickEvent.cs @@ -0,0 +1,108 @@ +namespace IFoxCAD.Event; +internal static class BeginDoubleClickEvent +{ + private static readonly Type returnType = typeof(void); + private static readonly Type firstType = typeof(object); + private static readonly Type secondType = typeof(BeginDoubleClickEventArgs); + private static readonly HashSet dic = new(); + internal static void Initlize(Assembly assembly) + { + var types = assembly.GetTypes(); + foreach (var type in types) + { + if (!type.IsClass) + continue; + foreach (var methodInfo in type.GetMethods()) + { + foreach (Attribute att in methodInfo.GetCustomAttributes(typeof(BeginDoubleClickAttribute), false)) + { + if (att is not BeginDoubleClickAttribute targetAtt) + continue; + if (!methodInfo.IsStatic) + throw new ArgumentException($"标记{nameof(BeginDoubleClickAttribute)}特性的方法{type.Name}.{methodInfo.Name},应为静态方法"); + if (methodInfo.ReturnType != returnType) + throw new ArgumentException($"标记{nameof(BeginDoubleClickAttribute)}特性的方法{type.Name}.{methodInfo.Name},返回值应为void"); + var args = methodInfo.GetParameters(); + if (args.Length > 2) + throw new ArgumentException($"标记{nameof(BeginDoubleClickAttribute)}特性的方法{type.Name}.{methodInfo.Name},参数类型错误"); + + + EventParameterType? ept = null; + if (args.Length == 0) + ept = EventParameterType.None; + else if (args.Length == 1) + { + if (args[0].ParameterType == firstType) + ept = EventParameterType.Object; + else if (args[0].ParameterType == secondType) + ept = EventParameterType.EventArgs; + } + else if (args.Length == 2 && args[0].ParameterType == firstType && args[1].ParameterType == secondType) + { + ept = EventParameterType.Complete; + } + if (ept is null) + throw new ArgumentException($"标记{nameof(BeginDoubleClickAttribute)}特性的方法{type.Name}.{methodInfo.Name},参数类型错误"); + dic.Add(new(methodInfo, ept.Value, targetAtt.Level)); + break; + } + } + } + AddEvent(); + } + + internal static void AddEvent() + { + Acap.BeginDoubleClick -= Acap_BeginDoubleClick; + Acap.BeginDoubleClick += Acap_BeginDoubleClick; + } + + internal static void RemoveEvent() + { + Acap.BeginDoubleClick -= Acap_BeginDoubleClick; + } + private static void Acap_BeginDoubleClick(object sender, BeginDoubleClickEventArgs e) + { +#if Debug + if (!EventFactory.closeCheck.Invoke()) + { + EventFactory.RemoveEvent(CadEvent.All); + return; + } +#endif + foreach (var eventMethodInfo in dic.OrderByDescending(a => a.Level)) + { + switch (eventMethodInfo.ParameterType) + { + case EventParameterType.None: + eventMethodInfo.Method.Invoke(null, new object[0]); + break; + case EventParameterType.Object: + eventMethodInfo.Method.Invoke(null, new[] { sender }); + break; + case EventParameterType.EventArgs: + eventMethodInfo.Method.Invoke(null, new[] { e }); + break; + case EventParameterType.Complete: + eventMethodInfo.Method.Invoke(null, new[] { sender, e }); + break; + } + } + } + +} +[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)] +public class BeginDoubleClickAttribute : Attribute +{ + /// s + /// 系统变量修改时触发被标记的函数 + /// 返回值应为void + /// 参数不大于2个且只能为object和BeginDoubleClickEventArgs + /// + /// 级别(越高越先触发) + public BeginDoubleClickAttribute( int level = -1) + { + Level = level; + } + public int Level { get; } +} \ No newline at end of file diff --git a/src/Event/IFox.Event.Shared/EventEx/DocumentLockModeChangedEvent.cs b/src/Event/IFox.Event.Shared/EventEx/DocumentLockModeChangedEvent.cs new file mode 100644 index 0000000..3ec726c --- /dev/null +++ b/src/Event/IFox.Event.Shared/EventEx/DocumentLockModeChangedEvent.cs @@ -0,0 +1,123 @@ +namespace IFoxCAD.Event; +internal static class DocumentLockModeChangedEvent +{ + private static readonly Type returnType = typeof(void); + private static readonly Type firstType = typeof(object); + private static readonly Type secondType = typeof(DocumentLockModeChangedEventArgs); + private static readonly Dictionary> dic = new(); + internal static void Initlize(Assembly assembly) + { + var types = assembly.GetTypes(); + foreach (var type in types) + { + if (!type.IsClass) + continue; + foreach (var methodInfo in type.GetMethods()) + { + foreach (Attribute att in methodInfo.GetCustomAttributes(typeof(DocumentLockModeChangedAttribute), false)) + { + if (att is not DocumentLockModeChangedAttribute targetAtt) + continue; + if (!methodInfo.IsStatic) + throw new ArgumentException($"{nameof(DocumentLockModeChangedAttribute)}Եķ{type.Name}.{methodInfo.Name},ӦΪ̬"); + if (methodInfo.ReturnType != returnType) + throw new ArgumentException($"{nameof(DocumentLockModeChangedAttribute)}Եķ{type.Name}.{methodInfo.Name}ֵӦΪvoid"); + var args = methodInfo.GetParameters(); + var key = targetAtt.CommandName.ToUpper(); + if (!dic.ContainsKey(key)) + { + dic.Add(key, new()); + } + if (args.Length > 2) + throw new ArgumentException($"{nameof(DocumentLockModeChangedAttribute)}Եķ{type.Name}.{methodInfo.Name}ʹ"); + + + EventParameterType? ept = null; + if (args.Length == 0) + ept = EventParameterType.None; + else if (args.Length == 1) + { + if (args[0].ParameterType == firstType) + ept = EventParameterType.Object; + else if (args[0].ParameterType == secondType) + ept = EventParameterType.EventArgs; + } + else if (args.Length == 2 && args[0].ParameterType == firstType && args[1].ParameterType == secondType) + { + ept = EventParameterType.Complete; + } + if (ept is null) + throw new ArgumentException($"{nameof(DocumentLockModeChangedAttribute)}Եķ{type.Name}.{methodInfo.Name}ʹ"); + dic[key].Add(new(methodInfo, ept.Value, targetAtt.Level)); + break; + } + } + } + AddEvent(); + } + internal static void AddEvent() + { + Acap.DocumentManager.DocumentLockModeChanged -= DocumentManager_DocumentLockModeChanged; + Acap.DocumentManager.DocumentLockModeChanged += DocumentManager_DocumentLockModeChanged; + } + + internal static void RemoveEvent() + { + Acap.DocumentManager.DocumentLockModeChanged -= DocumentManager_DocumentLockModeChanged; + } + private static void DocumentManager_DocumentLockModeChanged(object sender, DocumentLockModeChangedEventArgs e) + { + var key = e.GlobalCommandName.ToUpper(); + if (!dic.ContainsKey(key)) + return; + +#if Debug + if (!EventFactory.closeCheck.Invoke()) + { + EventFactory.RemoveEvent(CadEvent.All); + return; + } +#endif + foreach (var eventMethodInfo in dic[key].OrderByDescending(a => a.Level)) + { + switch (eventMethodInfo.ParameterType) + { + case EventParameterType.None: + eventMethodInfo.Method.Invoke(null, new object[0]); + break; + case EventParameterType.Object: + eventMethodInfo.Method.Invoke(null, new[] { sender }); + break; + case EventParameterType.EventArgs: + eventMethodInfo.Method.Invoke(null, new[] { e }); + break; + case EventParameterType.Complete: + eventMethodInfo.Method.Invoke(null, new[] { sender, e }); + break; + } + } + } + +} +[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)] +public class DocumentLockModeChangedAttribute : Attribute +{ + /// s + /// ϵͳ޸ʱǵĺ + /// ֵӦΪvoid + /// 2ֻΪobjectDocumentLockModeChangedEventArgs + /// + /// + /// (ԽԽȴ) + public DocumentLockModeChangedAttribute(string commandName, int level = -1) + { + CommandName = commandName; + Level = level; + } + + /// + /// ϵͳ + /// + public string CommandName { get; } + public int Level { get; } +} \ No newline at end of file diff --git a/src/Event/IFox.Event.Shared/EventEx/SystemVariableChangedEvent.cs b/src/Event/IFox.Event.Shared/EventEx/SystemVariableChangedEvent.cs new file mode 100644 index 0000000..bdca9df --- /dev/null +++ b/src/Event/IFox.Event.Shared/EventEx/SystemVariableChangedEvent.cs @@ -0,0 +1,123 @@ +namespace IFoxCAD.Event; +internal static class SystemVariableChangedEvent +{ + private static readonly Type returnType = typeof(void); + private static readonly Type firstType = typeof(object); + private static readonly Type secondType = typeof(SystemVariableChangedEventArgs); + private static readonly Dictionary> dic = new(); + internal static void Initlize(Assembly assembly) + { + var types = assembly.GetTypes(); + foreach (var type in types) + { + if (!type.IsClass) + continue; + foreach (var methodInfo in type.GetMethods()) + { + foreach (Attribute att in methodInfo.GetCustomAttributes(typeof(SystemVariableChangedAttribute), false)) + { + if (att is not SystemVariableChangedAttribute targetAtt) + continue; + if (!methodInfo.IsStatic) + throw new ArgumentException($"{nameof(SystemVariableChangedAttribute)}Եķ{type.Name}.{methodInfo.Name},ӦΪ̬"); + if (methodInfo.ReturnType != returnType) + throw new ArgumentException($"{nameof(SystemVariableChangedAttribute)}Եķ{type.Name}.{methodInfo.Name}ֵӦΪvoid"); + var args = methodInfo.GetParameters(); + var key = targetAtt.Name.ToUpper(); + if (!dic.ContainsKey(key)) + { + dic.Add(key, new()); + } + if (args.Length > 2) + throw new ArgumentException($"{nameof(SystemVariableChangedAttribute)}Եķ{type.Name}.{methodInfo.Name}ʹ"); + + + EventParameterType? ept = null; + if (args.Length == 0) + ept = EventParameterType.None; + else if (args.Length == 1) + { + if (args[0].ParameterType == firstType) + ept = EventParameterType.Object; + else if (args[0].ParameterType == secondType) + ept = EventParameterType.EventArgs; + } + else if (args.Length == 2 && args[0].ParameterType == firstType && args[1].ParameterType == secondType) + { + ept = EventParameterType.Complete; + } + if (ept is null) + throw new ArgumentException($"{nameof(SystemVariableChangedAttribute)}Եķ{type.Name}.{methodInfo.Name}ʹ"); + dic[key].Add(new(methodInfo, ept.Value, targetAtt.Level)); + break; + } + } + } + AddEvent(); + } + internal static void AddEvent() + { + Acap.SystemVariableChanged -= Acap_SystemVariableChanged; + Acap.SystemVariableChanged += Acap_SystemVariableChanged; + } + internal static void RemoveEvent() + { + Acap.SystemVariableChanged -= Acap_SystemVariableChanged; + } + private static void Acap_SystemVariableChanged(object sender, SystemVariableChangedEventArgs e) + { + var key = e.Name.ToUpper(); + if (!dic.ContainsKey(key)) + return; + +#if Debug + if (!EventFactory.closeCheck.Invoke()) + { + EventFactory.RemoveEvent(CadEvent.All); + return; + } +#endif + + foreach (var eventMethodInfo in dic[key].OrderByDescending(a => a.Level)) + { + switch (eventMethodInfo.ParameterType) + { + case EventParameterType.None: + eventMethodInfo.Method.Invoke(null, new object[0]); + break; + case EventParameterType.Object: + eventMethodInfo.Method.Invoke(null, new[] { sender }); + break; + case EventParameterType.EventArgs: + eventMethodInfo.Method.Invoke(null, new[] { e }); + break; + case EventParameterType.Complete: + eventMethodInfo.Method.Invoke(null, new[] { sender, e }); + break; + } + } + } + +} +[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)] +public class SystemVariableChangedAttribute : Attribute +{ + /// s + /// ϵͳ޸ʱǵĺ\n + /// \nֵӦΪvoid + /// 2ֻΪobjectSystemVariableChangedEventArgs + /// + /// ϵͳ + /// (ԽԽȴ) + public SystemVariableChangedAttribute(string name, int level = -1) + { + Name = name; + Level = level; + } + + /// + /// ϵͳ + /// + public string Name { get; } + public int Level { get; } +} \ No newline at end of file diff --git a/src/Event/IFox.Event.Shared/EventFactory/CadEvent.cs b/src/Event/IFox.Event.Shared/EventFactory/CadEvent.cs new file mode 100644 index 0000000..8e3b0bf --- /dev/null +++ b/src/Event/IFox.Event.Shared/EventFactory/CadEvent.cs @@ -0,0 +1,26 @@ +namespace IFoxCAD.Event; + +[Flags] +public enum CadEvent +{ + /// + /// 无 + /// + None = 0b0, + /// + /// 全选 + /// + All = 0b1111111111111111111111111111111, + /// + /// 系统变量修改 + /// + SystemVariableChanged = 0b1, + /// + /// 文档锁定事件 + /// + DocumentLockModeChanged = 0b10, + /// + /// 开始双击 + /// + BeginDoubleClick=0b100, +} \ No newline at end of file diff --git a/src/Event/IFox.Event.Shared/EventFactory/EventFactory.cs b/src/Event/IFox.Event.Shared/EventFactory/EventFactory.cs new file mode 100644 index 0000000..ea02a68 --- /dev/null +++ b/src/Event/IFox.Event.Shared/EventFactory/EventFactory.cs @@ -0,0 +1,88 @@ +namespace IFoxCAD.Event; +public static class EventFactory +{ + /// + /// ʹCad¼ + /// + /// ¼ö + /// + public static void UseCadEvent(CadEvent cadEvent, Assembly? assembly = null) + { + assembly ??= Assembly.GetCallingAssembly(); + IdleAction.Add(() => + { + if ((cadEvent & CadEvent.SystemVariableChanged) != 0) + { + SystemVariableChangedEvent.Initlize(assembly); + } + if ((cadEvent & CadEvent.DocumentLockModeChanged) != 0) + { + DocumentLockModeChangedEvent.Initlize(assembly); + } + if ((cadEvent & CadEvent.BeginDoubleClick) != 0) + { + BeginDoubleClickEvent.Initlize(assembly); + } + }); + } + /// + /// ʱر¼(Ҫö) + /// + /// + /// + public static EventTemporaryShutdownManager TemporaryShutdown(CadEvent cadEvent = CadEvent.All) + { + return new EventTemporaryShutdownManager(cadEvent); + } + /// + /// ¼ + /// + /// ¼ö + public static void AddEvent(CadEvent cadEvent) + { + if ((cadEvent & CadEvent.SystemVariableChanged) != 0) + { + SystemVariableChangedEvent.AddEvent(); + } + if ((cadEvent & CadEvent.DocumentLockModeChanged) != 0) + { + DocumentLockModeChangedEvent.AddEvent(); + } + if ((cadEvent & CadEvent.BeginDoubleClick) != 0) + { + BeginDoubleClickEvent.AddEvent(); + } + } + /// + /// Ƴ¼ + /// + /// ¼ö + public static void RemoveEvent(CadEvent cadEvent) + { + if ((cadEvent & CadEvent.SystemVariableChanged) != 0) + { + SystemVariableChangedEvent.RemoveEvent(); + } + if ((cadEvent & CadEvent.DocumentLockModeChanged) != 0) + { + DocumentLockModeChangedEvent.RemoveEvent(); + } + if ((cadEvent & CadEvent.BeginDoubleClick) != 0) + { + BeginDoubleClickEvent.RemoveEvent(); + } + } + + internal static Func closeCheck = () => true; +#if Debug + /// + /// жȫ¼Debugʹã + /// 㶯̬ضθʱжص֮ǰdllжҪû + /// + /// + public static void SetCloseCondition(this Func condition) + { + closeCheck = condition; + } +#endif +} \ No newline at end of file diff --git a/src/Event/IFox.Event.Shared/EventFactory/EventMethodInfo.cs b/src/Event/IFox.Event.Shared/EventFactory/EventMethodInfo.cs new file mode 100644 index 0000000..b0251a5 --- /dev/null +++ b/src/Event/IFox.Event.Shared/EventFactory/EventMethodInfo.cs @@ -0,0 +1,22 @@ +namespace IFoxCAD.Event; + +public class EventMethodInfo +{ + public EventMethodInfo(MethodInfo method, EventParameterType parameterType, int level) + { + Method = method; + ParameterType = parameterType; + Level = level; + } + + public MethodInfo Method { get; } + public EventParameterType ParameterType { get; } + public int Level { get; } +} +public enum EventParameterType +{ + None = 0, + Object = 1, + EventArgs = 2, + Complete = 3, +} \ No newline at end of file diff --git a/src/Event/IFox.Event.Shared/EventFactory/EventTemporaryShutdownManager.cs b/src/Event/IFox.Event.Shared/EventFactory/EventTemporaryShutdownManager.cs new file mode 100644 index 0000000..b67d814 --- /dev/null +++ b/src/Event/IFox.Event.Shared/EventFactory/EventTemporaryShutdownManager.cs @@ -0,0 +1,40 @@ +namespace IFoxCAD.Event; + +public class EventTemporaryShutdownManager : IDisposable +{ + private readonly CadEvent _cadEvent; + /// + /// 临时关闭事件,dispose的时候重开,防止事件嵌套时使用 + /// + /// 事件枚举 + internal EventTemporaryShutdownManager(CadEvent cadEvent) + { + _cadEvent = cadEvent; + EventFactory.RemoveEvent(_cadEvent); + } + #region Dispose + + private bool _isDisposed = false; + public bool IsDisposed => _isDisposed; + + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + if (!_isDisposed) + { + EventFactory.AddEvent(_cadEvent); + _isDisposed = true; + } + } + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + #endregion +} + diff --git a/src/Event/IFox.Event.Shared/IFox.Event.Shared.projitems b/src/Event/IFox.Event.Shared/IFox.Event.Shared.projitems new file mode 100644 index 0000000..7707f6c --- /dev/null +++ b/src/Event/IFox.Event.Shared/IFox.Event.Shared.projitems @@ -0,0 +1,20 @@ + + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + true + c4f9a0cf-920e-41d0-bf51-0a59df660ad9 + + + IFox.Event.Shared + + + + + + + + + + + \ No newline at end of file diff --git a/src/Event/IFox.Event.Shared/IFox.Event.Shared.shproj b/src/Event/IFox.Event.Shared/IFox.Event.Shared.shproj new file mode 100644 index 0000000..8932f2e --- /dev/null +++ b/src/Event/IFox.Event.Shared/IFox.Event.Shared.shproj @@ -0,0 +1,13 @@ + + + + c4f9a0cf-920e-41d0-bf51-0a59df660ad9 + 14.0 + + + + + + + + -- Gitee From 12a7710dc99356092fb3813c339498d700fc1e36 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sun, 28 May 2023 22:07:38 +0800 Subject: [PATCH 115/453] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=8E=B7=E5=8F=96CAD?= =?UTF-8?q?=E9=BC=A0=E6=A0=87=E5=BD=93=E5=89=8D=E4=BD=8D=E7=BD=AE=E5=9D=90?= =?UTF-8?q?=E6=A0=87=E7=9A=84=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../IFox.CAD.Shared/ExtensionMethod/EditorEx.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs index ffd5f3e..6e2310d 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs @@ -1100,4 +1100,19 @@ public static void PrepareForJig(this Editor ed, IEnumerable ents) } } #endregion + + #region Extension + + /// + /// 获取CAD鼠标当前位置坐标 + /// + /// 命令栏 + /// 坐标(可能为null) + public static Point3d? GetCurrentMouthPoint(this Editor ed) + { + return ed.RunLisp("(grread T)", RunLispFlag.AcedEvaluateLisp)?.AsArray() + .FirstOrDefault(tv => tv.TypeCode == 5009).Value as Point3d?; + } + + #endregion } \ No newline at end of file -- Gitee From 7ab94d04e73e4aa61ae7c9fa0a9b3e1dcfcc8ed0 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sun, 28 May 2023 22:26:31 +0800 Subject: [PATCH 116/453] =?UTF-8?q?=E5=A2=9E=E5=8A=A0DocumentActivated?= =?UTF-8?q?=E4=BA=8B=E4=BB=B6=E7=9A=84=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../EventEx/DocumentActivatedEvent.cs | 108 ++++++++++++++++++ .../EventFactory/CadEvent.cs | 6 +- .../EventFactory/EventFactory.cs | 12 ++ .../IFox.Event.Shared.projitems | 1 + 4 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 src/Event/IFox.Event.Shared/EventEx/DocumentActivatedEvent.cs diff --git a/src/Event/IFox.Event.Shared/EventEx/DocumentActivatedEvent.cs b/src/Event/IFox.Event.Shared/EventEx/DocumentActivatedEvent.cs new file mode 100644 index 0000000..884fe73 --- /dev/null +++ b/src/Event/IFox.Event.Shared/EventEx/DocumentActivatedEvent.cs @@ -0,0 +1,108 @@ +namespace IFoxCAD.Event; +internal static class DocumentActivatedEvent +{ + private static readonly Type returnType = typeof(void); + private static readonly Type firstType = typeof(object); + private static readonly Type secondType = typeof(DocumentCollectionEventArgs); + private static readonly HashSet dic = new(); + internal static void Initlize(Assembly assembly) + { + var types = assembly.GetTypes(); + foreach (var type in types) + { + if (!type.IsClass) + continue; + foreach (var methodInfo in type.GetMethods()) + { + foreach (Attribute att in methodInfo.GetCustomAttributes(typeof(DocumentActivatedAttribute), false)) + { + if (att is not DocumentActivatedAttribute targetAtt) + continue; + if (!methodInfo.IsStatic) + throw new ArgumentException($"标记{nameof(DocumentActivatedAttribute)}特性的方法{type.Name}.{methodInfo.Name},应为静态方法"); + if (methodInfo.ReturnType != returnType) + throw new ArgumentException($"标记{nameof(DocumentActivatedAttribute)}特性的方法{type.Name}.{methodInfo.Name},返回值应为void"); + var args = methodInfo.GetParameters(); + if (args.Length > 2) + throw new ArgumentException($"标记{nameof(DocumentActivatedAttribute)}特性的方法{type.Name}.{methodInfo.Name},参数类型错误"); + + + EventParameterType? ept = null; + if (args.Length == 0) + ept = EventParameterType.None; + else if (args.Length == 1) + { + if (args[0].ParameterType == firstType) + ept = EventParameterType.Object; + else if (args[0].ParameterType == secondType) + ept = EventParameterType.EventArgs; + } + else if (args.Length == 2 && args[0].ParameterType == firstType && args[1].ParameterType == secondType) + { + ept = EventParameterType.Complete; + } + if (ept is null) + throw new ArgumentException($"标记{nameof(DocumentActivatedAttribute)}特性的方法{type.Name}.{methodInfo.Name},参数类型错误"); + dic.Add(new(methodInfo, ept.Value, targetAtt.Level)); + break; + } + } + } + AddEvent(); + } + + internal static void AddEvent() + { + Acap.DocumentManager.DocumentActivated -= DocumentManager_DocumentActivated; + Acap.DocumentManager.DocumentActivated += DocumentManager_DocumentActivated; + } + + internal static void RemoveEvent() + { + Acap.DocumentManager.DocumentActivated -= DocumentManager_DocumentActivated; + } + private static void DocumentManager_DocumentActivated(object sender, DocumentCollectionEventArgs e) + { +#if Debug + if (!EventFactory.closeCheck.Invoke()) + { + EventFactory.RemoveEvent(CadEvent.All); + return; + } +#endif + foreach (var eventMethodInfo in dic.OrderByDescending(a => a.Level)) + { + switch (eventMethodInfo.ParameterType) + { + case EventParameterType.None: + eventMethodInfo.Method.Invoke(null, new object[0]); + break; + case EventParameterType.Object: + eventMethodInfo.Method.Invoke(null, new[] { sender }); + break; + case EventParameterType.EventArgs: + eventMethodInfo.Method.Invoke(null, new[] { e }); + break; + case EventParameterType.Complete: + eventMethodInfo.Method.Invoke(null, new[] { sender, e }); + break; + } + } + } + +} +[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)] +public class DocumentActivatedAttribute : Attribute +{ + /// s + /// 系统变量修改时触发被标记的函数 + /// 返回值应为void + /// 参数不大于2个且只能为object和DocumentCollectionEventArgs + /// + /// 级别(越高越先触发) + public DocumentActivatedAttribute(int level = -1) + { + Level = level; + } + public int Level { get; } +} \ No newline at end of file diff --git a/src/Event/IFox.Event.Shared/EventFactory/CadEvent.cs b/src/Event/IFox.Event.Shared/EventFactory/CadEvent.cs index 8e3b0bf..570a414 100644 --- a/src/Event/IFox.Event.Shared/EventFactory/CadEvent.cs +++ b/src/Event/IFox.Event.Shared/EventFactory/CadEvent.cs @@ -22,5 +22,9 @@ public enum CadEvent /// /// 开始双击 /// - BeginDoubleClick=0b100, + BeginDoubleClick = 0b100, + /// + /// 文档激活 + /// + DocumentActivated = 0b1000, } \ No newline at end of file diff --git a/src/Event/IFox.Event.Shared/EventFactory/EventFactory.cs b/src/Event/IFox.Event.Shared/EventFactory/EventFactory.cs index ea02a68..bb43eff 100644 --- a/src/Event/IFox.Event.Shared/EventFactory/EventFactory.cs +++ b/src/Event/IFox.Event.Shared/EventFactory/EventFactory.cs @@ -23,6 +23,10 @@ public static void UseCadEvent(CadEvent cadEvent, Assembly? assembly = null) { BeginDoubleClickEvent.Initlize(assembly); } + if ((cadEvent & CadEvent.DocumentActivated) != 0) + { + DocumentActivatedEvent.Initlize(assembly); + } }); } /// @@ -52,6 +56,10 @@ public static void AddEvent(CadEvent cadEvent) { BeginDoubleClickEvent.AddEvent(); } + if ((cadEvent & CadEvent.DocumentActivated) != 0) + { + DocumentActivatedEvent.AddEvent(); + } } /// /// Ƴ¼ @@ -71,6 +79,10 @@ public static void RemoveEvent(CadEvent cadEvent) { BeginDoubleClickEvent.RemoveEvent(); } + if ((cadEvent & CadEvent.DocumentActivated) != 0) + { + DocumentActivatedEvent.RemoveEvent(); + } } internal static Func closeCheck = () => true; diff --git a/src/Event/IFox.Event.Shared/IFox.Event.Shared.projitems b/src/Event/IFox.Event.Shared/IFox.Event.Shared.projitems index 7707f6c..137e275 100644 --- a/src/Event/IFox.Event.Shared/IFox.Event.Shared.projitems +++ b/src/Event/IFox.Event.Shared/IFox.Event.Shared.projitems @@ -9,6 +9,7 @@ IFox.Event.Shared + -- Gitee From f432e0b66d98133603fa54ae9ea058b7c49c96db Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sun, 28 May 2023 22:28:37 +0800 Subject: [PATCH 117/453] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BA=8B=E4=BB=B6?= =?UTF-8?q?=E7=B1=BB=E5=BA=94=E7=94=A8=E8=8C=83=E5=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Event/IFox.Event.Shared/EventFactory/EventMethodInfo.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Event/IFox.Event.Shared/EventFactory/EventMethodInfo.cs b/src/Event/IFox.Event.Shared/EventFactory/EventMethodInfo.cs index b0251a5..1f71246 100644 --- a/src/Event/IFox.Event.Shared/EventFactory/EventMethodInfo.cs +++ b/src/Event/IFox.Event.Shared/EventFactory/EventMethodInfo.cs @@ -1,6 +1,6 @@ namespace IFoxCAD.Event; -public class EventMethodInfo +internal class EventMethodInfo { public EventMethodInfo(MethodInfo method, EventParameterType parameterType, int level) { @@ -13,7 +13,7 @@ public EventMethodInfo(MethodInfo method, EventParameterType parameterType, int public EventParameterType ParameterType { get; } public int Level { get; } } -public enum EventParameterType +internal enum EventParameterType { None = 0, Object = 1, -- Gitee From e5cc6d54825b8e8d1f5dcbb416884f2666784efe Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Tue, 30 May 2023 14:34:28 +0000 Subject: [PATCH 118/453] =?UTF-8?q?=E6=96=B0=E5=BB=BA=20EVENT?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Event/EVENT/.keep | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/Event/EVENT/.keep diff --git a/src/Event/EVENT/.keep b/src/Event/EVENT/.keep new file mode 100644 index 0000000..e69de29 -- Gitee From 6fb8796b054d7d0e27c5cb3a4fc0a600a8b1a17f Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 1 Jun 2023 16:33:09 +0800 Subject: [PATCH 119/453] =?UTF-8?q?=E6=96=B0=E5=BB=BA=E6=96=87=E5=AD=97?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=AF=B9=E9=BD=90=E7=82=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/DBTextEx.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/DBTextEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/DBTextEx.cs index 1f8105f..c88002b 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/DBTextEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/DBTextEx.cs @@ -11,11 +11,12 @@ public static class DBTextEx /// 插入点 /// 文本内容 /// 文字高度 + /// 对齐方式 /// 文字所在的数据库 /// 文字属性设置委托 /// 文字对象 /// - public static DBText CreateDBText(Point3d position, string text, double height, Database? database = null,Action? action = null) + public static DBText CreateDBText(Point3d position, string text, double height,AttachmentPoint justify = AttachmentPoint.BottomLeft, Database? database = null,Action? action = null) { if (string.IsNullOrEmpty(text)) throw new ArgumentNullException(nameof(text), "创建文字无内容"); @@ -28,7 +29,7 @@ public static DBText CreateDBText(Point3d position, string text, double height, acText.TextString = text; acText.Position = position; // 插入点(一定要先设置) - acText.Justify = AttachmentPoint.BaseLeft; // 使他们对齐 + acText.Justify = justify; // 使他们对齐 action?.Invoke(acText); -- Gitee From e24f4072fab8f4d0ecaadaec9c86bcf0402d5f04 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sat, 3 Jun 2023 16:31:58 +0800 Subject: [PATCH 120/453] =?UTF-8?q?NestedForEach=E8=BE=93=E5=85=A5?= =?UTF-8?q?=E5=8F=82=E6=95=B0=E6=94=B9=E4=B8=BAEntity=EF=BC=8C=E8=99=BD?= =?UTF-8?q?=E7=84=B6=E4=B8=8D=E5=90=88=E8=A7=84=EF=BC=8C=E4=BD=86=E6=98=AF?= =?UTF-8?q?=E5=A5=BD=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs index 23efd3f..4bfd039 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs @@ -209,7 +209,7 @@ public static void ForEach(this BlockReference brf, Action块参照 /// 委托 /// 事务 - public static void NestedForEach(this BlockReference blockReference, Action action, DBTrans? tr = null) + public static void NestedForEach(this Entity blockReference, Action action, DBTrans? tr = null) { tr ??= DBTrans.GetTop(blockReference.IsNewObject ? Env.Database : blockReference.Database); var queue = new Queue<(Entity, Matrix3d)>(); -- Gitee From cede1d5d444b0e8b72fd752adba0fda230bfb9b9 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sat, 3 Jun 2023 21:50:23 +0800 Subject: [PATCH 121/453] =?UTF-8?q?=E6=B7=BB=E5=8A=A0ObjectIdCollection.Ge?= =?UTF-8?q?tObject=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/ObjectIdEx.cs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs index 2b9f915..ebfa130 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs @@ -44,7 +44,23 @@ public static IEnumerable GetObject(this IEnumerable ids, .Select(id => id.GetObject(openMode, openErased, openLockedLayer)) .OfType(); } - + /// + /// 获取指定类型对象集合 + /// + /// 指定的泛型 + /// 对象id集合 + /// 打开模式 + /// 是否打开已删除对象,默认为不打开 + /// 是否打开锁定图层对象,默认为不打开 + /// 指定类型对象集合 + [System.Diagnostics.DebuggerStepThrough] + public static IEnumerable GetObject(this ObjectIdCollection ids, + OpenMode openMode = OpenMode.ForRead, + bool openErased = false, + bool openLockedLayer = false) where T : DBObject + { + return ids.Cast().GetObject(openMode, openErased, openLockedLayer); + } /// /// 返回符合类型的对象id /// -- Gitee From edce2eef0bc7936cb67e604e0c7eca325f9ff512 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Sun, 7 May 2023 16:10:08 +0800 Subject: [PATCH 122/453] =?UTF-8?q?=E5=B0=86=E4=BA=8B=E5=8A=A1=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E4=B8=AD=E7=9A=84=E4=BF=9D=E5=AD=98=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E7=A7=BB=E8=87=B3=E6=95=B0=E6=8D=AE=E5=BA=93=E6=89=A9=E5=B1=95?= =?UTF-8?q?=E5=87=BD=E6=95=B0=E5=86=85.fixed=20#I710JF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.GCAD/GlobalUsings.cs | 9 +- .../ExtensionMethod/DBObjectEx.cs | 4 +- .../ExtensionMethod/DatabaseEx.cs | 162 ++++++++++++++++++ .../IFox.CAD.Shared/IFox.CAD.Shared.projitems | 1 + src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs | 157 ----------------- src/CAD/IFox.CAD.ZCAD/GlobalUsings.cs | 10 +- tests/TestShared/Copyclip.cs | 2 +- tests/TestShared/TestBlock.cs | 4 +- tests/TestShared/TestDBTrans.cs | 10 +- tests/TestShared/TestText.cs | 2 +- tests/TestShared/TestXrefEx.cs | 4 +- 11 files changed, 183 insertions(+), 182 deletions(-) create mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/DatabaseEx.cs diff --git a/src/CAD/IFox.CAD.GCAD/GlobalUsings.cs b/src/CAD/IFox.CAD.GCAD/GlobalUsings.cs index 08de9aa..35120c1 100644 --- a/src/CAD/IFox.CAD.GCAD/GlobalUsings.cs +++ b/src/CAD/IFox.CAD.GCAD/GlobalUsings.cs @@ -1,4 +1,4 @@ -/// 系统引用 +// 系统引用 global using System; global using System.Collections; global using System.Collections.Generic; @@ -17,7 +17,7 @@ global using Registry = Microsoft.Win32.Registry; global using RegistryKey = Microsoft.Win32.RegistryKey; -/// cad 引用 +// cad 引用 global using GrxCAD.ApplicationServices; global using GrxCAD.EditorInput; global using GrxCAD.Colors; @@ -26,6 +26,7 @@ global using GrxCAD.Runtime; global using Acap = GrxCAD.ApplicationServices.Application; global using Acgi = GrxCAD.GraphicsInterface; +global using Acaop = GrxCAD.ApplicationServices.Application; global using GrxCAD.DatabaseServices.Filters; global using GrxCAD; @@ -43,9 +44,7 @@ global using Cad_DxfFiler = GrxCAD.DatabaseServices.DxfFiler; global using Cad_ErrorStatus = GrxCAD.Runtime.ErrorStatus; -/// ifoxcad.basal 引用 +// ifoxcad.basal 引用 global using IFoxCAD.Basal; -#if !NewtonsoftJson global using System.Web.Script.Serialization; -#endif \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBObjectEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBObjectEx.cs index f535937..c881ad9 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBObjectEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBObjectEx.cs @@ -1,6 +1,4 @@ -using System.Linq; - -namespace IFoxCAD.Cad; +namespace IFoxCAD.Cad; /// /// 实体对象扩展类 diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/DatabaseEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/DatabaseEx.cs new file mode 100644 index 0000000..6f14471 --- /dev/null +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/DatabaseEx.cs @@ -0,0 +1,162 @@ +namespace IFoxCAD.Cad; + +/// +/// 数据库扩展函数 +/// +public static class DatabaseEx +{ + /// + /// 保存文件 + /// + /// 数据库 + /// 文件版本 + public static void SaveDwgFile(this Database db, DwgVersion version = DwgVersion.AC1800) + { + db.SaveFile(version); + } + + /// + /// 保存文件
+ ///
+ /// 数据库 + /// 默认2004dwg;若保存dxf则需要在路径输入扩展名 + /// 为true时候无效,将变为自动识别环境变量 + /// 另存为文件,前台将调用时它将无效,将变为弹出面板 + /// 保存路径失败的提示 + public static void SaveFile(this Database db, DwgVersion version = DwgVersion.AC1800, + bool automatic = true, + string? saveAsFile = null, + bool echoes = true) + { + // 遍历当前所有文档,文档必然是前台的 + Document? doc = null; + foreach (Document docItem in Acaop.DocumentManager) + { + if (docItem.Database.Filename == db.Filename) + { + doc = docItem; + break; + } + } + // 前台开图,使用命令保存;不需要切换文档 + if (doc != null) + { + // 无法把 给这个面板 + doc.SendStringToExecute(saveAsFile == null ? "_qsave\n" : $"_Saveas\n", false, true, true); + return; + } + + // 后台开图,用数据库保存 + string? fileMsg; + bool creatFlag = false; + if (string.IsNullOrWhiteSpace(saveAsFile)) + { + fileMsg = db.Filename; + saveAsFile = fileMsg; + //creatFlag = true; + } + else + { + fileMsg = saveAsFile; + + // 路径失败也保存到桌面 + var path = Path.GetDirectoryName(saveAsFile); + if (string.IsNullOrWhiteSpace(path)) + { + creatFlag = true; + } + else if (!Directory.Exists(path)) + { + try { Directory.CreateDirectory(path); } + catch { creatFlag = true; } + } + + // 文件名缺失时 + if (!creatFlag && + string.IsNullOrWhiteSpace(Path.GetFileName(saveAsFile))) + creatFlag = true; + } + if (saveAsFile != null) + { + var fileNameWith = Path.GetFileNameWithoutExtension(saveAsFile); + if (string.IsNullOrWhiteSpace(fileNameWith)) + creatFlag = true; + } + else + { + creatFlag = true; + } + + if (creatFlag) + { + var (error, file) = db.GetOrCreateSaveAsFile(); + if (echoes && error) + System.Windows.Forms.MessageBox.Show($"错误参数:\n{fileMsg}\n\n它将保存:\n{file}", "错误的文件路径"); + saveAsFile = file; + } + + if (Path.GetExtension(saveAsFile)!.ToLower().Contains("dxf")) + { + // dxf用任何版本号都会报错 +#if acad || gcad + db.DxfOut(saveAsFile, 7, true); +#endif + +#if zcad // 中望这里没有测试 + db.DxfOut(saveAsFile, 7, version, true); +#endif + return; + } + + if (automatic) + version = Env.GetDefaultDwgVersion(); + + // dwg需要版本号,而dxf不用,dwg用dxf版本号会报错 + // 若扩展名和版本号冲突,按照扩展名为准 + if (version.IsDxfVersion()) + version = DwgVersion.Current; + + db.SaveAs(saveAsFile, version); + } + + /// + /// 获取文件名,无效的话就制造 + /// + /// + private static (bool error, string path) GetOrCreateSaveAsFile(this Database db) + { + var file = db.Filename; + if (!string.IsNullOrWhiteSpace(file)) + return (false, file); + + // 为了防止用户输入了错误的路径造成无法保存, + // 所以此处将进行保存到桌面, + // 而不是弹出警告就结束 + // 防止前台关闭了所有文档导致没有Editor,所以使用 MessageBox 发送警告 + var fileName = Path.GetFileNameWithoutExtension(file); + var fileExt = Path.GetExtension(file); + + if (string.IsNullOrWhiteSpace(fileName)) + fileName = DateTime.Now.ToString("--yyMMdd--hhmmssffff"); + if (string.IsNullOrWhiteSpace(fileExt)) + fileExt = ".dwg"; + + // 构造函数(fileName)用了不存在的路径进行后台打开,就会出现此问题 + // 测试命令 FileNotExist + var dir = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + + "\\后台保存出错的文件\\"; + + if (!Directory.Exists(dir)) + Directory.CreateDirectory(dir); + + file = dir + fileName + fileExt; + while (File.Exists(file)) + { + var time = DateTime.Now.ToString("--yyMMdd--hhmmssffff"); + file = dir + fileName + time + fileExt; + System.Threading.Thread.Sleep(100); + } + return (true, file); + } + +} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems b/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems index d87bdaf..993d1da 100644 --- a/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems +++ b/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems @@ -25,6 +25,7 @@ + diff --git a/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs b/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs index e5e8ff7..0d6c982 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs @@ -3,8 +3,6 @@ namespace IFoxCAD.Cad; using System.Diagnostics; using System.IO; -using System.Threading; -using System.Windows.Forms; /// /// 事务栈 @@ -461,161 +459,6 @@ public ObjectId GetObjectId(string handleString) } #endregion - #region 保存文件 - /// - /// 保存文件 - /// - /// - public void SaveDwgFile(DwgVersion version = DwgVersion.AC1800) - { - SaveFile(version); - } - - /// - /// 保存文件
- ///
- /// 默认2004dwg;若保存dxf则需要在路径输入扩展名 - /// 为true时候无效,将变为自动识别环境变量 - /// 另存为文件,前台将调用时它将无效,将变为弹出面板 - /// 保存路径失败的提示 - public void SaveFile(DwgVersion version = DwgVersion.AC1800, - bool automatic = true, - string? saveAsFile = null, - bool echoes = true) - { - // 遍历当前所有文档,文档必然是前台的 - Document? doc = null; - foreach (Document docItem in Acaop.DocumentManager) - { - if (docItem.Database.Filename == this.Database.Filename) - { - doc = docItem; - break; - } - } - // 前台开图,使用命令保存;不需要切换文档 - if (doc != null) - { - // 无法把 给这个面板 - doc.SendStringToExecute(saveAsFile == null ? "_qsave\n" : $"_Saveas\n", false, true, true); - return; - } - - // 后台开图,用数据库保存 - string? fileMsg; - bool creatFlag = false; - if (string.IsNullOrWhiteSpace(saveAsFile)) - { - fileMsg = _fileName; - saveAsFile = fileMsg; - //creatFlag = true; - } - else - { - fileMsg = saveAsFile; - - // 路径失败也保存到桌面 - var path = Path.GetDirectoryName(saveAsFile); - if (string.IsNullOrWhiteSpace(path)) - { - creatFlag = true; - } - else if (!Directory.Exists(path)) - { - try { Directory.CreateDirectory(path); } - catch { creatFlag = true; } - } - - // 文件名缺失时 - if (!creatFlag && - string.IsNullOrWhiteSpace(Path.GetFileName(saveAsFile))) - creatFlag = true; - } - if (saveAsFile != null) - { - var fileNameWith = Path.GetFileNameWithoutExtension(saveAsFile); - if (string.IsNullOrWhiteSpace(fileNameWith)) - creatFlag = true; - } - else - { - creatFlag = true; - } - - if (creatFlag) - { - var (error, file) = GetOrCreateSaveAsFile(); - if (echoes && error) - MessageBox.Show($"错误参数:\n{fileMsg}\n\n它将保存:\n{file}", "错误的文件路径"); - saveAsFile = file; - } - - if (Path.GetExtension(saveAsFile).ToLower().Contains("dxf")) - { - // dxf用任何版本号都会报错 -#if acad || gcad - Database.DxfOut(saveAsFile, 7, true); -#endif - -#if zcad // 中望这里没有测试 - Database.DxfOut(saveAsFile, 7, version, true); -#endif - return; - } - - if (automatic) - version = Env.GetDefaultDwgVersion(); - - // dwg需要版本号,而dxf不用,dwg用dxf版本号会报错 - // 若扩展名和版本号冲突,按照扩展名为准 - if (version.IsDxfVersion()) - version = DwgVersion.Current; - - Database.SaveAs(saveAsFile, version); - } - - /// - /// 获取文件名,无效的话就制造 - /// - /// - private (bool error, string path) GetOrCreateSaveAsFile() - { - var file = Database.Filename; - if (!string.IsNullOrWhiteSpace(file)) - return (false, file); - - // 为了防止用户输入了错误的路径造成无法保存, - // 所以此处将进行保存到桌面, - // 而不是弹出警告就结束 - // 防止前台关闭了所有文档导致没有Editor,所以使用 MessageBox 发送警告 - var fileName = Path.GetFileNameWithoutExtension(_fileName); - var fileExt = Path.GetExtension(_fileName); - - if (string.IsNullOrWhiteSpace(fileName)) - fileName = DateTime.Now.ToString("--yyMMdd--hhmmssffff"); - if (string.IsNullOrWhiteSpace(fileExt)) - fileExt = ".dwg"; - - // 构造函数(fileName)用了不存在的路径进行后台打开,就会出现此问题 - // 测试命令 FileNotExist - var dir = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) - + "\\后台保存出错的文件\\"; - - if (!Directory.Exists(dir)) - Directory.CreateDirectory(dir); - - file = dir + fileName + fileExt; - while (File.Exists(file)) - { - var time = DateTime.Now.ToString("--yyMMdd--hhmmssffff"); - file = dir + fileName + time + fileExt; - Thread.Sleep(100); - } - return (true, file); - } - - #endregion - #region 前台后台任务 /// /// 前台后台任务分别处理 diff --git a/src/CAD/IFox.CAD.ZCAD/GlobalUsings.cs b/src/CAD/IFox.CAD.ZCAD/GlobalUsings.cs index add1774..d3dd2e5 100644 --- a/src/CAD/IFox.CAD.ZCAD/GlobalUsings.cs +++ b/src/CAD/IFox.CAD.ZCAD/GlobalUsings.cs @@ -1,4 +1,4 @@ -/// 系统引用 +// 系统引用 global using System; global using System.Collections; global using System.Collections.Generic; @@ -17,7 +17,7 @@ global using Registry = Microsoft.Win32.Registry; global using RegistryKey = Microsoft.Win32.RegistryKey; -/// cad 引用 +// cad 引用 global using ZwSoft.ZwCAD.ApplicationServices; global using ZwSoft.ZwCAD.EditorInput; global using ZwSoft.ZwCAD.Colors; @@ -25,7 +25,7 @@ global using ZwSoft.ZwCAD.Geometry; global using ZwSoft.ZwCAD.Runtime; global using Acap = ZwSoft.ZwCAD.ApplicationServices.Application; - +global using Acaop = ZwSoft.ZwCAD.ApplicationServices.Application; global using ZwSoft.ZwCAD.DatabaseServices.Filters; global using ZwSoft.ZwCAD; @@ -40,9 +40,7 @@ global using Cad_DxfFiler = ZwSoft.ZwCAD.DatabaseServices.DxfFiler; global using Cad_ErrorStatus = ZwSoft.ZwCAD.Runtime.ErrorStatus; -/// ifoxcad.basal 引用 +// ifoxcad.basal 引用 global using IFoxCAD.Basal; -#if !NewtonsoftJson global using System.Web.Script.Serialization; -#endif \ No newline at end of file diff --git a/tests/TestShared/Copyclip.cs b/tests/TestShared/Copyclip.cs index 61c4cbf..3b164d3 100644 --- a/tests/TestShared/Copyclip.cs +++ b/tests/TestShared/Copyclip.cs @@ -315,7 +315,7 @@ void Copy(bool getPoint, bool isEraseSsget = false) // 大于dwg07格式的,保存为07,以实现高低版本通用剪贴板 // 小于dwg07格式的,本工程没有支持cad06dll if ((int)DwgVersion.Current >= 27) - fileTr.SaveFile((DwgVersion)27, false); + fileTr.Database.SaveFile((DwgVersion)27, false); else throw new ArgumentException($"版本过低,无法保存,版本号:{DwgVersion.Current}"); } diff --git a/tests/TestShared/TestBlock.cs b/tests/TestShared/TestBlock.cs index d2ccad6..86838a8 100644 --- a/tests/TestShared/TestBlock.cs +++ b/tests/TestShared/TestBlock.cs @@ -107,7 +107,7 @@ public void Test_BlockDefbehind() return new List { line, acText }; }); - tr.SaveDwgFile(); + tr.Database.SaveDwgFile(); } @@ -213,7 +213,7 @@ public void Test_InsertBlockWithDoubleDatabase() }); tr.CurrentSpace.InsertBlock(Point3d.Origin, "test456"); - tr.SaveDwgFile(); + tr.Database.SaveDwgFile(); } diff --git a/tests/TestShared/TestDBTrans.cs b/tests/TestShared/TestDBTrans.cs index 2c6c77a..94beb2f 100644 --- a/tests/TestShared/TestDBTrans.cs +++ b/tests/TestShared/TestDBTrans.cs @@ -66,7 +66,7 @@ public static void CmdTest_ForEachDemo() public void FileNotExist() { using DBTrans tr = new("test.dwg"); - tr.SaveFile((DwgVersion)24, false); + tr.Database.SaveFile((DwgVersion)24, false); } // 前台:由于是弹出面板,此时路径不会起任何作用 @@ -74,7 +74,7 @@ public void FileNotExist() public void FileNotExist2() { using DBTrans tr = new(); - tr.SaveFile(saveAsFile: "D:\\"); + tr.Database.SaveFile(saveAsFile: "D:\\"); } // 后台:只有路径,没有文件名 @@ -82,10 +82,10 @@ public void FileNotExist2() public void FileNotExist3() { using DBTrans tr = new("D:\\"); - tr.SaveDwgFile(); + tr.Database.SaveDwgFile(); using DBTrans tr2 = new("D:\\"); - tr2.SaveFile(saveAsFile: "D:\\"); + tr2.Database.SaveFile(saveAsFile: "D:\\"); } @@ -97,7 +97,7 @@ public void Test_SaveDwgFile() var circle = CircleEx.CreateCircle(new Point3d(10, 10, 0), 20)!; tr.ModelSpace.AddEntity(circle); // tr.Database.SaveAs(filename,DwgVersion.Current); - tr.SaveDwgFile(); + tr.Database.SaveDwgFile(); } [CommandMethod(nameof(Test_DBTransAbort))] public void Test_DBTransAbort() diff --git a/tests/TestShared/TestText.cs b/tests/TestShared/TestText.cs index e147fbc..b25dab6 100644 --- a/tests/TestShared/TestText.cs +++ b/tests/TestShared/TestText.cs @@ -29,7 +29,7 @@ public void TestBackDBText() t.AlignmentPoint = new(1, 1, 0); t.ColorIndex = 2; })); - tr.SaveDwgFile(); + tr.Database.SaveDwgFile(); } diff --git a/tests/TestShared/TestXrefEx.cs b/tests/TestShared/TestXrefEx.cs index 8142200..7fa7f3e 100644 --- a/tests/TestShared/TestXrefEx.cs +++ b/tests/TestShared/TestXrefEx.cs @@ -10,7 +10,7 @@ public static void Test_Bind1() using var tr = new DBTrans(fileName, fileOpenMode: FileOpenMode.OpenForReadAndAllShare/*后台绑定特别注意*/); tr.XrefFactory(XrefModes.Bind); - tr.SaveDwgFile(); + tr.Database.SaveDwgFile(); } //前台绑定 @@ -19,6 +19,6 @@ public static void Test_Bind2() { using var tr = new DBTrans(); tr.XrefFactory(XrefModes.Bind); - tr.SaveDwgFile(); + tr.Database.SaveDwgFile(); } } \ No newline at end of file -- Gitee From a9f6114ddb65ad6751f28d86f592044c84997a05 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Sun, 7 May 2023 18:03:30 +0800 Subject: [PATCH 123/453] =?UTF-8?q?=E6=B8=85=E7=90=86=E9=A1=B9=E7=9B=AE?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E4=B8=AD=E7=9A=84=E8=AD=A6=E5=91=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.ACAD/IFox.CAD.ACAD.csproj | 3 +-- src/CAD/IFox.CAD.GCAD/IFox.CAD.GCAD.csproj | 3 +-- src/CAD/IFox.CAD.ZCAD/IFox.CAD.ZCAD.csproj | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/CAD/IFox.CAD.ACAD/IFox.CAD.ACAD.csproj b/src/CAD/IFox.CAD.ACAD/IFox.CAD.ACAD.csproj index 64082ed..8e48e1c 100644 --- a/src/CAD/IFox.CAD.ACAD/IFox.CAD.ACAD.csproj +++ b/src/CAD/IFox.CAD.ACAD/IFox.CAD.ACAD.csproj @@ -1,7 +1,7 @@  - NET48 + NET48 true true MSB3270 @@ -22,7 +22,6 @@ True - diff --git a/src/CAD/IFox.CAD.GCAD/IFox.CAD.GCAD.csproj b/src/CAD/IFox.CAD.GCAD/IFox.CAD.GCAD.csproj index 838bb41..71473f7 100644 --- a/src/CAD/IFox.CAD.GCAD/IFox.CAD.GCAD.csproj +++ b/src/CAD/IFox.CAD.GCAD/IFox.CAD.GCAD.csproj @@ -1,7 +1,7 @@  - NET48 + NET48 true true @@ -25,7 +25,6 @@ True - diff --git a/src/CAD/IFox.CAD.ZCAD/IFox.CAD.ZCAD.csproj b/src/CAD/IFox.CAD.ZCAD/IFox.CAD.ZCAD.csproj index a810b27..da8e0b4 100644 --- a/src/CAD/IFox.CAD.ZCAD/IFox.CAD.ZCAD.csproj +++ b/src/CAD/IFox.CAD.ZCAD/IFox.CAD.ZCAD.csproj @@ -1,7 +1,7 @@  - NET48 + NET48 true true @@ -24,7 +24,6 @@ True - -- Gitee From e0592a90387fe1cacf57db936d2bc8407770dcae Mon Sep 17 00:00:00 2001 From: vicwjb Date: Tue, 6 Jun 2023 23:08:59 +0800 Subject: [PATCH 124/453] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/CheckFactory.cs | 2 ++ tests/TestShared/TestBlock.cs | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/CheckFactory.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/CheckFactory.cs index 3e5bb4e..42bb785 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/CheckFactory.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/CheckFactory.cs @@ -1,4 +1,6 @@ #if Debug +using System.Windows.Forms; + namespace IFoxCAD.Cad; public static class CheckFactory { diff --git a/tests/TestShared/TestBlock.cs b/tests/TestShared/TestBlock.cs index 86838a8..081241b 100644 --- a/tests/TestShared/TestBlock.cs +++ b/tests/TestShared/TestBlock.cs @@ -207,7 +207,7 @@ public void Test_InsertBlockWithDoubleDatabase() }, () => { var line = new Line(new(0, 0, 0), new(1, 1, 0)); - var actext = DBTextEx.CreateDBText(Point3d.Origin, "123", 2.5, tr.Database); + var actext = DBTextEx.CreateDBText(Point3d.Origin, "123", 2.5, database: tr.Database); return new List { line,actext }; -- Gitee From 049ecdbece02bb081ccc646a3777bef725dfe14c Mon Sep 17 00:00:00 2001 From: vicwjb Date: Tue, 6 Jun 2023 23:12:54 +0800 Subject: [PATCH 125/453] =?UTF-8?q?=E4=BB=85=E4=BF=9D=E7=95=99=E7=94=9F?= =?UTF-8?q?=E6=88=90=E6=BA=90=E7=A0=81=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Basal/IFox.Basal/IFox.Basal.csproj | 1 + src/CAD/IFox.CAD.ACAD/IFox.CAD.ACAD.csproj | 1 + 2 files changed, 2 insertions(+) diff --git a/src/Basal/IFox.Basal/IFox.Basal.csproj b/src/Basal/IFox.Basal/IFox.Basal.csproj index ad2622c..75a4841 100644 --- a/src/Basal/IFox.Basal/IFox.Basal.csproj +++ b/src/Basal/IFox.Basal/IFox.Basal.csproj @@ -5,6 +5,7 @@ true true MSB3270 + false diff --git a/src/CAD/IFox.CAD.ACAD/IFox.CAD.ACAD.csproj b/src/CAD/IFox.CAD.ACAD/IFox.CAD.ACAD.csproj index 8e48e1c..2fa77f1 100644 --- a/src/CAD/IFox.CAD.ACAD/IFox.CAD.ACAD.csproj +++ b/src/CAD/IFox.CAD.ACAD/IFox.CAD.ACAD.csproj @@ -5,6 +5,7 @@ true true MSB3270 + false -- Gitee From bb9855ecd1009dd26a95e377bb4de71f8ac3e7d8 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Fri, 9 Jun 2023 20:48:19 +0800 Subject: [PATCH 126/453] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/SingleKeyWordHook.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SingleKeyWordHook.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SingleKeyWordHook.cs index 05b079d..91b659c 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SingleKeyWordHook.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SingleKeyWordHook.cs @@ -45,6 +45,7 @@ public SingleKeyWordHook(bool escapeMode = true) _key = Keys.None; _working = true; _escapeMode = escapeMode; + Acap.PreTranslateMessage -= Acap_PreTranslateMessage; Acap.PreTranslateMessage += Acap_PreTranslateMessage; } #endregion @@ -122,7 +123,7 @@ private void Acap_PreTranslateMessage(object sender, PreTranslateMessageEventArg // 此bool是防止按键被长按时出错 _isResponsed = true; // 这里选择发送回车或者ESC//ESC稳妥一些,但是要promptResult的判断顺序 - SingleKeyWordHook.KeyBoardSendKey(_escapeMode? Keys.Escape:Keys.Enter); + KeyBoardSendKey(_escapeMode ? Keys.Escape : Keys.Enter); } } } -- Gitee From bcf6aa84166d631763c9595202aca6d545c2da15 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sun, 11 Jun 2023 23:31:50 +0800 Subject: [PATCH 127/453] =?UTF-8?q?=E4=B8=AD=E6=9C=9B=E7=9A=84worldDraw.Ra?= =?UTF-8?q?wGeometry.Draw=E4=BC=9A=E6=8A=A5=E9=94=99=EF=BC=8C=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E6=9D=A1=E4=BB=B6=E7=BC=96=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigEx.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigEx.cs index d88a073..000673f 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigEx.cs @@ -172,12 +172,16 @@ protected override bool WorldDraw(WorldDraw draw) _worldDrawFlag = true; WorldDrawEvent?.Invoke(draw); _drawEntitys.ForEach(ent => { +#if zcad draw.Geometry.Draw(ent); +#else + draw.RawGeometry.Draw(ent); +#endif }); _worldDrawFlag = false; return true; } - #endregion +#endregion #region 方法 /// -- Gitee From b5fae4574cf62819845650b2a4a7708104486fd9 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sun, 11 Jun 2023 23:38:42 +0800 Subject: [PATCH 128/453] =?UTF-8?q?=E5=B0=86=E7=82=B9=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E4=BB=8EGeometryEx=E8=BF=81=E7=A7=BB=E8=87=B3PointEx?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/GeometryEx.cs | 81 ----------------- .../ExtensionMethod/PointEx.cs | 88 ++++++++++++++++++- 2 files changed, 84 insertions(+), 85 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs index 46abb53..44689e7 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs @@ -575,87 +575,6 @@ public static Size GetSize(this Extents3d ext) return new(width, height); } - /// - /// 将三维点转换为二维点 - /// - /// 三维点 - /// 二维点 - public static Point2d Point2d(this Point3d pt) - { - return new(pt.X, pt.Y); - } - /// - /// 将三维点集转换为二维点集 - /// - /// 三维点集 - /// 二维点集 - public static IEnumerable Point2d(this IEnumerable pts) - { - return pts.Select(pt => pt.Point2d()); - } - /// - /// 将二维点转换为三维点 - /// - /// 二维点 - /// Z值 - /// 三维点 - public static Point3d Point3d(this Point2d pt, double z = 0) - { - return new(pt.X, pt.Y, z); - } - - /// - /// 获取两个点之间的中点 - /// - /// 第一点 - /// 第二点 - /// 返回两个点之间的中点 - public static Point3d GetMidPointTo(this Point3d pt1, Point3d pt2) - { - return new(pt1.X * 0.5 + pt2.X * 0.5, - pt1.Y * 0.5 + pt2.Y * 0.5, - pt1.Z * 0.5 + pt2.Z * 0.5); - } - - - /// - /// 根据世界坐标计算用户坐标 - /// - /// 基点世界坐标 - /// 基点用户坐标 - /// 目标世界坐标 - /// 坐标网旋转角,按x轴正向逆时针弧度 - /// 目标用户坐标 - public static Point3d TransPoint(this Point3d basePt, Point3d userPt, Point3d transPt, double ang) - { - Matrix3d transMat = Matrix3d.Displacement(userPt - basePt); - Matrix3d roMat = Matrix3d.Rotation(-ang, Vector3d.ZAxis, userPt); - return transPt.TransformBy(roMat * transMat); - } - /// - /// 计算指定距离和角度的点 - /// - /// 本函数仅适用于x-y平面 - /// 基点 - /// 角度,x轴正向逆时针弧度 - /// 距离 - /// 目标点 - public static Point3d Polar(this Point3d pt, double ang, double len) - { - return pt + Vector3d.XAxis.RotateBy(ang, Vector3d.ZAxis) * len; - } - /// - /// 计算指定距离和角度的点 - /// - /// 本函数仅适用于x-y平面 - /// 基点 - /// 角度,x轴正向逆时针弧度 - /// 距离 - /// 目标点 - public static Point2d Polar(this Point2d pt, double ang, double len) - { - return pt + Vector2d.XAxis.RotateBy(ang) * len; - } /// /// 重绘 /// diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/PointEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/PointEx.cs index 1f25075..5822962 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/PointEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/PointEx.cs @@ -1,5 +1,3 @@ - - namespace IFoxCAD.Cad; public static class PointEx @@ -34,9 +32,9 @@ public static string GetHashString(this Point3d pt, int xyz = 3, int decimalReta public static double GetAngle(this Point3d startPoint, Point3d endPoint, Vector3d? direction = null) { if (direction != null) - _PlaneCache = new Plane(Point3d.Origin, direction.Value); + _PlaneCache = new Plane(new Point3d(), direction.Value); if (_PlaneCache == null) - _PlaneCache = new Plane(Point3d.Origin, Vector3d.ZAxis); + _PlaneCache = new Plane(new Point3d(), Vector3d.ZAxis); return startPoint.GetVectorTo(endPoint).AngleOnPlane(_PlaneCache); } /// @@ -62,6 +60,19 @@ public static Point2d GetMidPointTo(this Point2d a, Point2d b) return new Point2d(a.X * 0.5 + b.X * 0.5, a.Y * 0.5 + b.Y * 0.5); } + + /// + /// 获取两个点之间的中点 + /// + /// 第一点 + /// 第二点 + /// 返回两个点之间的中点 + public static Point3d GetMidPointTo(this Point3d pt1, Point3d pt2) + { + return new(pt1.X * 0.5 + pt2.X * 0.5, + pt1.Y * 0.5 + pt2.Y * 0.5, + pt1.Z * 0.5 + pt2.Z * 0.5); + } /// /// Z值归零 /// @@ -72,6 +83,75 @@ internal static Point3d Z20(this Point3d point) return new Point3d(point.X, point.Y, 0); } + /// + /// 将三维点转换为二维点 + /// + /// 三维点 + /// 二维点 + public static Point2d Point2d(this Point3d pt) + { + return new(pt.X, pt.Y); + } + /// + /// 将三维点集转换为二维点集 + /// + /// 三维点集 + /// 二维点集 + public static IEnumerable Point2d(this IEnumerable pts) + { + return pts.Select(pt => pt.Point2d()); + } + /// + /// 将二维点转换为三维点 + /// + /// 二维点 + /// Z值 + /// 三维点 + public static Point3d Point3d(this Point2d pt, double z = 0) + { + return new(pt.X, pt.Y, z); + } + + + + /// + /// 根据世界坐标计算用户坐标 + /// + /// 基点世界坐标 + /// 基点用户坐标 + /// 目标世界坐标 + /// 坐标网旋转角,按x轴正向逆时针弧度 + /// 目标用户坐标 + public static Point3d TransPoint(this Point3d basePt, Point3d userPt, Point3d transPt, double ang) + { + Matrix3d transMat = Matrix3d.Displacement(userPt - basePt); + Matrix3d roMat = Matrix3d.Rotation(-ang, Vector3d.ZAxis, userPt); + return transPt.TransformBy(roMat * transMat); + } + /// + /// 计算指定距离和角度的点 + /// + /// 本函数仅适用于x-y平面 + /// 基点 + /// 角度,x轴正向逆时针弧度 + /// 距离 + /// 目标点 + public static Point3d Polar(this Point3d pt, double ang, double len) + { + return pt + Vector3d.XAxis.RotateBy(ang, Vector3d.ZAxis) * len; + } + /// + /// 计算指定距离和角度的点 + /// + /// 本函数仅适用于x-y平面 + /// 基点 + /// 角度,x轴正向逆时针弧度 + /// 距离 + /// 目标点 + public static Point2d Polar(this Point2d pt, double ang, double len) + { + return pt + Vector2d.XAxis.RotateBy(ang) * len; + } /// http://www.lee-mac.com/bulgeconversion.html /// /// 求凸度,判断三点是否一条直线上 -- Gitee From 683422548a803c8e49a5b4dac0a3b2b1cf5d52b0 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Sun, 18 Jun 2023 00:24:52 +0800 Subject: [PATCH 129/453] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20ArgumentNullEx.Thr?= =?UTF-8?q?owIfNull()=20=E5=87=BD=E6=95=B0=EF=BC=8C=E5=B9=B6=E5=B0=86=20No?= =?UTF-8?q?tNull=20=E5=87=BD=E6=95=B0=E6=A0=87=E8=AE=B0=E4=B8=BA=E8=BF=87?= =?UTF-8?q?=E6=97=B6=EF=BC=8C=E5=87=86=E5=A4=87=E5=9C=A8=20v0.8=E8=BF=9B?= =?UTF-8?q?=E8=A1=8C=E7=A7=BB=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../General/ArgumentNullEx.cs | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/Basal/IFox.Basal.Shared/General/ArgumentNullEx.cs b/src/Basal/IFox.Basal.Shared/General/ArgumentNullEx.cs index 198b237..0239889 100644 --- a/src/Basal/IFox.Basal.Shared/General/ArgumentNullEx.cs +++ b/src/Basal/IFox.Basal.Shared/General/ArgumentNullEx.cs @@ -5,12 +5,36 @@ /// public static class ArgumentNullEx { + /// + /// 检查参数是否为 null + /// + /// 参数 + /// 参数名字 + public static void ThrowIfNull([NotNull] object? argument, + [CallerArgumentExpression(nameof(argument))] string? paramName = null) + { + if (argument is null) + { + Throw(paramName); + } + } + + [DoesNotReturn] + private static void Throw(string? paramName) => throw new ArgumentNullException(paramName); + + + + + + + /// /// 检查参数是否为 null /// /// 参数 /// 参数为null时的提示信息 /// + [Obsolete("请使用 ArgumentNullEx.ThrowIfNull(value);")] public static void NotNull([NotNull] this object? value, [CallerArgumentExpression(nameof(value))] string valueExpression = "") { _ = value ?? throw new ArgumentNullException(nameof(value), valueExpression); -- Gitee From 4972c4032e0803c67cd2bd827974709ca07f0947 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Sun, 18 Jun 2023 16:43:07 +0800 Subject: [PATCH 130/453] =?UTF-8?q?=E5=8F=91=E5=B8=830.7=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Basal/Directory.Build.props | 6 +++--- src/CAD/Directory.Build.props | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Basal/Directory.Build.props b/src/Basal/Directory.Build.props index 375e114..ea5f887 100644 --- a/src/Basal/Directory.Build.props +++ b/src/Basal/Directory.Build.props @@ -1,8 +1,8 @@  - 0.7.0-alpha1 - 发布0.7.0-alpha1版 + 0.7.0 + 发布0.7.0 @@ -20,7 +20,7 @@ InspireFunction - xsfhlzh;vicwjb;liuqihong + xsfhlzh;vicwjb;liuqihong;DYH InspireFunction 基于.NET的二次开发基本类库. MIT diff --git a/src/CAD/Directory.Build.props b/src/CAD/Directory.Build.props index 795781f..6eedb0f 100644 --- a/src/CAD/Directory.Build.props +++ b/src/CAD/Directory.Build.props @@ -1,8 +1,8 @@  - 0.7.0-alpha1 - 发布0.7.0-alpha1版 + 0.7.0 + 发布0.7.0 @@ -19,7 +19,7 @@ InspireFunction - xsfhlzh;vicwjb;liuqihong + xsfhlzh;vicwjb;liuqihong;DYH InspireFunction 基于.NET的二次开发基本类库. MIT -- Gitee From 34dd4c755edb5de2c9675f28b0bc08663dd1de41 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Mon, 19 Jun 2023 15:04:51 +0800 Subject: [PATCH 131/453] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=EF=BC=9A=E8=8E=B7?= =?UTF-8?q?=E5=8F=96=E9=9D=9E=E7=AD=89=E6=AF=94=E8=BD=AC=E6=8D=A2=E7=9A=84?= =?UTF-8?q?=E6=9B=B2=E7=BA=BF=E6=96=B9=E6=B3=95=EF=BC=88=E6=97=8B=E8=BD=AC?= =?UTF-8?q?=E6=8A=95=E5=BD=B1=E6=B3=95=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/CurveEx.cs | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/CurveEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/CurveEx.cs index 7b121f2..25c3e70 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/CurveEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/CurveEx.cs @@ -274,6 +274,46 @@ public static List BreakCurveOnZPlane(this List curves) return newCurves; } + + /// + /// 获取非等比转换的曲线(旋转投影法) + /// + /// 转换前的曲线 + /// 基点 + /// x方向比例 + /// y方向比例 + /// 转换后的曲线 + public static Curve GetScaleCurve(this Curve cur, Point3d pt, double x, double y) + { + // 先做个z平面 + using var zplane = new Plane(pt, Vector3d.ZAxis); + // 克隆一个,防止修改到原来的 + using var cur2 = cur.CloneEx(); + + // 因为旋转投影后只能比原来小,所以遇到先放大 + while (Math.Abs(x) > 1 || Math.Abs(y) > 1) + { + cur2.TransformBy(Matrix3d.Scaling(2, pt)); + x /= 2; + y /= 2; + } + // 旋转投影 + var xA = Math.Acos(x); + cur2.TransformBy(Matrix3d.Rotation(xA, Vector3d.YAxis, pt)); + + using var cur3 = cur2.GetOrthoProjectedCurve(zplane); + + // 再次旋转投影 + var yA = Math.Acos(y); + cur3.TransformBy(Matrix3d.Rotation(yA, Vector3d.XAxis, pt)); + var cur4 = cur3.GetOrthoProjectedCurve(zplane); + + //设置属性 + cur4.SetPropertiesFrom(cur); + return cur4; + } + + // 转换DBCurve为GeCurved #region Curve -- Gitee From 4b47d9395f08b836769687947beed1d51fd3d84b Mon Sep 17 00:00:00 2001 From: vicwjb <403009819@qq.com> Date: Wed, 21 Jun 2023 15:24:01 +0800 Subject: [PATCH 132/453] =?UTF-8?q?=E5=8F=96=E6=B6=88nullable=E5=8C=85?= =?UTF-8?q?=E7=9A=84=E5=BC=95=E7=94=A8=EF=BC=8C=E5=9C=A8basal=E9=87=8C?= =?UTF-8?q?=E7=9B=B4=E6=8E=A5=E6=8F=90=E4=BE=9B=E7=9B=B8=E5=85=B3=E7=9A=84?= =?UTF-8?q?=E7=89=B9=E6=80=A7=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../IFox.Basal.Shared.projitems | 4 +- .../{General => Nullable}/ArgumentNullEx.cs | 27 --- .../CallerArgumentExpressionAttribute.cs | 22 ++ .../Nullable/NullableAttributes.cs | 196 ++++++++++++++++++ src/Basal/IFox.Basal/IFox.Basal.csproj | 4 - src/CAD/IFox.CAD.ACAD/IFox.CAD.ACAD.csproj | 9 - src/CAD/IFox.CAD.GCAD/IFox.CAD.GCAD.csproj | 7 - src/CAD/IFox.CAD.ZCAD/IFox.CAD.ZCAD.csproj | 7 - 8 files changed, 221 insertions(+), 55 deletions(-) rename src/Basal/IFox.Basal.Shared/{General => Nullable}/ArgumentNullEx.cs (62%) create mode 100644 src/Basal/IFox.Basal.Shared/Nullable/CallerArgumentExpressionAttribute.cs create mode 100644 src/Basal/IFox.Basal.Shared/Nullable/NullableAttributes.cs diff --git a/src/Basal/IFox.Basal.Shared/IFox.Basal.Shared.projitems b/src/Basal/IFox.Basal.Shared/IFox.Basal.Shared.projitems index ace7153..9328526 100644 --- a/src/Basal/IFox.Basal.Shared/IFox.Basal.Shared.projitems +++ b/src/Basal/IFox.Basal.Shared/IFox.Basal.Shared.projitems @@ -16,7 +16,6 @@ - @@ -29,6 +28,9 @@ + + + diff --git a/src/Basal/IFox.Basal.Shared/General/ArgumentNullEx.cs b/src/Basal/IFox.Basal.Shared/Nullable/ArgumentNullEx.cs similarity index 62% rename from src/Basal/IFox.Basal.Shared/General/ArgumentNullEx.cs rename to src/Basal/IFox.Basal.Shared/Nullable/ArgumentNullEx.cs index 0239889..2a9fe39 100644 --- a/src/Basal/IFox.Basal.Shared/General/ArgumentNullEx.cs +++ b/src/Basal/IFox.Basal.Shared/Nullable/ArgumentNullEx.cs @@ -24,10 +24,6 @@ public static void ThrowIfNull([NotNull] object? argument, - - - - /// /// 检查参数是否为 null /// @@ -40,27 +36,4 @@ public static void NotNull([NotNull] this object? value, [CallerArgumentExpressi _ = value ?? throw new ArgumentNullException(nameof(value), valueExpression); } } -} - -namespace System.Runtime.CompilerServices -{ - /// - /// 指示参数将为另一个参数传递的表达式捕获为字符串。 - /// - [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] - public sealed class CallerArgumentExpressionAttribute : Attribute - { - /// - /// 初始化 CallerArgumentExpressionAttribute 类的新实例。 - /// - /// - public CallerArgumentExpressionAttribute(string parameterName) - { - ParameterName = parameterName; - } - /// - /// 获取其表达式应捕获为字符串的参数的名称。 - /// - public string ParameterName { get; } - } } \ No newline at end of file diff --git a/src/Basal/IFox.Basal.Shared/Nullable/CallerArgumentExpressionAttribute.cs b/src/Basal/IFox.Basal.Shared/Nullable/CallerArgumentExpressionAttribute.cs new file mode 100644 index 0000000..aceee41 --- /dev/null +++ b/src/Basal/IFox.Basal.Shared/Nullable/CallerArgumentExpressionAttribute.cs @@ -0,0 +1,22 @@ +namespace System.Runtime.CompilerServices +{ + /// + /// 指示参数将为另一个参数传递的表达式捕获为字符串。 + /// + [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] + internal sealed class CallerArgumentExpressionAttribute : Attribute + { + /// + /// 初始化 CallerArgumentExpressionAttribute 类的新实例。 + /// + /// + public CallerArgumentExpressionAttribute(string parameterName) + { + ParameterName = parameterName; + } + /// + /// 获取其表达式应捕获为字符串的参数的名称。 + /// + public string ParameterName { get; } + } +} \ No newline at end of file diff --git a/src/Basal/IFox.Basal.Shared/Nullable/NullableAttributes.cs b/src/Basal/IFox.Basal.Shared/Nullable/NullableAttributes.cs new file mode 100644 index 0000000..361f88f --- /dev/null +++ b/src/Basal/IFox.Basal.Shared/Nullable/NullableAttributes.cs @@ -0,0 +1,196 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Diagnostics.CodeAnalysis +{ +#if !NETSTANDARD2_1 + /// Specifies that null is allowed as an input even if the corresponding type disallows it. + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)] +#if SYSTEM_PRIVATE_CORELIB + public +#else + internal +#endif + sealed class AllowNullAttribute : Attribute { } + + /// Specifies that null is disallowed as an input even if the corresponding type allows it. + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)] +#if SYSTEM_PRIVATE_CORELIB + public +#else + internal +#endif + sealed class DisallowNullAttribute : Attribute { } + + /// Specifies that an output may be null even if the corresponding type disallows it. + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)] +#if SYSTEM_PRIVATE_CORELIB + public +#else + internal +#endif + sealed class MaybeNullAttribute : Attribute { } + + /// Specifies that an output will not be null even if the corresponding type allows it. Specifies that an input argument was not null when the call returns. + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)] +#if SYSTEM_PRIVATE_CORELIB + public +#else + internal +#endif + sealed class NotNullAttribute : Attribute { } + + /// Specifies that when a method returns , the parameter may be null even if the corresponding type disallows it. + [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] +#if SYSTEM_PRIVATE_CORELIB + public +#else + internal +#endif + sealed class MaybeNullWhenAttribute : Attribute + { + /// Initializes the attribute with the specified return value condition. + /// + /// The return value condition. If the method returns this value, the associated parameter may be null. + /// + public MaybeNullWhenAttribute(bool returnValue) => ReturnValue = returnValue; + + /// Gets the return value condition. + public bool ReturnValue { get; } + } + + /// Specifies that when a method returns , the parameter will not be null even if the corresponding type allows it. + [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] +#if SYSTEM_PRIVATE_CORELIB + public +#else + internal +#endif + sealed class NotNullWhenAttribute : Attribute + { + /// Initializes the attribute with the specified return value condition. + /// + /// The return value condition. If the method returns this value, the associated parameter will not be null. + /// + public NotNullWhenAttribute(bool returnValue) => ReturnValue = returnValue; + + /// Gets the return value condition. + public bool ReturnValue { get; } + } + + /// Specifies that the output will be non-null if the named parameter is non-null. + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, AllowMultiple = true, Inherited = false)] +#if SYSTEM_PRIVATE_CORELIB + public +#else + internal +#endif + sealed class NotNullIfNotNullAttribute : Attribute + { + /// Initializes the attribute with the associated parameter name. + /// + /// The associated parameter name. The output will be non-null if the argument to the parameter specified is non-null. + /// + public NotNullIfNotNullAttribute(string parameterName) => ParameterName = parameterName; + + /// Gets the associated parameter name. + public string ParameterName { get; } + } + + /// Applied to a method that will never return under any circumstance. + [AttributeUsage(AttributeTargets.Method, Inherited = false)] +#if SYSTEM_PRIVATE_CORELIB + public +#else + internal +#endif + sealed class DoesNotReturnAttribute : Attribute { } + + /// Specifies that the method will not return if the associated Boolean parameter is passed the specified value. + [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] +#if SYSTEM_PRIVATE_CORELIB + public +#else + internal +#endif + sealed class DoesNotReturnIfAttribute : Attribute + { + /// Initializes the attribute with the specified parameter value. + /// + /// The condition parameter value. Code after the method will be considered unreachable by diagnostics if the argument to + /// the associated parameter matches this value. + /// + public DoesNotReturnIfAttribute(bool parameterValue) => ParameterValue = parameterValue; + + /// Gets the condition parameter value. + public bool ParameterValue { get; } + } +#endif + + /// Specifies that the method or property will ensure that the listed field and property members have not-null values. + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] +#if SYSTEM_PRIVATE_CORELIB + public +#else + internal +#endif + sealed class MemberNotNullAttribute : Attribute + { + /// Initializes the attribute with a field or property member. + /// + /// The field or property member that is promised to be not-null. + /// + public MemberNotNullAttribute(string member) => Members = new[] { member }; + + /// Initializes the attribute with the list of field and property members. + /// + /// The list of field and property members that are promised to be not-null. + /// + public MemberNotNullAttribute(params string[] members) => Members = members; + + /// Gets field or property member names. + public string[] Members { get; } + } + + /// Specifies that the method or property will ensure that the listed field and property members have not-null values when returning with the specified return value condition. + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] +#if SYSTEM_PRIVATE_CORELIB + public +#else + internal +#endif + sealed class MemberNotNullWhenAttribute : Attribute + { + /// Initializes the attribute with the specified return value condition and a field or property member. + /// + /// The return value condition. If the method returns this value, the associated parameter will not be null. + /// + /// + /// The field or property member that is promised to be not-null. + /// + public MemberNotNullWhenAttribute(bool returnValue, string member) + { + ReturnValue = returnValue; + Members = new[] { member }; + } + + /// Initializes the attribute with the specified return value condition and list of field and property members. + /// + /// The return value condition. If the method returns this value, the associated parameter will not be null. + /// + /// + /// The list of field and property members that are promised to be not-null. + /// + public MemberNotNullWhenAttribute(bool returnValue, params string[] members) + { + ReturnValue = returnValue; + Members = members; + } + + /// Gets the return value condition. + public bool ReturnValue { get; } + + /// Gets field or property member names. + public string[] Members { get; } + } +} diff --git a/src/Basal/IFox.Basal/IFox.Basal.csproj b/src/Basal/IFox.Basal/IFox.Basal.csproj index 75a4841..062524c 100644 --- a/src/Basal/IFox.Basal/IFox.Basal.csproj +++ b/src/Basal/IFox.Basal/IFox.Basal.csproj @@ -11,10 +11,6 @@ - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - 4.7.0 diff --git a/src/CAD/IFox.CAD.ACAD/IFox.CAD.ACAD.csproj b/src/CAD/IFox.CAD.ACAD/IFox.CAD.ACAD.csproj index 2fa77f1..46b3b52 100644 --- a/src/CAD/IFox.CAD.ACAD/IFox.CAD.ACAD.csproj +++ b/src/CAD/IFox.CAD.ACAD/IFox.CAD.ACAD.csproj @@ -17,7 +17,6 @@ - @@ -26,13 +25,6 @@ - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - @@ -41,7 +33,6 @@ - diff --git a/src/CAD/IFox.CAD.GCAD/IFox.CAD.GCAD.csproj b/src/CAD/IFox.CAD.GCAD/IFox.CAD.GCAD.csproj index 71473f7..d478104 100644 --- a/src/CAD/IFox.CAD.GCAD/IFox.CAD.GCAD.csproj +++ b/src/CAD/IFox.CAD.GCAD/IFox.CAD.GCAD.csproj @@ -28,13 +28,6 @@ - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - diff --git a/src/CAD/IFox.CAD.ZCAD/IFox.CAD.ZCAD.csproj b/src/CAD/IFox.CAD.ZCAD/IFox.CAD.ZCAD.csproj index da8e0b4..b4a31e6 100644 --- a/src/CAD/IFox.CAD.ZCAD/IFox.CAD.ZCAD.csproj +++ b/src/CAD/IFox.CAD.ZCAD/IFox.CAD.ZCAD.csproj @@ -27,13 +27,6 @@ - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - -- Gitee From ef4bb6567f87c905661b147cbde1f2f9bf130170 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sat, 24 Jun 2023 15:40:56 +0800 Subject: [PATCH 133/453] =?UTF-8?q?=E4=BF=AE=E6=94=B9null=E8=AD=A6?= =?UTF-8?q?=E5=91=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Basal/IFox.Basal.Shared/WindowsAPI/WindowsAPI.cs | 2 +- src/CAD/IFox.CAD.Shared/Algorithms/Graph/Graph.cs | 7 +++---- src/CAD/IFox.CAD.Shared/Algorithms/QuadTree/Rect.cs | 6 +++--- src/CAD/IFox.CAD.Shared/AutoReg/MethodInfoHelper.cs | 2 +- src/CAD/IFox.CAD.Shared/CadVersion/AcadVersion.cs | 2 +- src/CAD/IFox.CAD.Shared/Copyclip/BitmapTool.cs | 2 +- src/CAD/IFox.CAD.Shared/Copyclip/EmfTool.cs | 4 ++-- src/CAD/IFox.CAD.Shared/Copyclip/TagClipboardInfo.cs | 2 +- src/CAD/IFox.CAD.Shared/ExtensionMethod/CurveEx.cs | 12 ++++++------ .../ExtensionMethod/Entity/BlockReferenceEx.cs | 6 +++--- src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigEx.cs | 5 +---- src/CAD/IFox.CAD.Shared/ExtensionMethod/PointEx.cs | 4 ++-- .../ExtensionMethod/SelectionSetEx.cs | 4 ++-- .../ExtensionMethod/SymbolTableRecordEx.cs | 2 +- src/CAD/IFox.CAD.Shared/ExtensionMethod/XrefEx.cs | 6 +++--- .../HatchConverter.cs" | 6 +++--- .../HatchInfo.cs" | 2 +- src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs | 6 +++--- src/CAD/IFox.CAD.Shared/Runtime/Env.cs | 6 +++--- src/CAD/IFox.CAD.Shared/Runtime/SymbolTable.cs | 4 ++-- 20 files changed, 43 insertions(+), 47 deletions(-) diff --git a/src/Basal/IFox.Basal.Shared/WindowsAPI/WindowsAPI.cs b/src/Basal/IFox.Basal.Shared/WindowsAPI/WindowsAPI.cs index 6f8ac91..489f588 100644 --- a/src/Basal/IFox.Basal.Shared/WindowsAPI/WindowsAPI.cs +++ b/src/Basal/IFox.Basal.Shared/WindowsAPI/WindowsAPI.cs @@ -82,7 +82,7 @@ public static bool GlobalLockTask(IntPtr data, Action task) { //if (task == null) // throw new ArgumentNullException(nameof(task)); - task.NotNull(nameof(task)); + ArgumentNullEx.ThrowIfNull(task); if (data == IntPtr.Zero) return false; diff --git a/src/CAD/IFox.CAD.Shared/Algorithms/Graph/Graph.cs b/src/CAD/IFox.CAD.Shared/Algorithms/Graph/Graph.cs index ee6e059..75bdc5b 100644 --- a/src/CAD/IFox.CAD.Shared/Algorithms/Graph/Graph.cs +++ b/src/CAD/IFox.CAD.Shared/Algorithms/Graph/Graph.cs @@ -92,9 +92,8 @@ public void AddEdge(Curve3d curve) { //if (curve == null) // throw new ArgumentNullException(nameof(curve)); - - curve.NotNull(nameof(curve)); - + + ArgumentNullEx.ThrowIfNull(curve); var start = AddVertex(curve.StartPoint); var end = AddVertex(curve.EndPoint); @@ -156,7 +155,7 @@ public void RemoveEdge(Curve3d curve) { //if (curve == null) // throw new ArgumentNullException(nameof(curve)); - curve.NotNull(nameof(curve)); + ArgumentNullEx.ThrowIfNull(curve); RemoveVertex(curve.StartPoint); RemoveVertex(curve.EndPoint); diff --git a/src/CAD/IFox.CAD.Shared/Algorithms/QuadTree/Rect.cs b/src/CAD/IFox.CAD.Shared/Algorithms/QuadTree/Rect.cs index a4c219d..170ebdd 100644 --- a/src/CAD/IFox.CAD.Shared/Algorithms/QuadTree/Rect.cs +++ b/src/CAD/IFox.CAD.Shared/Algorithms/QuadTree/Rect.cs @@ -317,7 +317,7 @@ public static bool IsRectAngle(List? ptList, double tolerance = 1e-8) //if (ptList == null) // throw new ArgumentNullException(nameof(ptList)); - ptList.NotNull(nameof(ptList)); + ArgumentNullEx.ThrowIfNull(ptList); var pts = ptList.ToList(); /* * 消重,不这里设置,否则这不是一个正确的单元测试 @@ -372,7 +372,7 @@ public static bool IsRect(List? ptList, double tolerance = 1e-10) { //if (ptList == null) // throw new ArgumentNullException(nameof(ptList)); - ptList.NotNull(nameof(ptList)); + ArgumentNullEx.ThrowIfNull(ptList); var pts = ptList.ToList(); if (ptList.Count == 5) { @@ -422,7 +422,7 @@ public static bool RectAnglePointOrder(List? pts) { //if (pts == null) // throw new ArgumentNullException(nameof(pts)); - pts.NotNull(nameof(pts)); + ArgumentNullEx.ThrowIfNull(pts); if (!Rect.IsRectAngle(pts)) return false; diff --git a/src/CAD/IFox.CAD.Shared/AutoReg/MethodInfoHelper.cs b/src/CAD/IFox.CAD.Shared/AutoReg/MethodInfoHelper.cs index 5eb5f93..31be527 100644 --- a/src/CAD/IFox.CAD.Shared/AutoReg/MethodInfoHelper.cs +++ b/src/CAD/IFox.CAD.Shared/AutoReg/MethodInfoHelper.cs @@ -15,7 +15,7 @@ internal static class MethodInfoHelper /// 已经外部创建的对象,为空则此处创建 public static object? Invoke(this MethodInfo methodInfo, ref object? instance) { - methodInfo.NotNull(nameof(methodInfo)); + ArgumentNullEx.ThrowIfNull(methodInfo); object? result = null; if (methodInfo.IsStatic) { diff --git a/src/CAD/IFox.CAD.Shared/CadVersion/AcadVersion.cs b/src/CAD/IFox.CAD.Shared/CadVersion/AcadVersion.cs index 6fe6afd..92813b3 100644 --- a/src/CAD/IFox.CAD.Shared/CadVersion/AcadVersion.cs +++ b/src/CAD/IFox.CAD.Shared/CadVersion/AcadVersion.cs @@ -50,7 +50,7 @@ public static List Versions /// cad版本号对象 public static CadVersion? FromApp(object app) { - app.NotNull(nameof(app)); + ArgumentNullEx.ThrowIfNull(app); string acver = app.GetType() .InvokeMember( diff --git a/src/CAD/IFox.CAD.Shared/Copyclip/BitmapTool.cs b/src/CAD/IFox.CAD.Shared/Copyclip/BitmapTool.cs index 444acae..e16ad87 100644 --- a/src/CAD/IFox.CAD.Shared/Copyclip/BitmapTool.cs +++ b/src/CAD/IFox.CAD.Shared/Copyclip/BitmapTool.cs @@ -139,7 +139,7 @@ public static void CaptureWndImage(IntPtr hWnd, Action action) { //if (action == null) // throw new ArgumentNullException(nameof(action)); - action.NotNull(nameof(action)); + ArgumentNullEx.ThrowIfNull(action); var hDC = GetDC(hWnd); var hMemDC = CreateCompatibleDC(hDC); if (hMemDC == IntPtr.Zero) diff --git a/src/CAD/IFox.CAD.Shared/Copyclip/EmfTool.cs b/src/CAD/IFox.CAD.Shared/Copyclip/EmfTool.cs index da8ca7d..b49f08f 100644 --- a/src/CAD/IFox.CAD.Shared/Copyclip/EmfTool.cs +++ b/src/CAD/IFox.CAD.Shared/Copyclip/EmfTool.cs @@ -547,7 +547,7 @@ public static void SetEnhMetaFileDescriptionEx(ref IntPtr hMetaFile, string desc { //if (hMetaFile == IntPtr.Zero) // throw new ArgumentNullException(nameof(hMetaFile)); - hMetaFile.NotNull(nameof(hMetaFile)); + ArgumentNullEx.ThrowIfNull(hMetaFile); var emh = EnhMetaHeader.Create(hMetaFile);//emf结构 GetEnhMetaFileHeader // 创建画布句柄 IntRect intRect = emh.rclFrame; //new(0, 0, 0, 0); @@ -820,7 +820,7 @@ public static void ToMetafile(byte[] data, Func task) { //if (task == null) // throw new ArgumentNullException(nameof(task)); - task.NotNull(nameof(task)); + ArgumentNullEx.ThrowIfNull(task); IntPtr hemf = SetEnhMetaFileBits((uint)data.Length, data); using var mf = new Metafile(hemf, true); if (task.Invoke(mf)) // 对图像进行操作,就不能进行删除句柄 diff --git a/src/CAD/IFox.CAD.Shared/Copyclip/TagClipboardInfo.cs b/src/CAD/IFox.CAD.Shared/Copyclip/TagClipboardInfo.cs index 2fbdbe3..024bb36 100644 --- a/src/CAD/IFox.CAD.Shared/Copyclip/TagClipboardInfo.cs +++ b/src/CAD/IFox.CAD.Shared/Copyclip/TagClipboardInfo.cs @@ -313,7 +313,7 @@ public static bool OpenClipboardTask(bool isWrite, Action action) { //if (action == null) // throw new ArgumentNullException(nameof(action)); - action.NotNull(nameof(action)); + ArgumentNullEx.ThrowIfNull(action); bool openFlag = false; try { diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/CurveEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/CurveEx.cs index 25c3e70..4effd50 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/CurveEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/CurveEx.cs @@ -27,7 +27,7 @@ public static IEnumerable GetSplitCurves(this Curve curve, IEnumerable GetSplitCurves(this Curve curve, IEnumerable x); @@ -70,7 +70,7 @@ public static IEnumerable GetSplitCurves(this Curve curve, IEnumerable(); } @@ -91,7 +91,7 @@ public static IEnumerable GetSplitCurves(this Curve curve, IEnumerable { var pt = curve.GetClosestPointTo(point, false); @@ -109,7 +109,7 @@ public static IEnumerable GetSplitCurves(this Curve curve, IEnumerable所有的闭合环的曲线集合 public static IEnumerable GetAllCycle(this IEnumerable curves) { - curves.NotNull(nameof(curves)); + ArgumentNullEx.ThrowIfNull(curves); // 新建图 var graph = new Graph(); @@ -143,7 +143,7 @@ public static IEnumerable GetAllCycle(this IEnumerable curves) /// 打断后的曲线列表 public static List BreakCurve(this List curves) { - curves.NotNull(nameof(curves)); + ArgumentNullEx.ThrowIfNull(curves); var geCurves = new List(); // 存储曲线转换后的复合曲线 var paramss = new List>(); // 存储每个曲线的交点参数值 diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs index 4bfd039..ce29afe 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs @@ -163,7 +163,7 @@ public static IEnumerable GetAttributes(this BlockReference [System.Diagnostics.DebuggerStepThrough] public static void ForEach(this BlockReference brf, Action action) { - action.NotNull(nameof(action)); + ArgumentNullEx.ThrowIfNull(action); var tr = DBTrans.GetTopTransaction(brf.Database); if (tr.GetObject(brf.BlockTableRecord) is BlockTableRecord btr) { @@ -179,7 +179,7 @@ public static void ForEach(this BlockReference brf, Action action) [System.Diagnostics.DebuggerStepThrough] public static void ForEach(this BlockReference brf, Action action) { - action.NotNull(nameof(action)); + ArgumentNullEx.ThrowIfNull(action); var tr = DBTrans.GetTopTransaction(brf.Database); if (tr.GetObject(brf.BlockTableRecord) is BlockTableRecord btr) { @@ -195,7 +195,7 @@ public static void ForEach(this BlockReference brf, Action [System.Diagnostics.DebuggerStepThrough] public static void ForEach(this BlockReference brf, Action action) { - action.NotNull(nameof(action)); + ArgumentNullEx.ThrowIfNull(action); var tr = DBTrans.GetTopTransaction(brf.Database); if (tr.GetObject(brf.BlockTableRecord) is BlockTableRecord btr) { diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigEx.cs index 000673f..99fc5f2 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigEx.cs @@ -319,10 +319,7 @@ static JigPromptPointOptions JigPointOptions() public void SetSpaceIsKeyword() { var opt = _options; - //if (opt == null) - // throw new ArgumentNullException(nameof(_options)); - opt.NotNull(nameof(_options)); - + ArgumentNullEx.ThrowIfNull(opt); if ((opt.UserInputControls & UserInputControls.NullResponseAccepted) == UserInputControls.NullResponseAccepted) opt.UserInputControls ^= UserInputControls.NullResponseAccepted; // 输入了鼠标右键,结束jig if ((opt.UserInputControls & UserInputControls.AnyBlankTerminatesInput) == UserInputControls.AnyBlankTerminatesInput) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/PointEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/PointEx.cs index 5822962..307e234 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/PointEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/PointEx.cs @@ -189,7 +189,7 @@ public static double GetArcBulge(this Point2d arc1, Point2d arc2, Point2d arc3, [System.Diagnostics.DebuggerStepThrough] public static void End2End(this Point2dCollection ptcol) { - ptcol.NotNull(nameof(ptcol)); + ArgumentNullEx.ThrowIfNull(ptcol); if (ptcol.Count == 0 || ptcol[0].Equals(ptcol[^1]))// 首尾相同直接返回 return; @@ -209,7 +209,7 @@ public static void End2End(this Point2dCollection ptcol) [System.Diagnostics.DebuggerStepThrough] public static void End2End(this Point3dCollection ptcol) { - ptcol.NotNull(nameof(ptcol)); + ArgumentNullEx.ThrowIfNull(ptcol); if (ptcol.Count == 0 || ptcol[0].Equals(ptcol[^1]))// 首尾相同直接返回 return; diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SelectionSetEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SelectionSetEx.cs index 31733f0..d247364 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SelectionSetEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SelectionSetEx.cs @@ -81,7 +81,7 @@ public static IEnumerable GetEntities(this SelectionSet ss, { //if (ss is null) // throw new ArgumentNullException(nameof(ss)); - ss.NotNull(nameof(ss)); + ArgumentNullEx.ThrowIfNull(ss); return ss.GetObjectIds() .Select(id => id.GetObject(openMode, openErased, openLockedLayer)) .OfType(); @@ -127,7 +127,7 @@ public static void ForEach(this SelectionSet ss, bool openErased = false, bool openLockedLayer = false) where T : Entity { - action.NotNull(nameof(action)); + ArgumentNullEx.ThrowIfNull(action); LoopState state = new(); var ents = ss.GetEntities(openMode, openErased, openLockedLayer); diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs index b93b88a..cdd0fe2 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs @@ -300,7 +300,7 @@ public static void ForEach(this TRecord record, Action(brf.BlockTableRecord);// 块表记录 @@ -485,8 +485,8 @@ public XrefPath(BlockReference brf, DBTrans tr) //if (fileRelations == null) // throw new ArgumentNullException(nameof(fileRelations)); - directory.NotNull(nameof(directory)); - fileRelations.NotNull(nameof(fileRelations)); + ArgumentNullEx.ThrowIfNull(directory); + ArgumentNullEx.ThrowIfNull(fileRelations); string? result = null; switch (converterModes) diff --git "a/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchConverter.cs" "b/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchConverter.cs" index 688bf78..245255a 100644 --- "a/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchConverter.cs" +++ "b/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchConverter.cs" @@ -163,8 +163,8 @@ static void HatchLoopIsPolyline(HatchLoop loop, HatchConverterData hcData) //if (hcData is null) // throw new ArgumentNullException(nameof(hcData)); - loop.NotNull(nameof(loop)); - hcData.NotNull(nameof(hcData)); + ArgumentNullEx.ThrowIfNull(loop); + ArgumentNullEx.ThrowIfNull(hcData); // 判断为圆形: @@ -194,7 +194,7 @@ static void HatchLoopIsPolyline(HatchLoop loop, HatchConverterData hcData) //if (loop is null) // throw new ArgumentNullException(nameof(loop)); - loop.NotNull(nameof(loop)); + ArgumentNullEx.ThrowIfNull(loop); if (loop.Curves.Count != 2) throw new ArgumentException( diff --git "a/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchInfo.cs" "b/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchInfo.cs" index a57beb8..bf1fa8d 100644 --- "a/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchInfo.cs" +++ "b/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchInfo.cs" @@ -296,7 +296,7 @@ public HatchInfo AppendLoop(Point2dCollection pts, { //if (pts == null) // throw new ArgumentNullException(nameof(pts)); - pts.NotNull(nameof(pts)); + ArgumentNullEx.ThrowIfNull(pts); pts.End2End(); // 2011新增API,可以不生成图元的情况下加入边界, // 通过这里进入的话,边界 _boundaryIds 是空的,那么 Build() 时候就需要过滤空的 diff --git a/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs b/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs index 0d6c982..f2410bd 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs @@ -38,9 +38,9 @@ public static Transaction GetTopTransaction(Database database) /// public static DBTrans GetTop(Database database) { - database.NotNull(nameof(database)); + ArgumentNullEx.ThrowIfNull(database); var trans = database.TransactionManager.TopTransaction; - trans.NotNull(nameof(trans)); + ArgumentNullEx.ThrowIfNull(trans); foreach (var item in _dBTrans) { @@ -477,7 +477,7 @@ public void Task(Action action, bool handlingDBTextDeviation = true) { //if (action == null) // throw new ArgumentNullException(nameof(action)); - action.NotNull(nameof(action)); + ArgumentNullEx.ThrowIfNull(action); // 前台开图 || 后台直接处理 if (Document != null || !handlingDBTextDeviation) { diff --git a/src/CAD/IFox.CAD.Shared/Runtime/Env.cs b/src/CAD/IFox.CAD.Shared/Runtime/Env.cs index f294941..5e5888e 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/Env.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/Env.cs @@ -709,8 +709,8 @@ public static string GetAcapVersionDll(string str = "acdb") // throw new ArgumentNullException(nameof(key)); //if (value == null) // throw new ArgumentNullException(nameof(value)); - key.NotNull(nameof(key)); - value.NotNull(nameof(value)); + ArgumentNullEx.ThrowIfNull(key); + ArgumentNullEx.ThrowIfNull(value); var currentVar = Env.GetVar(key); @@ -742,7 +742,7 @@ public static Dictionary SaveCadVar(Dictionary a { //if (args is null) // throw new ArgumentNullException(nameof(args)); - args.NotNull(nameof(args)); + ArgumentNullEx.ThrowIfNull(args); var dict = new Dictionary(); foreach (var item in args) { diff --git a/src/CAD/IFox.CAD.Shared/Runtime/SymbolTable.cs b/src/CAD/IFox.CAD.Shared/Runtime/SymbolTable.cs index 1e5a121..62b500b 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/SymbolTable.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/SymbolTable.cs @@ -280,7 +280,7 @@ public ObjectId GetRecordFrom(SymbolTable table, string name, b { //if (table is null) // throw new ArgumentNullException(nameof(table), "对象为null"); - table.NotNull(nameof(table)); + ArgumentNullEx.ThrowIfNull(table); ObjectId rid = this[name]; bool has = rid != ObjectId.Null; @@ -375,7 +375,7 @@ public void ForEach(Action task, { //if (task == null) // throw new ArgumentNullException(nameof(task)); - task.NotNull(nameof(task)); + ArgumentNullEx.ThrowIfNull(task); LoopState state = new();/*这种方式比Action改Func更友好*/ int i = 0; foreach (var id in this) -- Gitee From 5c548fcdf1ee47bef71f927168e8a81e4562b778 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Mon, 26 Jun 2023 16:07:49 +0800 Subject: [PATCH 134/453] =?UTF-8?q?=E6=9B=B4=E6=96=B0readme=E6=96=87?= =?UTF-8?q?=E4=BB=B6=EF=BC=8C=E5=B0=86=E5=B8=AE=E5=8A=A9=E6=96=87=E6=A1=A3?= =?UTF-8?q?=E7=9A=84=E5=86=85=E5=AE=B9=E5=AF=BC=E8=88=AA=E8=87=B3=E9=87=91?= =?UTF-8?q?=E5=B1=B1=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 166 ++++++------------------------------------------------ 1 file changed, 16 insertions(+), 150 deletions(-) diff --git a/README.md b/README.md index c29b07b..7438f0b 100644 --- a/README.md +++ b/README.md @@ -12,165 +12,31 @@ 可以加群交流: -![ifoxcad用户交流群群二维码](./docs/png/ifoxcad用户交流群群二维码.png) +![IFoxCad用户交流群群二维码](./docs/png/ifoxcad用户交流群群二维码.png) -#### 二、 快速入门 +#### 二、 使用帮助 -- 打开vs,新建一个standard类型的类库项目,**注意,需要选择类型的时候一定要选standard2.0** +IFoxCAD的项目文档请看 **[IFoxCAD类库从入门到精通](https://www.kdocs.cn/l/cc6ZXSa0vMgD)**。 -- 双击项目,打开项目文件: - - - 修改项目文件里的`netcore2.0`为`NET45`。其中的net45,可以改为NET45以上的标准TFM(如:net45、net46、net47等等)。同时可以指定多版本。具体的详细的教程见 [VS通过添加不同引用库,建立多条件编译](https://www.yuque.com/vicwjb/zqpcd0/ufbwyl)。 - - - 在 ` xxx ` 中增加 `preview`,主要是为了支持最新的语法,本项目采用了最新的语法编写。项目文件现在的内容类似如下: +#### 三、IFoxCad 项目模版 -```xml - - - net45 - preview - - -``` +目前由于IFoxCad的版本分为0.5、0.6、0.7三个大的版本同时在发布,所以项目模版分为两个主要的版本: -- 右键项目文件,选择管理nuget程序包。 +- vs模版插件 +- net项目模版 -- 在nuget程序里搜索**ifox**,记得将包括预发行版打钩。截止本文最后更新时,nuget上最新的版本为ifox.cad.source 0.5.2.1版本和ifox.Basal.source 0.5.2.3版本。点击安装就可以。 +建议使用net项目模版来创建项目,具体的区别可以去上面的文档里查看 **[4.4 IFoxCad 项目模版](https://kdocs.cn/l/cc6ZXSa0vMgD?linkname=ulYcRm6f9a)** -- 添加引用,在新建的项目里的cs文件里添加相关的引用 +#### 四、使用IFoxCad的几种方式 -```csharp -using Autodesk.AutoCAD.ApplicationServices; -using Autodesk.AutoCAD.EditorInput; -using Autodesk.AutoCAD.Runtime; -using Autodesk.AutoCAD.Geometry; -using Autodesk.AutoCAD.DatabaseServices; -using IFoxCAD.Cad; -``` +目前IFoxCad的几种使用方式: +**[4.5 使用IFoxCad的几种方式](https://kdocs.cn/l/cc6ZXSa0vMgD?linkname=mhBJO1Vchu)** -- 添加代码 +#### 五、参与项目的方式 -```csharp -[CommandMethod(nameof(Hello))] -public void Hello() -{ - using DBTrans tr = new(); - var line1 = new Line(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); - tr.CurrentSpace.AddEntity(line1); - // 如果您没有添加preview到项目文件里的话:按如下旧语法: - // using(var tr = new DBTrans()) - // { - // var line1 = new Line(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); - // tr.CurrentSpace.AddEntity(line1); - // } -} -``` +期待你的参与,你可以做如下的工作来帮助IFoxCad发展: -这段代码就是在cad的当前空间内添加了一条直线。 +- 如果你在使用的过程中发现IFoxCad的某些不足或者bug,你可以在 [项目issues](https://gitee.com/inspirefunction/ifoxcad/issues) 里提交issue来供开发人员进行完善。 +- 帮助开发人员编写使用文档,文档地址见 **[IFoxCAD类库从入门到精通](https://www.kdocs.cn/l/cc6ZXSa0vMgD)** +- fork本项目,修复bug,增加功能,并提交pr。 -- 生成,然后打开cad,netload命令将刚刚生成的dll加载。如果需要调试需要设置启动程序为cad。 - -- 运行hello命令,然后缩放一下视图,现在一条直线和一个圆已经显示在屏幕上了 - -#### 三、屏蔽IFox的元组、索引、范围功能 - -特别提醒: 考虑到早期的框架没有提供System.Range类型(net core 开始提供)、System.Index类型(net core 开始提供)、System.ValueTuple类型(net 47开始提供),本项目IFox.Basal包里包含了他们。 如果引用了包含System.Range等类型的第三方包(如IndexRange等),请在项目文件中定义NOINDEX、NORANGE、NOVALUETUPLE常量,以避免重复定义。上述代码能起作用的前提是用源码包,普通包暂时无解。 - -```xml - - $(Configuration);NOINDEX;NORANGE;NOVALUETUPLE - -``` - -**NOINDEX、NORANGE、NOVALUETUPLE 分别针对三种类型,哪种类型冲突就定义哪种。** - -#### 四、编译 IFox 源码工程 - -由于vs2022抛弃了某几个net版本,所以我们同时安装vs2019和vs2022,然后使用vs2022; -其中的原因是vs2019拥有全部net版本,而vs2022拥有最新的分析器和语法。 - -编译本项目需要你准备好git,具体的安装教程可以去网上搜索一下。当然也可以利用vs的git来完成。 - -首先在gitee上fork本项目到你的账号,然后clone到本地。 - -原生git使用命令行,打开终端/powershell/cmd,cd到你要存放的目录,然后运行下面的命令,把里面的yourname替换为你的名字,这样就在本地创建了一个ifoxcad文件夹,里面就是本项目的所有源码。 - -``` -git clone https://gitee.com/yourname/ifoxcad.git -``` - -当然也可以采用vs的图形化操作,打开vs,选择 克隆存储库-->填入仓库地址和存放路径-->点击克隆。新手小白推荐用此办法。 - -打开ifoxcad文件夹,双击解决方案文件,打开vs,等待项目打开,加载nuget包,然后生成就可以了。 - -**切记,不要用低版本的vs打开本项目,因为本项目采用了某些新的语法,所以老版本的vs是不兼容的。** - -#### 五、IFoxCad 项目模版 - -可以在vs扩展菜单-管理扩展中搜索ifoxcad,即可安装项目模板。使用项目模版可以方便的创建支持多目标多版本的使用ifoxcad类库的项目和类。如果无法在vs的市场里下载,就去上面的QQ群里下载。 - -项目模版里的自动加载选择了简单api,ifox还提供了一套功能更强大的api,具体的可以参考[自动加载和初始化](/docs/autoreg.md)。 - -#### 六、使用IFoxCad的几种方式 - -目前ifox提供了三种使用方式,**建议一般的用户使用第二种源码包的形式。有志于本项目发展并想提交点代码的可以选择第三种。** - -- 第一种是直接使用普通的nuget包。 - - 此种方式使用便捷,只要在项目中引用了IFox.CAD.ACAD的包,就可以直接使用了。缺点一是无法控制ifox提供的元组功能的屏蔽,导致和其他的三方包的冲突;二是生成目录里带有ifox的dll。 - -- 第二种是使用源码包。 - - 此种方式使用便捷,只要在项目中引用了IFox.Basal.Source和IFox.CAD.Source两个nuget包就可以直接使用了。优点就是使用简单,生成的目录里没有ifox的dll,同时还可以通过定义预处理常量的方式屏蔽ifox提供的元组等功能。缺点就是无法修改源码,即便解包修改了,也不会同步到nuget上。 - -- 第三种是使用git子模块。 - - 此种方法使用步骤复杂,需要熟悉git及其子模块的使用,需要引用ifox里的共享项目文件。优点就是可以使用最新的代码,可以修改代码。具体的可以参考如下说明进行: - - **让 IFox 作为您的子模块** - - IFox的develop分支是一个多cad版本分支,您可以利用此作为您的[git项目子模块](https://www.cnblogs.com/JJBox/p/13876501.html#_label13). - - 子模块是以`共享工程`的方式加入到您的工程的,其为`IFox.CAD.Shared`: -1. 千万不要用`IFox.CAD.ACAD`内的工程作为引用,否则您将遭遇cad加载失效. - -2. 一些全局命名空间的缺少,我们也建议您使用全局命名空间来补充, - 您只需要按照`IFox.CAD.ACAD`的`GlobalUsings.cs`文件一样添加就好了. - -3. 若您使用acad是09版本以下的,比如 07 08版本,建议你升级至09 版本以上. - -4. 上面的例子告诉了大家如何使用子模块。 - -#### 七、软件架构及相关说明 - -1. [软件架构说明](/docs/关于IFoxCAD的架构说明.md) - -2. [扩展函数说明](/docs/关于扩展函数的说明.md) - -3. [事务管理器用法](/docs/DBTrans.md) - -4. [选择集过滤器用法](/docs/SelectionFilter.md) - -5. [符号表用法](/docs/SymbolTable.md) - -6. [WPF支持](/docs/WPF.md) - -7. [自动加载与初始化](/docs/autoreg.md) - -8. 天秀的打开模式提权 - - 由于cad的对象是有打开模式,是否可写等等,为了安全起见,在处理对象时,一般是用读模式打开,然后需要写数据的时候在提权为写模式,然后在降级到读模式,但是这个过程中,很容易漏掉某些步骤,然后cad崩溃。为了处理这些情况,内裤提供了提权类来保证读写模式的有序转换。 - - ```csharp - // 第一种方式,采用的是事务管理的模式 - using(line.ForWrite()) // 开启对象写模式提权事务 - { - // 处理代码 - } // 关闭事务自动处理读写模式 - // 第二种方式,采用的是委托的形式 - line.ForWrite(e => { - // 处理代码 - }); - ``` - -9. 未完待续。。。。 -- Gitee From c5856f4cf9d7ee4d378adec09e41cb23d0330385 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Mon, 26 Jun 2023 16:57:21 +0800 Subject: [PATCH 135/453] =?UTF-8?q?=E5=88=A0=E9=99=A4editorconfig=E6=96=87?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .editorconfig | 225 -------------------------------------------------- IFoxCAD.sln | 1 - 2 files changed, 226 deletions(-) delete mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index f76aad0..0000000 --- a/.editorconfig +++ /dev/null @@ -1,225 +0,0 @@ -# 如果要从更高级别的目录继承 .editorconfig 设置,请删除以下行 -root = true - -# c# 文件 -[*.cs] - -#### Core EditorConfig 选项 #### - -# 缩进和间距 -indent_size = 4 -indent_style = space -tab_width = 4 - -# 新行首选项 -end_of_line = crlf -insert_final_newline = false - -#### .NET 编码约定 #### - -# 组织 Using -dotnet_separate_import_directive_groups = false -dotnet_sort_system_directives_first = false -file_header_template = unset - -# this. 和 Me. 首选项 -dotnet_style_qualification_for_event = false -dotnet_style_qualification_for_field = false -dotnet_style_qualification_for_method = false -dotnet_style_qualification_for_property = false - -# 语言关键字与 bcl 类型首选项 -dotnet_style_predefined_type_for_locals_parameters_members = true -dotnet_style_predefined_type_for_member_access = true - -# 括号首选项 -dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity -dotnet_style_parentheses_in_other_binary_operators = always_for_clarity -dotnet_style_parentheses_in_other_operators = never_if_unnecessary -dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity - -# 修饰符首选项 -dotnet_style_require_accessibility_modifiers = for_non_interface_members - -# 表达式级首选项 -dotnet_style_coalesce_expression = true -dotnet_style_collection_initializer = true -dotnet_style_explicit_tuple_names = true -dotnet_style_namespace_match_folder = true -dotnet_style_null_propagation = true -dotnet_style_object_initializer = true -dotnet_style_operator_placement_when_wrapping = beginning_of_line -dotnet_style_prefer_auto_properties = true -dotnet_style_prefer_compound_assignment = true -dotnet_style_prefer_conditional_expression_over_assignment = true -dotnet_style_prefer_conditional_expression_over_return = true -dotnet_style_prefer_foreach_explicit_cast_in_source = when_strongly_typed -dotnet_style_prefer_inferred_anonymous_type_member_names = true -dotnet_style_prefer_inferred_tuple_names = true -dotnet_style_prefer_is_null_check_over_reference_equality_method = true:error -dotnet_style_prefer_simplified_boolean_expressions = true -dotnet_style_prefer_simplified_interpolation = true - -# 字段首选项 -dotnet_style_readonly_field = true - -# 参数首选项 -dotnet_code_quality_unused_parameters = all - -# 禁止显示首选项 -dotnet_remove_unnecessary_suppression_exclusions = 0 - -# 新行首选项 -dotnet_style_allow_multiple_blank_lines_experimental = true -dotnet_style_allow_statement_immediately_after_block_experimental = true - -#### c# 编码约定 #### - -# var 首选项 -csharp_style_var_elsewhere = false -csharp_style_var_for_built_in_types = false -csharp_style_var_when_type_is_apparent = false - -# Expression-bodied 成员 -csharp_style_expression_bodied_accessors = true -csharp_style_expression_bodied_constructors = false -csharp_style_expression_bodied_indexers = true -csharp_style_expression_bodied_lambdas = true -csharp_style_expression_bodied_local_functions = false -csharp_style_expression_bodied_methods = false -csharp_style_expression_bodied_operators = false -csharp_style_expression_bodied_properties = true - -# 模式匹配首选项 -csharp_style_pattern_matching_over_as_with_null_check = true -csharp_style_pattern_matching_over_is_with_cast_check = true -csharp_style_prefer_extended_property_pattern = true -csharp_style_prefer_not_pattern = true -csharp_style_prefer_pattern_matching = true -csharp_style_prefer_switch_expression = true - -# Null 检查首选项 -csharp_style_conditional_delegate_call = true - -# 修饰符首选项 -csharp_prefer_static_local_function = true -csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async - -# 代码块首选项 -csharp_prefer_braces = true -csharp_prefer_simple_using_statement = true -csharp_style_namespace_declarations = block_scoped -csharp_style_prefer_method_group_conversion = true -csharp_style_prefer_top_level_statements = true - -# 表达式级首选项 -csharp_prefer_simple_default_expression = true -csharp_style_deconstructed_variable_declaration = true -csharp_style_implicit_object_creation_when_type_is_apparent = true -csharp_style_inlined_variable_declaration = true -csharp_style_prefer_index_operator = true -csharp_style_prefer_local_over_anonymous_function = true -csharp_style_prefer_null_check_over_type_check = true -csharp_style_prefer_range_operator = true -csharp_style_prefer_tuple_swap = true -csharp_style_prefer_utf8_string_literals = true -csharp_style_throw_expression = true -csharp_style_unused_value_assignment_preference = discard_variable -csharp_style_unused_value_expression_statement_preference = discard_variable - -# "using" 指令首选项 -csharp_using_directive_placement = outside_namespace - -# 新行首选项 -csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true -csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true -csharp_style_allow_embedded_statements_on_same_line_experimental = true - -#### C# 格式规则 #### - -# 新行首选项 -csharp_new_line_before_catch = true -csharp_new_line_before_else = true -csharp_new_line_before_finally = true -csharp_new_line_before_members_in_anonymous_types = true -csharp_new_line_before_members_in_object_initializers = true -csharp_new_line_before_open_brace = accessors,anonymous_methods,anonymous_types,control_blocks,methods,object_collection_array_initializers,properties,types -csharp_new_line_between_query_expression_clauses = true - -# 缩进首选项 -csharp_indent_block_contents = true -csharp_indent_braces = false -csharp_indent_case_contents = false -csharp_indent_case_contents_when_block = false -csharp_indent_labels = one_less_than_current -csharp_indent_switch_labels = true - -# 空格键首选项 -csharp_space_after_cast = false -csharp_space_after_colon_in_inheritance_clause = true -csharp_space_after_comma = true -csharp_space_after_dot = false -csharp_space_after_keywords_in_control_flow_statements = true -csharp_space_after_semicolon_in_for_statement = true -csharp_space_around_binary_operators = before_and_after -csharp_space_around_declaration_statements = false -csharp_space_before_colon_in_inheritance_clause = true -csharp_space_before_comma = false -csharp_space_before_dot = false -csharp_space_before_open_square_brackets = false -csharp_space_before_semicolon_in_for_statement = false -csharp_space_between_empty_square_brackets = false -csharp_space_between_method_call_empty_parameter_list_parentheses = false -csharp_space_between_method_call_name_and_opening_parenthesis = false -csharp_space_between_method_call_parameter_list_parentheses = false -csharp_space_between_method_declaration_empty_parameter_list_parentheses = false -csharp_space_between_method_declaration_name_and_open_parenthesis = false -csharp_space_between_method_declaration_parameter_list_parentheses = false -csharp_space_between_parentheses = false -csharp_space_between_square_brackets = false - -# 包装首选项 -csharp_preserve_single_line_blocks = true -csharp_preserve_single_line_statements = true - -#### 命名样式 #### - -# 命名规则 - -dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion -dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface -dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i - -dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion -dotnet_naming_rule.types_should_be_pascal_case.symbols = types -dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case - -dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion -dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members -dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case - -# 符号规范 - -dotnet_naming_symbols.interface.applicable_kinds = interface -dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected -dotnet_naming_symbols.interface.required_modifiers = - -dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum -dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected -dotnet_naming_symbols.types.required_modifiers = - -dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method -dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected -dotnet_naming_symbols.non_field_members.required_modifiers = - -# 命名样式 - -dotnet_naming_style.pascal_case.required_prefix = -dotnet_naming_style.pascal_case.required_suffix = -dotnet_naming_style.pascal_case.word_separator = -dotnet_naming_style.pascal_case.capitalization = pascal_case - -dotnet_naming_style.begins_with_i.required_prefix = I -dotnet_naming_style.begins_with_i.required_suffix = -dotnet_naming_style.begins_with_i.word_separator = -dotnet_naming_style.begins_with_i.capitalization = pascal_case diff --git a/IFoxCAD.sln b/IFoxCAD.sln index 802ff1c..af5039b 100644 --- a/IFoxCAD.sln +++ b/IFoxCAD.sln @@ -5,7 +5,6 @@ VisualStudioVersion = 17.1.32113.165 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Config", "Config", "{786E7347-B116-4F26-9AEF-33EB0AB88D58}" ProjectSection(SolutionItems) = preProject - .editorconfig = .editorconfig .gitattributes = .gitattributes .gitignore = .gitignore EndProjectSection -- Gitee From 1de031fc1957538bc94d1d3a18e1e6f8456a4107 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Tue, 27 Jun 2023 11:54:42 +0800 Subject: [PATCH 136/453] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E2=80=9D=E5=BB=B6?= =?UTF-8?q?=E8=BF=9F=E6=9B=B4=E6=96=B0=E5=9B=BE=E5=B1=82=E9=94=81=E5=AE=9A?= =?UTF-8?q?=E6=B7=A1=E6=98=BE=E7=8A=B6=E6=80=81=E2=80=9C=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/Runtime/Env.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/CAD/IFox.CAD.Shared/Runtime/Env.cs b/src/CAD/IFox.CAD.Shared/Runtime/Env.cs index 5e5888e..5d69e63 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/Env.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/Env.cs @@ -764,5 +764,16 @@ public static Dictionary SaveCadVar(Dictionary a } return dict; } + /// + /// 延迟更新图层锁定淡显状态 + /// 在有锁定或解锁图层的命令的末尾使用 + /// + public static void DelayUpdateLayLockFade() + { + const string lfName = "LAYLOCKFADECTL"; + int lf = Convert.ToInt32(Acap.GetSystemVariable(lfName).ToString()); + Acap.SetSystemVariable(lfName, -lf); + IdleAction.Add(() => Acap.SetSystemVariable(lfName, lf)); + } #endregion } \ No newline at end of file -- Gitee From 669473f2e53acafc8c03a8a1da4debf44f16d2e1 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Wed, 28 Jun 2023 00:04:23 +0800 Subject: [PATCH 137/453] =?UTF-8?q?=E6=A0=B9=E6=8D=AErider=E7=9A=84?= =?UTF-8?q?=E6=8F=90=E7=A4=BA=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.GCAD/GlobalUsings.cs | 12 +- src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs | 65 ++++----- src/CAD/IFox.CAD.Shared/Runtime/Env.cs | 128 ++++++++---------- .../IFox.CAD.Shared/Runtime/SymbolTable.cs | 28 ++-- src/CAD/IFox.CAD.ZCAD/GlobalUsings.cs | 9 +- 5 files changed, 99 insertions(+), 143 deletions(-) diff --git a/src/CAD/IFox.CAD.GCAD/GlobalUsings.cs b/src/CAD/IFox.CAD.GCAD/GlobalUsings.cs index 35120c1..e788f51 100644 --- a/src/CAD/IFox.CAD.GCAD/GlobalUsings.cs +++ b/src/CAD/IFox.CAD.GCAD/GlobalUsings.cs @@ -10,10 +10,8 @@ global using Microsoft.Win32; global using System.ComponentModel; global using System.Runtime.InteropServices; -global using System.Collections.Specialized; global using Exception = System.Exception; - global using Registry = Microsoft.Win32.Registry; global using RegistryKey = Microsoft.Win32.RegistryKey; @@ -25,13 +23,8 @@ global using GrxCAD.Geometry; global using GrxCAD.Runtime; global using Acap = GrxCAD.ApplicationServices.Application; -global using Acgi = GrxCAD.GraphicsInterface; global using Acaop = GrxCAD.ApplicationServices.Application; - global using GrxCAD.DatabaseServices.Filters; -global using GrxCAD; - -global using GrxCAD.Internal; // jig命名空间会引起Viewport/Polyline等等重义,最好逐个引入 using Autodesk.AutoCAD.GraphicsInterface global using GrxCAD.GraphicsInterface; @@ -40,11 +33,8 @@ global using Group = GrxCAD.DatabaseServices.Group; global using Viewport = GrxCAD.DatabaseServices.Viewport; global using Polyline = GrxCAD.DatabaseServices.Polyline; -global using Cad_DwgFiler = GrxCAD.DatabaseServices.DwgFiler; -global using Cad_DxfFiler = GrxCAD.DatabaseServices.DxfFiler; -global using Cad_ErrorStatus = GrxCAD.Runtime.ErrorStatus; // ifoxcad.basal 引用 global using IFoxCAD.Basal; -global using System.Web.Script.Serialization; + diff --git a/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs b/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs index f2410bd..926ba60 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs @@ -13,7 +13,7 @@ namespace IFoxCAD.Cad; public sealed class DBTrans : IDisposable { [DebuggerBrowsable(DebuggerBrowsableState.Never)] - private string DebuggerDisplay => ToString(" | "); + private string DebuggerDisplay => ToString(); #region 静态函数 /// @@ -560,52 +560,45 @@ private void Dispose(bool disposing) // 不重复释放,并设置已经释放 if (IsDisposed) return; - IsDisposed = true; - - // 致命错误时候此处是空,直接跳过 - if (Transaction != null) + + if (disposing) { - if (_commit) - { - // 刷新队列(后台不刷新) - Editor?.Redraw(); - // 调用cad的事务进行提交,释放托管状态(托管对象) - Transaction.Commit(); - } - else + // 致命错误时候此处是空,直接跳过 + if (Transaction != null) { - // 否则取消所有的修改 - Transaction.Abort(); - } + if (_commit) + { + // 刷新队列(后台不刷新) + Editor?.Redraw(); + // 调用cad的事务进行提交,释放托管状态(托管对象) + Transaction.Commit(); + } + else + { + // 否则取消所有的修改 + Transaction.Abort(); + } - // 将cad事务进行销毁 - if (!Transaction.IsDisposed) - Transaction.Dispose(); + // 将cad事务进行销毁 + if (!Transaction.IsDisposed) + Transaction.Dispose(); + } + // 将文档锁销毁 + _documentLock?.Dispose(); } - // 将文档锁销毁 - _documentLock?.Dispose(); // 将当前事务栈弹栈 _dBTrans.Pop(); + IsDisposed = true; } #endregion #region ToString + /// public override string ToString() - { - return ToString(null, null); - } - /// - public string ToString(IFormatProvider? provider) - { - return ToString(null, provider); - } - /// -#pragma warning disable IDE0060 // 删除未使用的参数 - public string ToString(string? format = null, IFormatProvider? formatProvider = null) -#pragma warning restore IDE0060 // 删除未使用的参数 + { List lines = new() { @@ -616,11 +609,11 @@ public string ToString(string? format = null, IFormatProvider? formatProvider = $"Document = {Document != null}", $"Editor = {Editor != null}", - $"Transaction = {Transaction != null}", - $"Database = {Database != null}" + $"Transaction = {Transaction.UnmanagedObject}", + $"Database = {Database.Filename}" }; - return string.Join(!string.IsNullOrWhiteSpace(format) ? format : "\n", lines.ToArray()); + return string.Join("\n", lines.ToArray()); } #endregion } \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/Runtime/Env.cs b/src/CAD/IFox.CAD.Shared/Runtime/Env.cs index 5d69e63..aadcc0f 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/Env.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/Env.cs @@ -22,7 +22,7 @@ public static class Env /// /// 当前文档 /// - public static Document Document => Acap.DocumentManager.MdiActiveDocument; + public static Document Document => Acaop.DocumentManager.MdiActiveDocument; /// /// 编辑器对象 @@ -47,7 +47,7 @@ public static class Env /// 对象 public static object GetCurrentProfileProperty(string subSectionName, string propertyName) { - UserConfigurationManager ucm = Acap.UserConfigurationManager; + UserConfigurationManager ucm = Acaop.UserConfigurationManager; IConfigurationSection cpf = ucm.OpenCurrentProfile(); IConfigurationSection ss = cpf.OpenSubsection(subSectionName); return ss.ReadProperty(propertyName, ""); @@ -61,7 +61,7 @@ public static object GetCurrentProfileProperty(string subSectionName, string pro /// 配置项 public static IConfigurationSection GetDialogSection(object dialog) { - UserConfigurationManager ucm = Acap.UserConfigurationManager; + UserConfigurationManager ucm = Acaop.UserConfigurationManager; IConfigurationSection ds = ucm.OpenDialogSection(dialog); return ds; } @@ -73,7 +73,7 @@ public static IConfigurationSection GetDialogSection(object dialog) /// 配置项 public static IConfigurationSection GetGlobalSection(string propertyName) { - UserConfigurationManager ucm = Acap.UserConfigurationManager; + UserConfigurationManager ucm = Acaop.UserConfigurationManager; IConfigurationSection gs = ucm.OpenGlobalSection(); IConfigurationSection ss = gs.OpenSubsection(propertyName); return ss; @@ -87,34 +87,28 @@ public static IConfigurationSection GetGlobalSection(string propertyName) /// public static bool CmdEcho { - get => Convert.ToInt16(Acap.GetSystemVariable("cmdecho")) == 1; - set => Acap.SetSystemVariable("cmdecho", Convert.ToInt16(value)); + get => Convert.ToInt16(Acaop.GetSystemVariable("cmdecho")) == 1; + set => Acaop.SetSystemVariable("cmdecho", Convert.ToInt16(value)); } /// /// 获取Cad当前是否有活动命令 /// - public static bool CmdActive => Convert.ToBoolean(Acap.GetSystemVariable("CMDACTIVE")); + public static bool CmdActive => Convert.ToBoolean(Acaop.GetSystemVariable("CMDACTIVE")); /// /// 控制在光标是否为正交模式, 为打开正交, 为关闭正交 /// public static bool OrthoMode { - get => Convert.ToInt16(Acap.GetSystemVariable("ORTHOMODE")) == 1; - set => Acap.SetSystemVariable("ORTHOMODE", Convert.ToInt16(value)); + get => Convert.ToInt16(Acaop.GetSystemVariable("ORTHOMODE")) == 1; + set => Acaop.SetSystemVariable("ORTHOMODE", Convert.ToInt16(value)); } /// /// 读写系统变量LastPoint的坐标(UCS) /// public static Point3d LastPoint { - get - { - return (Point3d)Acap.GetSystemVariable("LASTPOINT"); - } - set - { - Acap.SetSystemVariable("LASTPOINT", value); - } + get => (Point3d)Acaop.GetSystemVariable("LASTPOINT"); + set => Acaop.SetSystemVariable("LASTPOINT", value); } #region Dimblk @@ -225,7 +219,7 @@ public enum DimblkType ArchTick } - private static readonly Dictionary dimdescdict = new() + private static readonly Dictionary Dimdescdict = new() { { "实心闭合", DimblkType.Defult }, { "点", DimblkType.Dot }, @@ -279,7 +273,7 @@ public static DimblkType Dimblk { get { - string s = ((string)Acap.GetSystemVariable("dimblk")).ToUpper(); + string s = ((string)Acaop.GetSystemVariable("dimblk")).ToUpper(); // if (string.IsNullOrEmpty(s)) // { // return DimblkType.Defult; @@ -293,12 +287,12 @@ public static DimblkType Dimblk // return s.ToEnum(); // // return s.FromDescName(); // } - return dimdescdict[s]; + return Dimdescdict[s]; } set { string s = GetDimblkName(value); - Acap.SetSystemVariable("dimblk", s); + Acaop.SetSystemVariable("dimblk", s); } } @@ -338,6 +332,7 @@ public static ObjectId GetDimblkId(DimblkType dimblk) /// /// 捕捉模式系统变量类型 /// + [Flags] public enum OSModeType { /// @@ -421,14 +416,8 @@ public enum OSModeType /// public static OSModeType OSMode { - get - { - return (OSModeType)Convert.ToInt16(Acap.GetSystemVariable("osmode")); - } - set - { - Acap.SetSystemVariable("osmode", (int)value); - } + get => (OSModeType)Convert.ToInt16(Acaop.GetSystemVariable("osmode")); + set => Acaop.SetSystemVariable("osmode", (int)value); } /// /// 捕捉模式osm1是否包含osm2 @@ -443,9 +432,9 @@ public static bool Include(this OSModeType osm1, OSModeType osm2) #endregion OsMode - private static string GetName(this T value) + private static string? GetName(this T value) { - return Enum.GetName(typeof(T), value); + return Enum.GetName(typeof(T), value!); } #endregion Enum @@ -456,9 +445,9 @@ private static string GetName(this T value) /// /// 变量名 /// 变量值 - public static object GetVar(string? varName) + public static object? GetVar(string? varName) { - return Acap.GetSystemVariable(varName); + return Acaop.GetSystemVariable(varName); } /// /// 设置cad系统变量
@@ -469,16 +458,16 @@ public static object GetVar(string? varName) /// 变量名 /// 变量值 /// 输出异常,默认true;此设置仅为打印到命令栏,无法控制vs输出 - public static void SetVar(string? varName, object? value, bool echo = true) + public static void SetVar(string varName, object value, bool echo = true) { try { - Acap.SetSystemVariable(varName, value); + Acaop.SetSystemVariable(varName, value); } - catch (System.Exception) + catch (Exception) { if (echo) - Env.Print($"{varName} 是不存在的变量!"); + Print($"{varName} 是不存在的变量!"); } } #endregion @@ -592,7 +581,7 @@ public static int SetEnv(string? name, string? var) /// 判断当前是否在UCS坐标下 ///
/// Bool - public static bool IsUcs() => (short)GetVar("WORLDUCS") == 0; + public static bool IsUcs() => (short)GetVar("WORLDUCS")! == 0; #region dwg版本号/cad版本号/年份 @@ -602,27 +591,26 @@ public static int SetEnv(string? name, string? var) /// public static DwgVersion GetDefaultDwgVersion() { - DwgVersion version; var ffs = Env.GetEnv("DefaultFormatForSave"); - version = ffs switch + var version = ffs switch { - "1" => DwgVersion.AC1009,// R12/LT12 dxf - "8" => DwgVersion.AC1014,// R14/LT98/LT97 dwg - "12" => DwgVersion.AC1015,// 2000 dwg - "13" => DwgVersion.AC1800a,// 2000 dxf - "24" => DwgVersion.AC1800,// 2004 dwg - "25" => (DwgVersion)26,// 2004 dxf - "36" => (DwgVersion)27,// 2007 dwg DwgVersion.AC1021 - "37" => (DwgVersion)28,// 2007 dxf + "1" => DwgVersion.AC1009, // R12/LT12 dxf + "8" => DwgVersion.AC1014, // R14/LT98/LT97 dwg + "12" => DwgVersion.AC1015, // 2000 dwg + "13" => DwgVersion.AC1800a, // 2000 dxf + "24" => DwgVersion.AC1800, // 2004 dwg + "25" => (DwgVersion)26, // 2004 dxf + "36" => (DwgVersion)27, // 2007 dwg DwgVersion.AC1021 + "37" => (DwgVersion)28, // 2007 dxf // "38" => (DwgVersion),// dwt 样板文件...啊惊没找到这个是什么 - "48" => (DwgVersion)29,// 2010 dwg DwgVersion.AC1024 - "49" => (DwgVersion)30,// 2010 dxf - "60" => (DwgVersion)31,// 2013 dwg DwgVersion.AC1027 - "61" => (DwgVersion)32,// 2013 dxf - "64" => (DwgVersion)33,// 2018 dwg DwgVersion.AC1032 - "65" => (DwgVersion)34,// 2018 dxf - _ => throw new NotImplementedException(),// 提醒维护 + "48" => (DwgVersion)29, // 2010 dwg DwgVersion.AC1024 + "49" => (DwgVersion)30, // 2010 dxf + "60" => (DwgVersion)31, // 2013 dwg DwgVersion.AC1027 + "61" => (DwgVersion)32, // 2013 dxf + "64" => (DwgVersion)33, // 2018 dwg DwgVersion.AC1032 + "65" => (DwgVersion)34, // 2018 dxf + _ => throw new NotImplementedException(), // 提醒维护 }; return version; } @@ -654,7 +642,7 @@ public static bool IsDxfVersion(this DwgVersion dwgVersion) /// 超出年份就报错 public static int GetAcadVersion() { - var ver = Acap.Version.Major + "." + Acap.Version.Minor; + var ver = Acaop.Version.Major + "." + Acaop.Version.Minor; int acarVarNum = ver switch { "16.2" => 2006, @@ -686,7 +674,7 @@ public static int GetAcadVersion() /// dll的前面 public static string GetAcapVersionDll(string str = "acdb") { - return str + Acap.Version.Major + ".dll"; + return str + Acaop.Version.Major + ".dll"; } #endregion @@ -696,28 +684,20 @@ public static string GetAcapVersionDll(string str = "acdb") /// 设置cad系统变量
/// 提供一个反序列化后,无cad异常输出的功能
/// 注意,您需要再此执行时候设置文档锁
- ///
/// 否则也将导致修改数据库异常
///
/// /// /// 成功返回当前值,失败null /// - public static object? SetVarEx(string? key, string? value) + public static object? SetVarEx(string key, string value) { - //if (key == null) - // throw new ArgumentNullException(nameof(key)); - //if (value == null) - // throw new ArgumentNullException(nameof(value)); - ArgumentNullEx.ThrowIfNull(key); - ArgumentNullEx.ThrowIfNull(value); - - - var currentVar = Env.GetVar(key); - if (currentVar == null) + + var currentVar = GetVar(key); + if (currentVar is null) return null; - object? valueType = currentVar.GetType().Name switch + object valueType = currentVar.GetType().Name switch { "String" => value.Replace("\"", string.Empty), "Double" => double.Parse(value), @@ -727,7 +707,7 @@ public static string GetAcapVersionDll(string str = "acdb") }; // 相同的参数进行设置会发生一次异常 - if (currentVar.ToString().ToUpper() != valueType!.ToString().ToUpper()) + if (!string.Equals(currentVar.ToString(), valueType.ToString(), StringComparison.CurrentCultureIgnoreCase)) Env.SetVar(key, valueType); return currentVar; @@ -771,9 +751,9 @@ public static Dictionary SaveCadVar(Dictionary a public static void DelayUpdateLayLockFade() { const string lfName = "LAYLOCKFADECTL"; - int lf = Convert.ToInt32(Acap.GetSystemVariable(lfName).ToString()); - Acap.SetSystemVariable(lfName, -lf); - IdleAction.Add(() => Acap.SetSystemVariable(lfName, lf)); + int lf = Convert.ToInt32(Acaop.GetSystemVariable(lfName).ToString()); + Acaop.SetSystemVariable(lfName, -lf); + IdleAction.Add(() => Acaop.SetSystemVariable(lfName, lf)); } #endregion } \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/Runtime/SymbolTable.cs b/src/CAD/IFox.CAD.Shared/Runtime/SymbolTable.cs index 62b500b..585f412 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/SymbolTable.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/SymbolTable.cs @@ -12,7 +12,7 @@ public class SymbolTable : IEnumerable /// /// 事务管理器 /// - internal DBTrans DTrans { get; private set; } + private DBTrans DTrans { get; set; } /// /// 数据库 /// @@ -276,7 +276,7 @@ public IEnumerable GetRecordNames(Func filter) /// 符号表记录名 /// 是否覆盖, 为覆盖, 为不覆盖 /// 对象id - public ObjectId GetRecordFrom(SymbolTable table, string name, bool over) + private ObjectId GetRecordFrom(SymbolTable table, string name, bool over) { //if (table is null) // throw new ArgumentNullException(nameof(table), "对象为null"); @@ -284,19 +284,17 @@ public ObjectId GetRecordFrom(SymbolTable table, string name, b ObjectId rid = this[name]; bool has = rid != ObjectId.Null; - if ((has && over) || !has) - { - ObjectId id = table[name]; - using IdMapping map = new(); - using ObjectIdCollection ids = new() { id }; - table.Database.WblockCloneObjects( - ids, - CurrentSymbolTable.Id, - map, - DuplicateRecordCloning.Replace, - false); - rid = map[id].Value; - } + if ((!has || !over) && has) return rid; + ObjectId id = table[name]; + using IdMapping map = new(); + using ObjectIdCollection ids = new() { id }; + table.Database.WblockCloneObjects( + ids, + CurrentSymbolTable.Id, + map, + DuplicateRecordCloning.Replace, + false); + rid = map[id].Value; return rid; } diff --git a/src/CAD/IFox.CAD.ZCAD/GlobalUsings.cs b/src/CAD/IFox.CAD.ZCAD/GlobalUsings.cs index d3dd2e5..2720596 100644 --- a/src/CAD/IFox.CAD.ZCAD/GlobalUsings.cs +++ b/src/CAD/IFox.CAD.ZCAD/GlobalUsings.cs @@ -10,8 +10,7 @@ global using Microsoft.Win32; global using System.ComponentModel; global using System.Runtime.InteropServices; -global using System.Collections.Specialized; - +global using System.Web.Script.Serialization; global using Exception = System.Exception; global using Registry = Microsoft.Win32.Registry; @@ -27,7 +26,6 @@ global using Acap = ZwSoft.ZwCAD.ApplicationServices.Application; global using Acaop = ZwSoft.ZwCAD.ApplicationServices.Application; global using ZwSoft.ZwCAD.DatabaseServices.Filters; -global using ZwSoft.ZwCAD; // jig命名空间会引起Viewport/Polyline等等重义,最好逐个引入 using ZwSoft.ZwCAD.GraphicsInterface global using ZwSoft.ZwCAD.GraphicsInterface; @@ -36,11 +34,8 @@ global using Group = ZwSoft.ZwCAD.DatabaseServices.Group; global using Viewport = ZwSoft.ZwCAD.DatabaseServices.Viewport; global using Polyline = ZwSoft.ZwCAD.DatabaseServices.Polyline; -global using Cad_DwgFiler = ZwSoft.ZwCAD.DatabaseServices.DwgFiler; -global using Cad_DxfFiler = ZwSoft.ZwCAD.DatabaseServices.DxfFiler; -global using Cad_ErrorStatus = ZwSoft.ZwCAD.Runtime.ErrorStatus; // ifoxcad.basal 引用 global using IFoxCAD.Basal; -global using System.Web.Script.Serialization; + -- Gitee From 53175e49d6aa87e29951f272e27c7f1e8644139d Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Fri, 30 Jun 2023 14:28:33 +0800 Subject: [PATCH 138/453] =?UTF-8?q?=E4=BF=AE=E6=94=B9GetDrawOrderTable?= =?UTF-8?q?=E7=9A=84=E6=97=A0=E7=94=A8=E5=8F=82=E6=95=B0=EF=BC=8C=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0openMode=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/SymbolTableRecordEx.cs | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs index cdd0fe2..42cb186 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs @@ -40,9 +40,9 @@ public static void DeepCloneEx(this BlockTableRecord btr, ObjectIdCollection obj // foreach (ObjectId item in blockIds) // result.Add(mapping[item].Value); } - catch + catch { - + } } } @@ -83,7 +83,8 @@ public static IEnumerable AddEntity(this BlockTableRecord btr, IEnu var tr = DBTrans.GetTopTransaction(btr.Database); using (btr.ForWrite()) { - return ents.Select(ent => { + return ents.Select(ent => + { ObjectId id = btr.AppendEntity(ent); tr.AddNewlyCreatedDBObject(ent, true); return id; @@ -123,7 +124,7 @@ public static IEnumerable GetEntities(this BlockTableRecord btr, return btr .Cast() - .Where(id=>id.ObjectClass.IsDerivedFrom(rxc)) + .Where(id => id.ObjectClass.IsDerivedFrom(rxc)) .Select(id => id.GetObject(openMode, openErased, openLockedLayer)) .OfType(); } @@ -157,17 +158,17 @@ public static IEnumerable> GetObjectIds(this BlockTa /// 获取绘制顺序表 ///
/// 块表 - /// 事务 + /// 开启方式 /// 是否打开已删除对象,默认为不打开 /// 是否打开锁定图层对象,默认为不打开 /// 绘制顺序表 - public static DrawOrderTable? GetDrawOrderTable(this BlockTableRecord btr, - Transaction? trans = null, + public static DrawOrderTable GetDrawOrderTable(this BlockTableRecord btr, + OpenMode openMode = OpenMode.ForRead, bool openErased = false, bool openLockedLayer = false) { var tr = DBTrans.GetTopTransaction(btr.Database); - return tr.GetObject(btr.DrawOrderTableId, OpenMode.ForRead, openErased, openLockedLayer); + return (DrawOrderTable)tr.GetObject(btr.DrawOrderTableId, openMode, openErased, openLockedLayer); } #endregion @@ -215,13 +216,13 @@ public static ObjectId InsertBlock(this BlockTableRecord blockTableRecord, { //trans ??= DBTrans.Top.Transaction; var tr = DBTrans.GetTop(blockTableRecord.Database); - + if (!tr.BlockTable.Has(blockId)) { tr.Editor?.WriteMessage($"\n不存在块定义。"); return ObjectId.Null; } - + using var blockref = new BlockReference(position, blockId) { -- Gitee From 0a93a390fc74cdd85add37f9a0b69795522cdc0c Mon Sep 17 00:00:00 2001 From: vicwjb Date: Fri, 30 Jun 2023 15:20:24 +0800 Subject: [PATCH 139/453] =?UTF-8?q?=E5=B1=8F=E8=94=BDtests/TestAcad09plus/?= =?UTF-8?q?Properties/=E6=96=87=E4=BB=B6=E5=A4=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index e910608..fe816ab 100644 --- a/.gitignore +++ b/.gitignore @@ -407,4 +407,5 @@ healthchecksdb .vscode #ifoxcad -#tests/TestConsole/ \ No newline at end of file +#tests/TestConsole/ +tests/TestAcad09plus/Properties/ \ No newline at end of file -- Gitee From bf86bb73af3ad1e9c4e2a51120b414bcd21274aa Mon Sep 17 00:00:00 2001 From: vicwjb Date: Fri, 30 Jun 2023 15:23:59 +0800 Subject: [PATCH 140/453] =?UTF-8?q?=E8=A7=A3=E5=86=B3zoom=E5=8D=A1?= =?UTF-8?q?=E9=A1=BF=E9=97=AE=E9=A2=98=E3=80=82fixed=20#I7HCP0=20=E6=B8=85?= =?UTF-8?q?=E7=90=86testconsole=E9=A1=B9=E7=9B=AE=E7=9A=84=E5=A4=9A?= =?UTF-8?q?=E4=BD=99=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/EditorEx.cs | 7 ++- tests/TestConsole/GlobalUsings.cs | 11 ++-- tests/TestConsole/Helper.cs | 22 -------- tests/TestConsole/Program.cs | 52 +++++++++++++++++-- tests/TestConsole/TestConsole.csproj | 13 +---- tests/TestShared/TestEditor.cs | 11 ++++ 6 files changed, 71 insertions(+), 45 deletions(-) delete mode 100644 tests/TestConsole/Helper.cs diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs index 6e2310d..a1043d0 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs @@ -730,6 +730,8 @@ public static Matrix3d GetMatrix(this Editor editor, CoordinateSystemCode from, #region 缩放 + // todo 暂时先屏蔽这个又臭又长的代码,待搞明白为什么都这么写之后再说 +#if false /// /// 缩放窗口范围 /// @@ -772,8 +774,9 @@ public static void ZoomWindow(this Editor ed, Point3d minPoint, Point3d maxPoint .Convert2d(Curve2dEx._planeCache); ed.SetCurrentView(vtr); - ed.Regen(); + //ed.Regen(); } +#endif /// /// 缩放窗口范围 @@ -870,7 +873,7 @@ public static void ZoomObject(this Editor ed, Entity ent, double offsetDist = 0. ed.ZoomWindow(ext.MinPoint, ext.MaxPoint, offsetDist); } - #endregion +#endregion #region Get交互类 diff --git a/tests/TestConsole/GlobalUsings.cs b/tests/TestConsole/GlobalUsings.cs index 6328a67..87d3183 100644 --- a/tests/TestConsole/GlobalUsings.cs +++ b/tests/TestConsole/GlobalUsings.cs @@ -2,13 +2,14 @@ global using System; global using System.Collections; global using System.Collections.Generic; -global using System.IO; global using System.Linq; global using System.Text; -global using System.Reflection; -global using System.Text.RegularExpressions; global using Microsoft.Win32; global using System.ComponentModel; global using System.Runtime.CompilerServices; - -global using IFoxCAD.Basal; \ No newline at end of file +global using System.Runtime.InteropServices; +global using System.Diagnostics; +global using System.Threading; +global using System.Linq.Expressions; +global using System.Collections.ObjectModel; +global using System.Diagnostics.CodeAnalysis; diff --git a/tests/TestConsole/Helper.cs b/tests/TestConsole/Helper.cs deleted file mode 100644 index 6fba766..0000000 --- a/tests/TestConsole/Helper.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace TestConsole; - -public static class Helper -{ - public static void ForEach(this IEnumerable ints, Action action) - { - LoopState state = new(); - foreach (var item in ints) - { - action(item, state); - if (!state.IsRun) - break; - } - - // int forNum = 5; - // var result = Parallel.For(0, forNum, (int i, ParallelLoopState pls) => { - // if (i > 2) - // pls.Break(); - // Task.Delay(10).Wait(); - // }); - } -} \ No newline at end of file diff --git a/tests/TestConsole/Program.cs b/tests/TestConsole/Program.cs index 514c252..74ce9d7 100644 --- a/tests/TestConsole/Program.cs +++ b/tests/TestConsole/Program.cs @@ -8,10 +8,38 @@ using System.Collections.Generic; using System.Text; using System.Diagnostics; +using CalculatorDemo; + +Console.WriteLine("release"); + +var a = new PointA(); +var b = new PointB(); + +CalculatorDemo.Program.TestTimes2(1000000, "PointA:", (i) => +{ + a.X = i * 0.1; + a.Y = i * 0.1; +}); +CalculatorDemo.Program.TestTimes2(1000000, "PointB:", (i) => +{ + b.X = i * 0.1; + b.Y = i * 0.1; +}); #if true namespace CalculatorDemo { + public class PointA + { + public double X; + public double Y; + } + public class PointB + { + public double X { set; get; } + public double Y { set; get; } + } + class Program { static void Main(string[] args) @@ -34,11 +62,7 @@ static void Main(string[] args) Console.WriteLine(aa[1..^2]); - var time = Timer.RunTime(() => { - for (int i = 0; i < 10000000; i++) - i++; - }, Timer.TimeEnum.Second); - Console.WriteLine($"代码执行的时间:{time}"); + } private static int addtuple((int ,int ) b) @@ -62,6 +86,24 @@ private static void AddTwoNumbers22(Action action) { action(10, 20); } + + public static void TestTimes2(int count, string message, Action action) + { + System.Diagnostics.Stopwatch watch = new(); + watch.Start(); // 开始监视代码运行时间 + for (int i = 0; i < count; i++) + action.Invoke(i);// 需要测试的代码 + watch.Stop(); // 停止监视 + TimeSpan timespan = watch.Elapsed; // 获取当前实例测量得出的总时间 + double time = timespan.TotalMilliseconds; + string name = "毫秒"; + if (timespan.TotalMilliseconds > 1000) + { + time = timespan.TotalSeconds; + name = "秒"; + } + Console.WriteLine($"{message} 代码执行 {count} 次的时间:{time} ({name})"); // 总毫秒数 + } } public static class Fors diff --git a/tests/TestConsole/TestConsole.csproj b/tests/TestConsole/TestConsole.csproj index 673e547..c1b52da 100644 --- a/tests/TestConsole/TestConsole.csproj +++ b/tests/TestConsole/TestConsole.csproj @@ -5,24 +5,15 @@ enable Exe - NET45 + NET48 enable preview - + - NET40 - enable - preview - NOINDEX;NORANGE;NOVALUETUPLE - - - - - diff --git a/tests/TestShared/TestEditor.cs b/tests/TestShared/TestEditor.cs index 2c368f1..4d0ea4b 100644 --- a/tests/TestShared/TestEditor.cs +++ b/tests/TestShared/TestEditor.cs @@ -44,6 +44,17 @@ public void Test_ZoomExtents() Env.Editor.ZoomExtents(); } + [CommandMethod(nameof(Test_Zoom_1))] + public void Test_Zoom_1() + { + Env.Editor.Zoom(new(0, 0, 0),200,200); + } + [CommandMethod(nameof(Test_Zoom_2))] + public void Test_Zoom_2() + { + Env.Editor.ZoomWindow(new(-100,-100,0),new(100,100,0)); + } + [CommandMethod(nameof(Test_Ssget))] public void Test_Ssget() { -- Gitee From 3c81b19f7a02e8d4d1546640d35df77d4b1d2f09 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Fri, 30 Jun 2023 15:30:06 +0800 Subject: [PATCH 141/453] =?UTF-8?q?=E5=B1=8F=E8=94=BD=E4=B8=8D=E6=88=90?= =?UTF-8?q?=E5=8A=9F=EF=BC=8C=E7=BB=A7=E7=BB=AD=E8=AF=95=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index fe816ab..75cf760 100644 --- a/.gitignore +++ b/.gitignore @@ -407,5 +407,4 @@ healthchecksdb .vscode #ifoxcad -#tests/TestConsole/ -tests/TestAcad09plus/Properties/ \ No newline at end of file +**/Properties/launchSettings.json -- Gitee From 08616607e1cb9c7d2fa747721a874c7e41cb4eae Mon Sep 17 00:00:00 2001 From: vicwjb Date: Fri, 30 Jun 2023 15:52:22 +0800 Subject: [PATCH 142/453] =?UTF-8?q?=E5=88=A0=E9=99=A4=E8=AF=95=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/TestAcad09plus/Properties/launchSettings.json | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 tests/TestAcad09plus/Properties/launchSettings.json diff --git a/tests/TestAcad09plus/Properties/launchSettings.json b/tests/TestAcad09plus/Properties/launchSettings.json deleted file mode 100644 index 4b464c3..0000000 --- a/tests/TestAcad09plus/Properties/launchSettings.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "profiles": { - "Test": { - "commandName": "Executable", - "executablePath": "C:\\Program Files\\Autodesk\\AutoCAD 2021\\acad.exe", - "commandLineArgs": "/nologo", - "nativeDebugging": false - } - } -} \ No newline at end of file -- Gitee From db0f6d334cb06d71a7ac7303303047ab0a691e06 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Fri, 30 Jun 2023 15:58:00 +0800 Subject: [PATCH 143/453] =?UTF-8?q?=E5=88=A0=E9=99=A4=E4=B8=8D=E7=9F=A5?= =?UTF-8?q?=E9=81=93=E5=B9=B2=E5=95=A5=E7=9A=84=E9=85=8D=E7=BD=AE=E6=96=87?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Properties/Resources.Designer.cs | 63 ----------- .../TestAcad09plus/Properties/Resources.resx | 101 ------------------ 2 files changed, 164 deletions(-) delete mode 100644 tests/TestAcad09plus/Properties/Resources.Designer.cs delete mode 100644 tests/TestAcad09plus/Properties/Resources.resx diff --git a/tests/TestAcad09plus/Properties/Resources.Designer.cs b/tests/TestAcad09plus/Properties/Resources.Designer.cs deleted file mode 100644 index 1617020..0000000 --- a/tests/TestAcad09plus/Properties/Resources.Designer.cs +++ /dev/null @@ -1,63 +0,0 @@ -//------------------------------------------------------------------------------ -// -// 此代码由工具生成。 -// 运行时版本:4.0.30319.42000 -// -// 对此文件的更改可能会导致不正确的行为,并且如果 -// 重新生成代码,这些更改将会丢失。 -// -//------------------------------------------------------------------------------ - -namespace Test.Properties { - using System; - - - /// - /// 一个强类型的资源类,用于查找本地化的字符串等。 - /// - // 此类是由 StronglyTypedResourceBuilder - // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 - // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen - // (以 /str 作为命令选项),或重新生成 VS 项目。 - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// 返回此类使用的缓存的 ResourceManager 实例。 - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Test.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// 重写当前线程的 CurrentUICulture 属性,对 - /// 使用此强类型资源类的所有资源查找执行重写。 - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - } -} diff --git a/tests/TestAcad09plus/Properties/Resources.resx b/tests/TestAcad09plus/Properties/Resources.resx deleted file mode 100644 index 4fdb1b6..0000000 --- a/tests/TestAcad09plus/Properties/Resources.resx +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file -- Gitee From c68dee78fb1ff6b028002cae6109b51e03d9127f Mon Sep 17 00:00:00 2001 From: vicwjb Date: Tue, 4 Jul 2023 00:35:01 +0800 Subject: [PATCH 144/453] =?UTF-8?q?=E8=B0=83=E7=90=86=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../IFox.CAD.Shared/ResultData/XdataList.cs | 19 +- tests/TestShared/TestAddEntity.cs | 254 ++---------------- tests/TestShared/TestDBTrans.cs | 47 +++- tests/TestShared/TestLayer.cs | 66 +++++ tests/TestShared/TestShared.projitems | 2 + tests/TestShared/TestXdata.cs | 108 ++++++++ 6 files changed, 249 insertions(+), 247 deletions(-) create mode 100644 tests/TestShared/TestLayer.cs create mode 100644 tests/TestShared/TestXdata.cs diff --git a/src/CAD/IFox.CAD.Shared/ResultData/XdataList.cs b/src/CAD/IFox.CAD.Shared/ResultData/XdataList.cs index 94f04d7..bd0ff99 100644 --- a/src/CAD/IFox.CAD.Shared/ResultData/XdataList.cs +++ b/src/CAD/IFox.CAD.Shared/ResultData/XdataList.cs @@ -25,8 +25,8 @@ public XDataList(IEnumerable values) : base(values) { } /// 组码值 public override void Add(int code, object obj) { - if (code < 1000 || code > 1071) - throw new System.Exception("传入的组码值不是 XData 有效范围!"); + if (code is < 1000 or > 1071) + throw new Exception("传入的组码值不是 XData 有效范围!"); Add(new TypedValue(code, obj)); } @@ -63,7 +63,7 @@ public bool Contains(string appName) public bool Contains(string appName, object value) { bool result = false; - RangeTask(appName, (tv, state, i) => { + RangeTask(appName, (tv, state, _) => { if (tv.Value.Equals(value)) { result = true; @@ -93,7 +93,7 @@ public List GetXdataAppIndex(string appName, DxfCode[] dxfCodes) /// 区间任务 /// /// - void RangeTask(string appName, Action action) + private void RangeTask(string appName, Action action) { LoopState state = new(); // 在名称和名称之间找 @@ -110,12 +110,11 @@ void RangeTask(string appName, Action action) if (appNameIndex != -1)//找到了下一个名称 break; } - if (appNameIndex != -1) // 找下一个的时候,获取任务(移除)的对象 - { - action(this[i], state, i); - if (!state.IsRun) - break; - } + + if (appNameIndex == -1) continue; // 找下一个的时候,获取任务(移除)的对象 + action(this[i], state, i); + if (!state.IsRun) + break; } } diff --git a/tests/TestShared/TestAddEntity.cs b/tests/TestShared/TestAddEntity.cs index 774ffb9..9c95534 100644 --- a/tests/TestShared/TestAddEntity.cs +++ b/tests/TestShared/TestAddEntity.cs @@ -1,41 +1,7 @@ -using System.Diagnostics; -using System.Web.UI.WebControls; - -namespace Test; +namespace Test; public partial class Test { - [CommandMethod(nameof(Test_DBTrans))] - public void Test_DBTrans() - { - using DBTrans tr = new(); - if (tr.Editor is null) - return; - tr.Editor.WriteMessage("\n测试 Editor 属性是否工作!"); - tr.Editor.WriteMessage("\n----------开始测试--------------"); - tr.Editor.WriteMessage("\n测试document属性是否工作"); - if (tr.Document == Getdoc()) - { - tr.Editor.WriteMessage("\ndocument 正常"); - } - tr.Editor.WriteMessage("\n测试database属性是否工作"); - if (tr.Database == Getdb()) - { - tr.Editor.WriteMessage("\ndatabase 正常"); - } - - Line line = new(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); - Circle circle = new(new Point3d(0, 0, 0), Vector3d.ZAxis, 2); - // var lienid = tr.AddEntity(line); - // var cirid = tr.AddEntity(circle); - // var linent = tr.GetObject(lienid); - // var lineent = tr.GetObject(cirid); - // var linee = tr.GetObject(cirid); // 经测试,类型不匹配,返回null - // var dd = tr.GetObject(lienid); - // List ds = new() { linee, dd }; - // tr.CurrentSpace.AddEntity(line,tr); - } - // add entity test [CommandMethod(nameof(Test_Addent))] public void Test_Addent() @@ -75,54 +41,7 @@ public void Test_DrawCircle() tr.Editor?.WriteMessage("三点画圆失败"); tr.CurrentSpace.AddEntity(circle3!); } - - [CommandMethod(nameof(Test_LayerAdd0))] - public void Test_LayerAdd0() - { - using DBTrans tr = new(); - tr.LayerTable.Add("1"); - tr.LayerTable.Add("2", lt => { - lt.Color = Color.FromColorIndex(ColorMethod.ByColor, 1); - lt.LineWeight = LineWeight.LineWeight030; - }); - tr.LayerTable.Remove("3"); - tr.LayerTable.Delete("0"); - tr.LayerTable.Change("4", lt => { - lt.Color = Color.FromColorIndex(ColorMethod.ByColor, 2); - }); - } - - - // 添加图层 - [CommandMethod(nameof(Test_LayerAdd1))] - public void Test_LayerAdd1() - { - using DBTrans tr = new(); - tr.LayerTable.Add("test1", Color.FromColorIndex(ColorMethod.ByColor, 1)); - } - - // 添加图层 - [CommandMethod(nameof(Test_LayerAdd2))] - public void Test_LayerAdd2() - { - using DBTrans tr = new(); - tr.LayerTable.Add("test2", 2); - // tr.LayerTable["3"] = new LayerTableRecord(); - } - // 删除图层 - [CommandMethod(nameof(Test_LayerDel))] - public void Test_LayerDel() - { - using DBTrans tr = new(); - Env.Editor.WriteMessage(tr.LayerTable.Delete("0").ToString()); // 删除图层 0 - Env.Editor.WriteMessage(tr.LayerTable.Delete("Defpoints").ToString());// 删除图层 Defpoints - Env.Editor.WriteMessage(tr.LayerTable.Delete("1").ToString()); // 删除不存在的图层 1 - Env.Editor.WriteMessage(tr.LayerTable.Delete("2").ToString()); // 删除有图元的图层 2 - Env.Editor.WriteMessage(tr.LayerTable.Delete("3").ToString()); // 删除图层 3 - - tr.LayerTable.Remove("2"); // 测试是否能强制删除 - } - + // 添加直线 [CommandMethod(nameof(Test_AddLine1))] public void Test_AddLine1() @@ -184,139 +103,34 @@ public void Test_AddPolyline2() tr.CurrentSpace.AddEntity(pl); } - - - - // 测试扩展数据 - static readonly string _appname = "myapp2"; - // 增 - [CommandMethod(nameof(Test_AddXdata))] - public void Test_AddXdata() + [CommandMethod(nameof(Test_AddPolyline3))] + public void Test_AddPolyline3() { - using DBTrans tr = new(); - var appname = "myapp2"; - - tr.RegAppTable.Add("myapp1"); - tr.RegAppTable.Add(appname); // add函数会默认的在存在这个名字的时候返回这个名字的regapp的id,不存在就新建 - tr.RegAppTable.Add("myapp3"); - tr.RegAppTable.Add("myapp4"); + using var tr = new DBTrans(); - var line = new Line(new Point3d(0, 0, 0), new Point3d(1, 1, 0)) + var pts = new List { - XData = new XDataList() - { - { DxfCode.ExtendedDataRegAppName, "myapp1" }, // 可以用dxfcode和int表示组码 - { DxfCode.ExtendedDataAsciiString, "xxxxxxx" }, - {1070, 12 }, - { DxfCode.ExtendedDataRegAppName, appname }, // 可以用dxfcode和int表示组码,移除中间的测试 - { DxfCode.ExtendedDataAsciiString, "要移除的我" }, - {1070, 12 }, - { DxfCode.ExtendedDataRegAppName, "myapp3" }, // 可以用dxfcode和int表示组码 - { DxfCode.ExtendedDataAsciiString, "aaaaaaaaa" }, - {1070, 12 }, - { DxfCode.ExtendedDataRegAppName, "myapp4" }, // 可以用dxfcode和int表示组码 - { DxfCode.ExtendedDataAsciiString, "bbbbbbbbb" }, - {1070, 12 } - } + new(0, 0, 0), + new(0, 1, 0), + new(1, 1, 0), + new(1, 0, 0) }; + var pline = pts.CreatePolyline(); + tr.CurrentSpace.AddEntity(pline); - tr.CurrentSpace.AddEntity(line); - } - // 删 - [CommandMethod(nameof(Test_RemoveXdata))] - public void Test_RemoveXdata() - { - var res = Env.Editor.GetEntity("\n select the entity:"); - if (res.Status == PromptStatus.OK) - { - using DBTrans tr = new(); - var ent = tr.GetObject(res.ObjectId); - if (ent == null || ent.XData == null) - return; - - Env.Printl("\n移除前:" + ent.XData.ToString()); - - ent.RemoveXData(_appname, DxfCode.ExtendedDataAsciiString); - Env.Printl("\n移除成员后:" + ent.XData.ToString()); - - ent.RemoveXData(_appname); - Env.Printl("\n移除appName后:" + ent.XData.ToString()); - } - } - // 查 - [CommandMethod(nameof(Test_GetXdata))] - public void Test_GetXdata() - { - using DBTrans tr = new(); - tr.RegAppTable.ForEach(id => - id.GetObject()?.Name.Print()); - tr.RegAppTable.GetRecords().ForEach(rec => rec.Name.Print()); - tr.RegAppTable.GetRecordNames().ForEach(name => name.Print()); - tr.RegAppTable.ForEach(reg => reg.Name.Print(), checkIdOk: false); - - // var res = ed.GetEntity("\n select the entity:"); - // if (res.Status == PromptStatus.OK) - // { - // using DBTrans tr = new(); - // tr.RegAppTable.ForEach(id => id.GetObject().Print()); - // var data = tr.GetObject(res.ObjectId).XData; - // ed.WriteMessage(data.ToString()); - // } - - // 查询appName里面是否含有某个 - - var res = Env.Editor.GetEntity("\n select the entity:"); - if (res.Status == PromptStatus.OK) + var pline1 = pts.CreatePolyline(p => { - var ent = tr.GetObject(res.ObjectId); - if (ent == null || ent.XData == null) - return; - - XDataList data = ent.XData; - if (data.Contains(_appname)) - Env.Printl("含有appName:" + _appname); - else - Env.Printl("不含有appName:" + _appname); - - var str = "要移除的我"; - if (data.Contains(_appname, str)) - Env.Printl("含有内容:" + str); - else - Env.Printl("不含有内容:" + str); - } - } - // 改 - [CommandMethod(nameof(Test_ChangeXdata))] - public void Test_ChangeXdata() - { - var res = Env.Editor.GetEntity("\n select the entity:"); - if (res.Status != PromptStatus.OK) - return; - using DBTrans tr = new(); - var data = tr.GetObject(res.ObjectId)!; - data.ChangeXData(_appname, DxfCode.ExtendedDataAsciiString, "change"); - - if (data.XData == null) - return; - Env.Printl(data.XData.ToString()); + p.Closed = true; + p.ConstantWidth = 0.2; + p.ColorIndex = 1; + }); + tr.CurrentSpace.AddEntity(pline1); } + - [CommandMethod(nameof(Test_PrintLayerName))] - public void Test_PrintLayerName() - { - using DBTrans tr = new(); - foreach (var layerRecord in tr.LayerTable.GetRecords()) - { - tr.Editor?.WriteMessage(layerRecord.Name); - } - foreach (var layerRecord in tr.LayerTable.GetRecords()) - { - tr.Editor?.WriteMessage(layerRecord.Name); - break; - } - } + [CommandMethod(nameof(Test_Rec))] @@ -348,34 +162,20 @@ public void Test_Rec() #pragma warning disable CS0219 // 变量已被赋值,但从未使用过它的值 Tools.TestTimes(1000000, "三次点乘", () => { - var result = false; - if (Math.Abs(p12.DotProduct(p23)) < 1e8 && - Math.Abs(p23.DotProduct(p34)) < 1e8 && - Math.Abs(p34.DotProduct(p41)) < 1e8) - result = true; + bool result = Math.Abs(p12.DotProduct(p23)) < 1e8 && + Math.Abs(p23.DotProduct(p34)) < 1e8 && + Math.Abs(p34.DotProduct(p41)) < 1e8; }); Tools.TestTimes(1000000, "三次垂直", () => { - var result = false; - if (p12.IsParallelTo(p23) && - p23.IsParallelTo(p34) && - p34.IsParallelTo(p41)) - result = true; + bool result = p12.IsParallelTo(p23) && + p23.IsParallelTo(p34) && + p34.IsParallelTo(p41); }); #pragma warning restore CS0219 // 变量已被赋值,但从未使用过它的值 } - public Database Getdb() - { - var db = Acap.DocumentManager.MdiActiveDocument.Database; - return db; - } - - public Document Getdoc() - { - var doc = Acap.DocumentManager.MdiActiveDocument; - return doc; - } + [CommandMethod(nameof(Test_EntRoration))] diff --git a/tests/TestShared/TestDBTrans.cs b/tests/TestShared/TestDBTrans.cs index 94beb2f..145724a 100644 --- a/tests/TestShared/TestDBTrans.cs +++ b/tests/TestShared/TestDBTrans.cs @@ -2,6 +2,41 @@ public class TestTrans { + [CommandMethod(nameof(Test_DBTrans))] + public void Test_DBTrans() + { + using DBTrans tr = new(); + if (tr.Editor is null) + return; + tr.Editor.WriteMessage("\n测试 Editor 属性是否工作!"); + tr.Editor.WriteMessage("\n----------开始测试--------------"); + tr.Editor.WriteMessage("\n测试document属性是否工作"); + if (tr.Document == Getdoc()) + { + tr.Editor.WriteMessage("\ndocument 正常"); + } + tr.Editor.WriteMessage("\n测试database属性是否工作"); + if (tr.Database == Getdb()) + { + tr.Editor.WriteMessage("\ndatabase 正常"); + } + } + + private static Database Getdb() + { + var db = Acaop.DocumentManager.MdiActiveDocument.Database; + return db; + } + + private static Document Getdoc() + { + var doc = Acaop.DocumentManager.MdiActiveDocument; + return doc; + } + + + + [CommandMethod(nameof(CmdTest_DBTransActiveOpenDwg), CommandFlags.Session)] public static void CmdTest_DBTransActiveOpenDwg() { @@ -140,23 +175,15 @@ public void Test_TopTransaction() var tr1 = HostApplicationServices.WorkingDatabase.TransactionManager.TopTransaction; using DBTrans tr2 = new(); var tr3 = HostApplicationServices.WorkingDatabase.TransactionManager.TopTransaction; - var tr6 = Acap.DocumentManager.MdiActiveDocument.TransactionManager.TopTransaction; + var tr6 = Acaop.DocumentManager.MdiActiveDocument.TransactionManager.TopTransaction; Env.Print(tr2.Transaction == tr3); Env.Print(tr3 == tr6); using DBTrans tr4 = new(); var tr5 = HostApplicationServices.WorkingDatabase.TransactionManager.TopTransaction; - var tr7 = Acap.DocumentManager.MdiActiveDocument.TransactionManager.TopTransaction; + var tr7 = Acaop.DocumentManager.MdiActiveDocument.TransactionManager.TopTransaction; Env.Print(tr4.Transaction == tr5); Env.Print(tr5 == tr7); var trm = HostApplicationServices.WorkingDatabase.TransactionManager; - // var ptt = tr.GetObject(pl).GetClosestPointTo(pt,false); - // var pt1 = new Point3d(0, 0.00000000000001, 0); - // var pt2 = new Point3d(0, 0.00001, 0); - // Env.Print(Tolerance.Global.EqualPoint); - // Env.Print(pt1.IsEqualTo(pt2).ToString()); - // Env.Print(pt1.IsEqualTo(pt2,new Tolerance(0.0,1e-6)).ToString()); - // Env.Print((pt1 == pt2).ToString()); - // Env.Print((pt1 != pt2).ToString()); } } \ No newline at end of file diff --git a/tests/TestShared/TestLayer.cs b/tests/TestShared/TestLayer.cs new file mode 100644 index 0000000..6405a5c --- /dev/null +++ b/tests/TestShared/TestLayer.cs @@ -0,0 +1,66 @@ +namespace Test; + +public class TestLayer +{ + [CommandMethod(nameof(Test_LayerAdd0))] + public void Test_LayerAdd0() + { + using DBTrans tr = new(); + tr.LayerTable.Add("1"); + tr.LayerTable.Add("2", lt => { + lt.Color = Color.FromColorIndex(ColorMethod.ByColor, 1); + lt.LineWeight = LineWeight.LineWeight030; + }); + tr.LayerTable.Remove("3"); + tr.LayerTable.Delete("0"); + tr.LayerTable.Change("4", lt => { + lt.Color = Color.FromColorIndex(ColorMethod.ByColor, 2); + }); + } + + + // 添加图层 + [CommandMethod(nameof(Test_LayerAdd1))] + public void Test_LayerAdd1() + { + using DBTrans tr = new(); + tr.LayerTable.Add("test1", Color.FromColorIndex(ColorMethod.ByColor, 1)); + } + + // 添加图层 + [CommandMethod(nameof(Test_LayerAdd2))] + public void Test_LayerAdd2() + { + using DBTrans tr = new(); + tr.LayerTable.Add("test2", 2); + // tr.LayerTable["3"] = new LayerTableRecord(); + } + // 删除图层 + [CommandMethod(nameof(Test_LayerDel))] + public void Test_LayerDel() + { + using DBTrans tr = new(); + Env.Printl(tr.LayerTable.Delete("0").ToString()); // 删除图层 0 + Env.Printl(tr.LayerTable.Delete("Defpoints").ToString());// 删除图层 Defpoints + Env.Printl(tr.LayerTable.Delete("1").ToString()); // 删除不存在的图层 1 + Env.Printl(tr.LayerTable.Delete("2").ToString()); // 删除有图元的图层 2 + Env.Printl(tr.LayerTable.Delete("3").ToString()); // 删除图层 3 + + tr.LayerTable.Remove("2"); // 测试是否能强制删除 + } + + [CommandMethod(nameof(Test_PrintLayerName))] + public void Test_PrintLayerName() + { + using DBTrans tr = new(); + foreach (var layerRecord in tr.LayerTable.GetRecords()) + { + Env.Printl(layerRecord.Name); + } + foreach (var layerRecord in tr.LayerTable.GetRecords()) + { + Env.Printl(layerRecord.Name); + break; + } + } +} \ No newline at end of file diff --git a/tests/TestShared/TestShared.projitems b/tests/TestShared/TestShared.projitems index e6dfbbe..b29bbf6 100644 --- a/tests/TestShared/TestShared.projitems +++ b/tests/TestShared/TestShared.projitems @@ -29,6 +29,7 @@ + @@ -38,6 +39,7 @@ + diff --git a/tests/TestShared/TestXdata.cs b/tests/TestShared/TestXdata.cs new file mode 100644 index 0000000..7ac2d31 --- /dev/null +++ b/tests/TestShared/TestXdata.cs @@ -0,0 +1,108 @@ +namespace Test; + +public class TestXdata +{ + // 测试扩展数据 + private const string Appname = "myapp2"; + + // 增 + [CommandMethod(nameof(Test_AddXdata))] + public void Test_AddXdata() + { + using DBTrans tr = new(); + + tr.RegAppTable.Add("myapp1"); + tr.RegAppTable.Add(Appname); // add函数会默认的在存在这个名字的时候返回这个名字的regapp的id,不存在就新建 + tr.RegAppTable.Add("myapp3"); + tr.RegAppTable.Add("myapp4"); + + var line = new Line(new Point3d(0, 0, 0), new Point3d(1, 1, 0)) + { + XData = new XDataList() + { + { DxfCode.ExtendedDataRegAppName, "myapp1" }, // 可以用dxfcode和int表示组码 + { DxfCode.ExtendedDataAsciiString, "xxxxxxx" }, + {1070, 12 }, + { DxfCode.ExtendedDataRegAppName, Appname }, // 可以用dxfcode和int表示组码,移除中间的测试 + { DxfCode.ExtendedDataAsciiString, "要移除的我" }, + {1070, 12 }, + { DxfCode.ExtendedDataRegAppName, "myapp3" }, // 可以用dxfcode和int表示组码 + { DxfCode.ExtendedDataAsciiString, "aaaaaaaaa" }, + {1070, 12 }, + { DxfCode.ExtendedDataRegAppName, "myapp4" }, // 可以用dxfcode和int表示组码 + { DxfCode.ExtendedDataAsciiString, "bbbbbbbbb" }, + {1070, 12 } + } + }; + + tr.CurrentSpace.AddEntity(line); + } + // 删 + [CommandMethod(nameof(Test_RemoveXdata))] + public void Test_RemoveXdata() + { + var res = Env.Editor.GetEntity("\n select the entity:"); + if (res.Status != PromptStatus.OK) return; + + using DBTrans tr = new(); + var ent = tr.GetObject(res.ObjectId); + if (ent == null || ent.XData == null) + return; + + Env.Printl("\n移除前:" + ent.XData); + + ent.RemoveXData(Appname, DxfCode.ExtendedDataAsciiString); + Env.Printl("\n移除成员后:" + ent.XData); + + ent.RemoveXData(Appname); + Env.Printl("\n移除appName后:" + ent.XData); + } + // 查 + [CommandMethod(nameof(Test_GetXdata))] + public void Test_GetXdata() + { + using DBTrans tr = new(); + tr.RegAppTable.ForEach(id => + id.GetObject()?.Name.Print()); + tr.RegAppTable.GetRecords().ForEach(rec => rec.Name.Print()); + tr.RegAppTable.GetRecordNames().ForEach(name => name.Print()); + tr.RegAppTable.ForEach(reg => reg.Name.Print(), checkIdOk: false); + + // 查询appName里面是否含有某个 + + var res = Env.Editor.GetEntity("\n select the entity:"); + if (res.Status != PromptStatus.OK) return; + + var ent = tr.GetObject(res.ObjectId); + if (ent == null || ent.XData == null) + return; + + XDataList data = ent.XData; + if (data.Contains(Appname)) + Env.Printl("含有appName:" + Appname); + else + Env.Printl("不含有appName:" + Appname); + + const string str = "要移除的我"; + if (data.Contains(Appname, str)) + Env.Printl("含有内容:" + str); + else + Env.Printl("不含有内容:" + str); + } + // 改 + [CommandMethod(nameof(Test_ChangeXdata))] + public void Test_ChangeXdata() + { + var res = Env.Editor.GetEntity("\n select the entity:"); + if (res.Status != PromptStatus.OK) return; + + using DBTrans tr = new(); + var data = tr.GetObject(res.ObjectId)!; + data.ChangeXData(Appname, DxfCode.ExtendedDataAsciiString, "change"); + + if (data.XData == null) + return; + Env.Printl(data.XData.ToString()); + } + +} \ No newline at end of file -- Gitee From eeee0b36c41582a3e93ea210f6f6eab762950f40 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 6 Jul 2023 15:22:33 +0800 Subject: [PATCH 145/453] =?UTF-8?q?=E8=A7=84=E8=8C=83Event=E6=9E=9A?= =?UTF-8?q?=E4=B8=BE=E7=B1=BB=E7=9A=84=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Event/IFox.Event.Shared/EventFactory/CadEvent.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Event/IFox.Event.Shared/EventFactory/CadEvent.cs b/src/Event/IFox.Event.Shared/EventFactory/CadEvent.cs index 570a414..3b91cdc 100644 --- a/src/Event/IFox.Event.Shared/EventFactory/CadEvent.cs +++ b/src/Event/IFox.Event.Shared/EventFactory/CadEvent.cs @@ -6,25 +6,25 @@ public enum CadEvent /// /// 无 /// - None = 0b0, + None = 0, /// /// 全选 /// - All = 0b1111111111111111111111111111111, + All = -1, /// /// 系统变量修改 /// - SystemVariableChanged = 0b1, + SystemVariableChanged = 1 << 1, /// /// 文档锁定事件 /// - DocumentLockModeChanged = 0b10, + DocumentLockModeChanged = 1 << 2, /// /// 开始双击 /// - BeginDoubleClick = 0b100, + BeginDoubleClick = 1 << 3, /// /// 文档激活 /// - DocumentActivated = 0b1000, + DocumentActivated = 1 << 4, } \ No newline at end of file -- Gitee From 4b2a388ae1dc6d5ef89572dead4b3d0fdc3b585c Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 6 Jul 2023 17:02:50 +0800 Subject: [PATCH 146/453] =?UTF-8?q?=E5=85=81=E8=AE=B8=E6=A0=87=E8=AE=B0?= =?UTF-8?q?=E7=89=B9=E5=BE=81=E5=AD=97=E7=AC=A6=E4=B8=B2=E7=9A=84=E4=BA=8B?= =?UTF-8?q?=E4=BB=B6=E9=87=8D=E5=A4=8D=E5=8A=A0=E5=9C=A8=E5=90=8C=E4=B8=80?= =?UTF-8?q?=E4=B8=AA=E6=96=B9=E6=B3=95=E4=B8=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../EventEx/DocumentLockModeChangedEvent.cs | 5 ++--- .../IFox.Event.Shared/EventEx/SystemVariableChangedEvent.cs | 1 - 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Event/IFox.Event.Shared/EventEx/DocumentLockModeChangedEvent.cs b/src/Event/IFox.Event.Shared/EventEx/DocumentLockModeChangedEvent.cs index 3ec726c..e5acb16 100644 --- a/src/Event/IFox.Event.Shared/EventEx/DocumentLockModeChangedEvent.cs +++ b/src/Event/IFox.Event.Shared/EventEx/DocumentLockModeChangedEvent.cs @@ -49,7 +49,6 @@ internal static void Initlize(Assembly assembly) if (ept is null) throw new ArgumentException($"{nameof(DocumentLockModeChangedAttribute)}Եķ{type.Name}.{methodInfo.Name}ʹ"); dic[key].Add(new(methodInfo, ept.Value, targetAtt.Level)); - break; } } } @@ -99,10 +98,10 @@ private static void DocumentManager_DocumentLockModeChanged(object sender, Docum } } -[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)] +[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = true)] public class DocumentLockModeChangedAttribute : Attribute { - /// s + /// /// ϵͳ޸ʱǵĺ /// ֵӦΪvoid /// 2ֻΪobjectDocumentLockModeChangedEventArgs diff --git a/src/Event/IFox.Event.Shared/EventEx/SystemVariableChangedEvent.cs b/src/Event/IFox.Event.Shared/EventEx/SystemVariableChangedEvent.cs index bdca9df..798e35f 100644 --- a/src/Event/IFox.Event.Shared/EventEx/SystemVariableChangedEvent.cs +++ b/src/Event/IFox.Event.Shared/EventEx/SystemVariableChangedEvent.cs @@ -49,7 +49,6 @@ internal static void Initlize(Assembly assembly) if (ept is null) throw new ArgumentException($"{nameof(SystemVariableChangedAttribute)}Եķ{type.Name}.{methodInfo.Name}ʹ"); dic[key].Add(new(methodInfo, ept.Value, targetAtt.Level)); - break; } } } -- Gitee From 04f2dbb714178dd0b43c391c1a0da8d1a208091b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=91=E5=82=B2=E5=B4=96-=E5=BF=98=E9=9C=84?= <702099480@qq.com> Date: Fri, 21 Jul 2023 00:56:42 +0000 Subject: [PATCH 147/453] =?UTF-8?q?update=20src/CAD/IFox.CAD.Shared/Extens?= =?UTF-8?q?ionMethod/EditorEx.cs.=20=E4=BD=BF=E7=94=A8DrawVectors=E6=97=B6?= =?UTF-8?q?=EF=BC=8C=E5=9C=A8=E5=B1=8F=E5=B9=95=E6=B2=A1=E6=9C=89=E4=BB=BB?= =?UTF-8?q?=E4=BD=95=E6=98=BE=E7=A4=BA=EF=BC=8C=E5=A2=9E=E5=8A=A0DrawLineV?= =?UTF-8?q?ectors=E7=BB=98=E5=88=B6=E5=A4=9A=E6=9D=A1=E7=BA=BF=E6=AE=B5?= =?UTF-8?q?=E5=92=8CDrawEndToEndVectors=E7=BB=98=E5=88=B6=E9=A6=96?= =?UTF-8?q?=E5=B0=BE=E7=9B=B8=E8=BF=9E=E7=9A=84=E7=9F=A2=E9=87=8F=E5=9B=BE?= =?UTF-8?q?=E5=BD=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 云傲崖-忘霄 <702099480@qq.com> --- .../ExtensionMethod/EditorEx.cs | 44 ++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs index a1043d0..4df7607 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs @@ -602,7 +602,49 @@ public static void DrawCircle(this Editor editor, Point2d pnt, short colorIndex, editor.DrawVectors(pnts, colorIndex, true); } - + /// + /// 根据点表绘制矢量线段(每两点为一条线段的起始点和终止点) + /// + /// 用户交互对象 + /// 点表 + /// CAD颜色索引 默认-红色 + /// 是否高亮显示,默认为 + public static void DrawLineVectors(this Editor editor, IEnumerable points, int colorIndex = 1, + bool drawHighlighted = false) + { + Point3d endPoint1, endPoint2; + var itor = points.GetEnumerator(); + while (itor.MoveNext()) + { + endPoint1 = itor.Current; + if (!itor.MoveNext()) return; + endPoint2 = itor.Current; + editor.DrawVector(endPoint1, endPoint2, colorIndex, drawHighlighted); + } + } + /// + /// 根据点表绘制首尾相连的矢量 + /// + /// 用户交互对象 + /// 点表 + /// CAD颜色索引;默认:1为红色 + /// 是否闭合; 为闭合,默认: 为不闭合 + /// 是否高亮显示;为高亮显示,默认:为不高亮显示 + public static void DrawEndToEndVectors(this Editor editor, IEnumerable points, int colorIndex = 1, + bool isclose = false, bool drawHighlighted = false) + { + var itor = points.GetEnumerator(); + if (points.Count() < 1 || !itor.MoveNext()) return; + Point3d endPoint1 = itor.Current, endPoint2 = new(), firstEndPoint = endPoint1; + while (itor.MoveNext()) + { + endPoint2 = itor.Current; + editor.DrawVector(endPoint1, endPoint2, colorIndex, drawHighlighted); + endPoint1 = endPoint2; + } + if (isclose) + editor.DrawVector(endPoint2, firstEndPoint, colorIndex, drawHighlighted); + } #endregion #region 矩阵 -- Gitee From 6fca3f544b04edbf2220678cb39bcf71dc0ce247 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=91=E5=82=B2=E5=B4=96-=E5=BF=98=E9=9C=84?= <702099480@qq.com> Date: Fri, 21 Jul 2023 01:15:53 +0000 Subject: [PATCH 148/453] update src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 云傲崖-忘霄 <702099480@qq.com> --- src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs index 4df7607..c083b35 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs @@ -607,8 +607,8 @@ public static void DrawCircle(this Editor editor, Point2d pnt, short colorIndex, /// /// 用户交互对象 /// 点表 - /// CAD颜色索引 默认-红色 - /// 是否高亮显示,默认为 + /// CAD颜色索引;默认:1为红色 + /// 是否高亮显示;为高亮显示,默认:为不高亮显示 public static void DrawLineVectors(this Editor editor, IEnumerable points, int colorIndex = 1, bool drawHighlighted = false) { -- Gitee From d877c8e02ac25ade22af14894d9a1ba7e92f6ac8 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Fri, 21 Jul 2023 16:49:16 +0800 Subject: [PATCH 149/453] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=9C=86=E5=BC=A7?= =?UTF-8?q?=E8=BD=AC=E5=A4=9A=E6=AE=B5=E7=BA=BF=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/Entity/ArcEx.cs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/ArcEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/ArcEx.cs index a037653..53f5825 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/ArcEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/ArcEx.cs @@ -65,6 +65,22 @@ public static Arc CreateArc(Point3d startPoint, Point3d centerPoint, double angl arc.EndAngle = startVector.Angle + angle; return arc; } - + /// + /// 圆弧转为多段线 + /// + /// 圆弧 + /// 多段线 + public static Polyline ToPolyline(this Arc arc) + { + var plane = new Plane(arc.Center, arc.Normal); + var pl = new Polyline(); + pl.Normal = arc.Normal; + pl.AddVertexAt(0, arc.StartPoint.Convert2d(plane), + Math.Tan(arc.TotalAngle * 0.25), 0, 0); + pl.AddVertexAt(1, arc.EndPoint.Convert2d(plane), 0, 0, 0); + pl.TransformBy(Matrix3d.Displacement(pl.StartPoint.GetVectorTo(arc.StartPoint))); + pl.SetPropertiesFrom(arc); + return pl; + } #endregion } \ No newline at end of file -- Gitee From 40daa5782eea4f3c5f1016d434c227bd114b9e51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=91=E5=82=B2=E5=B4=96-=E5=BF=98=E9=9C=84?= <702099480@qq.com> Date: Fri, 28 Jul 2023 08:06:08 +0000 Subject: [PATCH 150/453] =?UTF-8?q?=E4=BF=AE=E5=A4=8Ddrawvectors=E5=87=BD?= =?UTF-8?q?=E6=95=B0=E9=94=99=E8=AF=AF.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 云傲崖-忘霄 <702099480@qq.com> --- src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs index c083b35..4d7915a 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs @@ -534,7 +534,7 @@ public static void DrawVectors(this Editor editor, IEnumerable pnts, sh var rlst = new LispList { { LispDataType.Int16, colorIndex } }; rlst.AddRange(GetLines(pnts, isClosed)); - editor.DrawVectors(rlst, editor.CurrentUserCoordinateSystem); + editor.DrawVectors(new(rlst.ToArray()), Matrix3d.Identity); } /// @@ -577,7 +577,7 @@ public static void DrawCircles(this Editor editor, IEnumerable pnts, sh rlst.AddRange(GetLines(tpnts, true)); } - editor.DrawVectors(rlst, editor.CurrentUserCoordinateSystem); + editor.DrawVectors(new(rlst.ToArray()), editor.CurrentUserCoordinateSystem); } /// -- Gitee From f8c003e56d0effca3a54ebdb7a9d0136d11e6acf Mon Sep 17 00:00:00 2001 From: vicwjb Date: Sat, 29 Jul 2023 16:31:23 +0800 Subject: [PATCH 151/453] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=BC=A7=E5=BA=A6?= =?UTF-8?q?=E8=A7=92=E5=BA=A6=E4=BA=92=E8=BD=AC=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Basal/IFox.Basal.Shared/General/MathEx.cs | 22 +++++++++++++++++++ .../IFox.Basal.Shared.projitems | 1 + tests/TestShared/TestPoint.cs | 22 ++++++++++++++----- 3 files changed, 40 insertions(+), 5 deletions(-) create mode 100644 src/Basal/IFox.Basal.Shared/General/MathEx.cs diff --git a/src/Basal/IFox.Basal.Shared/General/MathEx.cs b/src/Basal/IFox.Basal.Shared/General/MathEx.cs new file mode 100644 index 0000000..d33b404 --- /dev/null +++ b/src/Basal/IFox.Basal.Shared/General/MathEx.cs @@ -0,0 +1,22 @@ +namespace IFoxCAD.Basal; + +/// +/// 数学函数扩展类 +/// +public static class MathEx +{ + /// + /// 转换弧度到角度 + /// + /// 弧度值 + /// 角度(10进制小数) + public static double ConvertRadToDeg(double rad) => rad / Math.PI * 180; + + /// + /// 转换角度(10进制小数)到弧度 + /// + /// 角度 + /// 弧度 + public static double ConvertDegToRad(double deg) => deg / 180 * Math.PI; +} + diff --git a/src/Basal/IFox.Basal.Shared/IFox.Basal.Shared.projitems b/src/Basal/IFox.Basal.Shared/IFox.Basal.Shared.projitems index 9328526..7b0e25f 100644 --- a/src/Basal/IFox.Basal.Shared/IFox.Basal.Shared.projitems +++ b/src/Basal/IFox.Basal.Shared/IFox.Basal.Shared.projitems @@ -26,6 +26,7 @@ + diff --git a/tests/TestShared/TestPoint.cs b/tests/TestShared/TestPoint.cs index f3ba101..4f5beef 100644 --- a/tests/TestShared/TestPoint.cs +++ b/tests/TestShared/TestPoint.cs @@ -1,11 +1,23 @@ namespace Test; - - -using System.Diagnostics; - - public class TestPoint { + [CommandMethod(nameof(Test_GetAngle))] + public void Test_GetAngle() + { + var pt1 = new Point2d(0, 0); + var pt2 = new Point2d(1, 1); + var angle_pt1_pt2 = pt1.GetAngle(pt2); + var angle_pt2_pt1 = pt2.GetAngle(pt1); + Env.Printl($"pt1-pt2 angle is : {angle_pt1_pt2}, 角度是: {MathEx.ConvertRadToDeg(angle_pt1_pt2)}"); + Env.Printl($"pt2-pt1 angle is : {angle_pt2_pt1}, 角度是: {MathEx.ConvertRadToDeg(angle_pt2_pt1)}"); + + var polar = pt1.Polar(Math.PI / 2, 10); + Env.Printl($"pt1 90° 距离10的点是: {polar}"); + + } + + + /// /// 红黑树排序点集 /// -- Gitee From 169d9ff42684bca2d801bd75ffb4711f09952cb2 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Sun, 30 Jul 2023 22:01:28 +0800 Subject: [PATCH 152/453] =?UTF-8?q?=E4=BF=AE=E5=A4=8DAppendSupportPath?= =?UTF-8?q?=E7=9A=84=E9=94=99=E8=AF=AF=EF=BC=8C=E5=90=8C=E6=97=B6=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E7=A7=BB=E9=99=A4cad=E6=94=AF=E6=8C=81=E7=9B=AE?= =?UTF-8?q?=E5=BD=95=E7=9A=84=E5=87=BD=E6=95=B0=E3=80=82fixed=20#I7ONZ3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/AutoReg/AutoLoad.cs | 26 ------- src/CAD/IFox.CAD.Shared/Runtime/Env.cs | 76 +++++++++++++++++++-- tests/TestShared/CmdINI.cs | 2 +- tests/TestShared/TestEnv.cs | 57 ++++++++++++++++ 4 files changed, 127 insertions(+), 34 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/AutoReg/AutoLoad.cs b/src/CAD/IFox.CAD.Shared/AutoReg/AutoLoad.cs index a3efa5c..5eaf5b9 100644 --- a/src/CAD/IFox.CAD.Shared/AutoReg/AutoLoad.cs +++ b/src/CAD/IFox.CAD.Shared/AutoReg/AutoLoad.cs @@ -58,32 +58,6 @@ private static RegistryKey GetAcAppKey() RegistryKey ackey = Registry.CurrentUser.OpenSubKey(key, true); return ackey.CreateSubKey("Applications"); } - /// - /// 添加 path 到 acad环境变量 - /// - /// 目录 - protected static void AppendSupportPath(string path) - { - - string key = HostApplicationServices.Current.UserRegistryProductRootKey; - // 计算机\HKEY_CURRENT_USER\SOFTWARE\Autodesk\AutoCAD\R24.0\ACAD-4101:804 - RegistryKey ackey = Registry.CurrentUser.OpenSubKey($@"{key}\Profiles"); - - var listkey = ackey.GetSubKeyNames(); - foreach (var item in listkey) - { - var acadkey = ackey.OpenSubKey($@"{item}\General", true); - var name = "ACAD"; - var str = acadkey.GetValue(name)?.ToString(); - if (str is not null && !str.Contains(path)) - { - acadkey.SetValue(name, $@"{str}{path};"); - } - - } - - ackey.Close(); - } private bool SearchForReg() { diff --git a/src/CAD/IFox.CAD.Shared/Runtime/Env.cs b/src/CAD/IFox.CAD.Shared/Runtime/Env.cs index aadcc0f..f204bc1 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/Env.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/Env.cs @@ -445,7 +445,7 @@ public static bool Include(this OSModeType osm1, OSModeType osm2) /// /// 变量名 /// 变量值 - public static object? GetVar(string? varName) + public static object GetVar(string varName) { return Acaop.GetSystemVariable(varName); } @@ -510,7 +510,7 @@ public static void SetVar(string varName, object value, bool echo = true) /// /// 变量名 /// 返回值从不为null,需判断 - public static string GetEnv(string? name) + public static string GetEnv(string name) { // 它将混合查询以下路径: // acad2008注册表路径: 计算机\HKEY_CURRENT_USER\SOFTWARE\Autodesk\AutoCAD\R17.1\ACAD-6001:804\FixedProfile\General @@ -534,7 +534,7 @@ public static string GetEnv(string? name) /// 变量名 /// 变量值 /// - public static int SetEnv(string? name, string? var) + public static int SetEnv(string name, string var) { return AcedSetEnv(name, new StringBuilder(var)); } @@ -565,6 +565,70 @@ public static int SetEnv(string? name, string? var) // } #endregion + #region 支持文件目录 + + /// + /// 添加目录至CAD支持搜索的路径 + /// + /// 目录 + public static void AppendSupportPath(params string[] folders) + { + if (!folders.Any()) return; + var acadPath = GetEnv("ACAD"); + var acadPathLower = acadPath.ToLower(); + acadPath = folders + // 路径不存在或者格式非法会导致添加失败 + .Where(item => Directory.Exists(item) && !acadPathLower.Contains(item.ToLower())) + .Aggregate(acadPath, (current, item) => current + ";" + item); + if (acadPath != null) SetEnv("ACAD", acadPath); + } + + /// + /// 删除支持搜索文件目录 + /// + /// 目录 + public static void RemoveSupportPath(params string[] folders) + { + var acadPath = GetEnv("ACAD"); + var acadPathArr = acadPath.Split(';').ToList(); + foreach (var folder in folders) + { + acadPathArr.RemoveAll(item => item.ToLower().Contains(folder.ToLower())); + } + SetEnv("ACAD", string.Join(";", acadPathArr)); + } + + /// + /// 添加目录至CAD受信任的位置 + /// + /// 目录 + public static void AppendTrustedPath(params string[] folders) + { + if (!folders.Any()) return; + var trustedPath = Env.GetVar("TRUSTEDPATHS").ToString(); + var trustedPathLower = trustedPath.ToLower(); + trustedPath = folders + .Where(item => + Directory.Exists(item) && !trustedPathLower.Contains(item.ToLower())) + .Aggregate(trustedPath, (current, item) => current + ";" + item); + if (trustedPath != null) SetVar("TRUSTEDPATHS", trustedPath); + } + /// + /// 移除信任目录 + /// + /// 目录 + public static void RemoveTrustedPath(params string[] folders) + { + var trustedPath = GetVar("TRUSTEDPATHS").ToString(); + var trustedPathArr = trustedPath.Split(';').ToList(); + foreach (var folder in folders) + { + trustedPathArr.RemoveAll(item => item.ToLower().Contains(folder.ToLower())); + } + SetVar("TRUSTEDPATHS", string.Join(";", trustedPathArr)); + } + + #endregion /// /// 命令行打印,会自动调用对象的toString函数 @@ -581,7 +645,7 @@ public static int SetEnv(string? name, string? var) /// 判断当前是否在UCS坐标下 /// /// Bool - public static bool IsUcs() => (short)GetVar("WORLDUCS")! == 0; + public static bool IsUcs() => (short)GetVar("WORLDUCS") == 0; #region dwg版本号/cad版本号/年份 @@ -690,12 +754,10 @@ public static string GetAcapVersionDll(string str = "acdb") /// /// 成功返回当前值,失败null /// - public static object? SetVarEx(string key, string value) + public static object SetVarEx(string key, string value) { var currentVar = GetVar(key); - if (currentVar is null) - return null; object valueType = currentVar.GetType().Name switch { diff --git a/tests/TestShared/CmdINI.cs b/tests/TestShared/CmdINI.cs index 0eeff28..363e360 100644 --- a/tests/TestShared/CmdINI.cs +++ b/tests/TestShared/CmdINI.cs @@ -176,7 +176,7 @@ public override void Initialize() Env.Print("loading..."); // 将程序的目录加入信任路径 - AppendSupportPath(CurrentDirectory.FullName); + // Env.AppendSupportPath(CurrentDirectory.FullName); } public override void Terminate() diff --git a/tests/TestShared/TestEnv.cs b/tests/TestShared/TestEnv.cs index 9aaaa0c..88eb912 100644 --- a/tests/TestShared/TestEnv.cs +++ b/tests/TestShared/TestEnv.cs @@ -123,5 +123,62 @@ public static void Test_GetEnv() Env.Printl("GetEnv:" + Env.GetEnv("abc")); Env.Printl("GetEnv PATH:" + Env.GetEnv("PATH")); + + Env.Printl($"getenv-acad: {Env.GetEnv("ACAD")}"); + Env.Printl($"getvar-acad: {Env.GetVar("TRUSTEDPATHS")}"); + Env.Printl($"getenv-TRUSTEDPATHS: {Env.GetEnv("TRUSTEDPATHS")}"); + Env.Printl($"getenv-osmode: {Env.GetEnv("osmode")}"); + Env.Printl($"getvar-osmode: {Env.GetVar("osmode")}"); } + [CommandMethod(nameof(Test_AppendPath))] + public static void Test_AppendPath() + { + Directory.Exists(@"C:\Folder4").Print(); + Env.AppendSupportPath(@"C:\Folder4", @"C:\Folder5", @"C:\Folder6"); + // Env.AppendTrustedPath(@"c:\a\x",@"c:\a\c"); + // AppendSupportPath(@"c:\a\c"); + Env.GetEnv("ACAD").Print(); + // Env.SetEnv("ACAD", @"C:\Folder1;"+Env.GetEnv("ACAD")); + Env.GetEnv("ACAD").Contains(@"C:\Folder1").Print(); + + } + + [CommandMethod(nameof(Test_RemovePath))] + public static void Test_RemovePath() + { + // var acad = Acaop.TryGetSystemVariable("ACAD").ToString(); + // acad.Print(); + // Acaop.SetSystemVariable("ACAD", acad + @";c:\a\x"); + Env.GetEnv("ACAD").Print(); + Env.RemoveSupportPath(); + // Env.RemoveTrustedPath(@"c:\a\x"); + Env.GetEnv("ACAD").Print(); + } + + public static void AppendSupportPath(string path) + { + + string key = HostApplicationServices.Current.UserRegistryProductRootKey; + // 计算机\HKEY_CURRENT_USER\SOFTWARE\Autodesk\AutoCAD\R24.0\ACAD-4101:804 + var ackey = Registry.CurrentUser.OpenSubKey($@"{key}\Profiles") ?? null; + + if (ackey != null) + { + var listkey = ackey.GetSubKeyNames(); + foreach (var item in listkey) + { + var acadkey = ackey.OpenSubKey($@"{item}\General", true); + const string name = "ACAD"; + var str = acadkey?.GetValue(name)?.ToString(); + if (str != null && !str.ToLower().Contains(path.ToLower())) + { + acadkey?.SetValue(name, $@"{str}{path};"); + } + } + } + + ackey?.Close(); + } + + } \ No newline at end of file -- Gitee From b0ba804fb1d4ccbba6e8f1e3e81ac09fa20582b0 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Sun, 30 Jul 2023 22:36:22 +0800 Subject: [PATCH 153/453] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20Point2dCollection?= =?UTF-8?q?=20=E6=96=B9=E6=B3=95EndToEnd=E9=94=99=E8=AF=AF=E3=80=82=20fixe?= =?UTF-8?q?d=20#I7NOQO?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/PointEx.cs | 41 +++++++++++------- tests/TestShared/TestPoint.cs | 43 ++++++++++++++++++- 2 files changed, 66 insertions(+), 18 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/PointEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/PointEx.cs index 307e234..76220f9 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/PointEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/PointEx.cs @@ -78,7 +78,7 @@ public static Point3d GetMidPointTo(this Point3d pt1, Point3d pt2) /// /// 点 /// 新点 - internal static Point3d Z20(this Point3d point) + public static Point3d Z20(this Point3d point) { return new Point3d(point.X, point.Y, 0); } @@ -124,8 +124,8 @@ public static Point3d Point3d(this Point2d pt, double z = 0) /// 目标用户坐标 public static Point3d TransPoint(this Point3d basePt, Point3d userPt, Point3d transPt, double ang) { - Matrix3d transMat = Matrix3d.Displacement(userPt - basePt); - Matrix3d roMat = Matrix3d.Rotation(-ang, Vector3d.ZAxis, userPt); + var transMat = Matrix3d.Displacement(userPt - basePt); + var roMat = Matrix3d.Rotation(-ang, Vector3d.ZAxis, userPt); return transPt.TransformBy(roMat * transMat); } /// @@ -163,21 +163,30 @@ public static Point2d Polar(this Point2d pt, double ang, double len) /// 逆时针为正,顺时针为负 public static double GetArcBulge(this Point2d arc1, Point2d arc2, Point2d arc3, double tol = 1e-10) { - double dStartAngle = arc2.GetAngle(arc1); - double dEndAngle = arc2.GetAngle(arc3); + var dStartAngle = arc2.GetAngle(arc1); + var dEndAngle = arc2.GetAngle(arc3); // 求的P1P2与P1P3夹角 var talAngle = (Math.PI - dStartAngle + dEndAngle) / 2; // 凸度==拱高/半弦长==拱高比值/半弦长比值 // 有了比值就不需要拿到拱高值和半弦长值了,因为接下来是相除得凸度 - double bulge = Math.Sin(talAngle) / Math.Cos(talAngle); - - // 处理精度 - if (bulge is > 0.9999 and < 1.0001) - bulge = 1; - else if (bulge is < -0.9999 and > -1.0001) - bulge = -1; - else if (Math.Abs(bulge) < tol) - bulge = 0; + var bulge = Math.Sin(talAngle) / Math.Cos(talAngle); + + switch (bulge) + { + // 处理精度 + case > 0.9999 and < 1.0001: + bulge = 1; + break; + case < -0.9999 and > -1.0001: + bulge = -1; + break; + default: + { + if (Math.Abs(bulge) < tol) + bulge = 0; + break; + } + } return bulge; } @@ -196,7 +205,7 @@ public static void End2End(this Point2dCollection ptcol) // 首尾不同,去加一个到最后 var lst = new Point2d[ptcol.Count + 1]; - for (int i = 0; i < lst.Length; i++) + for (int i = 0; i < ptcol.Count; i++) lst[i] = ptcol[i]; lst[^1] = lst[0]; @@ -215,7 +224,7 @@ public static void End2End(this Point3dCollection ptcol) // 首尾不同,去加一个到最后 var lst = new Point3d[ptcol.Count + 1]; - for (int i = 0; i < lst.Length; i++) + for (int i = 0; i < ptcol.Count; i++) lst[i] = ptcol[i]; lst[^1] = lst[0]; diff --git a/tests/TestShared/TestPoint.cs b/tests/TestShared/TestPoint.cs index 4f5beef..d6b5f57 100644 --- a/tests/TestShared/TestPoint.cs +++ b/tests/TestShared/TestPoint.cs @@ -15,8 +15,47 @@ public void Test_GetAngle() Env.Printl($"pt1 90° 距离10的点是: {polar}"); } - - + [CommandMethod(nameof(Test_Endtoend))] + public void Test_Endtoend() + { + var pts = new Point2dCollection + { + new(0, 0), + new(0, 1), + new(1, 1), + new(1, 0) + }; + foreach (var pt in pts) + { + Env.Printl($"X={pt.X},Y={pt.Y}"); + } + pts.End2End(); + Env.Printl("-------"); + foreach (var pt in pts) + { + Env.Printl($"X={pt.X},Y={pt.Y}"); + } + Env.Printl("--------"); + var ptss = new Point3dCollection + { + new(0, 0,0), + new(0, 1,0), + new(1, 1,0), + new(1, 0,0) + }; + + foreach (Point3d pt in ptss) + { + Env.Printl($"X={pt.X},Y={pt.Y},Z={pt.Z}"); + } + ptss.End2End(); + Env.Printl("-------"); + foreach (Point3d pt in ptss) + { + Env.Printl($"X={pt.X},Y={pt.Y},Z={pt.Z}"); + } + + } /// /// 红黑树排序点集 -- Gitee From f3bab12c98fbbd91fe04b9c28517d762896f9de6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=91=E5=82=B2=E5=B4=96?= <702099480@qq.com> Date: Mon, 31 Jul 2023 10:02:57 +0800 Subject: [PATCH 154/453] =?UTF-8?q?=E5=A2=9E=E5=8A=A0CAD=E9=94=99=E8=AF=AF?= =?UTF-8?q?=E5=A4=A7=E5=85=A8ErrorInfoEx=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.ACAD/GlobalUsings.cs | 1 + src/CAD/IFox.CAD.GCAD/GlobalUsings.cs | 1 + .../ExtensionMethod/ErrorInfoEx.cs | 421 ++++++++++++++++++ .../IFox.CAD.Shared/IFox.CAD.Shared.projitems | 1 + src/CAD/IFox.CAD.ZCAD/GlobalUsings.cs | 1 + 5 files changed, 425 insertions(+) create mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/ErrorInfoEx.cs diff --git a/src/CAD/IFox.CAD.ACAD/GlobalUsings.cs b/src/CAD/IFox.CAD.ACAD/GlobalUsings.cs index 2e27cbf..09348ab 100644 --- a/src/CAD/IFox.CAD.ACAD/GlobalUsings.cs +++ b/src/CAD/IFox.CAD.ACAD/GlobalUsings.cs @@ -25,6 +25,7 @@ global using Autodesk.AutoCAD.Runtime; global using Acap = Autodesk.AutoCAD.ApplicationServices.Application; global using Acaop = Autodesk.AutoCAD.ApplicationServices.Core.Application; +global using AcException = Autodesk.AutoCAD.Runtime.Exception; global using Autodesk.AutoCAD.DatabaseServices.Filters; diff --git a/src/CAD/IFox.CAD.GCAD/GlobalUsings.cs b/src/CAD/IFox.CAD.GCAD/GlobalUsings.cs index e788f51..a6666af 100644 --- a/src/CAD/IFox.CAD.GCAD/GlobalUsings.cs +++ b/src/CAD/IFox.CAD.GCAD/GlobalUsings.cs @@ -24,6 +24,7 @@ global using GrxCAD.Runtime; global using Acap = GrxCAD.ApplicationServices.Application; global using Acaop = GrxCAD.ApplicationServices.Application; +global using AcException = GrxCAD.Runtime.Exception; global using GrxCAD.DatabaseServices.Filters; // jig命名空间会引起Viewport/Polyline等等重义,最好逐个引入 using Autodesk.AutoCAD.GraphicsInterface diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ErrorInfoEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ErrorInfoEx.cs new file mode 100644 index 0000000..0f3c256 --- /dev/null +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ErrorInfoEx.cs @@ -0,0 +1,421 @@ +namespace IFoxCAD.Cad; + +/// +/// CAD错误大全 +/// +public static class ErrorInfoEx +{ + /// + /// 打印CAD错误信息到命令行 + /// 使用方法: + /// try + /// { + /// //你的代码 + /// } + /// catch (AcException acex) { acex.AcErrorInfo(); } + /// catch (Exception) { throw; } + /// + /// + /// AcException + internal static void AcErrorInfo(this AcException acex) + { + string infostr = acex.Message switch + { + "eAlreadyInDb" => "已经在数据库中了", + "eAmbiguousInput" => "模糊不清的输入", + "eAmbiguousOutput" => "模糊不清的输出", + "eAnonymousEntry" => "多重入口", + "eBrokenHandle" => "损坏的句柄", + "eBufferTooSmall" => "缓冲区太小", + "eContainerNotEmpty" => "容器不为空", + "eDeletedEntry" => "已经删除的函数入口", + "eDuplicateDxfField" => "DXF字段重复", + "eDuplicateIndex" => "重复的索引", + "eDuplicateKey" => "重复的关键字", + "eEndOfFile" => "文件结束", + "eEndOfObject" => "对象结束", + "eEntityInInactiveLayout" => "实体不在活动布局上", + "eHandleExists" => "句柄已存在", + "eHandleInUse" => "句柄被占用", + "eIllegalEntityType" => "非法的实体类型", + "eIllegalReplacement" => "非法的替代者", + "eInvalidAdsName" => "无效的ADS名称", + "eInvalidBlockName" => "不合理的块名称", + "eInvalidDwgVersion" => "不合理的DWG版本", + "eInvalidDxfCode" => "不合理的DXF编码", + "eInvalidExtents" => "无效的空间范围", + "eInvalidIndex" => "无效的索引", + "eInvalidInput" => "无效的输入", + "eInvalidKey" => "无效的关键字", + "eInvalidOpenState" => "无效的打开状态", + "eInvalidSymbolTableName" => "无效的符号名称", + "eIsReading" => "正在读取", + "eIsWriting" => "正在写入", + "eKeyNotFound" => "关键字未找到", + "eMissingDxfField" => "DXF字段缺失", + "eNegativeValueNotAllowed" => "不允许输入负数", + "eNotApplicable" => "不合适的", + "eNotImplementedYet" => "尚未实现", + "eNotOpenForRead" => "不是只读打开", + "eNotOpenForWrite" => "不是可写打开", + "eNotThatKindOfClass" => "类型不匹配", + "eNullBlockName" => "块名称为空", + "eNullEntityPointer" => "实体指针为空", + "eNullHandle" => "空句柄", + "eNullObjectId" => "对象ID为空", + "eNullObjectPointer" => "对象指针为空", + "eObjectToBeDeleted" => "对象即将被删除", + "eOk" => "正确", + "eOutOfDisk" => "硬盘容量不足", + "eOutOfMemory" => "内存不足", + "eUnknownHandle" => "未知句柄", + "eWrongDatabase" => "错误的数据库", + "eWrongObjectType" => "错误的类型", + "eInvalidResBuf" => "不合理的ResBuf", + "eBadDxfSequence" => "不正确的DXF顺序", + "eFilerError" => "文件错误", + "eVertexAfterFace" => "顶点在面后面", + "eInvalidFaceVertexIndex" => "不合理的面顶点顺序", + "eInvalidMeshVertexIndex" => "不合理的mesh顺序", + "eOtherObjectsBusy" => "其它对象忙", + "eMustFirstAddBlockToDb" => "必须先把块加入到数据库", + "eCannotNestBlockDefs" => "不可以嵌套块定义", + "eDwgRecoveredOK" => "修复DWG完成", + "eDwgNotRecoverable" => "无法修复DWG", + "eDxfPartiallyRead" => "DXF部分读取", + "eDxfReadAborted" => "读取DXF终止", + "eDxbPartiallyRead" => "DXB部分读取", + "eDwgCRCDoesNotMatch" => "DWG文件的CRC不匹配", + "eDwgSentinelDoesNotMatch" => "DWG文件的校验不匹配", + "eDwgObjectImproperlyRead" => "DWG文件错误读取", + "eNoInputFiler" => "没有找到输入过滤", + "eDwgNeedsAFullSave" => "DWG需要完全保存", + "eDxbReadAborted" => "DXB读取终止", + "eFileLockedByACAD" => "文件被ACAD锁定", + "eFileAccessErr" => "无法读取文件", + "eFileSystemErr" => "文件系统错误", + "eFileInternalErr" => "文件内部错误", + "eFileTooManyOpen" => "文件被打开太多次", + "eFileNotFound" => "未找到文件", + "eDwkLockFileFound" => "找到DWG锁定文件", + "eWasErased" => "对象被删除", + "ePermanentlyErased" => "对象被永久删除", + "eWasOpenForRead" => "对象只读打开", + "eWasOpenForWrite" => "对象可写打开", + "eWasOpenForUndo" => "对象撤销打开", + "eWasNotifying" => "对象被通知", + "eWasOpenForNotify" => "对象通知打开", + "eOnLockedLayer" => "对象在锁定图层上", + "eMustOpenThruOwner" => "必须经过所有者打开", + "eSubentitiesStillOpen" => "子对象依然打开着", + "eAtMaxReaders" => "超过最大打开次数", + "eIsWriteProtected" => "对象被写保护", + "eIsXRefObject" => "对象是XRef", + "eNotAnEntity" => "对象不是实体", + "eHadMultipleReaders" => "被多重打开", + "eDuplicateRecordName" => "重复的记录名称", + "eXRefDependent" => "依赖于XREF", + "eSelfReference" => "引用自身", + "eMissingSymbolTable" => "丢失符号化表", + "eMissingSymbolTableRec" => "丢失符号化记录", + "eWasNotOpenForWrite" => "不是可写打开", + "eCloseWasNotifying" => "对象关闭,正在执行通知", + "eCloseModifyAborted" => "对象关闭,修改被取消", + "eClosePartialFailure" => "对象关闭,部分操作未成功", + "eCloseFailObjectDamaged" => "对象被损坏,关闭失败", + "eCannotBeErasedByCaller" => "对象不可以被当前呼叫者删除", + "eCannotBeResurrected" => "不可以复活", + "eWasNotErased" => "对象未删除", + "eInsertAfter" => "在后面插入", + "eFixedAllErrors" => "修复了所有错误", + "eLeftErrorsUnfixed" => "剩下一些错误未修复", + "eUnrecoverableErrors" => "不可恢复的错误", + "eNoDatabase" => "没有数据库", + "eXdataSizeExceeded" => "扩展数据长度太大", + "eRegappIdNotFound" => "没有找到扩展数据注册ID", + "eRepeatEntity" => "重复实体", + "eRecordNotInTable" => "表中未找到记录", + "eIteratorDone" => "迭代器完成", + "eNullIterator" => "空的迭代器", + "eNotInBlock" => "不在块中", + "eOwnerNotInDatabase" => "所有者不在数据库中", + "eOwnerNotOpenForRead" => "所有者不是只读打开", + "eOwnerNotOpenForWrite" => "所有者不是可写打开", + "eExplodeBeforeTransform" => "在变换之前就被炸开了", + "eCannotScaleNonUniformly" => "不可以不同比例缩放", + "eNotInDatabase" => "不在数据库中", + "eNotCurrentDatabase" => "不是当前数据库", + "eIsAnEntity" => "是一个实体", + "eCannotChangeActiveViewport" => "不可以改变活动视口", + "eNotInPaperspace" => "不在图纸空间中", + "eCommandWasInProgress" => "正在执行命令", + "eGeneralModelingFailure" => "创建模型失败", + "eOutOfRange" => "超出范围", + "eNonCoplanarGeometry" => "没有平面几何对象", + "eDegenerateGeometry" => "退化的几何对象", + "eInvalidAxis" => "无效的轴线", + "ePointNotOnEntity" => "点不在实体上", + "eSingularPoint" => "单一的点", + "eInvalidOffset" => "无效的偏移", + "eNonPlanarEntity" => "没有平面的实体", + "eCannotExplodeEntity" => "不可分解的实体", + "eStringTooLong" => "字符串太短", + "eInvalidSymTableFlag" => "无效的符号化表标志", + "eUndefinedLineType" => "没有定义的线型", + "eInvalidTextStyle" => "无效的字体样式", + "eTooFewLineTypeElements" => "太少的线型要素", + "eTooManyLineTypeElements" => "太多的线型要素", + "eExcessiveItemCount" => "过多的项目", + "eIgnoredLinetypeRedef" => "忽略线型定义描述", + "eBadUCS" => "不好的用户坐标系", + "eBadPaperspaceView" => "不好的图纸空间视图", + "eSomeInputDataLeftUnread" => "一些输入数据未被读取", + "eNoInternalSpace" => "不是内部空间", + "eInvalidDimStyle" => "无效的标注样式", + "eInvalidLayer" => "无效的图层", + "eUserBreak" => "用户打断", + "eDwgNeedsRecovery" => "DWG文件需要修复", + "eDeleteEntity" => "删除实体", + "eInvalidFix" => "无效的方位", + "eFSMError" => "FSM错误", + "eBadLayerName" => "不好的图层名称", + "eLayerGroupCodeMissing" => "图层分组编码丢失", + "eBadColorIndex" => "不好的颜色索引号", + "eBadLinetypeName" => "不好的线型名称", + "eBadLinetypeScale" => "不好的线型缩放比例", + "eBadVisibilityValue" => "不好的可见性值", + "eProperClassSeparatorExpected" => "本身类未找到预期的分割符号(?)", + "eBadLineWeightValue" => "不好的线宽值", + "eBadColor" => "不好的颜色", + "ePagerError" => "页面错误", + "eOutOfPagerMemory" => "页面内存不足", + "ePagerWriteError" => "页面不可写", + "eWasNotForwarding" => "不是促进(?)", + "eInvalidIdMap" => "无效的ID字典", + "eInvalidOwnerObject" => "无效的所有者", + "eOwnerNotSet" => "未设置所有者", + "eWrongSubentityType" => "错误的子对象类型", + "eTooManyVertices" => "太多节点", + "eTooFewVertices" => "太少节点", + "eNoActiveTransactions" => "不活动的事务", + "eNotTopTransaction" => "不是最顶层的事务", + "eTransactionOpenWhileCommandEnded" => "在命令结束的时候打开(/开始)事务", + "eInProcessOfCommitting" => "在提交事务的过程中", + "eNotNewlyCreated" => "不是新创建的", + "eLongTransReferenceError" => "长事务引用错误", + "eNoWorkSet" => "没有工作集", + "eAlreadyInGroup" => "已经在组中了", + "eNotInGroup" => "不在组中", + "eInvalidREFIID" => "无效的REFIID", + "eInvalidNormal" => "无效的标准", + "eInvalidStyle" => "无效的样式", + "eCannotRestoreFromAcisFile" => "不可以从Acis(?)文件中恢复", + "eMakeMeProxy" => "自我代理", + "eNLSFileNotAvailable" => "无效的NLS文件", + "eNotAllowedForThisProxy" => "不允许这个代理", + "eNotSupportedInDwgApi" => "在Dwg Api中不支持", + "ePolyWidthLost" => "多段线宽度丢失", + "eNullExtents" => "空的空间范围", + "eExplodeAgain" => "再一次分解", + "eBadDwgHeader" => "坏的DWG文件头", + "eLockViolation" => "锁定妨碍当前操作", + "eLockConflict" => "锁定冲突", + "eDatabaseObjectsOpen" => "数据库对象打开", + "eLockChangeInProgress" => "锁定改变中", + "eVetoed" => "禁止", + "eNoDocument" => "没有文档", + "eNotFromThisDocument" => "不是从这个文档", + "eLISPActive" => "LISP活动", + "eTargetDocNotQuiescent" => "目标文档活动中", + "eDocumentSwitchDisabled" => "禁止文档转换", + "eInvalidContext" => "无效的上下文环境", + "eCreateFailed" => "创建失败", + "eCreateInvalidName" => "创建无效名称", + "eSetFailed" => "设置失败", + "eDelDoesNotExist" => "删除对象不存在", + "eDelIsModelSpace" => "删除模型空间", + "eDelLastLayout" => "删除最后一个布局", + "eDelUnableToSetCurrent" => "删除后无法设置当前对象", + "eDelUnableToFind" => "没有找到删除对象", + "eRenameDoesNotExist" => "重命名对象不存在", + "eRenameIsModelSpace" => "不可以重命令模型空间", + "eRenameInvalidLayoutName" => "重命名无效的布局名称", + "eRenameLayoutAlreadyExists" => "重命名布局名称已存在", + "eRenameInvalidName" => "重命名无效名称", + "eCopyDoesNotExist" => "拷贝不存在", + "eCopyIsModelSpace" => "拷贝是模型空间", + "eCopyFailed" => "拷贝失败", + "eCopyInvalidName" => "拷贝无效名称", + "eCopyNameExists" => "拷贝名称存在", + "eProfileDoesNotExist" => "配置名称不存在", + "eInvalidFileExtension" => "无效的文件后缀名成", + "eInvalidProfileName" => "无效的配置文件名称", + "eFileExists" => "文件存在", + "eProfileIsInUse" => "配置文件存在", + "eCantOpenFile" => "打开文件失败", + "eNoFileName" => "没有文件名称", + "eRegistryAccessError" => "读取注册表错误", + "eRegistryCreateError" => "创建注册表项错误", + "eBadDxfFile" => "坏的DXF文件", + "eUnknownDxfFileFormat" => "未知的DXF文件格式", + "eMissingDxfSection" => "丢失DXF分段", + "eInvalidDxfSectionName" => "无效的DXF分段名称", + "eNotDxfHeaderGroupCode" => "无效的DXF组码", + "eUndefinedDxfGroupCode" => "没有定义DXF组码", + "eNotInitializedYet" => "没有初始化", + "eInvalidDxf2dPoint" => "无效的DXF二维点", + "eInvalidDxf3dPoint" => "无效的DXD三维点", + "eBadlyNestedAppData" => "坏的嵌套应用程序数据", + "eIncompleteBlockDefinition" => "不完整的块定义", + "eIncompleteComplexObject" => "不完整的合成(?复杂)对象", + "eBlockDefInEntitySection" => "块定义在实体段中", + "eNoBlockBegin" => "没有块开始", + "eDuplicateLayerName" => "重复的图层名称", + "eBadPlotStyleName" => "不好的打印样式名称", + "eDuplicateBlockName" => "重复的块名称", + "eBadPlotStyleType" => "不好的打印样式类型", + "eBadPlotStyleNameHandle" => "不好的打印样式名称句柄", + "eUndefineShapeName" => "没有定义形状名称", + "eDuplicateBlockDefinition" => "重复的块定义", + "eMissingBlockName" => "丢失了块名称", + "eBinaryDataSizeExceeded" => "二进制数据长度太长", + "eObjectIsReferenced" => "对象被引用", + "eNoThumbnailBitmap" => "没有缩略图", + "eGuidNoAddress" => "未找到GUID地址", + "eMustBe0to2" => "必须是0到2", + "eMustBe0to3" => "必须是0到3", + "eMustBe0to4" => "必须是0到4", + "eMustBe0to5" => "必须是0到5", + "eMustBe0to8" => "必须是0到8", + "eMustBe1to8" => "必须是1到8", + "eMustBe1to15" => "必须是1到15", + "eMustBePositive" => "必须为正数", + "eMustBeNonNegative" => "必须为非负数", + "eMustBeNonZero" => "不可以等于0", + "eMustBe1to6" => "必须是1到6", + "eNoPlotStyleTranslationTable" => "没有打印样式事务表(?)", + "ePlotStyleInColorDependentMode" => "打印样式依赖颜色", + "eMaxLayouts" => "最大布局数量", + "eNoClassId" => "没有类ID", + "eUndoOperationNotAvailable" => "撤销操作无效", + "eUndoNoGroupBegin" => "撤销操作没有组开始", + "eHatchTooDense" => "填充太密集", + "eOpenFileCancelled" => "打开文件取消", + "eNotHandled" => "没有处理", + "eMakeMeProxyAndResurrect" => "将自己变成代理然后复活", + "eFileMissingSections" => "文件丢失分段", + "eRepeatedDwgRead" => "重复的读取DWG文件", + "eWrongCellType" => "错误的单元格类型", + "eCannotChangeColumnType" => "不可以改变列类型", + "eRowsMustMatchColumns" => "行必须匹配列", + "eFileSharingViolation" => "文件共享妨碍", + "eUnsupportedFileFormat" => "不支持的文件格式", + "eObsoleteFileFormat" => "废弃的文件格式", + "eDwgShareDemandLoad" => "DWG共享要求加载(?)", + "eDwgShareReadAccess" => "DWG共享读取", + "eDwgShareWriteAccess" => "DWG共享写入", + "eLoadFailed" => "加载失败", + "eDeviceNotFound" => "驱动未找到", + "eNoCurrentConfig" => "没有当前配置", + "eNullPtr" => "空指针", + "eNoLayout" => "没有布局", + "eIncompatiblePlotSettings" => "不兼容的打印设置", + "eNonePlotDevice" => "没有打印驱动", + "eNoMatchingMedia" => "没有匹配的打印尺寸", + "eInvalidView" => "无效的视图", + "eInvalidWindowArea" => "无效的窗口范围", + "eInvalidPlotArea" => "无效的打印范围", + "eCustomSizeNotPossible" => "用户输入的打印尺寸不可能存在", + "ePageCancelled" => "纸张取消", + "ePlotCancelled" => "打印取消", + "eInvalidEngineState" => "无效的引擎状态", + "ePlotAlreadyStarted" => "已经开始在打印了", + "eNoErrorHandler" => "没有错误处理", + "eInvalidPlotInfo" => "无效的打印信息", + "eNumberOfCopiesNotSupported" => "不支持打印份数", + "eLayoutNotCurrent" => "不是当前布局", + "eGraphicsNotGenerated" => "绘图对象创建失败(?)", + "eCannotPlotToFile" => "不可以打印到文件", + "eMustPlotToFile" => "必须打印到文件", + "eNotMultiPageCapable" => "不支持多种纸张", + "eBackgroundPlotInProgress" => "正在后台打印", + "eSubSelectionSetEmpty" => "子选择集被设置为空", + "eInvalidObjectId" => "无效的对象ID或者对象ID不在当前数据库", + "eInvalidXrefObjectId" => "无效的XREF对象ID或者XREF对象ID不在当前数据库", + "eNoViewAssociation" => "未找到对应的视图对象", + "eNoLabelBlock" => "视口未找到关联的块", + "eUnableToSetViewAssociation" => "设置视图关联视口失败", + "eUnableToGetViewAssociation" => "无法找到关联的视图", + "eUnableToSetLabelBlock" => "无法设置关联的块", + "eUnableToGetLabelBlock" => "无法获取关联的块", + "eUnableToRemoveAssociation" => "无法移除视口关联对象", + "eUnableToSyncModelView" => "无法同步视口和模型空间视图", + "eSecInitializationFailure" => "SEC(?)初始化错误", + "eSecErrorReadingFile" => "SEC(?)读取文件错误", + "eSecErrorWritingFile" => "SEC(?)写入文件错误", + "eSecInvalidDigitalID" => "SEC(?)无效的数字ID", + "eSecErrorGeneratingTimestamp" => "SEC(?)创建时间戳错误", + "eSecErrorComputingSignature" => "SEC(?)电子签名错误", + "eSecErrorWritingSignature" => "SEC(?)写入签名错误", + "eSecErrorEncryptingData" => "SEC(?)加密数据错误", + "eSecErrorCipherNotSupported" => "SEC(?)不支持的密码", + "eSecErrorDecryptingData" => "SEC(?)解密数据错误", + "eInetBase" => "网络错误", + "eInetOk" => "网络正常", + "eInetInCache" => "在缓冲区中", + "eInetFileNotFound" => "网络文件不存在", + "eInetBadPath" => "不好的网络路径", + "eInetTooManyOpenFiles" => "打开太多网络文件", + "eInetFileAccessDenied" => "打开网络文件被拒绝", + "eInetInvalidFileHandle" => "无效的网络文件句柄", + "eInetDirectoryFull" => "网络文件夹目录已满", + "eInetHardwareError" => "网络硬件错误", + "eInetSharingViolation" => "违反网络共享", + "eInetDiskFull" => "网络硬盘满了", + "eInetFileGenericError" => "网络文件创建错误", + "eInetValidURL" => "无效的URL地址", + "eInetNotAnURL" => "不是URL地址", + "eInetNoWinInet" => "没有WinInet(?)", + "eInetOldWinInet" => "旧的WinInet(?)", + "eInetNoAcadInet" => "无法连接ACAD网站", + "eInetNotImplemented" => "无法应用网络", + "eInetProtocolNotSupported" => "网络协议不支持", + "eInetCreateInternetSessionFailed" => "创建网络会话失败", + "eInetInternetSessionConnectFailed" => "连接网络会话失败", + "eInetInternetSessionOpenFailed" => "打开网络会话失败", + "eInetInvalidAccessType" => "无效的网络接收类型", + "eInetFileOpenFailed" => "打开网络文件失败", + "eInetHttpOpenRequestFailed" => "打开HTTP协议失败", + "eInetUserCancelledTransfer" => "用户取消了网络传输", + "eInetHttpBadRequest" => "不合理的网络请求", + "eInetHttpAccessDenied" => "HTTP协议拒绝", + "eInetHttpPaymentRequired" => "HTTP协议要求付费", + "eInetHttpRequestForbidden" => "禁止HTTP请求", + "eInetHttpObjectNotFound" => "HTTP对象未找到", + "eInetHttpBadMethod" => "不合理的HTTP请求方法", + "eInetHttpNoAcceptableResponse" => "不接受的HTTP回复", + "eInetHttpProxyAuthorizationRequired" => "要求HTTP代理授权", + "eInetHttpTimedOut" => "HTTP超时", + "eInetHttpConflict" => "HTTP冲突", + "eInetHttpResourceGone" => "网络资源被用光", + "eInetHttpLengthRequired" => "HTTP请求长度是必须的", + "eInetHttpPreconditionFailure" => "HTTP预处理失败", + "eInetHttpRequestTooLarge" => "HTTP请求太大", + "eInetHttpUriTooLong" => "URL地址太长", + "eInetHttpUnsupportedMedia" => "HTTP不支持的媒体", + "eInetHttpServerError" => "HTTP服务器错误", + "eInetHttpNotSupported" => "HTTP不支持", + "eInetHttpBadGateway" => "HTTP网关错误", + "eInetHttpServiceUnavailable" => "HTTP服务当前不可用", + "eInetHttpGatewayTimeout" => "HTTP网关超时", + "eInetHttpVersionNotSupported" => "HTTP版本不支持", + "eInetInternetError" => "HTTP网络错误", + "eInetGenericException" => "HTTP常规异常", + "eInetUnknownError" => "HTTP未知错误", + "eAlreadyActive" => "已经是活动的了", + "eAlreadyInactive" => "已经是不活动的了", + _ => acex.Message, + }; + Env.Print($"{acex.Message}:{infostr}"); + } +} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems b/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems index 993d1da..bec68a4 100644 --- a/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems +++ b/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems @@ -23,6 +23,7 @@ + diff --git a/src/CAD/IFox.CAD.ZCAD/GlobalUsings.cs b/src/CAD/IFox.CAD.ZCAD/GlobalUsings.cs index 2720596..2b57555 100644 --- a/src/CAD/IFox.CAD.ZCAD/GlobalUsings.cs +++ b/src/CAD/IFox.CAD.ZCAD/GlobalUsings.cs @@ -25,6 +25,7 @@ global using ZwSoft.ZwCAD.Runtime; global using Acap = ZwSoft.ZwCAD.ApplicationServices.Application; global using Acaop = ZwSoft.ZwCAD.ApplicationServices.Application; +global using AcException = ZwSoft.ZwCAD.Runtime.Exception; global using ZwSoft.ZwCAD.DatabaseServices.Filters; // jig命名空间会引起Viewport/Polyline等等重义,最好逐个引入 using ZwSoft.ZwCAD.GraphicsInterface -- Gitee From dd7a9c051b78b4b4c8658fd7b14ca96d5cef9ae5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=91=E5=82=B2=E5=B4=96?= <702099480@qq.com> Date: Tue, 1 Aug 2023 07:27:47 +0800 Subject: [PATCH 155/453] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=B6=88=E6=81=AF?= =?UTF-8?q?=E6=89=93=E5=8D=B0=E4=B8=BA=E6=B6=88=E6=81=AF=E5=BC=B9=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/ErrorInfoEx.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ErrorInfoEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ErrorInfoEx.cs index 0f3c256..00da86e 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ErrorInfoEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ErrorInfoEx.cs @@ -416,6 +416,6 @@ internal static void AcErrorInfo(this AcException acex) "eAlreadyInactive" => "已经是不活动的了", _ => acex.Message, }; - Env.Print($"{acex.Message}:{infostr}"); + Acap.ShowAlertDialog($"{acex.Message}:{infostr}"); } } \ No newline at end of file -- Gitee From 7e31d4dcf3caab47e203af6fd6cc0134e2eecd5a Mon Sep 17 00:00:00 2001 From: zhinanheshang Date: Thu, 3 Aug 2023 17:01:32 +0800 Subject: [PATCH 156/453] =?UTF-8?q?=E9=87=8D=E6=9E=84EntityBoundingInfo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Entity/EntityBoundingInfo.cs | 490 +++++++++++------- .../ExtensionMethod/Entity/EntityEx.cs | 2 +- 2 files changed, 308 insertions(+), 184 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs index a9227a0..dda10c6 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs @@ -2,217 +2,341 @@ namespace IFoxCAD.Cad; /// -/// AABB和OBB信息 +/// 和尚777 重构 +/// 包围盒信息 /// public struct BoundingInfo { - public double MinX; - public double MinY; - public double MinZ; - - public double MaxX; - public double MaxY; - public double MaxZ; - - /// - /// AABB这里永远是0 - /// - public double Angle; - public bool IsEffective; - - public Point3d Min => new(MinX, MinY, MinZ); - public Point3d Max => new(MaxX, MaxY, MaxZ); - public Extents3d Extents3d => new(Min, Max); - public Extents2d Extents2d => new(MinX, MinY, MaxX, MaxY); - - public BoundingInfo(double minX, double minY, double minZ, - double maxX, double maxY, double maxZ, - bool isEffective, double angle = 0) - { - MinX = minX; - MinY = minY; - MinZ = minZ; - MaxX = maxX; - MaxY = maxY; - MaxZ = maxZ; - IsEffective = isEffective; - Angle = angle; - } + public double MinX; + public double MinY; + public double MinZ; - public BoundingInfo(Point3d min, Point3d max, bool isEffective, double angle = 0) - : this(min.X, min.Y, min.Z, - max.X, max.Y, max.Z, - isEffective, angle) - { } - - // public BoundingInfo(Rect rect, double angle = 0) - // { - // MinX = rect.X; - // MinY = rect.Y; - // MinZ = 0; - // MaxX = rect.Right; - // MaxY = rect.Top; - // MaxZ = 0; - // Angle = angle; - // } - - public override string ToString() - { - return Extents3d.ToString(); - } + public double MaxX; + public double MaxY; + public double MaxZ; + public Point3d P1 => new(MinX, MinY, MinZ); + public Point3d P2 => P1.GetMidPointTo(P3); + public Point3d P3 => new(MaxX, MinY, MinZ); + public Point3d P4 => P1.GetMidPointTo(P7); + public Point3d P5 => P1.GetMidPointTo(P9); + public Point3d P6 => P3.GetMidPointTo(P9); + public Point3d P7 => new(MinX, MaxY, MinZ); + public Point3d P8 => P7.GetMidPointTo(P9); + public Point3d P9 => new(MaxX, MaxY, MaxZ); + public Point3d Min => new(MinX, MinY, MinZ); + public Point3d Max => new(MaxX, MaxY, MaxZ); + public double Height => Math.Abs(MaxX - MinX); + public double Width => Math.Abs(MaxY - MinY); + public Extents3d Extents3d { get; } + public Extents2d Extents2d => new(MinX, MinY, MaxX, MaxY); + + public BoundingInfo(Extents3d ext) + { + MinX = ext.MinPoint.X; + MinY = ext.MinPoint.Y; + MinZ = ext.MinPoint.Z; + MaxX = ext.MaxPoint.X; + MaxY = ext.MaxPoint.Y; + MaxZ = ext.MaxPoint.Z; + Extents3d = ext; + } + public BoundingInfo(Extents2d ext) + { + MinX = ext.MinPoint.X; + MinY = ext.MinPoint.Y; + MinZ = 0; + MaxX = ext.MaxPoint.X; + MaxY = ext.MaxPoint.Y; + MaxZ = 0; + var pt1 = new Point3d(MinX, MinY, 0); + var pt9 = new Point3d(MaxX, MaxY, 0); + Extents3d = new Extents3d(pt1, pt9); + } + public override string ToString() + { + return Extents3d.ToString(); + } + + public void Move(Point3d pt1, Point3d pt2) + { + var ve = pt1 - pt2; + MinX -= ve.X; + MinY -= ve.Y; + MinZ -= ve.Z; + MaxX -= ve.X; + MaxY -= ve.Y; + MaxZ -= ve.Z; + } + +} +public static class EntityBoundingInfo +{ + + /// + /// 获取实体包围盒信息 + /// + /// + /// + /// + public static BoundingInfo? GetBoundingInfo(this Entity ent, double dist = 0) + { + return ent.GetEntityBoxEx()?.GetBoundingInfo(dist); + } + + /// + /// 获取包围盒信息 + /// + /// + /// + /// + public static BoundingInfo? GetBoundingInfo(this Extents3d ext, double dist = 0) + { + var p1 = ext.MinPoint.Offset(-dist, -dist); + var p2 = ext.MaxPoint.Offset(dist, dist); + var e = new Extents3d(p1, p2); + return new(e); + } + /// + /// 获取实体包围盒 + /// + /// + /// + static Extents3d? GetEntityBox(this Entity ent) + { + if (!ent.Bounds.HasValue) + return null; + //if (ent is BlockReference brf) + // ext = brf.GeometryExtentsBestFit(); - public void Move(Point3d pt1, Point3d pt2) + if (ent is Spline spl) + return spl.ToPolyline().GeometricExtents; + + else if (ent is MText mtext) + return GetMTextBox(mtext); + + else if (ent is Table table) { - var ve = pt1 - pt2; - MinX -= ve.X; - MinY -= ve.Y; - MinZ -= ve.Z; - MaxX -= ve.X; - MaxY -= ve.Y; - MaxZ -= ve.Z; + table.RecomputeTableBlock(true); + return table.GeometricExtents; } -} -public class EntityBoundingInfo -{ - #region 保存异常类型的日志 - - static readonly HashSet _typeNames; - /// - /// 为了保证更好的性能, - /// 只是在第一次调用此功能的时候进行读取, - /// 免得高频调用时候高频触发磁盘 - /// - static EntityBoundingInfo() + else if (ent is Dimension dim) { - _typeNames = new(); - - + dim.RecomputeDimensionBlock(true); + return dim.GeometricExtents; } + else + return ent.GeometricExtents; + + } - + /// + /// 获取多行文本的正交包围盒 + /// + /// + /// + static Extents3d GetMTextBox(MText mText) + { - - #endregion + return mText.GetMTextBoxCorners().ToExtents3D(); + } - /// - /// 获取图元包围盒 - /// - /// - /// (左下角,右上角,是否有效) - /// 异常: - /// 会将包围盒类型记录到所属路径中,以此查询 - public static BoundingInfo GetBoundingInfo(Entity ent) + /// + /// 获取点集包围盒 + /// + /// + /// + static Extents3d ToExtents3D(this IEnumerable pts) + { + var ext = new Extents3d(); + foreach (Point3d pt in pts) { -#if Debug_Cause_Error - // 错误类型处理 - if (ent is AttributeDefinition) // 属性定义 - return new(Point3d.Origin, Point3d.Origin, false); - if (ent is Xline xline)// 参照线 - return new(xline.BasePoint, xline.BasePoint, true); - if (ent is Ray ray)// 射线 - return new(ray.BasePoint, ray.BasePoint, true); -#endif - // 指定类型处理 - if (ent is BlockReference brf) - return GetBoxInfoInBlockReference(brf); - if (ent is MText mText) - return GetBoxInfoInMText(mText); - - if (!_typeNames.Contains(ent.GetType().Name)) // 屏蔽天正等等缺失包围盒的类型 - try - { - return new(ent.GeometricExtents.MinPoint, ent.GeometricExtents.MaxPoint, true); - } - catch { } - return new(Point3d.Origin, Point3d.Origin, false); + ext.AddPoint(pt); } + return ext; + } - /// - /// 处理块参照 - /// - static BoundingInfo GetBoxInfoInBlockReference(BlockReference brf) + /// + /// 获取块的包围盒 + /// + /// + /// + /// + static void GetBlockBox(this Entity en, ref Extents3d ext, ref Matrix3d mat) + { + if (en is BlockReference block) { - try + var matins = mat * block.BlockTransform; + if (block.BlockTableRecord.GetObject() is BlockTableRecord btr) + foreach (ObjectId id in btr) { - // 这个获取是原点附近,需要平移到块基点 - var fit = brf.GeometryExtentsBestFit(); - //var minX = fit.MinPoint.X + brf.Position.X; - //var minY = fit.MinPoint.Y + brf.Position.Y; - //var minZ = fit.MinPoint.Z + brf.Position.Z; - //var maxX = fit.MaxPoint.X + brf.Position.X; - //var maxY = fit.MaxPoint.Y + brf.Position.Y; - //var maxZ = fit.MaxPoint.Z + brf.Position.Z; - //return new(minX, minY, minZ, maxX, maxY, maxZ, true); - return new(fit.MinPoint, fit.MaxPoint, true); + id.GetObject(); + if (id.GetObject() is Entity ent1) + { + if (ent1.Visible != true) + continue; + if (ent1 is AttributeDefinition att) + { + if (att != null && (!att.Constant || att.Invisible)) + continue; + } + GetBlockBox(ent1, ref ext, ref matins); + } } - catch + if (block.AttributeCollection.Count > 0) + { + foreach (ObjectId attid in block.AttributeCollection) { - // 如果是一条参照线的组块,将导致获取包围盒时报错 - // 0x01 是否需要进入块内,然后拿到每个图元的BasePoint再计算中点?感觉过于复杂. - // 0x02 这个时候拿基点走就算了 - return new(brf.Position, brf.Position, true); + if (attid.GetObject() is AttributeReference att) + { + if (!att.Invisible && att.Visible) + GetBlockBox(att, ref ext, ref mat); + } } + } } - - /// - /// 处理多行文字 - /// - static BoundingInfo GetBoxInfoInMText(MText mtxt) + else { - /* - * MText Aussehen - * ------------------------------------ - * | | | - * | | |ht - * | | | - * |-----wl-------插入点------wr-------| - * | | | - * | | |hb - * | | | - * ------------------------------------ - */ - - double width = mtxt.ActualWidth;// 实际宽度 - double height = mtxt.ActualHeight;// 实际高度 - double wl = 0.0; - double hb = 0.0; - - // 对齐方式 - switch (mtxt.Attachment) + if (mat.IsUniscaledOrtho()) + { + using (var ent1 = en.GetTransformedCopy(mat)) { - case AttachmentPoint.TopCenter: - case AttachmentPoint.MiddleCenter: - case AttachmentPoint.BottomCenter: - wl = width * -0.5; - break; - case AttachmentPoint.TopRight: - case AttachmentPoint.MiddleRight: - case AttachmentPoint.BottomRight: - wl = -width; - break; + if (ext.IsEmptyExt()) + { + var e = ent1.GetEntityBox(); + if (e.HasValue) + ext = e.Value; + } + else + { + var e = ent1.GetEntityBox(); + if (e.HasValue) + ext.AddExtents(e.Value); + } } - switch (mtxt.Attachment) + } + else + { + var e = en.GetEntityBox(); + if (e.HasValue) { - case AttachmentPoint.TopLeft: - case AttachmentPoint.TopCenter: - case AttachmentPoint.TopRight: - hb = -height;// 下边线到插入点的距离 - break; - case AttachmentPoint.MiddleLeft: - case AttachmentPoint.MiddleCenter: - case AttachmentPoint.MiddleRight: - hb = height * -0.5; - break; + Extents3d entext = e.Value; + entext.TransformBy(mat); + if (ext.IsEmptyExt()) + ext = entext; + else + ext.AddExtents(entext); } + return; + } + } + return; + } + /// + /// 获取多行文字包围盒4点 + /// + /// + /// + public static Point3d[] GetMTextBoxCorners(this MText mtext) + { + double width = mtext.ActualWidth; + double height = mtext.ActualHeight; + Point3d point1, point2; + switch (mtext.Attachment) + { + case AttachmentPoint.TopLeft: + default: + point1 = new Point3d(0.0, -height, 0.0); + point2 = new Point3d(width, 0.0, 0.0); + break; + case AttachmentPoint.TopCenter: + point1 = new Point3d(-width * 0.5, -height, 0.0); + point2 = new Point3d(width * 0.5, 0.0, 0.0); + break; + case AttachmentPoint.TopRight: + point1 = new Point3d(-width, -height, 0.0); + point2 = new Point3d(0.0, 0.0, 0.0); + break; + case AttachmentPoint.MiddleLeft: + point1 = new Point3d(0.0, -height * 0.5, 0.0); + point2 = new Point3d(width, height * 0.5, 0.0); + break; + case AttachmentPoint.MiddleCenter: + point1 = new Point3d(-width * 0.5, -height * 0.5, 0.0); + point2 = new Point3d(width * 0.5, height * 0.5, 0.0); + break; + case AttachmentPoint.MiddleRight: + point1 = new Point3d(-width, -height * 0.5, 0.0); + point2 = new Point3d(0.0, height * 0.5, 0.0); + break; + case AttachmentPoint.BottomLeft: + point1 = new Point3d(0.0, 0.0, 0.0); + point2 = new Point3d(width, height, 0.0); + break; + case AttachmentPoint.BottomCenter: + point1 = new Point3d(-width * 0.5, 0.0, 0.0); + point2 = new Point3d(width * 0.5, height, 0.0); + break; + case AttachmentPoint.BottomRight: + point1 = new Point3d(-width, 0.0, 0.0); + point2 = new Point3d(0.0, height, 0.0); + break; + } - double wr = width + wl; - double ht = height + hb; + var xform = + Matrix3d.Displacement(mtext.Location.GetAsVector()) * + Matrix3d.Rotation(mtext.Rotation, mtext.Normal, Point3d.Origin) * + Matrix3d.PlaneToWorld(new Plane(Point3d.Origin, mtext.Normal)); - Point3d center = mtxt.Location; - return new(center.X + wl, center.Y + hb, 0, - center.X + wr, center.Y + ht, 0, - true, - mtxt.Rotation); + return new[] + { + point1.TransformBy(xform), + new Point3d(point2.X, point1.Y, 0.0).TransformBy(xform), + point2.TransformBy(xform), + new Point3d(point1.X, point2.Y, 0.0).TransformBy(xform) + }; + } + /// + /// 获取实体包围盒 + /// + /// + /// + public static Extents3d? GetEntityBoxEx(this Entity ent) + { + if (ent is BlockReference block) + { + Extents3d blockExt = default; + var mat = Matrix3d.Identity; + block!.GetBlockBox(ref blockExt, ref mat); + if (blockExt.IsEmptyExt()) + return null; + return blockExt; } + return GetEntityBox(ent); + } + + /// + /// 判断包围盒是否有效 + /// + /// + /// + static bool IsEmptyExt(this Extents3d ext) + { + if (ext.MinPoint.DistanceTo(ext.MaxPoint) < Tolerance.Global.EqualPoint) + return true; + else + return false; + } + /// + /// 点偏移 + /// + /// + /// + /// + /// + /// + static Point3d Offset(this Point3d pt, double x, double y, double z = 0) + { + return new Point3d(pt.X + x, pt.Y + y, pt.Z + z); + } } \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityEx.cs index bd7c64d..4b14bd8 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityEx.cs @@ -148,7 +148,7 @@ public static Extents3d GetExtents(this IEnumerable ents) /// 包围盒信息 /// 异常: /// 会将包围盒类型记录到所属路径中,以此查询 - public static BoundingInfo GetBoundingBoxEx(this Entity ent) + public static BoundingInfo? GetBoundingBoxEx(this Entity ent) { return EntityBoundingInfo.GetBoundingInfo(ent); } -- Gitee From 1591b84e2f170237ecd0712823e4d1d6093f25fa Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Fri, 4 Aug 2023 09:07:59 +0800 Subject: [PATCH 157/453] =?UTF-8?q?=E5=B0=8F=E4=B8=9C=E8=A5=BF=E5=B0=B1?= =?UTF-8?q?=E7=9B=B4=E6=8E=A5using=E4=BA=86=EF=BC=8C=E6=B2=A1=E5=BF=85?= =?UTF-8?q?=E8=A6=81=E9=83=BD=E6=90=9E=E6=88=90global=20using=E5=BC=BA?= =?UTF-8?q?=E8=BF=AB=E7=97=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/ErrorInfoEx.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ErrorInfoEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ErrorInfoEx.cs index 00da86e..5c118c8 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ErrorInfoEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ErrorInfoEx.cs @@ -1,4 +1,5 @@ -namespace IFoxCAD.Cad; +using AcException= Autodesk.AutoCAD.Runtime.Exception; +namespace IFoxCAD.Cad; /// /// CAD错误大全 -- Gitee From 42030dc6379aca884e3a1e42e1aa09870a807a05 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Fri, 4 Aug 2023 11:28:02 +0800 Subject: [PATCH 158/453] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=9D=A1=E4=BB=B6?= =?UTF-8?q?=E7=BC=96=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/ErrorInfoEx.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ErrorInfoEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ErrorInfoEx.cs index 5c118c8..5b2ead1 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ErrorInfoEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ErrorInfoEx.cs @@ -1,4 +1,6 @@ -using AcException= Autodesk.AutoCAD.Runtime.Exception; +#if acad +using AcException= Autodesk.AutoCAD.Runtime.Exception; +#endif namespace IFoxCAD.Cad; /// -- Gitee From 433efded1d1b66d30a562ee6d8786c3aac5348b6 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Fri, 4 Aug 2023 11:30:35 +0800 Subject: [PATCH 159/453] =?UTF-8?q?=E7=9B=B4=E6=8E=A5global=20using?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/ErrorInfoEx.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ErrorInfoEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ErrorInfoEx.cs index 5b2ead1..156a928 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ErrorInfoEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ErrorInfoEx.cs @@ -1,5 +1,5 @@ #if acad -using AcException= Autodesk.AutoCAD.Runtime.Exception; +global using AcException = Autodesk.AutoCAD.Runtime.Exception; #endif namespace IFoxCAD.Cad; -- Gitee From d8ee85f66a47e4b967b524f9ea557120b4856526 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Fri, 4 Aug 2023 11:45:43 +0800 Subject: [PATCH 160/453] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=A4=9A=E7=89=88?= =?UTF-8?q?=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/ErrorInfoEx.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ErrorInfoEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ErrorInfoEx.cs index 156a928..27a84f3 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ErrorInfoEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ErrorInfoEx.cs @@ -1,6 +1,11 @@ #if acad global using AcException = Autodesk.AutoCAD.Runtime.Exception; +#elif gcad +global using AcException =Gstarsoft.GstarCAD.Runtime.Exception; +#elif zcad +global using AcException=ZwSoft.ZwCAD.Runtime.Exception; #endif + namespace IFoxCAD.Cad; /// -- Gitee From 97e1eee44f893f3d375d9172a6343ba35e2e25a8 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Fri, 4 Aug 2023 11:55:58 +0800 Subject: [PATCH 161/453] =?UTF-8?q?=E6=94=B9=E5=9B=9E=E5=8E=BB=E4=BA=86?= =?UTF-8?q?=EF=BC=8C=E5=A6=A5=E5=8D=8F=EF=BC=8C=E8=BF=98=E6=98=AF=E5=8F=91?= =?UTF-8?q?=E5=85=AC=E5=91=8A=E5=90=A7=E6=9A=82=E6=97=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/ErrorInfoEx.cs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ErrorInfoEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ErrorInfoEx.cs index 27a84f3..00da86e 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ErrorInfoEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ErrorInfoEx.cs @@ -1,12 +1,4 @@ -#if acad -global using AcException = Autodesk.AutoCAD.Runtime.Exception; -#elif gcad -global using AcException =Gstarsoft.GstarCAD.Runtime.Exception; -#elif zcad -global using AcException=ZwSoft.ZwCAD.Runtime.Exception; -#endif - -namespace IFoxCAD.Cad; +namespace IFoxCAD.Cad; /// /// CAD错误大全 -- Gitee From b39123cf8c32932393450593fb9e87a920f6a5aa Mon Sep 17 00:00:00 2001 From: zhinanheshang Date: Sat, 5 Aug 2023 20:43:31 +0800 Subject: [PATCH 162/453] =?UTF-8?q?=E9=87=8D=E6=9E=84EntityBoundingInfo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Entity/EntityBoundingInfo.cs | 108 ++++++++++++------ .../ExtensionMethod/Entity/EntityEx.cs | 10 +- 2 files changed, 79 insertions(+), 39 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs index dda10c6..cc5640c 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs @@ -14,17 +14,62 @@ public struct BoundingInfo public double MaxX; public double MaxY; public double MaxZ; - public Point3d P1 => new(MinX, MinY, MinZ); - public Point3d P2 => P1.GetMidPointTo(P3); - public Point3d P3 => new(MaxX, MinY, MinZ); - public Point3d P4 => P1.GetMidPointTo(P7); - public Point3d P5 => P1.GetMidPointTo(P9); - public Point3d P6 => P3.GetMidPointTo(P9); - public Point3d P7 => new(MinX, MaxY, MinZ); - public Point3d P8 => P7.GetMidPointTo(P9); - public Point3d P9 => new(MaxX, MaxY, MaxZ); - public Point3d Min => new(MinX, MinY, MinZ); - public Point3d Max => new(MaxX, MaxY, MaxZ); + + #region 包围盒9位码坐标 + /* + * 包围盒9位码坐标 + * P7---------------P8----------------P9 + * | | | + * | | | + * | | | + * P4---------------P5----------------P6 + * | | | + * | | | + * | | | + * P1---------------P2----------------P3 + */ + /// + /// 左下点 P1 + /// + public Point3d BottomLeft => new(MinX, MinY, MinZ); + /// + /// P2 + /// + public Point3d BottomCenter => BottomLeft.GetMidPointTo(BottomRight); + /// + /// P3 + /// + public Point3d BottomRight => new(MaxX, MinY, MinZ); + /// + /// P4 + /// + public Point3d MidLeft => BottomLeft.GetMidPointTo(TopLeft); + /// + /// P5 + /// + public Point3d MidCenter => BottomLeft.GetMidPointTo(TopRight); + /// + /// P6 + /// + public Point3d MidRight => BottomRight.GetMidPointTo(TopRight); + /// + /// P7 + /// + public Point3d TopLeft => new(MinX, MaxY, MinZ); + /// + /// P8 + /// + public Point3d TopCenter => TopLeft.GetMidPointTo(TopRight); + /// + /// 右上点 P9 + /// + public Point3d TopRight => new(MaxX, MaxY, MaxZ); + + // public Point3d Min => new(MinX, MinY, MinZ); + + // public Point3d Max => new(MaxX, MaxY, MaxZ); + #endregion + public double Height => Math.Abs(MaxX - MinX); public double Width => Math.Abs(MaxY - MinY); public Extents3d Extents3d { get; } @@ -72,30 +117,26 @@ public void Move(Point3d pt1, Point3d pt2) public static class EntityBoundingInfo { - /// - /// 获取实体包围盒信息 - /// - /// - /// - /// - public static BoundingInfo? GetBoundingInfo(this Entity ent, double dist = 0) - { - return ent.GetEntityBoxEx()?.GetBoundingInfo(dist); - } - /// /// 获取包围盒信息 /// /// /// /// - public static BoundingInfo? GetBoundingInfo(this Extents3d ext, double dist = 0) + public static BoundingInfo? GetBoundingInfo(this Extents3d ext) { - var p1 = ext.MinPoint.Offset(-dist, -dist); - var p2 = ext.MaxPoint.Offset(dist, dist); - var e = new Extents3d(p1, p2); - return new(e); + return new(ext); } + + // 包围盒外扩 + //public static BoundingInfo? GetBoundingInfo(this Extents3d ext, double dist = 0) + //{ + // var p1 = ext.MinPoint.Offset(-dist, -dist); + // var p2 = ext.MaxPoint.Offset(dist, dist); + // var e = new Extents3d(p1, p2); + // return new(e); + //} + /// /// 获取实体包围盒 /// @@ -137,7 +178,6 @@ public static class EntityBoundingInfo /// static Extents3d GetMTextBox(MText mText) { - return mText.GetMTextBoxCorners().ToExtents3D(); } @@ -233,7 +273,7 @@ static void GetBlockBox(this Entity en, ref Extents3d ext, ref Matrix3d mat) return; } /// - /// 获取多行文字包围盒4点 + /// 获取多行文字最小包围盒4点坐标 /// /// /// @@ -301,7 +341,7 @@ public static Point3d[] GetMTextBoxCorners(this MText mtext) /// /// /// - public static Extents3d? GetEntityBoxEx(this Entity ent) + public static Extents3d? GetEntityBoxEx( Entity ent) { if (ent is BlockReference block) { @@ -335,8 +375,8 @@ static bool IsEmptyExt(this Extents3d ext) /// /// /// - static Point3d Offset(this Point3d pt, double x, double y, double z = 0) - { - return new Point3d(pt.X + x, pt.Y + y, pt.Z + z); - } + //static Point3d Offset(this Point3d pt, double x, double y, double z = 0) + //{ + // return new Point3d(pt.X + x, pt.Y + y, pt.Z + z); + //} } \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityEx.cs index 4b14bd8..c3a2834 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityEx.cs @@ -132,8 +132,9 @@ public static Extents3d GetExtents(this IEnumerable ents) var ext = new Extents3d(); foreach (var item in ents) { - if (item.Bounds.HasValue) - ext.AddExtents(item.GeometricExtents); + var e = item.GetBoundingBoxEx(); + if (e.HasValue) + ext.AddExtents(e.Value.Extents3d); } return ext; } @@ -146,12 +147,11 @@ public static Extents3d GetExtents(this IEnumerable ents) /// /// /// 包围盒信息 - /// 异常: - /// 会将包围盒类型记录到所属路径中,以此查询 public static BoundingInfo? GetBoundingBoxEx(this Entity ent) { - return EntityBoundingInfo.GetBoundingInfo(ent); + return EntityBoundingInfo.GetEntityBoxEx(ent)?.GetBoundingInfo(); } + /// /// 获取拉伸点 /// -- Gitee From ad90e8b81321e4b2e3f2ff6273d53641abe6cfb7 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Sat, 5 Aug 2023 20:39:12 +0800 Subject: [PATCH 163/453] =?UTF-8?q?=E5=A2=9E=E5=8A=A0extent3d=E7=94=BB?= =?UTF-8?q?=E5=A4=9A=E6=AE=B5=E7=BA=BF=E5=92=8C=E7=82=B9=E9=9B=86=E9=81=8D?= =?UTF-8?q?=E5=8E=86=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/CollectionEx.cs | 17 +++ .../ExtensionMethod/Entity/PolylineEx.cs | 29 ++++- tests/TestShared/TestBlock.cs | 1 + tests/TestShared/TestDBTrans.cs | 2 +- tests/TestShared/TestExtents.cs | 119 +++++++++++++----- 5 files changed, 133 insertions(+), 35 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/CollectionEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/CollectionEx.cs index acd120a..916d534 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/CollectionEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/CollectionEx.cs @@ -100,6 +100,23 @@ public static void ForEach(this IEnumerable source, Action action) foreach (var element in source) action.Invoke(element); } + + /// + /// 遍历集合,执行委托 + /// + /// 集合值的类型 + /// 集合 + /// 委托 + [System.Diagnostics.DebuggerStepThrough] //[DebuggerHidden] 两个特性差不多 + public static void ForEach(this IEnumerable source, Action action) + { + var i = 0; + foreach (var element in source) + { + action.Invoke(i, element); + i++; + } + } /// /// 遍历集合,执行委托(允许循环中断) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/PolylineEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/PolylineEx.cs index da2d650..7a48715 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/PolylineEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/PolylineEx.cs @@ -69,7 +69,7 @@ public static Polyline CreatePolyline(this IEnumerable points, Action

{ + points.ForEach((index, pt) => { pl.AddVertexAt(index, pt.Point2d(), 0, 0, 0); }); action?.Invoke(pl); @@ -88,12 +88,37 @@ public static Polyline CreatePolyline(this IEnumerable<(Point3d pt, double bulge Polyline pl = new(); pl.SetDatabaseDefaults(); - pts.ForEach((vertex, state, index) => { + pts.ForEach((index, vertex) => { pl.AddVertexAt(index, vertex.pt.Point2d(), vertex.bulge, vertex.startWidth, vertex.endWidth); }); action?.Invoke(pl); return pl; } + + ///

+ /// 根据Extents3d创建多段线
+ /// 此多段线无默认全局宽度0,无圆弧段,标高为0 + ///
+ /// Extents3d + /// 多段线属性设置委托 + /// 多段线对象 + public static Polyline CreatePolyline(this Extents3d points, Action? action = null) + { + var pts = new List() + { + points.MinPoint.Point2d(), + new(points.MinPoint.X, points.MaxPoint.Y), + points.MaxPoint.Point2d(), + new(points.MaxPoint.X, points.MinPoint.Y) + }; + Polyline pl = new(); + pl.SetDatabaseDefaults(); + pts.ForEach((index, pt) => { + pl.AddVertexAt(index, pt, 0, 0, 0); + }); + action?.Invoke(pl); + return pl; + } #endregion diff --git a/tests/TestShared/TestBlock.cs b/tests/TestShared/TestBlock.cs index 081241b..d990682 100644 --- a/tests/TestShared/TestBlock.cs +++ b/tests/TestShared/TestBlock.cs @@ -39,6 +39,7 @@ public void Test_GetBoundingBoxEx() continue; var box = item.GetBoundingBoxEx(); Env.Print("min:" + box.Min + ";max" + box.Max); + tr.CurrentSpace.AddEntity(new Line(box.Min, box.Max)); } } diff --git a/tests/TestShared/TestDBTrans.cs b/tests/TestShared/TestDBTrans.cs index 145724a..0cb64b3 100644 --- a/tests/TestShared/TestDBTrans.cs +++ b/tests/TestShared/TestDBTrans.cs @@ -61,7 +61,7 @@ public static void CmdTest_ForEachDemo() // id.Print(); //} - tr.BlockTable.ForEach(action: (id, state) => { + tr.BlockTable.ForEach(action: (id) => { id.Print(); }); tr.BlockTable.ForEach(action: (id, state, index) => { diff --git a/tests/TestShared/TestExtents.cs b/tests/TestShared/TestExtents.cs index da59ebd..2687565 100644 --- a/tests/TestShared/TestExtents.cs +++ b/tests/TestShared/TestExtents.cs @@ -1,48 +1,103 @@ - +namespace TestShared; -namespace TestShared +public class TestExtents { - public class TestExtents + [CommandMethod(nameof(Test_BlockExtents))] + public void Test_BlockExtents() { - [CommandMethod(nameof(TestExtents))] - public void TestBlockExtents() + using var tr = new DBTrans(); + var ent = Env.Editor.GetEntity("pick the entity"); + if (ent.Status != PromptStatus.OK ) { - using var tr = new DBTrans(); - var ent = Env.Editor.GetEntity("pick the entity"); - if (ent.Status != PromptStatus.OK ) - { - return; - } + return; + } - var block = ent.ObjectId.GetObject(); - if (block != null && block.Bounds.HasValue) - { - var extent = block.GeometricExtents; - var pts = new List() { - extent.MinPoint, - new Point3d(extent.MinPoint.X,extent.MaxPoint.Y,0), - extent.MaxPoint, - new Point3d(extent.MaxPoint.X,extent.MinPoint.Y,0), + var block = ent.ObjectId.GetObject(); + if (block != null && block.Bounds.HasValue) + { + var extent = block.GeometricExtents; + var pts = new List() { + extent.MinPoint, + new Point3d(extent.MinPoint.X,extent.MaxPoint.Y,0), + extent.MaxPoint, + new Point3d(extent.MaxPoint.X,extent.MinPoint.Y,0), - }; + }; - tr.CurrentSpace.AddEntity(pts.CreatePolyline(action: e => e.ColorIndex = 1)); - if (block is BlockReference block1) + tr.CurrentSpace.AddEntity(pts.CreatePolyline(action: e => e.ColorIndex = 1)); + + if (block is BlockReference block1) + { + var extents = block1.GeometryExtentsBestFit(); + var pts1 = new List() { - var extents = block1.GeometryExtentsBestFit(); - var pts1 = new List() { extents.MinPoint, - new Point3d(extents.MinPoint.X,extents.MaxPoint.Y,0), + new Point3d(extents.MinPoint.X, extents.MaxPoint.Y, 0), extents.MaxPoint, - new Point3d(extents.MaxPoint.X,extents.MinPoint.Y,0),}; - tr.CurrentSpace.AddEntity(pts.CreatePolyline(action: e => e.ColorIndex = 2)); + new Point3d(extents.MaxPoint.X, extents.MinPoint.Y, 0), + }; + tr.CurrentSpace.AddEntity(pts.CreatePolyline(action: e => e.ColorIndex = 2)); - var extents2 = block1.GetBoundingBoxEx(); - tr.CurrentSpace.AddEntity(pts.CreatePolyline(action: e => e.ColorIndex = 3)); - } + var extents2 = block1.GetBoundingBoxEx(); + tr.CurrentSpace.AddEntity(pts.CreatePolyline(action: e => e.ColorIndex = 3)); + + // 此处是计算块定义的包围盒,不是块参照的,所以一般情况下不需要使用。 + var ext = new Extents3d(); + ext.AddBlockExtents(block1.BlockTableRecord.GetObject()); + tr.CurrentSpace.AddEntity(ext.CreatePolyline(action: e => e.ColorIndex = 4)); + } + } + } + + [CommandMethod(nameof(Test_entextents))] + public void Test_entextents() + { + using var tr = new DBTrans(); + var a = Env.Editor.GetSelection().Value. + GetEntities(OpenMode.ForWrite); + foreach (var e in a) + { + var b = e.Bounds.HasValue; //获取是否有包围盒 + var name = e.ObjectId.ObjectClass.DxfName; + Env.Print($"{name}是否有包围盒-" + b); + if (b) + { + tr.CurrentSpace.AddEntity(e.Bounds!.Value.CreatePolyline(action: e => + { + e.ColorIndex = 4; + e.Closed = true; + })); + var ext = EntityBoundingInfo.GetBoundingInfo(e); + tr.CurrentSpace.AddEntity(ext.Extents3d.CreatePolyline(action: e => + { + e.ColorIndex = 5; + e.Closed = true; + })); + if (e is Curve spline) + { + var ge = spline.GetGeCurve(); + var box = ge.BoundBlock; + var lst = new List() + { + box.BasePoint, + box.BasePoint + box.Direction1, + box.BasePoint + box.Direction2, + box.BasePoint + box.Direction3, + }; + tr.CurrentSpace.AddEntity(lst.CreatePolyline(action: e => + { + e.ColorIndex = 6; + e.Closed = true; + })); + } + } + + + + } } -} +} \ No newline at end of file -- Gitee From fa15cb857a1f9afcbe78941daf7dcb47e248aa6d Mon Sep 17 00:00:00 2001 From: vicwjb Date: Sat, 5 Aug 2023 22:19:00 +0800 Subject: [PATCH 164/453] =?UTF-8?q?=E6=94=AF=E6=8C=81c#9.0=E7=9A=84init?= =?UTF-8?q?=E7=89=B9=E6=80=A7=E5=92=8Crecord?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../General/IsExternalInit.cs | 19 +++++++++++++++++++ .../IFox.Basal.Shared.projitems | 1 + 2 files changed, 20 insertions(+) create mode 100644 src/Basal/IFox.Basal.Shared/General/IsExternalInit.cs diff --git a/src/Basal/IFox.Basal.Shared/General/IsExternalInit.cs b/src/Basal/IFox.Basal.Shared/General/IsExternalInit.cs new file mode 100644 index 0000000..935714d --- /dev/null +++ b/src/Basal/IFox.Basal.Shared/General/IsExternalInit.cs @@ -0,0 +1,19 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Runtime.CompilerServices +{ + /// + /// Reserved to be used by the compiler for tracking metadata. + /// This class should not be used by developers in source code. + /// + [EditorBrowsable(EditorBrowsableState.Never)] +#if NET30_OR_GREATER + public +#else + internal +#endif + static class IsExternalInit + { + } +} \ No newline at end of file diff --git a/src/Basal/IFox.Basal.Shared/IFox.Basal.Shared.projitems b/src/Basal/IFox.Basal.Shared/IFox.Basal.Shared.projitems index 7b0e25f..abd241c 100644 --- a/src/Basal/IFox.Basal.Shared/IFox.Basal.Shared.projitems +++ b/src/Basal/IFox.Basal.Shared/IFox.Basal.Shared.projitems @@ -20,6 +20,7 @@ + -- Gitee From d871ce31ed692b7fd6422afe4cc5d3ed0acc23d4 Mon Sep 17 00:00:00 2001 From: zhinanheshang Date: Sun, 6 Aug 2023 20:28:48 +0800 Subject: [PATCH 165/453] =?UTF-8?q?=E5=8C=85=E5=9B=B4=E7=9B=92=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E9=9D=A2=E7=A7=AF=E5=B1=9E=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs index cc5640c..39eb5d7 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs @@ -72,6 +72,7 @@ public struct BoundingInfo public double Height => Math.Abs(MaxX - MinX); public double Width => Math.Abs(MaxY - MinY); + public double Area => Height * Width; public Extents3d Extents3d { get; } public Extents2d Extents2d => new(MinX, MinY, MaxX, MaxY); -- Gitee From 2cc7dbdfcc7c7568b71d2c01d94981c46aa09f51 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Sun, 6 Aug 2023 23:10:23 +0800 Subject: [PATCH 166/453] =?UTF-8?q?=E8=99=9A=E5=BF=83=E6=8E=A5=E5=8F=97?= =?UTF-8?q?=E6=84=8F=E8=A7=81=EF=BC=8C=E4=BF=AE=E5=A4=8D=E7=8E=AF=E5=A2=83?= =?UTF-8?q?=E5=8F=98=E9=87=8F=E8=B7=AF=E5=BE=84=E9=97=AE=E9=A2=98=E3=80=82?= =?UTF-8?q?fixed=20#I7QE0F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/Runtime/Env.cs | 70 +++++++++++++++++--------- 1 file changed, 47 insertions(+), 23 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/Runtime/Env.cs b/src/CAD/IFox.CAD.Shared/Runtime/Env.cs index f204bc1..645734f 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/Env.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/Env.cs @@ -574,13 +574,23 @@ public static int SetEnv(string name, string var) public static void AppendSupportPath(params string[] folders) { if (!folders.Any()) return; - var acadPath = GetEnv("ACAD"); - var acadPathLower = acadPath.ToLower(); - acadPath = folders - // 路径不存在或者格式非法会导致添加失败 - .Where(item => Directory.Exists(item) && !acadPathLower.Contains(item.ToLower())) - .Aggregate(acadPath, (current, item) => current + ";" + item); - if (acadPath != null) SetEnv("ACAD", acadPath); + var acadPath = Env.GetEnv("ACAD"); + var acadPathLowerArr = + acadPath + .ToLower() + .Split(';') + .Where(item => item != "") + .Select(item => + item[^1] == '\\' ? item.Remove(item.Length - 1) : item) + .ToHashSet(); + foreach (var folder in folders) { + if (!Directory.Exists(folder)) continue; + var folderLower = + folder[^1] == '\\' ? folder.Remove(folder.Length - 1).ToLower() : folder.ToLower(); + if (!acadPathLowerArr.Contains(folderLower)) + acadPath = folder + ";" + acadPath; //加到前面方便检查 + } + SetEnv("ACAD", acadPath); } /// @@ -589,11 +599,13 @@ public static void AppendSupportPath(params string[] folders) /// 目录 public static void RemoveSupportPath(params string[] folders) { - var acadPath = GetEnv("ACAD"); - var acadPathArr = acadPath.Split(';').ToList(); - foreach (var folder in folders) - { - acadPathArr.RemoveAll(item => item.ToLower().Contains(folder.ToLower())); + if (!folders.Any()) return; + var acadPathArr = GetEnv("ACAD").Split(';').ToList(); + foreach (var folder in folders) { + var folderLower = + folder[^1] == '\\' ? folder.Remove(folder.Length - 1).ToLower() : folder.ToLower(); + acadPathArr.RemoveAll(item => + (item[^1] == '\\' ? item.Remove(item.Length - 1).ToLower() : item.ToLower()) == folderLower); } SetEnv("ACAD", string.Join(";", acadPathArr)); } @@ -606,12 +618,22 @@ public static void AppendTrustedPath(params string[] folders) { if (!folders.Any()) return; var trustedPath = Env.GetVar("TRUSTEDPATHS").ToString(); - var trustedPathLower = trustedPath.ToLower(); - trustedPath = folders - .Where(item => - Directory.Exists(item) && !trustedPathLower.Contains(item.ToLower())) - .Aggregate(trustedPath, (current, item) => current + ";" + item); - if (trustedPath != null) SetVar("TRUSTEDPATHS", trustedPath); + var trustedPathLowerArr = + trustedPath + .ToLower() + .Split(';') + .Where(item => item != "") + .Select(item => + item[^1] == '\\' ? item.Remove(item.Length - 1) : item) + .ToHashSet(); + foreach (var folder in folders) { + if (!Directory.Exists(folder)) continue; + var folderLower = + folder[^1] == '\\' ? folder.Remove(folder.Length - 1).ToLower() : folder.ToLower(); + if (!trustedPathLowerArr.Contains(folderLower)) + trustedPath = folder + ";" + trustedPath; //加到前面方便检查 + } + SetVar("TRUSTEDPATHS", trustedPath); } /// /// 移除信任目录 @@ -619,11 +641,13 @@ public static void AppendTrustedPath(params string[] folders) /// 目录 public static void RemoveTrustedPath(params string[] folders) { - var trustedPath = GetVar("TRUSTEDPATHS").ToString(); - var trustedPathArr = trustedPath.Split(';').ToList(); - foreach (var folder in folders) - { - trustedPathArr.RemoveAll(item => item.ToLower().Contains(folder.ToLower())); + if (!folders.Any()) return; + var trustedPathArr = GetVar("TRUSTEDPATHS").ToString().Split(';').ToList(); + foreach (var folder in folders) { + var folderLower = + folder[^1] == '\\' ? folder.Remove(folder.Length - 1).ToLower() : folder.ToLower(); + trustedPathArr.RemoveAll(item => + (item[^1] == '\\' ? item.Remove(item.Length - 1).ToLower() : item.ToLower()) == folderLower); } SetVar("TRUSTEDPATHS", string.Join(";", trustedPathArr)); } -- Gitee From f88663afe7586e8667748c5eae9887b4de9fd4a6 Mon Sep 17 00:00:00 2001 From: zhinanheshang Date: Mon, 7 Aug 2023 16:45:10 +0800 Subject: [PATCH 167/453] =?UTF-8?q?=E5=AE=9E=E4=BD=93=E5=8C=85=E5=9B=B4?= =?UTF-8?q?=E7=9B=92=E4=BF=A1=E6=81=AF=E7=B1=BB,=E8=A1=A5=E6=B3=A8?= =?UTF-8?q?=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Entity/EntityBoundingInfo.cs | 104 ++++++++++++++---- 1 file changed, 85 insertions(+), 19 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs index 39eb5d7..b416abb 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs @@ -7,12 +7,32 @@ namespace IFoxCAD.Cad; /// public struct BoundingInfo { + #region 成员 + + + /// + /// MinPoint.X + /// public double MinX; + /// + /// MinPoint.Y + /// public double MinY; + /// + /// MinPoint.Z + /// public double MinZ; - + /// + /// MaxPoint.X + /// public double MaxX; + /// + /// MaxPoint.Y + /// public double MaxY; + /// + /// MaxPoint.Z + /// public double MaxZ; #region 包围盒9位码坐标 @@ -29,7 +49,7 @@ public struct BoundingInfo * P1---------------P2----------------P3 */ /// - /// 左下点 P1 + /// MinPoint 左下点 P1 /// public Point3d BottomLeft => new(MinX, MinY, MinZ); /// @@ -61,7 +81,7 @@ public struct BoundingInfo /// public Point3d TopCenter => TopLeft.GetMidPointTo(TopRight); /// - /// 右上点 P9 + /// MaxPoint 右上点 P9 /// public Point3d TopRight => new(MaxX, MaxY, MaxZ); @@ -70,12 +90,39 @@ public struct BoundingInfo // public Point3d Max => new(MaxX, MaxY, MaxZ); #endregion + /// + /// 高 + /// public double Height => Math.Abs(MaxX - MinX); + + /// + /// 宽 + /// public double Width => Math.Abs(MaxY - MinY); + + /// + /// 面积 + /// public double Area => Height * Width; + + /// + /// 3D包围盒 + /// public Extents3d Extents3d { get; } + + /// + /// 2D包围盒 + /// public Extents2d Extents2d => new(MinX, MinY, MaxX, MaxY); + #endregion + + #region 构造 + + /// + /// 包围盒信息3D构造 + /// + /// 包围盒 public BoundingInfo(Extents3d ext) { MinX = ext.MinPoint.X; @@ -86,6 +133,11 @@ public BoundingInfo(Extents3d ext) MaxZ = ext.MaxPoint.Z; Extents3d = ext; } + + /// + /// 包围盒信息2D构造 + /// + /// 包围盒 public BoundingInfo(Extents2d ext) { MinX = ext.MinPoint.X; @@ -98,11 +150,22 @@ public BoundingInfo(Extents2d ext) var pt9 = new Point3d(MaxX, MaxY, 0); Extents3d = new Extents3d(pt1, pt9); } + + #endregion + + /// + /// 重写ToString + /// + /// 返回MinPoint,MaxPoint坐标 public override string ToString() { return Extents3d.ToString(); } - + /// + /// 移动包围盒 + /// + /// 基点 + /// 目标点 public void Move(Point3d pt1, Point3d pt2) { var ve = pt1 - pt2; @@ -115,15 +178,18 @@ public void Move(Point3d pt1, Point3d pt2) } } + +/// +/// 获取实体包围盒信息方法 +/// public static class EntityBoundingInfo { /// /// 获取包围盒信息 /// - /// - /// - /// + /// 包围盒 + /// 包围盒信息 public static BoundingInfo? GetBoundingInfo(this Extents3d ext) { return new(ext); @@ -141,8 +207,8 @@ public static class EntityBoundingInfo /// /// 获取实体包围盒 /// - /// - /// + /// 实体 + /// 包围盒 static Extents3d? GetEntityBox(this Entity ent) { if (!ent.Bounds.HasValue) @@ -175,8 +241,8 @@ public static class EntityBoundingInfo /// /// 获取多行文本的正交包围盒 /// - /// - /// + /// 多行文本 + /// 包围盒 static Extents3d GetMTextBox(MText mText) { return mText.GetMTextBoxCorners().ToExtents3D(); @@ -185,8 +251,8 @@ static Extents3d GetMTextBox(MText mText) /// /// 获取点集包围盒 /// - /// - /// + /// Point3d点集 + /// 包围盒 static Extents3d ToExtents3D(this IEnumerable pts) { var ext = new Extents3d(); @@ -200,7 +266,7 @@ static Extents3d ToExtents3D(this IEnumerable pts) /// /// 获取块的包围盒 /// - /// + /// 实体 /// /// static void GetBlockBox(this Entity en, ref Extents3d ext, ref Matrix3d mat) @@ -276,8 +342,8 @@ static void GetBlockBox(this Entity en, ref Extents3d ext, ref Matrix3d mat) /// /// 获取多行文字最小包围盒4点坐标 /// - /// - /// + /// 多行文本 + /// 最小包围盒4点坐标 public static Point3d[] GetMTextBoxCorners(this MText mtext) { double width = mtext.ActualWidth; @@ -340,8 +406,8 @@ public static Point3d[] GetMTextBoxCorners(this MText mtext) /// /// 获取实体包围盒 /// - /// - /// + /// 实体 + /// 包围盒 public static Extents3d? GetEntityBoxEx( Entity ent) { if (ent is BlockReference block) @@ -359,7 +425,7 @@ public static Point3d[] GetMTextBoxCorners(this MText mtext) /// /// 判断包围盒是否有效 /// - /// + /// 包围盒 /// static bool IsEmptyExt(this Extents3d ext) { -- Gitee From c8789139e3dcd5713cb240a2f91344151f52ea3f Mon Sep 17 00:00:00 2001 From: vicwjb Date: Mon, 7 Aug 2023 21:38:43 +0800 Subject: [PATCH 168/453] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=92=8C=E5=B0=9A?= =?UTF-8?q?=E5=A4=A7=E4=BD=AC=E6=9B=B4=E6=96=B0=E5=90=8E=E7=9A=84=E5=85=B3?= =?UTF-8?q?=E8=81=94=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/Entity/BoundingInfo.cs | 179 +++++ .../Entity/EntityBoundingInfo.cs | 635 +++++++----------- .../IFox.CAD.Shared/IFox.CAD.Shared.projitems | 1 + tests/TestShared/Copyclip.cs | 13 +- tests/TestShared/TestBlock.cs | 9 +- tests/TestShared/TestExtents.cs | 4 +- tests/TestShared/TestXdata.cs | 26 +- 7 files changed, 447 insertions(+), 420 deletions(-) create mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BoundingInfo.cs diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BoundingInfo.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BoundingInfo.cs new file mode 100644 index 0000000..bf10c2e --- /dev/null +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BoundingInfo.cs @@ -0,0 +1,179 @@ +namespace IFoxCAD.Cad; + +/// +/// 和尚777 重构 +/// 包围盒信息 +/// +public struct BoundingInfo +{ + #region 成员 + + + /// + /// MinPoint.X + /// + public double MinX; + /// + /// MinPoint.Y + /// + public double MinY; + /// + /// MinPoint.Z + /// + public double MinZ; + /// + /// MaxPoint.X + /// + public double MaxX; + /// + /// MaxPoint.Y + /// + public double MaxY; + /// + /// MaxPoint.Z + /// + public double MaxZ; + + #region 包围盒9位码坐标 + /* + * 包围盒9位码坐标 + * P7---------------P8----------------P9 + * | | | + * | | | + * | | | + * P4---------------P5----------------P6 + * | | | + * | | | + * | | | + * P1---------------P2----------------P3 + */ + /// + /// MinPoint 左下点 P1 + /// + public readonly Point3d BottomLeft => new(MinX, MinY, MinZ); + /// + /// P2 + /// + public readonly Point3d BottomCenter => BottomLeft.GetMidPointTo(BottomRight); + /// + /// P3 + /// + public readonly Point3d BottomRight => new(MaxX, MinY, MinZ); + /// + /// P4 + /// + public readonly Point3d MidLeft => BottomLeft.GetMidPointTo(TopLeft); + /// + /// P5 + /// + public readonly Point3d MidCenter => BottomLeft.GetMidPointTo(TopRight); + /// + /// P6 + /// + public readonly Point3d MidRight => BottomRight.GetMidPointTo(TopRight); + /// + /// P7 + /// + public readonly Point3d TopLeft => new(MinX, MaxY, MinZ); + /// + /// P8 + /// + public readonly Point3d TopCenter => TopLeft.GetMidPointTo(TopRight); + /// + /// MaxPoint 右上点 P9 + /// + public readonly Point3d TopRight => new(MaxX, MaxY, MaxZ); + + // public Point3d Min => new(MinX, MinY, MinZ); + + // public Point3d Max => new(MaxX, MaxY, MaxZ); + #endregion + + /// + /// 高 + /// + public readonly double Height => Math.Abs(MaxX - MinX); + + /// + /// 宽 + /// + public readonly double Width => Math.Abs(MaxY - MinY); + + /// + /// 面积 + /// + public readonly double Area => Height * Width; + + /// + /// 3D包围盒 + /// + public Extents3d Extents3d { get; } + + /// + /// 2D包围盒 + /// + public readonly Extents2d Extents2d => new(MinX, MinY, MaxX, MaxY); + + #endregion + + #region 构造 + + /// + /// 包围盒信息3D构造 + /// + /// 包围盒 + public BoundingInfo(Extents3d ext) + { + MinX = ext.MinPoint.X; + MinY = ext.MinPoint.Y; + MinZ = ext.MinPoint.Z; + MaxX = ext.MaxPoint.X; + MaxY = ext.MaxPoint.Y; + MaxZ = ext.MaxPoint.Z; + Extents3d = ext; + } + + /// + /// 包围盒信息2D构造 + /// + /// 包围盒 + public BoundingInfo(Extents2d ext) + { + MinX = ext.MinPoint.X; + MinY = ext.MinPoint.Y; + MinZ = 0; + MaxX = ext.MaxPoint.X; + MaxY = ext.MaxPoint.Y; + MaxZ = 0; + var pt1 = new Point3d(MinX, MinY, 0); + var pt9 = new Point3d(MaxX, MaxY, 0); + Extents3d = new Extents3d(pt1, pt9); + } + + #endregion + + /// + /// 重写ToString + /// + /// 返回MinPoint,MaxPoint坐标 + public override string ToString() + { + return Extents3d.ToString(); + } + /// + /// 移动包围盒 + /// + /// 基点 + /// 目标点 + public void Move(Point3d pt1, Point3d pt2) + { + var ve = pt1 - pt2; + MinX -= ve.X; + MinY -= ve.Y; + MinZ -= ve.Z; + MaxX -= ve.X; + MaxY -= ve.Y; + MaxZ -= ve.Z; + } + +} diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs index b416abb..43c4f31 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs @@ -1,183 +1,4 @@ -#define Debug_Cause_Error -namespace IFoxCAD.Cad; - -/// -/// 和尚777 重构 -/// 包围盒信息 -/// -public struct BoundingInfo -{ - #region 成员 - - - /// - /// MinPoint.X - /// - public double MinX; - /// - /// MinPoint.Y - /// - public double MinY; - /// - /// MinPoint.Z - /// - public double MinZ; - /// - /// MaxPoint.X - /// - public double MaxX; - /// - /// MaxPoint.Y - /// - public double MaxY; - /// - /// MaxPoint.Z - /// - public double MaxZ; - - #region 包围盒9位码坐标 - /* - * 包围盒9位码坐标 - * P7---------------P8----------------P9 - * | | | - * | | | - * | | | - * P4---------------P5----------------P6 - * | | | - * | | | - * | | | - * P1---------------P2----------------P3 - */ - /// - /// MinPoint 左下点 P1 - /// - public Point3d BottomLeft => new(MinX, MinY, MinZ); - /// - /// P2 - /// - public Point3d BottomCenter => BottomLeft.GetMidPointTo(BottomRight); - /// - /// P3 - /// - public Point3d BottomRight => new(MaxX, MinY, MinZ); - /// - /// P4 - /// - public Point3d MidLeft => BottomLeft.GetMidPointTo(TopLeft); - /// - /// P5 - /// - public Point3d MidCenter => BottomLeft.GetMidPointTo(TopRight); - /// - /// P6 - /// - public Point3d MidRight => BottomRight.GetMidPointTo(TopRight); - /// - /// P7 - /// - public Point3d TopLeft => new(MinX, MaxY, MinZ); - /// - /// P8 - /// - public Point3d TopCenter => TopLeft.GetMidPointTo(TopRight); - /// - /// MaxPoint 右上点 P9 - /// - public Point3d TopRight => new(MaxX, MaxY, MaxZ); - - // public Point3d Min => new(MinX, MinY, MinZ); - - // public Point3d Max => new(MaxX, MaxY, MaxZ); - #endregion - - /// - /// 高 - /// - public double Height => Math.Abs(MaxX - MinX); - - /// - /// 宽 - /// - public double Width => Math.Abs(MaxY - MinY); - - /// - /// 面积 - /// - public double Area => Height * Width; - - /// - /// 3D包围盒 - /// - public Extents3d Extents3d { get; } - - /// - /// 2D包围盒 - /// - public Extents2d Extents2d => new(MinX, MinY, MaxX, MaxY); - - #endregion - - #region 构造 - - /// - /// 包围盒信息3D构造 - /// - /// 包围盒 - public BoundingInfo(Extents3d ext) - { - MinX = ext.MinPoint.X; - MinY = ext.MinPoint.Y; - MinZ = ext.MinPoint.Z; - MaxX = ext.MaxPoint.X; - MaxY = ext.MaxPoint.Y; - MaxZ = ext.MaxPoint.Z; - Extents3d = ext; - } - - /// - /// 包围盒信息2D构造 - /// - /// 包围盒 - public BoundingInfo(Extents2d ext) - { - MinX = ext.MinPoint.X; - MinY = ext.MinPoint.Y; - MinZ = 0; - MaxX = ext.MaxPoint.X; - MaxY = ext.MaxPoint.Y; - MaxZ = 0; - var pt1 = new Point3d(MinX, MinY, 0); - var pt9 = new Point3d(MaxX, MaxY, 0); - Extents3d = new Extents3d(pt1, pt9); - } - - #endregion - - /// - /// 重写ToString - /// - /// 返回MinPoint,MaxPoint坐标 - public override string ToString() - { - return Extents3d.ToString(); - } - /// - /// 移动包围盒 - /// - /// 基点 - /// 目标点 - public void Move(Point3d pt1, Point3d pt2) - { - var ve = pt1 - pt2; - MinX -= ve.X; - MinY -= ve.Y; - MinZ -= ve.Z; - MaxX -= ve.X; - MaxY -= ve.Y; - MaxZ -= ve.Z; - } - -} +namespace IFoxCAD.Cad; /// /// 获取实体包围盒信息方法 @@ -185,265 +6,265 @@ public void Move(Point3d pt1, Point3d pt2) public static class EntityBoundingInfo { - /// - /// 获取包围盒信息 - /// - /// 包围盒 - /// 包围盒信息 - public static BoundingInfo? GetBoundingInfo(this Extents3d ext) - { - return new(ext); - } + /// + /// 获取包围盒信息 + /// + /// 包围盒 + /// 包围盒信息 + public static BoundingInfo? GetBoundingInfo(this Extents3d ext) + { + return new(ext); + } - // 包围盒外扩 - //public static BoundingInfo? GetBoundingInfo(this Extents3d ext, double dist = 0) - //{ - // var p1 = ext.MinPoint.Offset(-dist, -dist); - // var p2 = ext.MaxPoint.Offset(dist, dist); - // var e = new Extents3d(p1, p2); - // return new(e); - //} + // 包围盒外扩 + //public static BoundingInfo? GetBoundingInfo(this Extents3d ext, double dist = 0) + //{ + // var p1 = ext.MinPoint.Offset(-dist, -dist); + // var p2 = ext.MaxPoint.Offset(dist, dist); + // var e = new Extents3d(p1, p2); + // return new(e); + //} + + /// + /// 获取实体包围盒 + /// + /// 实体 + /// 包围盒 + static Extents3d? GetEntityBox(this Entity ent) + { + if (!ent.Bounds.HasValue) + return null; + //if (ent is BlockReference brf) + // ext = brf.GeometryExtentsBestFit(); - /// - /// 获取实体包围盒 - /// - /// 实体 - /// 包围盒 - static Extents3d? GetEntityBox(this Entity ent) - { - if (!ent.Bounds.HasValue) - return null; - //if (ent is BlockReference brf) - // ext = brf.GeometryExtentsBestFit(); + if (ent is Spline spl) + return spl.ToPolyline().GeometricExtents; - if (ent is Spline spl) - return spl.ToPolyline().GeometricExtents; + else if (ent is MText mtext) + return GetMTextBox(mtext); - else if (ent is MText mtext) - return GetMTextBox(mtext); + else if (ent is Table table) + { + table.RecomputeTableBlock(true); + return table.GeometricExtents; + } + + else if (ent is Dimension dim) + { + dim.RecomputeDimensionBlock(true); + return dim.GeometricExtents; + } + else + return ent.GeometricExtents; - else if (ent is Table table) - { - table.RecomputeTableBlock(true); - return table.GeometricExtents; } - else if (ent is Dimension dim) + /// + /// 获取多行文本的正交包围盒 + /// + /// 多行文本 + /// 包围盒 + static Extents3d GetMTextBox(MText mText) { - dim.RecomputeDimensionBlock(true); - return dim.GeometricExtents; + return mText.GetMTextBoxCorners().ToExtents3D(); } - else - return ent.GeometricExtents; - - } - /// - /// 获取多行文本的正交包围盒 - /// - /// 多行文本 - /// 包围盒 - static Extents3d GetMTextBox(MText mText) - { - return mText.GetMTextBoxCorners().ToExtents3D(); - } - - /// - /// 获取点集包围盒 - /// - /// Point3d点集 - /// 包围盒 - static Extents3d ToExtents3D(this IEnumerable pts) - { - var ext = new Extents3d(); - foreach (Point3d pt in pts) + /// + /// 获取点集包围盒 + /// + /// Point3d点集 + /// 包围盒 + static Extents3d ToExtents3D(this IEnumerable pts) { - ext.AddPoint(pt); + var ext = new Extents3d(); + foreach (Point3d pt in pts) + { + ext.AddPoint(pt); + } + return ext; } - return ext; - } - /// - /// 获取块的包围盒 - /// - /// 实体 - /// - /// - static void GetBlockBox(this Entity en, ref Extents3d ext, ref Matrix3d mat) - { - if (en is BlockReference block) + /// + /// 获取块的包围盒 + /// + /// 实体 + /// + /// + static void GetBlockBox(this Entity en, ref Extents3d ext, ref Matrix3d mat) { - var matins = mat * block.BlockTransform; - if (block.BlockTableRecord.GetObject() is BlockTableRecord btr) - foreach (ObjectId id in btr) + if (en is BlockReference block) { - id.GetObject(); - if (id.GetObject() is Entity ent1) - { - if (ent1.Visible != true) - continue; - if (ent1 is AttributeDefinition att) + var matins = mat * block.BlockTransform; + if (block.BlockTableRecord.GetObject() is BlockTableRecord btr) + foreach (ObjectId id in btr) + { + id.GetObject(); + if (id.GetObject() is Entity ent1) + { + if (ent1.Visible != true) + continue; + if (ent1 is AttributeDefinition att) + { + if (att != null && (!att.Constant || att.Invisible)) + continue; + } + GetBlockBox(ent1, ref ext, ref matins); + } + } + if (block.AttributeCollection.Count > 0) { - if (att != null && (!att.Constant || att.Invisible)) - continue; + foreach (ObjectId attid in block.AttributeCollection) + { + if (attid.GetObject() is AttributeReference att) + { + if (!att.Invisible && att.Visible) + GetBlockBox(att, ref ext, ref mat); + } + } } - GetBlockBox(ent1, ref ext, ref matins); - } } - if (block.AttributeCollection.Count > 0) - { - foreach (ObjectId attid in block.AttributeCollection) + else { - if (attid.GetObject() is AttributeReference att) - { - if (!att.Invisible && att.Visible) - GetBlockBox(att, ref ext, ref mat); - } + if (mat.IsUniscaledOrtho()) + { + using (var ent1 = en.GetTransformedCopy(mat)) + { + if (ext.IsEmptyExt()) + { + var e = ent1.GetEntityBox(); + if (e.HasValue) + ext = e.Value; + } + else + { + var e = ent1.GetEntityBox(); + if (e.HasValue) + ext.AddExtents(e.Value); + } + } + } + else + { + var e = en.GetEntityBox(); + if (e.HasValue) + { + Extents3d entext = e.Value; + entext.TransformBy(mat); + if (ext.IsEmptyExt()) + ext = entext; + else + ext.AddExtents(entext); + } + return; + } } - } + return; } - else + /// + /// 获取多行文字最小包围盒4点坐标 + /// + /// 多行文本 + /// 最小包围盒4点坐标 + public static Point3d[] GetMTextBoxCorners(this MText mtext) { - if (mat.IsUniscaledOrtho()) - { - using (var ent1 = en.GetTransformedCopy(mat)) + double width = mtext.ActualWidth; + double height = mtext.ActualHeight; + Point3d point1, point2; + switch (mtext.Attachment) { - if (ext.IsEmptyExt()) - { - var e = ent1.GetEntityBox(); - if (e.HasValue) - ext = e.Value; - } - else - { - var e = ent1.GetEntityBox(); - if (e.HasValue) - ext.AddExtents(e.Value); - } + case AttachmentPoint.TopLeft: + default: + point1 = new Point3d(0.0, -height, 0.0); + point2 = new Point3d(width, 0.0, 0.0); + break; + case AttachmentPoint.TopCenter: + point1 = new Point3d(-width * 0.5, -height, 0.0); + point2 = new Point3d(width * 0.5, 0.0, 0.0); + break; + case AttachmentPoint.TopRight: + point1 = new Point3d(-width, -height, 0.0); + point2 = new Point3d(0.0, 0.0, 0.0); + break; + case AttachmentPoint.MiddleLeft: + point1 = new Point3d(0.0, -height * 0.5, 0.0); + point2 = new Point3d(width, height * 0.5, 0.0); + break; + case AttachmentPoint.MiddleCenter: + point1 = new Point3d(-width * 0.5, -height * 0.5, 0.0); + point2 = new Point3d(width * 0.5, height * 0.5, 0.0); + break; + case AttachmentPoint.MiddleRight: + point1 = new Point3d(-width, -height * 0.5, 0.0); + point2 = new Point3d(0.0, height * 0.5, 0.0); + break; + case AttachmentPoint.BottomLeft: + point1 = new Point3d(0.0, 0.0, 0.0); + point2 = new Point3d(width, height, 0.0); + break; + case AttachmentPoint.BottomCenter: + point1 = new Point3d(-width * 0.5, 0.0, 0.0); + point2 = new Point3d(width * 0.5, height, 0.0); + break; + case AttachmentPoint.BottomRight: + point1 = new Point3d(-width, 0.0, 0.0); + point2 = new Point3d(0.0, height, 0.0); + break; } - } - else - { - var e = en.GetEntityBox(); - if (e.HasValue) - { - Extents3d entext = e.Value; - entext.TransformBy(mat); - if (ext.IsEmptyExt()) - ext = entext; - else - ext.AddExtents(entext); - } - return; - } - } - return; - } - /// - /// 获取多行文字最小包围盒4点坐标 - /// - /// 多行文本 - /// 最小包围盒4点坐标 - public static Point3d[] GetMTextBoxCorners(this MText mtext) - { - double width = mtext.ActualWidth; - double height = mtext.ActualHeight; - Point3d point1, point2; - switch (mtext.Attachment) - { - case AttachmentPoint.TopLeft: - default: - point1 = new Point3d(0.0, -height, 0.0); - point2 = new Point3d(width, 0.0, 0.0); - break; - case AttachmentPoint.TopCenter: - point1 = new Point3d(-width * 0.5, -height, 0.0); - point2 = new Point3d(width * 0.5, 0.0, 0.0); - break; - case AttachmentPoint.TopRight: - point1 = new Point3d(-width, -height, 0.0); - point2 = new Point3d(0.0, 0.0, 0.0); - break; - case AttachmentPoint.MiddleLeft: - point1 = new Point3d(0.0, -height * 0.5, 0.0); - point2 = new Point3d(width, height * 0.5, 0.0); - break; - case AttachmentPoint.MiddleCenter: - point1 = new Point3d(-width * 0.5, -height * 0.5, 0.0); - point2 = new Point3d(width * 0.5, height * 0.5, 0.0); - break; - case AttachmentPoint.MiddleRight: - point1 = new Point3d(-width, -height * 0.5, 0.0); - point2 = new Point3d(0.0, height * 0.5, 0.0); - break; - case AttachmentPoint.BottomLeft: - point1 = new Point3d(0.0, 0.0, 0.0); - point2 = new Point3d(width, height, 0.0); - break; - case AttachmentPoint.BottomCenter: - point1 = new Point3d(-width * 0.5, 0.0, 0.0); - point2 = new Point3d(width * 0.5, height, 0.0); - break; - case AttachmentPoint.BottomRight: - point1 = new Point3d(-width, 0.0, 0.0); - point2 = new Point3d(0.0, height, 0.0); - break; - } - var xform = - Matrix3d.Displacement(mtext.Location.GetAsVector()) * - Matrix3d.Rotation(mtext.Rotation, mtext.Normal, Point3d.Origin) * - Matrix3d.PlaneToWorld(new Plane(Point3d.Origin, mtext.Normal)); + var xform = + Matrix3d.Displacement(mtext.Location.GetAsVector()) * + Matrix3d.Rotation(mtext.Rotation, mtext.Normal, Point3d.Origin) * + Matrix3d.PlaneToWorld(new Plane(Point3d.Origin, mtext.Normal)); - return new[] - { + return new[] + { point1.TransformBy(xform), new Point3d(point2.X, point1.Y, 0.0).TransformBy(xform), point2.TransformBy(xform), new Point3d(point1.X, point2.Y, 0.0).TransformBy(xform) }; - } - /// - /// 获取实体包围盒 - /// - /// 实体 - /// 包围盒 - public static Extents3d? GetEntityBoxEx( Entity ent) - { - if (ent is BlockReference block) + } + /// + /// 获取实体包围盒 + /// + /// 实体 + /// 包围盒 + public static Extents3d? GetEntityBoxEx(Entity ent) { - Extents3d blockExt = default; - var mat = Matrix3d.Identity; - block!.GetBlockBox(ref blockExt, ref mat); - if (blockExt.IsEmptyExt()) - return null; - return blockExt; + if (ent is BlockReference block) + { + Extents3d blockExt = default; + var mat = Matrix3d.Identity; + block!.GetBlockBox(ref blockExt, ref mat); + if (blockExt.IsEmptyExt()) + return null; + return blockExt; + } + return GetEntityBox(ent); } - return GetEntityBox(ent); - } - /// - /// 判断包围盒是否有效 - /// - /// 包围盒 - /// - static bool IsEmptyExt(this Extents3d ext) - { - if (ext.MinPoint.DistanceTo(ext.MaxPoint) < Tolerance.Global.EqualPoint) - return true; - else - return false; - } - /// - /// 点偏移 - /// - /// - /// - /// - /// - /// - //static Point3d Offset(this Point3d pt, double x, double y, double z = 0) - //{ - // return new Point3d(pt.X + x, pt.Y + y, pt.Z + z); - //} + /// + /// 判断包围盒是否有效 + /// + /// 包围盒 + /// + static bool IsEmptyExt(this Extents3d ext) + { + if (ext.MinPoint.DistanceTo(ext.MaxPoint) < Tolerance.Global.EqualPoint) + return true; + else + return false; + } + /// + /// 点偏移 + /// + /// + /// + /// + /// + /// + //static Point3d Offset(this Point3d pt, double x, double y, double z = 0) + //{ + // return new Point3d(pt.X + x, pt.Y + y, pt.Z + z); + //} } \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems b/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems index bec68a4..60ff37b 100644 --- a/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems +++ b/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems @@ -23,6 +23,7 @@ + diff --git a/tests/TestShared/Copyclip.cs b/tests/TestShared/Copyclip.cs index 3b164d3..52377f9 100644 --- a/tests/TestShared/Copyclip.cs +++ b/tests/TestShared/Copyclip.cs @@ -287,11 +287,14 @@ void Copy(bool getPoint, bool isEraseSsget = false) if (ent == null) continue; var info = ent.GetBoundingBoxEx(); - if (ent is BlockReference brf) - info.Move(brf.Position, Point3d.Origin); - minx = minx > info.MinX ? info.MinX : minx; - miny = miny > info.MinY ? info.MinY : miny; - minz = minz > info.MinZ ? info.MinZ : minz; + if (info != null) + { + if (ent is BlockReference brf) + info.Value.Move(brf.Position, Point3d.Origin); + minx = minx > info.Value.MinX ? info.Value.MinX : minx; + miny = miny > info.Value.MinY ? info.Value.MinY : miny; + minz = minz > info.Value.MinZ ? info.Value.MinZ : minz; + } } pt = new(minx, miny, minz); } diff --git a/tests/TestShared/TestBlock.cs b/tests/TestShared/TestBlock.cs index d990682..74bbc13 100644 --- a/tests/TestShared/TestBlock.cs +++ b/tests/TestShared/TestBlock.cs @@ -35,11 +35,10 @@ public void Test_GetBoundingBoxEx() return; foreach (var item in ents) { - if (item is null) - continue; - var box = item.GetBoundingBoxEx(); - Env.Print("min:" + box.Min + ";max" + box.Max); - tr.CurrentSpace.AddEntity(new Line(box.Min, box.Max)); + var box = item?.GetBoundingBoxEx(); + Env.Print("min:" + box?.BottomLeft + ";max" + box?.TopRight); + if (box != null) + tr.CurrentSpace.AddEntity(new Line(box.Value.BottomLeft, box.Value.TopRight)); } } diff --git a/tests/TestShared/TestExtents.cs b/tests/TestShared/TestExtents.cs index 2687565..b4916fe 100644 --- a/tests/TestShared/TestExtents.cs +++ b/tests/TestShared/TestExtents.cs @@ -69,8 +69,8 @@ public void Test_entextents() e.ColorIndex = 4; e.Closed = true; })); - var ext = EntityBoundingInfo.GetBoundingInfo(e); - tr.CurrentSpace.AddEntity(ext.Extents3d.CreatePolyline(action: e => + var ext = e.GetBoundingBoxEx(); + tr.CurrentSpace.AddEntity(ext?.Extents3d.CreatePolyline(action: e => { e.ColorIndex = 5; e.Closed = true; diff --git a/tests/TestShared/TestXdata.cs b/tests/TestShared/TestXdata.cs index 7ac2d31..a0c10af 100644 --- a/tests/TestShared/TestXdata.cs +++ b/tests/TestShared/TestXdata.cs @@ -25,6 +25,9 @@ public void Test_AddXdata() {1070, 12 }, { DxfCode.ExtendedDataRegAppName, Appname }, // 可以用dxfcode和int表示组码,移除中间的测试 { DxfCode.ExtendedDataAsciiString, "要移除的我" }, + { DxfCode.ExtendedDataAsciiString, "要移除的我" }, + { DxfCode.ExtendedDataAsciiString, "要移除的我" }, + { DxfCode.ExtendedDataAsciiString, "要移除的我" }, {1070, 12 }, { DxfCode.ExtendedDataRegAppName, "myapp3" }, // 可以用dxfcode和int表示组码 { DxfCode.ExtendedDataAsciiString, "aaaaaaaaa" }, @@ -35,7 +38,28 @@ public void Test_AddXdata() } }; - tr.CurrentSpace.AddEntity(line); + var line1 = new Line(new(0, 0, 0), new(2, 0, 0)); + line1.XData = new XDataList() + { + { DxfCode.ExtendedDataRegAppName, "myapp1" }, // 可以用dxfcode和int表示组码 + { DxfCode.ExtendedDataAsciiString, "xxxxxxx" }, + { 1070, 12 }, + { DxfCode.ExtendedDataRegAppName, Appname }, // 可以用dxfcode和int表示组码,移除中间的测试 + { DxfCode.ExtendedDataAsciiString, "要移除的我" }, + { DxfCode.ExtendedDataAsciiString, "要移除的我" }, + { DxfCode.ExtendedDataAsciiString, "要移除的我" }, + { DxfCode.ExtendedDataAsciiString, "要移除的我" }, + { 1070, 12 }, + { DxfCode.ExtendedDataRegAppName, "myapp3" }, // 可以用dxfcode和int表示组码 + { DxfCode.ExtendedDataAsciiString, "aaaaaaaaa" }, + { DxfCode.ExtendedDataAsciiString, "ccccccccc" }, + { 1070, 12 }, + { DxfCode.ExtendedDataRegAppName, "myapp4" }, // 可以用dxfcode和int表示组码 + { DxfCode.ExtendedDataAsciiString, "bbbbbbbbb" }, + { 1070, 12 } + }; + + tr.CurrentSpace.AddEntity(line,line1); } // 删 [CommandMethod(nameof(Test_RemoveXdata))] -- Gitee From d8c12d574f0a81f212ba5217b04377587e1a7e61 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Mon, 7 Aug 2023 22:41:21 +0800 Subject: [PATCH 169/453] =?UTF-8?q?=E5=8F=91=E5=B8=830.7.1=E7=89=88?= =?UTF-8?q?=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Basal/Directory.Build.props | 4 ++-- src/CAD/Directory.Build.props | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Basal/Directory.Build.props b/src/Basal/Directory.Build.props index ea5f887..29ab28e 100644 --- a/src/Basal/Directory.Build.props +++ b/src/Basal/Directory.Build.props @@ -1,8 +1,8 @@  - 0.7.0 - 发布0.7.0 + 0.7.1 + 发布0.7.1 diff --git a/src/CAD/Directory.Build.props b/src/CAD/Directory.Build.props index 6eedb0f..8bbe5a4 100644 --- a/src/CAD/Directory.Build.props +++ b/src/CAD/Directory.Build.props @@ -1,8 +1,8 @@  - 0.7.0 - 发布0.7.0 + 0.7.1 + 发布0.7.1 -- Gitee From b4ea140c3846b9bbd9ed215ea558a381ecae51bc Mon Sep 17 00:00:00 2001 From: vicwjb Date: Thu, 10 Aug 2023 02:31:43 +0000 Subject: [PATCH 170/453] =?UTF-8?q?=E5=8A=A0=E5=85=A5qq=E9=A2=91=E9=81=93?= =?UTF-8?q?=E9=93=BE=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: vicwjb --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 7438f0b..fef55fb 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,10 @@ ![IFoxCad用户交流群群二维码](./docs/png/ifoxcad用户交流群群二维码.png) + **QQ群为丐群,所以也可以加入qq频道交流:** + +[点击链接加入QQ频道【CAD二次开发】](https://pd.qq.com/s/2wmmkv4c2) + #### 二、 使用帮助 IFoxCAD的项目文档请看 **[IFoxCAD类库从入门到精通](https://www.kdocs.cn/l/cc6ZXSa0vMgD)**。 -- Gitee From ba6b1076a722c8d77acc8230d6f2fbc6b1fba197 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Tue, 15 Aug 2023 19:44:45 +0800 Subject: [PATCH 171/453] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=8C=85=E5=9B=B4?= =?UTF-8?q?=E7=9B=92=E5=AE=BD=E9=AB=98=E5=86=99=E5=8F=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../IFox.CAD.Shared/ExtensionMethod/Entity/BoundingInfo.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BoundingInfo.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BoundingInfo.cs index bf10c2e..c67d494 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BoundingInfo.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BoundingInfo.cs @@ -92,12 +92,12 @@ public struct BoundingInfo /// /// 高 /// - public readonly double Height => Math.Abs(MaxX - MinX); + public readonly double Height => Math.Abs(MaxY - MinY); /// /// 宽 /// - public readonly double Width => Math.Abs(MaxY - MinY); + public readonly double Width => Math.Abs(MaxX - MinX); /// /// 面积 -- Gitee From 2b02f3edf00e451ec067329d50150044116c47a4 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Tue, 15 Aug 2023 19:46:50 +0800 Subject: [PATCH 172/453] =?UTF-8?q?=E4=B8=8D=E5=85=81=E8=AE=B8=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E4=BF=AE=E6=94=B9=E5=8C=85=E5=9B=B4=E7=9B=92=E7=9A=84?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=EF=BC=8C=E4=BB=85=E5=86=85=E9=83=A8=E4=BF=AE?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/Entity/BoundingInfo.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BoundingInfo.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BoundingInfo.cs index c67d494..a6eebd5 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BoundingInfo.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BoundingInfo.cs @@ -12,27 +12,27 @@ public struct BoundingInfo /// /// MinPoint.X /// - public double MinX; + public double MinX { get; private set; } /// /// MinPoint.Y /// - public double MinY; + public double MinY { get; private set; } /// /// MinPoint.Z /// - public double MinZ; + public double MinZ { get; private set; } /// /// MaxPoint.X /// - public double MaxX; + public double MaxX { get; private set; } /// /// MaxPoint.Y /// - public double MaxY; + public double MaxY { get; private set; } /// /// MaxPoint.Z /// - public double MaxZ; + public double MaxZ { get; private set; } #region 包围盒9位码坐标 /* -- Gitee From 4978ba133e424513c354f9f17ffcddf799c886a8 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Wed, 16 Aug 2023 10:52:56 +0800 Subject: [PATCH 173/453] =?UTF-8?q?=E5=88=A0=E9=99=A4=E4=B8=8D=E5=BF=85?= =?UTF-8?q?=E8=A6=81=E7=9A=84GetObject=E6=93=8D=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs index 43c4f31..938789c 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs @@ -98,7 +98,6 @@ static void GetBlockBox(this Entity en, ref Extents3d ext, ref Matrix3d mat) if (block.BlockTableRecord.GetObject() is BlockTableRecord btr) foreach (ObjectId id in btr) { - id.GetObject(); if (id.GetObject() is Entity ent1) { if (ent1.Visible != true) -- Gitee From 0c38dad3b47a4db5037721576e117bc040b50ab3 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Thu, 24 Aug 2023 10:28:16 +0800 Subject: [PATCH 174/453] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=89=93=E6=96=AD?= =?UTF-8?q?=E6=9B=B2=E7=BA=BF=E4=BA=A4=E7=82=B9=E5=AE=B9=E5=B7=AE=E9=97=AE?= =?UTF-8?q?=E9=A2=98=E3=80=82fixed=20#I7UW6Z?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/CurveEx.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/CurveEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/CurveEx.cs index 4effd50..a5d97bb 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/CurveEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/CurveEx.cs @@ -145,6 +145,8 @@ public static List BreakCurve(this List curves) { ArgumentNullEx.ThrowIfNull(curves); + var tol = new Tolerance(0.01, 0.01); + var geCurves = new List(); // 存储曲线转换后的复合曲线 var paramss = new List>(); // 存储每个曲线的交点参数值 @@ -171,7 +173,7 @@ public static List BreakCurve(this List curves) var gc2 = geCurves[j]; var pars2 = paramss[j]; // 引用 - cci3d.Set(gc1, gc2, Vector3d.ZAxis); + cci3d.Set(gc1, gc2, Vector3d.ZAxis, tol); for (int k = 0; k < cci3d.NumberOfIntersectionPoints; k++) { -- Gitee From 11b1daaa61484a95637b456ec6621ce0d77f5ea9 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Thu, 24 Aug 2023 16:13:54 +0800 Subject: [PATCH 175/453] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=90=8E=E5=8F=B0?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=BA=93=E6=96=87=E5=AD=97=E5=AF=B9=E9=BD=90?= =?UTF-8?q?=E4=B8=8D=E6=AD=A3=E7=A1=AE=E7=9A=84=E9=97=AE=E9=A2=98=E3=80=82?= =?UTF-8?q?fixed=20#I7VO04?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/DatabaseEx.cs | 35 +++++++++++++++++++ .../ExtensionMethod/Entity/DBTextEx.cs | 9 +++-- .../ExtensionMethod/Entity/MTextEx.cs | 5 ++- 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/DatabaseEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/DatabaseEx.cs index 6f14471..d195d76 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/DatabaseEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/DatabaseEx.cs @@ -5,6 +5,16 @@ /// public static class DatabaseEx { + + /// + /// 打开切换活动数据库 + /// + /// 当前数据库 + /// 切换数据库对象 + public static SwitchDatabase SwitchDatabase(this Database db) => new(db); + + + /// /// 保存文件 /// @@ -159,4 +169,29 @@ private static (bool error, string path) GetOrCreateSaveAsFile(this Database db) return (true, file); } +} + +/// +/// 自动切换活动数据库 +/// +public class SwitchDatabase : IDisposable +{ + private readonly Database db; + /// + /// 切换活动数据库 + /// + /// 当前数据库 + public SwitchDatabase(Database database) + { + db = HostApplicationServices.WorkingDatabase; + HostApplicationServices.WorkingDatabase = database; + } + /// + /// 恢复活动数据库为默认 + /// + public void Dispose() + { + HostApplicationServices.WorkingDatabase = db; + GC.SuppressFinalize(this); + } } \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/DBTextEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/DBTextEx.cs index c88002b..aefb68d 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/DBTextEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/DBTextEx.cs @@ -21,9 +21,11 @@ public static DBText CreateDBText(Point3d position, string text, double height,A if (string.IsNullOrEmpty(text)) throw new ArgumentNullException(nameof(text), "创建文字无内容"); - var acText = new DBText(); + var workdb = database ?? DBTrans.Top.Database; + using var _ = new SwitchDatabase(workdb); - acText.SetDatabaseDefaults(database ?? DBTrans.Top.Database); + var acText = new DBText(); + acText.SetDatabaseDefaults(workdb); acText.Height = height; acText.TextString = text; @@ -36,7 +38,8 @@ public static DBText CreateDBText(Point3d position, string text, double height,A if (acText.Justify != AttachmentPoint.BaseLeft) acText.AlignmentPoint = position; - acText.AdjustAlignment(database ?? DBTrans.Top.Database); + acText.AdjustAlignment(workdb); + return acText; } diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/MTextEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/MTextEx.cs index 6cbaf08..3d05584 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/MTextEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/MTextEx.cs @@ -21,9 +21,12 @@ public static MText CreateMText(Point3d position, string text, double height, Da if (string.IsNullOrEmpty(text)) throw new ArgumentNullException(nameof(text), "创建文字无内容"); + var db = database ?? DBTrans.Top.Database; + using var _ = new SwitchDatabase(db); + var mText = new MText(); - mText.SetDatabaseDefaults(database ?? DBTrans.Top.Database); + mText.SetDatabaseDefaults(db); mText.TextHeight = height; // 高度 mText.Contents = text; // 内容 -- Gitee From 9932145e0254221680cde277c1ca1738caf14a63 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Fri, 25 Aug 2023 14:49:18 +0800 Subject: [PATCH 176/453] =?UTF-8?q?=E5=A2=9E=E5=8A=A0CreateBoundary?= =?UTF-8?q?=E7=9A=84=E6=98=93=E7=94=A8=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../HatchConverter.cs" | 66 ++++++++++++++++--- 1 file changed, 58 insertions(+), 8 deletions(-) diff --git "a/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchConverter.cs" "b/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchConverter.cs" index 245255a..9e16d24 100644 --- "a/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchConverter.cs" +++ "b/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchConverter.cs" @@ -116,7 +116,8 @@ public HatchConverter(Hatch hatch) : this() /// public void GetBoundarysData() { - _oldHatch?.ForEach(loop => { + _oldHatch?.ForEach(loop => + { HatchConverterData hcData = new(); bool isCurve2d = true; @@ -163,7 +164,7 @@ static void HatchLoopIsPolyline(HatchLoop loop, HatchConverterData hcData) //if (hcData is null) // throw new ArgumentNullException(nameof(hcData)); - ArgumentNullEx.ThrowIfNull(loop); + ArgumentNullEx.ThrowIfNull(loop); ArgumentNullEx.ThrowIfNull(hcData); @@ -269,6 +270,7 @@ static void HatchLoopIsCurve2d(HatchLoop loop, HatchConverterData hcData) /// 创建边界图元 /// /// 返回图元 + [Obsolete("使用带返回值的CreateBoundary替代")] public void CreateBoundary(List outEnts) { for (int i = 0; i < _hcDatas.Count; i++) @@ -292,25 +294,73 @@ public void CreateBoundary(List outEnts) } // 生成边界:圆 - data.CircleData.ForEach(item => { + data.CircleData.ForEach(item => + { outEnts.Add(new Circle(item.Center.Point3d(), Vector3d.ZAxis, item.Radius)); }); // 生成边界:样条曲线 - data.SplineData.ForEach(item => { + data.SplineData.ForEach(item => + { outEnts.Add(item.ToCurve()); }); } if (_oldHatch is not null) { - outEnts.ForEach(ent => { + outEnts.ForEach(ent => + { ent.Color = _oldHatch.Color; ent.Layer = _oldHatch.Layer; }); } } + public List CreateBoundary() + { + List outEnts = new List(); + for (int i = 0; i < _hcDatas.Count; i++) + { + var data = _hcDatas[i]; + // 生成边界:多段线 + if (data.PolyLineData.Count > 0) + { + Polyline pl = new(); + pl.SetDatabaseDefaults(); + for (int j = 0; j < data.PolyLineData.Count; j++) + { + pl.AddVertexAt(j, + data.PolyLineData[j].Vertex, + data.PolyLineData[j].Bulge, + data.PolyLineData[j].StartWidth, + data.PolyLineData[j].EndWidth); + } + outEnts.Add(pl); + } + + // 生成边界:圆 + data.CircleData.ForEach(item => + { + outEnts.Add(new Circle(item.Center.Point3d(), Vector3d.ZAxis, item.Radius)); + }); + + // 生成边界:样条曲线 + data.SplineData.ForEach(item => + { + outEnts.Add(item.ToCurve()); + }); + } + + if (_oldHatch is not null) + { + outEnts.ForEach(ent => + { + ent.Color = _oldHatch.Color; + ent.Layer = _oldHatch.Layer; + }); + } + return outEnts; + } /// /// 创建边界图元和新填充到当前空间 @@ -323,9 +373,9 @@ public ObjectId CreateBoundarysAndHatchToMsPs(BlockTableRecord btrOfAddEntitySpa bool boundaryAssociative = true, bool createHatchFlag = true) { - List boEnts = new(); - CreateBoundary(boEnts); - boEnts.ForEach(ent => { + List boEnts = CreateBoundary(); + boEnts.ForEach(ent => + { BoundaryIds.Add(btrOfAddEntitySpace.AddEntity(ent)); }); -- Gitee From 40d4ffa44655ad10d04cce5e5c9b47082fec862b Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Fri, 25 Aug 2023 15:36:24 +0800 Subject: [PATCH 177/453] =?UTF-8?q?=E5=A2=9E=E5=8A=A0Print=E5=87=BD?= =?UTF-8?q?=E6=95=B0=E7=9A=84=E6=98=93=E7=94=A8=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjEx.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjEx.cs index 1ad2a17..0fdf597 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjEx.cs @@ -11,7 +11,7 @@ public static class ObjEx /// public static void Print(this object obj) { - Acap.DocumentManager.MdiActiveDocument.Editor.WriteMessage($"{obj}\n"); + Acap.DocumentManager.MdiActiveDocument?.Editor.WriteMessage($"\n{obj}\n"); } /// /// 系统的打印 -- Gitee From 59e311d42f001aea860bf23b3345acc1254c256b Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Fri, 25 Aug 2023 15:42:35 +0800 Subject: [PATCH 178/453] =?UTF-8?q?=E5=88=A0=E9=99=A4printline=E5=87=BD?= =?UTF-8?q?=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjEx.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjEx.cs index 0fdf597..e81eeaf 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjEx.cs @@ -17,8 +17,8 @@ public static void Print(this object obj) /// 系统的打印 /// /// - public static void PrintLine(this object obj) - { - Console.WriteLine(obj.ToString()); - } + //public static void PrintLine(this object obj) + //{ + // Console.WriteLine(obj.ToString()); + //} } \ No newline at end of file -- Gitee From e6288e1a69524ecc382775090e7bf1ed92e92416 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Fri, 25 Aug 2023 16:20:39 +0800 Subject: [PATCH 179/453] =?UTF-8?q?=E5=9B=9B=E5=8F=89=E6=A0=91=E6=89=93?= =?UTF-8?q?=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/CurveEx.cs | 202 ++++++++++++++++-- 1 file changed, 181 insertions(+), 21 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/CurveEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/CurveEx.cs index a5d97bb..19d0290 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/CurveEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/CurveEx.cs @@ -93,7 +93,8 @@ public static IEnumerable GetSplitCurves(this Curve curve, IEnumerable { + points = points.OrderBy(point => + { var pt = curve.GetClosestPointTo(point, false); return curve.GetParameterAtPoint(pt); }); @@ -277,6 +278,165 @@ public static List BreakCurveOnZPlane(this List curves) return newCurves; } + /// + /// 打段曲线2维By四叉树 + /// + /// 目前对xline,ray的支持存在错误 + /// 需要更多的测试 + /// + /// + /// 曲线列表 + /// 容差 + /// 打断后的曲线列表 + public static List BreakCurve2dByQuadTree(this List sourceCurveList, double tol = 1e-6) + { + //var tolerance = new Tolerance(tol, tol); + var zPlane = new Plane(Point3d.Origin, Vector3d.ZAxis); + List curves = sourceCurveList.Select(c => c.GetOrthoProjectedCurve(zPlane)).ToList(); + var geCurves = new List(); + var xlines = new List(); + double minX = double.MaxValue; + double minY = double.MaxValue; + double maxX = double.MinValue; + double maxY = double.MinValue; + // 遍历每个曲线,计算出四叉树对象,加到四叉树曲线对象列表和四叉树容器中 + for (int i = 0; i < curves.Count; i++) + { + var curTemp = curves[i]; + if (curTemp is Ray || curTemp is Xline) + { + xlines.Add(curTemp); + } + else + { + var cc3d = curTemp.ToCompositeCurve3d(); + if (cc3d is not null) + { + var e3d = curTemp.GeometricExtents; + var rect = new Rect(e3d.MinPoint.Point2d(), e3d.MaxPoint.Point2d()); + var cit = new BreakCurveInfo(rect, curTemp, cc3d); + if (rect.Left < minX) minX = rect.Left; + if (rect.Right > maxX) maxX = rect.Right; + if (rect.Bottom < minY) minY = rect.Bottom; + if (rect.Top > maxY) maxY = rect.Top; + geCurves.Add(cit); + } + } + } + // 建四叉树容器 + var maxBox = new Rect(minX - 10, minY - 10, maxX + 10, maxY + 10); + xlines.ForEach(xl => + { + var cc3d = new CompositeCurve3d(new[] { xl.GetGeCurve() }); + var bci = new BreakCurveInfo(maxBox, xl, cc3d); + geCurves.Add(bci); + }); + var newCurves = new List(); + var quadTree = new QuadTree(maxBox); + foreach (var bci in geCurves) + { + quadTree.Insert(bci); + } + + var cci3d = new CurveCurveIntersector3d(); + + foreach (var gc1 in geCurves) + { + var parsList = new HashSet(); + var cts = quadTree.Query(new Rect(gc1.Left - tol, gc1.Bottom - tol, gc1.Right + tol, gc1.Top + tol)); + cts.Remove(gc1); + foreach (var gc2 in cts) + { + cci3d.Set(gc1.Cc3d, gc2.Cc3d, Vector3d.ZAxis, Tolerance.Global); + for (int k = 0; k < cci3d.NumberOfIntersectionPoints; k++) + { + var pars = cci3d.GetIntersectionParameters(k); + parsList.Add(pars[0]); + } + if (!gc2.Curve.Closed) + { + var cpt1 = gc1.Cc3d.GetClosestPointTo(gc2.Cc3d.StartPoint); + var cpt2 = gc1.Cc3d.GetClosestPointTo(gc2.Cc3d.EndPoint); + if (cpt1.Point.Distance2dTo(gc2.Cc3d.StartPoint) < tol && cpt1.Point.Distance2dTo(gc1.Cc3d.StartPoint) >= tol) + { + parsList.Add(cpt1.Parameter); + } + if (cpt2.Point.Distance2dTo(gc2.Cc3d.EndPoint) < tol && cpt2.Point.Distance2dTo(gc1.Cc3d.EndPoint) >= tol) + { + parsList.Add(cpt2.Parameter); + } + } + + } + if (gc1.Curve is Polyline || gc1.Curve is Spline) + { + cci3d.Set(gc1.Cc3d, gc1.Cc3d, Vector3d.ZAxis); + for (int k = 0; k < cci3d.NumberOfIntersectionPoints; k++) + { + var pars = cci3d.GetIntersectionParameters(k); + if (pars[0] == pars[1]) + continue; + parsList.Add(pars[0]); + parsList.Add(pars[1]); + } + } + var parsNew = parsList.OrderBy(d => d).ToList(); + + var cur = gc1.Curve; + if (parsNew.Count > 0) + { + var c3ds = Curve3dEx.GetSplitCurves(gc1.Cc3d, parsNew); + if (c3ds is not null && c3ds.Count > 1) + { + if (cur is Arc || (cur is Ellipse { Closed: false })) + { + foreach (var c3d in c3ds) + { + var c3dCur = Curve.CreateFromGeCurve(c3d); + + if (c3dCur is null || c3dCur.Closed || c3dCur is Circle || c3dCur.GetLength() < tol) + continue; + c3dCur.SetPropertiesFrom(cur); + newCurves.Add(c3dCur); + } + continue; + } + foreach (var c3d in c3ds) + { + var c3dCur = Curve.CreateFromGeCurve(c3d); + if (c3dCur is not null) + { + c3dCur.SetPropertiesFrom(cur); + newCurves.Add(c3dCur); + } + } + } + else + { + newCurves.Add(cur.CloneEx()); + } + } + else + { + newCurves.Add(cur.CloneEx()); + } + } + + return newCurves; + } + class BreakCurveInfo : QuadEntity + { + public Rect Rect { get; } + public Curve Curve { get; } + public CompositeCurve3d Cc3d { get; } + + public BreakCurveInfo(Rect rect, Curve curve, CompositeCurve3d cc3d) : base(rect) + { + Curve = curve; + Cc3d = cc3d; + Rect = rect; + } + } /// /// 获取非等比转换的曲线(旋转投影法) /// @@ -582,12 +742,12 @@ public static NurbCurve3d ToCurve3d(this Spline spl) { case Poly2dType.SimplePoly: case Poly2dType.FitCurvePoly: - Polyline pl = new(); - pl.SetDatabaseDefaults(); - pl.ConvertFrom(pl2d, false); - return ToCurve3d(pl); + Polyline pl = new(); + pl.SetDatabaseDefaults(); + pl.ConvertFrom(pl2d, false); + return ToCurve3d(pl); default: - return ToNurbCurve3d(pl2d); + return ToNurbCurve3d(pl2d); } // Polyline pl = new Polyline(); @@ -606,13 +766,13 @@ public static NurbCurve3d ToCurve3d(this Spline spl) { case Poly2dType.SimplePoly: case Poly2dType.FitCurvePoly: - Polyline pl = new(); - pl.SetDatabaseDefaults(); - pl.ConvertFrom(pl2d, false); - return ToNurbCurve3d(pl); + Polyline pl = new(); + pl.SetDatabaseDefaults(); + pl.ConvertFrom(pl2d, false); + return ToNurbCurve3d(pl); default: - return ToCurve3d(pl2d.Spline); + return ToCurve3d(pl2d.Spline); } } @@ -691,15 +851,15 @@ public static CompositeCurve3d ToCurve3d(this Polyline pl) switch (pl.GetSegmentType(i)) { case SegmentType.Line: - c3ds.Add(pl.GetLineSegmentAt(i)); - break; + c3ds.Add(pl.GetLineSegmentAt(i)); + break; case SegmentType.Arc: - c3ds.Add(pl.GetArcSegmentAt(i)); - break; + c3ds.Add(pl.GetArcSegmentAt(i)); + break; default: - break; + break; } } return new CompositeCurve3d(c3ds.ToArray()); @@ -719,15 +879,15 @@ public static CompositeCurve3d ToCurve3d(this Polyline pl) switch (pl.GetSegmentType(i)) { case SegmentType.Line: - nc3dtemp = new NurbCurve3d(pl.GetLineSegmentAt(i)); - break; + nc3dtemp = new NurbCurve3d(pl.GetLineSegmentAt(i)); + break; case SegmentType.Arc: - nc3dtemp = pl.GetArcSegmentAt(i).ToNurbCurve3d(); - break; + nc3dtemp = pl.GetArcSegmentAt(i).ToNurbCurve3d(); + break; default: - break; + break; } if (nc3d is null) nc3d = nc3dtemp; -- Gitee From 35d62def073a6bb0ce2985f3385b83d52c5a5a58 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Mon, 28 Aug 2023 09:58:20 +0800 Subject: [PATCH 180/453] =?UTF-8?q?=E6=9A=B4=E9=9C=B2Table.Add(Record)?= =?UTF-8?q?=E5=87=BD=E6=95=B0=EF=BC=8C=E6=96=B9=E4=BE=BF=E8=B0=83=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/Runtime/SymbolTable.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CAD/IFox.CAD.Shared/Runtime/SymbolTable.cs b/src/CAD/IFox.CAD.Shared/Runtime/SymbolTable.cs index 585f412..450f6f3 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/SymbolTable.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/SymbolTable.cs @@ -98,7 +98,7 @@ public bool Has(ObjectId objectId) /// /// 符号表记录 /// 对象id - private ObjectId Add(TRecord record) + public ObjectId Add(TRecord record) { ObjectId id; using (CurrentSymbolTable.ForWrite()) -- Gitee From e32390d46349f25548b8fe58ce1d35445cfa870d Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Mon, 28 Aug 2023 11:34:41 +0800 Subject: [PATCH 181/453] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=B1=82=E4=B8=A4?= =?UTF-8?q?=E7=82=B9=E5=9C=A8Z=E5=B9=B3=E9=9D=A2=E7=9A=84=E8=B7=9D?= =?UTF-8?q?=E7=A6=BB=E7=9A=84=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/PointEx.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/PointEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/PointEx.cs index 76220f9..024580a 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/PointEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/PointEx.cs @@ -189,7 +189,16 @@ public static double GetArcBulge(this Point2d arc1, Point2d arc2, Point2d arc3, } return bulge; } - + /// + /// 求两点在Z平面的距离 + /// + /// 点1 + /// 点2 + /// 距离 + public static double Distance2dTo(this Point3d pt1, Point3d pt2) + { + return new Vector2d(pt2.X - pt1.X, pt2.Y - pt1.Y).Length; + } #region 首尾相连 /// -- Gitee From 8a39b356c3e3162e50d5793fe918fde206b243a1 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Mon, 28 Aug 2023 11:35:52 +0800 Subject: [PATCH 182/453] =?UTF-8?q?=E5=9B=9B=E5=8F=89=E6=A0=91=E6=89=93?= =?UTF-8?q?=E6=96=AD=E6=9A=82=E6=97=B6=E6=8E=92=E9=99=A4=E6=B5=A9=E8=BE=B0?= =?UTF-8?q?cad?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/CurveEx.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/CurveEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/CurveEx.cs index 19d0290..4ed16e2 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/CurveEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/CurveEx.cs @@ -277,7 +277,7 @@ public static List BreakCurveOnZPlane(this List curves) return newCurves; } - +#if !gcad /// /// 打段曲线2维By四叉树 /// @@ -437,6 +437,7 @@ public BreakCurveInfo(Rect rect, Curve curve, CompositeCurve3d cc3d) : base(rect Rect = rect; } } +#endif /// /// 获取非等比转换的曲线(旋转投影法) /// -- Gitee From c5942fa09b99cc8acf14d1f08038626bec828510 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Mon, 28 Aug 2023 11:41:50 +0800 Subject: [PATCH 183/453] =?UTF-8?q?=E6=B6=88=E9=99=A4=E8=AD=A6=E5=91=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/AutoReg/IAutoGo.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/AutoReg/IAutoGo.cs b/src/CAD/IFox.CAD.Shared/AutoReg/IAutoGo.cs index f6f7ec4..1dbc831 100644 --- a/src/CAD/IFox.CAD.Shared/AutoReg/IAutoGo.cs +++ b/src/CAD/IFox.CAD.Shared/AutoReg/IAutoGo.cs @@ -217,14 +217,17 @@ public static void AppDomainGetTypes(Action action, string? dllNameWithout } } } +#if DEBUG catch (System.Exception e) { -#if DEBUG Debugx.Printl($"出错:{nameof(AppDomainGetTypes)};计数{error};错误信息:{e.Message}"); Debugger.Break(); +#else + catch + { #endif } - } +} /// /// 收集接口下的函数 -- Gitee From 8727b0ed7f0afe9551caa5546358918f7be5a704 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Mon, 28 Aug 2023 15:38:43 +0800 Subject: [PATCH 184/453] =?UTF-8?q?=E4=BA=8B=E5=8A=A1=E4=B8=AD=E7=9A=84red?= =?UTF-8?q?raw=E6=80=BB=E6=98=AF=E6=8A=A5=E9=94=99=EF=BC=8C=E5=85=88?= =?UTF-8?q?=E5=8E=BB=E6=8E=89=E4=BA=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs b/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs index 926ba60..40ce8aa 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs @@ -569,7 +569,7 @@ private void Dispose(bool disposing) if (_commit) { // 刷新队列(后台不刷新) - Editor?.Redraw(); + //Editor?.Redraw(); // 调用cad的事务进行提交,释放托管状态(托管对象) Transaction.Commit(); } -- Gitee From 5c97b97263c331809d46094f0851eeb15d538b60 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Mon, 28 Aug 2023 17:10:43 +0800 Subject: [PATCH 185/453] =?UTF-8?q?ssget=20=E6=94=AF=E6=8C=81=E4=B8=AD?= =?UTF-8?q?=E8=8B=B1=E6=96=87=E5=85=B3=E9=94=AE=E5=AD=97=E6=8F=90=E7=A4=BA?= =?UTF-8?q?=E3=80=82fixed=20#I7WA1W?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/EditorEx.cs | 22 ++++++++++++++----- tests/TestShared/TestEditor.cs | 10 ++++----- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs index 4d7915a..05b90e1 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs @@ -61,13 +61,16 @@ public static SelectionSet SelectByLineWeight(this Editor editor, LineWeight lin /// 模式 /// 过滤器 /// 消息 - /// 关键字和回调函数 + /// + /// 关键字和回调函数 + /// 不用使用下列关键字 "Window/Last/Crossing/BOX/ALL/Fence/WPolygon/CPolygon/Group/Add/Remove/Multiple/Previous/Undo/AUto/Single" + /// /// public static PromptSelectionResult SSGet(this Editor editor, string? mode = null, SelectionFilter? filter = null, (string add, string remove)? messages = null, - Dictionary? keywords = null) + Dictionary? keywords = null) { PromptSelectionOptions pso = new(); PromptSelectionResult ss; @@ -97,10 +100,17 @@ public static PromptSelectionResult SSGet(this Editor editor, pso.Keywords.Add(keyword); if (pso.MessageForRemoval is null) pso.MessageForAdding = "选择对象"; - pso.MessageForAdding += $"[{string.Join(" / ", keywords.Keys.ToArray())}]"; + + var str = keywords.Keys.Select(key => { + keywords.TryGetValue(key, out (string, Action) value); + return $"{value.Item1}({key})"; + }); + + + pso.MessageForAdding += $" [{string.Join("/", str)}]"; pso.KeywordInput += (s, e) => { - if (keywords.TryGetValue(e.Input, out Action value)) - value.Invoke(); + if (keywords.TryGetValue(e.Input, out (string, Action) value)) + value.Item2.Invoke(); }; } try @@ -634,7 +644,7 @@ public static void DrawEndToEndVectors(this Editor editor, IEnumerable bool isclose = false, bool drawHighlighted = false) { var itor = points.GetEnumerator(); - if (points.Count() < 1 || !itor.MoveNext()) return; + if (!points.Any() || !itor.MoveNext()) return; Point3d endPoint1 = itor.Current, endPoint2 = new(), firstEndPoint = endPoint1; while (itor.MoveNext()) { diff --git a/tests/TestShared/TestEditor.cs b/tests/TestShared/TestEditor.cs index 4d0ea4b..52b99aa 100644 --- a/tests/TestShared/TestEditor.cs +++ b/tests/TestShared/TestEditor.cs @@ -58,16 +58,14 @@ public void Test_Zoom_2() [CommandMethod(nameof(Test_Ssget))] public void Test_Ssget() { - var action_a = () => { Env.Print("this is a"); }; - var action_b = () => { Env.Print("this is b"); }; - var keyword = new Dictionary + var keyword = new Dictionary { - { "A", action_a }, - { "B", action_b } + { "D", ("你好", () => { Env.Print("this is c"); }) }, + { "B", ("hello", () => { Env.Print("this is b"); }) } }; - var ss = Env.Editor.SSGet(":S", messages: ("get", "del" ), + var ss = Env.Editor.SSGet(/*":S", */ messages: ("get", "del" ), keywords: keyword); Env.Print(ss!); } -- Gitee From 96bdab6dd0717632205a5b651ac97bc576894316 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Wed, 30 Aug 2023 16:59:23 +0800 Subject: [PATCH 186/453] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=AE=9E=E6=97=B6?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=E6=B7=BB=E5=8A=A0=E5=9B=BE=E5=85=83=E7=9A=84?= =?UTF-8?q?=E7=A4=BA=E4=BE=8B=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/TestShared/TestAddEntity.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/TestShared/TestAddEntity.cs b/tests/TestShared/TestAddEntity.cs index 9c95534..c8d1cd9 100644 --- a/tests/TestShared/TestAddEntity.cs +++ b/tests/TestShared/TestAddEntity.cs @@ -207,4 +207,18 @@ public void Test_TypeSpeed() var tt = line1.GetRXClass().DxfName == nameof(Line); }); } + + [CommandMethod(nameof(Test_sleeptrans))] + public static void Test_sleeptrans() + { + using var tr = new DBTrans(); + for (int i = 0; i < 100; i++) + { + var cir = CircleEx.CreateCircle(new Point3d(i, i, 0), 0.5); + cir.ColorIndex = i; + tr.CurrentSpace.AddEntity(cir); + tr.Editor?.Redraw(cir); + System.Threading.Thread.Sleep(10); + } + } } \ No newline at end of file -- Gitee From d5fc8ad9a2ec405dfc1654d1274ddba75d0f0e76 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Fri, 1 Sep 2023 15:23:31 +0800 Subject: [PATCH 187/453] =?UTF-8?q?=E8=A1=A5=E5=85=85api=E6=96=87=E6=A1=A3?= =?UTF-8?q?=E9=93=BE=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index fef55fb..f154371 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,9 @@ IFoxCAD的项目文档请看 **[IFoxCAD类库从入门到精通](https://www.kdocs.cn/l/cc6ZXSa0vMgD)**。 +IFoxCAD的API文档请看 **[IFoxCAD API 文档](https://inspirefunction.github.io/ifoxdoc/)**。**请注意这个网站需要科学浏览** + + #### 三、IFoxCad 项目模版 目前由于IFoxCad的版本分为0.5、0.6、0.7三个大的版本同时在发布,所以项目模版分为两个主要的版本: -- Gitee From 319e1b25d6cbb720dc22f3615b53484a1e5b8a58 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Wed, 6 Sep 2023 14:36:01 +0800 Subject: [PATCH 188/453] =?UTF-8?q?=E4=BF=AE=E5=A4=8DGetAttributes?= =?UTF-8?q?=E5=87=BD=E6=95=B0=EF=BC=8C=E5=85=88=E5=88=A4=E6=96=ADdatabase?= =?UTF-8?q?=E5=90=A6=E5=88=99=E8=8E=B7=E5=8F=96=E9=A1=B6=E5=B1=82=E4=BA=8B?= =?UTF-8?q?=E5=8A=A1=E4=BC=9A=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs index ce29afe..24fc3ed 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs @@ -140,9 +140,9 @@ public static void ChangeBlockProperty(this BlockReference blockReference, Dicti /// 属性集合 public static IEnumerable GetAttributes(this BlockReference owner) { - var trans = DBTrans.GetTopTransaction(owner.Database); if (owner.Database != null) { + var trans = DBTrans.GetTopTransaction(owner.Database); foreach (ObjectId id in owner.AttributeCollection) yield return (AttributeReference)trans.GetObject(id); } -- Gitee From 434c6129d37ea69ee7dbe4e8a4ddabb8e47fa4ca Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Wed, 6 Sep 2023 14:40:47 +0800 Subject: [PATCH 189/453] =?UTF-8?q?SymbolUtilityServices.RepairSymbolName?= =?UTF-8?q?=E5=9C=A8=E6=B5=A9=E8=BE=B0=E4=B8=AD=E5=90=8C=E6=A0=B7=E6=8A=A5?= =?UTF-8?q?=E9=94=99=EF=BC=8C=E4=BF=AE=E6=94=B9=E6=9D=A1=E4=BB=B6=E7=BC=96?= =?UTF-8?q?=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableEx.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableEx.cs index 5bef6ab..a182126 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableEx.cs @@ -186,7 +186,7 @@ public static ObjectId GetBlockFrom(this SymbolTable Date: Thu, 14 Sep 2023 11:01:09 +0800 Subject: [PATCH 190/453] =?UTF-8?q?GetXDictionary=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E4=B8=BA=E7=A9=BA=E5=8F=AF=E8=83=BD=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/DBDictionaryEx.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBDictionaryEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBDictionaryEx.cs index d0ca018..0d0c494 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBDictionaryEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBDictionaryEx.cs @@ -95,8 +95,9 @@ public static void SetXRecord(this DBDictionary dict, string key, XRecordDataLis /// /// 对象 /// 扩展字典对象 - public static DBDictionary? GetXDictionary(this DBObject obj) + public static DBDictionary GetXDictionary(this DBObject obj,OpenMode openMode =OpenMode.ForRead) { + var tr = DBTrans.GetTopTransaction(obj.Database); ObjectId id = obj.ExtensionDictionary; if (id.IsNull) { @@ -105,7 +106,7 @@ public static void SetXRecord(this DBDictionary dict, string key, XRecordDataLis id = obj.ExtensionDictionary; } - return id.GetObject(); + return (DBDictionary)tr.GetObject(id,openMode); } #region 数据表 -- Gitee From 87a7ec22bd169ded5c523f883fa8b65f78603f6a Mon Sep 17 00:00:00 2001 From: vicwjb Date: Wed, 6 Sep 2023 18:37:43 +0800 Subject: [PATCH 191/453] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E5=BB=B6=E4=BC=B8=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/TestShared/TestCurve.cs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/tests/TestShared/TestCurve.cs b/tests/TestShared/TestCurve.cs index 6669999..01d501d 100644 --- a/tests/TestShared/TestCurve.cs +++ b/tests/TestShared/TestCurve.cs @@ -80,8 +80,21 @@ public void Test_Graphspeed() +public partial class TestCurve +{ + [CommandMethod(nameof(Test_CurveExtend))] + public void Test_CurveExtend() + { + using var tr = new DBTrans(); + var ent = Env.Editor.GetEntity("pick curve").ObjectId.GetObject(); + if (ent is Curve curve) + curve.ForWrite(e => e.Extend(e.EndParam + 1)); + + } +} + -public class TestCurve +public partial class TestCurve { [CommandMethod(nameof(Test_BreakCurve))] public void Test_BreakCurve() -- Gitee From f6dfe0092d814b231fe9b3bdb07e97fb7d927b55 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Fri, 15 Sep 2023 15:56:13 +0800 Subject: [PATCH 192/453] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=8F=92=E5=85=A5?= =?UTF-8?q?=E5=9D=97=E5=87=BD=E6=95=B0=E4=B8=8D=E8=83=BD=E6=AD=A3=E7=A1=AE?= =?UTF-8?q?=E6=8F=92=E5=85=A5=E5=B1=9E=E6=80=A7=E5=9D=97=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98=E3=80=82fixed=20#I81J7J?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/SymbolTableRecordEx.cs | 33 +++++++++---------- tests/TestShared/TestAddEntity.cs | 4 +++ tests/TestShared/TestBlock.cs | 2 ++ 3 files changed, 22 insertions(+), 17 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs index 42cb186..df696d8 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs @@ -182,7 +182,6 @@ public static DrawOrderTable GetDrawOrderTable(this BlockTableRecord btr, /// 块插入比例,默认为1 /// 块插入旋转角(弧度),默认为0 /// 属性字典{Tag,Value},默认为null - /// 事务 /// 块参照对象id public static ObjectId InsertBlock(this BlockTableRecord blockTableRecord, Point3d position, string blockName, @@ -201,6 +200,7 @@ public static ObjectId InsertBlock(this BlockTableRecord blockTableRecord, Point /// /// 插入块参照 /// + /// 块表记录 /// 插入点 /// 块定义id /// 块插入比例,默认为1 @@ -231,28 +231,27 @@ public static ObjectId InsertBlock(this BlockTableRecord blockTableRecord, }; var objid = blockTableRecord.AddEntity(blockref); - if (atts != null) + var btr = tr.GetObject(blockref.BlockTableRecord)!; + if (btr.HasAttributeDefinitions) { - var btr = tr.GetObject(blockref.BlockTableRecord)!; - if (btr.HasAttributeDefinitions) + var attdefs = btr.GetEntities(); + foreach (var attdef in attdefs) { - var attdefs = btr.GetEntities(); - foreach (var attdef in attdefs) + using AttributeReference attref = new(); + attref.SetDatabaseDefaults(); + attref.SetAttributeFromBlock(attdef, blockref.BlockTransform); + attref.Position = attdef.Position.TransformBy(blockref.BlockTransform); + attref.AdjustAlignment(tr.Database); + if (atts is not null && atts.TryGetValue(attdef.Tag, out string str)) { - using AttributeReference attref = new(); - attref.SetDatabaseDefaults(); - attref.SetAttributeFromBlock(attdef, blockref.BlockTransform); - attref.Position = attdef.Position.TransformBy(blockref.BlockTransform); - attref.AdjustAlignment(tr.Database); - - if (atts.ContainsKey(attdef.Tag)) - attref.TextString = atts[attdef.Tag]; - - blockref.AttributeCollection.AppendAttribute(attref); - tr.Transaction.AddNewlyCreatedDBObject(attref, true); + attref.TextString = str; } + + blockref.AttributeCollection.AppendAttribute(attref); + tr.Transaction.AddNewlyCreatedDBObject(attref, true); } } + return objid; } #endregion diff --git a/tests/TestShared/TestAddEntity.cs b/tests/TestShared/TestAddEntity.cs index c8d1cd9..2200cac 100644 --- a/tests/TestShared/TestAddEntity.cs +++ b/tests/TestShared/TestAddEntity.cs @@ -215,6 +215,10 @@ public static void Test_sleeptrans() for (int i = 0; i < 100; i++) { var cir = CircleEx.CreateCircle(new Point3d(i, i, 0), 0.5); + if (cir is null) + { + return; + } cir.ColorIndex = i; tr.CurrentSpace.AddEntity(cir); tr.Editor?.Redraw(cir); diff --git a/tests/TestShared/TestBlock.cs b/tests/TestShared/TestBlock.cs index 74bbc13..7995ee0 100644 --- a/tests/TestShared/TestBlock.cs +++ b/tests/TestShared/TestBlock.cs @@ -193,8 +193,10 @@ public void Test_InsertBlockDef() { "tagTest4", "" } }; tr.CurrentSpace.InsertBlock(new Point3d(10, 10, 0), "test2", atts: def2); + tr.CurrentSpace.InsertBlock(new Point3d(20,20,0),"test2"); tr.CurrentSpace.InsertBlock(new Point3d(-10, 0, 0), "test44"); } + [CommandMethod(nameof(Test_InsertBlockWithDoubleDatabase))] public void Test_InsertBlockWithDoubleDatabase() { -- Gitee From d8057045355e0c224b45c0e5e4f77fe4b649a0f2 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Sun, 17 Sep 2023 23:55:10 +0800 Subject: [PATCH 193/453] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=8F=92=E5=85=A5?= =?UTF-8?q?=E5=9D=97=E7=9A=84=E6=B3=A8=E9=87=8A=E6=80=A7=E4=B8=A2=E5=A4=B1?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98=E3=80=82fixed=20#I820Z0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/SymbolTableRecordEx.cs | 40 +++++++++++-------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs index df696d8..7a665b8 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs @@ -230,26 +230,34 @@ public static ObjectId InsertBlock(this BlockTableRecord blockTableRecord, Rotation = rotation }; var objid = blockTableRecord.AddEntity(blockref); - + // 检查块的注释性 + using var ocm = blockTableRecord.Database.ObjectContextManager; + using var occ = ocm.GetContextCollection("ACDB_ANNOTATIONSCALES"); + if (blockref.Annotative == AnnotativeStates.True) + blockref.AddContext(occ.CurrentContext); + var btr = tr.GetObject(blockref.BlockTableRecord)!; - if (btr.HasAttributeDefinitions) + + if (!btr.HasAttributeDefinitions) return objid; + + var attdefs = btr.GetEntities(); + foreach (var attdef in attdefs) { - var attdefs = btr.GetEntities(); - foreach (var attdef in attdefs) + using AttributeReference attref = new(); + attref.SetDatabaseDefaults(); + attref.SetAttributeFromBlock(attdef, blockref.BlockTransform); + attref.Position = attdef.Position.TransformBy(blockref.BlockTransform); + attref.AdjustAlignment(tr.Database); + if (atts is not null && atts.TryGetValue(attdef.Tag, out string str)) { - using AttributeReference attref = new(); - attref.SetDatabaseDefaults(); - attref.SetAttributeFromBlock(attdef, blockref.BlockTransform); - attref.Position = attdef.Position.TransformBy(blockref.BlockTransform); - attref.AdjustAlignment(tr.Database); - if (atts is not null && atts.TryGetValue(attdef.Tag, out string str)) - { - attref.TextString = str; - } - - blockref.AttributeCollection.AppendAttribute(attref); - tr.Transaction.AddNewlyCreatedDBObject(attref, true); + attref.TextString = str; } + + if (blockref.Annotative == AnnotativeStates.True) + attref.AddContext(occ.CurrentContext); + + blockref.AttributeCollection.AppendAttribute(attref); + tr.Transaction.AddNewlyCreatedDBObject(attref, true); } return objid; -- Gitee From 2c01c64a2a5396330ef6c51a50140a1623ad2b2c Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Mon, 18 Sep 2023 14:54:41 +0800 Subject: [PATCH 194/453] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=9D=9E=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E5=BA=93=E4=B8=AD=E7=9A=84=E5=9D=97=E8=AF=BB=E5=8F=96?= =?UTF-8?q?=E5=B1=9E=E6=80=A7=E6=97=B6=E6=97=A0id=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/Entity/EntityBoundingInfo.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs index 938789c..e0e693a 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs @@ -112,13 +112,10 @@ static void GetBlockBox(this Entity en, ref Extents3d ext, ref Matrix3d mat) } if (block.AttributeCollection.Count > 0) { - foreach (ObjectId attid in block.AttributeCollection) + foreach (var att in block.GetAttributes()) { - if (attid.GetObject() is AttributeReference att) - { - if (!att.Invisible && att.Visible) - GetBlockBox(att, ref ext, ref mat); - } + if (!att.Invisible && att.Visible) + GetBlockBox(att, ref ext, ref mat); } } } -- Gitee From 216eeacab993960431590619285e1e862901652c Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Mon, 18 Sep 2023 14:55:55 +0800 Subject: [PATCH 195/453] =?UTF-8?q?=E4=BF=AE=E5=A4=8DGetTopTransaction?= =?UTF-8?q?=E6=96=B9=E6=B3=95=E5=A1=AB=E5=85=A5=E6=97=A0=E6=95=88=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E5=BA=93=E5=AF=BC=E8=87=B4=E8=87=B4=E5=91=BD=E9=94=99?= =?UTF-8?q?=E8=AF=AF=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs b/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs index 40ce8aa..3fb4a26 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs @@ -23,6 +23,7 @@ public sealed class DBTrans : IDisposable /// 事务对象 public static Transaction GetTopTransaction(Database database) { + ArgumentNullEx.ThrowIfNull(database); return database.TransactionManager.TopTransaction switch { { } tr => tr, -- Gitee From 1ca8fb4a61e9306b9e44dd47b721009577e249ce Mon Sep 17 00:00:00 2001 From: vicwjb Date: Tue, 19 Sep 2023 22:54:07 +0800 Subject: [PATCH 196/453] =?UTF-8?q?=E5=8D=87=E7=BA=A7=E8=87=B3=E6=B5=A9?= =?UTF-8?q?=E8=BE=B02024=EF=BC=8C=E5=A2=9E=E5=8A=A0=E6=B5=A9=E8=BE=B0?= =?UTF-8?q?=E7=9A=84=E6=B5=8B=E8=AF=95=E9=A1=B9=E7=9B=AE=EF=BC=8C=E5=90=88?= =?UTF-8?q?=E5=B9=B6autoreg=E9=87=8C=E7=9A=84=E9=87=8D=E5=A4=8D=E5=87=BD?= =?UTF-8?q?=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IFoxCAD.sln | 8 ++ src/CAD/IFox.CAD.GCAD/GlobalUsings.cs | 32 +++---- src/CAD/IFox.CAD.GCAD/IFox.CAD.GCAD.csproj | 13 +-- src/CAD/IFox.CAD.Shared/AutoReg/AutoLoad.cs | 38 +-------- src/CAD/IFox.CAD.Shared/AutoReg/AutoReg.cs | 72 ++++++++++++++++ .../IFox.CAD.Shared/AutoReg/AutoRegAssem.cs | 83 +------------------ .../ExtensionMethod/CollectionEx.cs | 29 ++----- .../ExtensionMethod/Jig/JigExTransient.cs | 4 +- .../IFox.CAD.Shared/IFox.CAD.Shared.projitems | 2 +- tests/TestGcad2024/GlobalUsings.cs | 49 +++++++++++ tests/TestGcad2024/TestGcad2024.csproj | 29 +++++++ tests/TestShared/TestMirrorFile.cs | 4 +- 12 files changed, 197 insertions(+), 166 deletions(-) create mode 100644 src/CAD/IFox.CAD.Shared/AutoReg/AutoReg.cs create mode 100644 tests/TestGcad2024/GlobalUsings.cs create mode 100644 tests/TestGcad2024/TestGcad2024.csproj diff --git a/IFoxCAD.sln b/IFoxCAD.sln index af5039b..e8a3d2c 100644 --- a/IFoxCAD.sln +++ b/IFoxCAD.sln @@ -60,6 +60,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Docs", "Docs", "{DA8EA8E7-A docs\关于扩展函数的说明.md = docs\关于扩展函数的说明.md EndProjectSection EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestGcad2024", "tests\TestGcad2024\TestGcad2024.csproj", "{FEC39964-9ECB-4567-8F68-94F80A39FA02}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -102,6 +104,10 @@ Global {6ED0A677-6621-4493-AF58-71C2BF31DFCE}.Debug|Any CPU.Build.0 = Debug|Any CPU {6ED0A677-6621-4493-AF58-71C2BF31DFCE}.Release|Any CPU.ActiveCfg = Release|Any CPU {6ED0A677-6621-4493-AF58-71C2BF31DFCE}.Release|Any CPU.Build.0 = Release|Any CPU + {FEC39964-9ECB-4567-8F68-94F80A39FA02}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FEC39964-9ECB-4567-8F68-94F80A39FA02}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FEC39964-9ECB-4567-8F68-94F80A39FA02}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FEC39964-9ECB-4567-8F68-94F80A39FA02}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -119,6 +125,7 @@ Global {F388F4B9-F636-414A-9BC9-2B008517B441} = {B2AB7DC7-DBF4-4197-808B-0D2A6613AF5E} {3D7D095D-EF0A-40B3-9776-5F08C61FD614} = {B2AB7DC7-DBF4-4197-808B-0D2A6613AF5E} {6ED0A677-6621-4493-AF58-71C2BF31DFCE} = {1EE1F817-39D3-43E5-B087-E7AD4D0BEC93} + {FEC39964-9ECB-4567-8F68-94F80A39FA02} = {C0BEFC15-6DF7-4636-BC76-4A0B88231470} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {31D6C754-CF6B-4AB0-9861-6923DD312350} @@ -131,6 +138,7 @@ Global tests\TestShared\TestShared.projitems*{ced63d2d-0af6-4831-806d-5e8e9b0d0a07}*SharedItemsImports = 13 src\CAD\IFox.CAD.Shared\IFox.CAD.Shared.projitems*{ef20e632-70a9-40eb-8c9a-539fd85fafad}*SharedItemsImports = 5 src\CAD\IFox.CAD.Shared\IFox.CAD.Shared.projitems*{f388f4b9-f636-414a-9bc9-2b008517b441}*SharedItemsImports = 5 + tests\TestShared\TestShared.projitems*{fec39964-9ecb-4567-8f68-94f80a39fa02}*SharedItemsImports = 5 src\Basal\IFox.Basal.Shared\IFox.Basal.Shared.projitems*{ff4e1cde-eeb3-4be8-8c1d-6b5b17a299c7}*SharedItemsImports = 5 EndGlobalSection EndGlobal diff --git a/src/CAD/IFox.CAD.GCAD/GlobalUsings.cs b/src/CAD/IFox.CAD.GCAD/GlobalUsings.cs index a6666af..a0398c2 100644 --- a/src/CAD/IFox.CAD.GCAD/GlobalUsings.cs +++ b/src/CAD/IFox.CAD.GCAD/GlobalUsings.cs @@ -16,24 +16,24 @@ global using RegistryKey = Microsoft.Win32.RegistryKey; // cad 引用 -global using GrxCAD.ApplicationServices; -global using GrxCAD.EditorInput; -global using GrxCAD.Colors; -global using GrxCAD.DatabaseServices; -global using GrxCAD.Geometry; -global using GrxCAD.Runtime; -global using Acap = GrxCAD.ApplicationServices.Application; -global using Acaop = GrxCAD.ApplicationServices.Application; -global using AcException = GrxCAD.Runtime.Exception; -global using GrxCAD.DatabaseServices.Filters; +global using Gssoft.Gscad.ApplicationServices; +global using Gssoft.Gscad.EditorInput; +global using Gssoft.Gscad.Colors; +global using Gssoft.Gscad.DatabaseServices; +global using Gssoft.Gscad.Geometry; +global using Gssoft.Gscad.Runtime; +global using Acap = Gssoft.Gscad.ApplicationServices.Application; +global using Acaop = Gssoft.Gscad.ApplicationServices.Core.Application; +global using AcException = Gssoft.Gscad.Runtime.Exception; +global using Gssoft.Gscad.DatabaseServices.Filters; // jig命名空间会引起Viewport/Polyline等等重义,最好逐个引入 using Autodesk.AutoCAD.GraphicsInterface -global using GrxCAD.GraphicsInterface; -global using WorldDraw = GrxCAD.GraphicsInterface.WorldDraw; -global using Manager = GrxCAD.GraphicsSystem.Manager; -global using Group = GrxCAD.DatabaseServices.Group; -global using Viewport = GrxCAD.DatabaseServices.Viewport; -global using Polyline = GrxCAD.DatabaseServices.Polyline; +global using Gssoft.Gscad.GraphicsInterface; +global using WorldDraw = Gssoft.Gscad.GraphicsInterface.WorldDraw; +global using Manager = Gssoft.Gscad.GraphicsSystem.Manager; +global using Group = Gssoft.Gscad.DatabaseServices.Group; +global using Viewport = Gssoft.Gscad.DatabaseServices.Viewport; +global using Polyline = Gssoft.Gscad.DatabaseServices.Polyline; // ifoxcad.basal 引用 global using IFoxCAD.Basal; diff --git a/src/CAD/IFox.CAD.GCAD/IFox.CAD.GCAD.csproj b/src/CAD/IFox.CAD.GCAD/IFox.CAD.GCAD.csproj index d478104..fa04e0b 100644 --- a/src/CAD/IFox.CAD.GCAD/IFox.CAD.GCAD.csproj +++ b/src/CAD/IFox.CAD.GCAD/IFox.CAD.GCAD.csproj @@ -16,18 +16,19 @@ $(Configuration);gcad - - - runtime - - - True + + + runtime + + + + diff --git a/src/CAD/IFox.CAD.Shared/AutoReg/AutoLoad.cs b/src/CAD/IFox.CAD.Shared/AutoReg/AutoLoad.cs index 5eaf5b9..934f40a 100644 --- a/src/CAD/IFox.CAD.Shared/AutoReg/AutoLoad.cs +++ b/src/CAD/IFox.CAD.Shared/AutoReg/AutoLoad.cs @@ -42,47 +42,13 @@ public AutoLoad() _info.Name = assem.GetName().Name; _info.LoadType = AssemLoadType.Startting; - if (!SearchForReg()) + if (!AutoReg.SearchForReg(_info)) { - RegApp(); + AutoReg.RegApp(_info); } } - #region RegApp - - private static RegistryKey GetAcAppKey() - { - - string key = HostApplicationServices.Current.UserRegistryProductRootKey; - RegistryKey ackey = Registry.CurrentUser.OpenSubKey(key, true); - return ackey.CreateSubKey("Applications"); - } - - private bool SearchForReg() - { - RegistryKey appkey = GetAcAppKey(); - var regApps = appkey.GetSubKeyNames(); - return regApps.Contains(_info.Name); - } - - /// - /// 在注册表写入自动加载的程序集信息 - /// - public void RegApp() - { - RegistryKey appkey = GetAcAppKey(); - RegistryKey rk = appkey.CreateSubKey(_info.Name); - rk.SetValue("DESCRIPTION", _info.Fullname, RegistryValueKind.String); - rk.SetValue("LOADCTRLS", _info.LoadType, RegistryValueKind.DWord); - rk.SetValue("LOADER", _info.Loader, RegistryValueKind.String); - rk.SetValue("MANAGED", 1, RegistryValueKind.DWord); - appkey.Close(); - - } - -#endregion RegApp - #region IExtensionApplication 成员 /// diff --git a/src/CAD/IFox.CAD.Shared/AutoReg/AutoReg.cs b/src/CAD/IFox.CAD.Shared/AutoReg/AutoReg.cs new file mode 100644 index 0000000..32e28db --- /dev/null +++ b/src/CAD/IFox.CAD.Shared/AutoReg/AutoReg.cs @@ -0,0 +1,72 @@ +namespace IFoxCAD.Cad; + +/// +/// 自动加载辅助类 +/// +public class AutoReg +{ + /// + /// 获取自动加载注册表位置节点 + /// + /// 注册表节点 + public static RegistryKey GetAcAppKey() + { + string key = HostApplicationServices.Current.UserRegistryProductRootKey; + RegistryKey ackey = Registry.CurrentUser.OpenSubKey(key, true); + return ackey.CreateSubKey("Applications"); + } + /// + /// 是否已经自动加载 + /// + /// 程序集信息 + /// 已经设置返回true,反之返回false + public static bool SearchForReg(AssemInfo info) + { + // 在使用netloadx的时候,此处注册表是失效的,具体原因要进行netloadx测试 + var appkey = GetAcAppKey(); + if (appkey.SubKeyCount == 0) + return false; + + var regApps = appkey.GetSubKeyNames(); + if (regApps.Contains(info.Name)) + { + // 20220409 bug:文件名相同,路径不同,需要判断路径 + var subkey = appkey.OpenSubKey(info.Name); + return subkey.GetValue("LOADER")?.ToString().ToLower() == info.Loader.ToLower(); + } + return false; + } + + /// + /// 在注册表写入自动加载的程序集信息 + /// + /// 程序集信息 + public static void RegApp(AssemInfo info) + { + RegistryKey appkey = GetAcAppKey(); + RegistryKey rk = appkey.CreateSubKey(info.Name); + rk.SetValue("DESCRIPTION", info.Fullname, RegistryValueKind.String); + rk.SetValue("LOADCTRLS", info.LoadType, RegistryValueKind.DWord); + rk.SetValue("LOADER", info.Loader, RegistryValueKind.String); + rk.SetValue("MANAGED", 1, RegistryValueKind.DWord); + appkey.Close(); + } + + /// + /// 卸载注册表信息 + /// + public static bool UnRegApp(AssemInfo info) + { + var appkey = GetAcAppKey(); + if (appkey.SubKeyCount == 0) + return false; + + var regApps = appkey.GetSubKeyNames(); + if (regApps.Contains(info.Name)) + { + appkey.DeleteSubKey(info.Name, false); + return true; + } + return false; + } +} diff --git a/src/CAD/IFox.CAD.Shared/AutoReg/AutoRegAssem.cs b/src/CAD/IFox.CAD.Shared/AutoReg/AutoRegAssem.cs index 88d084c..e07474e 100644 --- a/src/CAD/IFox.CAD.Shared/AutoReg/AutoRegAssem.cs +++ b/src/CAD/IFox.CAD.Shared/AutoReg/AutoRegAssem.cs @@ -58,8 +58,8 @@ public AutoRegAssem(AutoRegConfig autoRegConfig) if ((autoRegConfig & AutoRegConfig.Regedit) == AutoRegConfig.Regedit) { - if (!SearchForReg()) - RegApp(); + if (!AutoReg.SearchForReg(_info)) + AutoReg.RegApp(_info); } if ((autoRegConfig & AutoRegConfig.RemoveEMR) == AutoRegConfig.RemoveEMR) @@ -79,86 +79,7 @@ public AutoRegAssem(AutoRegConfig autoRegConfig) #region RegApp - /// - /// 获取当前cad注册表位置 - /// - /// 打开权限 - /// - public static RegistryKey GetAcAppKey(bool writable = true) - { - RegistryKey? ackey = null; - var hc = HostApplicationServices.Current; -#if acad || zcad // 中望此处缺乏测试 - string key = hc.UserRegistryProductRootKey; - ackey = Registry.CurrentUser.OpenSubKey(key, writable); -#endif - -#if gcad - // gcad 此处是否仍然有bug? 等待其他人测试反馈 - var key = hc.RegistryProductRootKey; // 浩辰2020读出来是"" - string regedit = ""; - if (Env.GetAcadVersion() == 2019) - regedit = @"Software\Gstarsoft\GstarCAD\R" + 19 + @"\zh-CN"; - if (Env.GetAcadVersion() == 2020) - regedit = @"Software\Gstarsoft\GstarCAD\B" + 20 + @"\zh-CN"; - ackey = Registry.CurrentUser.OpenSubKey(regedit, writable); -#endif - - return ackey.CreateSubKey("Applications"); - } - - /// - /// 卸载注册表信息 - /// - public bool UnRegApp() - { - var appkey = GetAcAppKey(); - if (appkey.SubKeyCount == 0) - return false; - - var regApps = appkey.GetSubKeyNames(); - if (regApps.Contains(_info.Name)) - { - appkey.DeleteSubKey(_info.Name, false); - return true; - } - return false; - } - /// - /// 是否已经存在注册表 - /// - /// - bool SearchForReg() - { - // 在使用netloadx的时候,此处注册表是失效的,具体原因要进行netloadx测试 - var appkey = GetAcAppKey(); - if (appkey.SubKeyCount == 0) - return false; - - var regApps = appkey.GetSubKeyNames(); - if (regApps.Contains(_info.Name)) - { - // 20220409 bug:文件名相同,路径不同,需要判断路径 - var info = appkey.OpenSubKey(_info.Name); - return info.GetValue("LOADER")?.ToString().ToLower() == _info.Loader.ToLower(); - } - return false; - } - - /// - /// 在注册表写入自动加载的程序集信息 - /// - public void RegApp() - { - var appkey = GetAcAppKey(); - var rk = appkey.CreateSubKey(_info.Name); - rk.SetValue("DESCRIPTION", _info.Fullname, RegistryValueKind.String); - rk.SetValue("LOADCTRLS", _info.LoadType, RegistryValueKind.DWord); - rk.SetValue("LOADER", _info.Loader, RegistryValueKind.String); - rk.SetValue("MANAGED", 1, RegistryValueKind.DWord); - appkey.Close(); - } // 这里的是不会自动执行的 public void Initialize() diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/CollectionEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/CollectionEx.cs index 916d534..c0962c7 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/CollectionEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/CollectionEx.cs @@ -1,7 +1,4 @@ -using System.ComponentModel; -using System.Xml.Linq; -using static System.Windows.Forms.AxHost; - + namespace IFoxCAD.Cad; /// @@ -190,11 +187,9 @@ public static bool Contains(this KeywordCollection collection, string name, case KeywordName.GlobalName: for (int i = 0; i < collection.Count; i++) { -#if gcad - var item = collection.get_Item(i); -#else + var item = collection[i]; -#endif + if (item.GlobalName == name) { contains = true; @@ -205,11 +200,9 @@ public static bool Contains(this KeywordCollection collection, string name, case KeywordName.LocalName: for (int i = 0; i < collection.Count; i++) { -#if gcad - var item = collection.get_Item(i); -#else + var item = collection[i]; -#endif + if (item.LocalName == name) { contains = true; @@ -220,11 +213,9 @@ public static bool Contains(this KeywordCollection collection, string name, case KeywordName.DisplayName: for (int i = 0; i < collection.Count; i++) { -#if gcad - var item = collection.get_Item(i); -#else + var item = collection[i]; -#endif + if (item.DisplayName == name) { contains = true; @@ -248,11 +239,9 @@ public static Dictionary GetDict(this KeywordCollection collecti Dictionary map = new(); for (int i = 0; i < collection.Count; i++) { -#if gcad - var item = collection.get_Item(i); -#else + var item = collection[i]; -#endif + map.Add(item.GlobalName, item.DisplayName); } return map; diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigExTransient.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigExTransient.cs index 9ac679a..a657c97 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigExTransient.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigExTransient.cs @@ -1,5 +1,4 @@ -#if !gcad -namespace IFoxCAD.Cad; +namespace IFoxCAD.Cad; /// /// 瞬态容器 @@ -143,4 +142,3 @@ protected virtual void Dispose(bool disposing) } #endregion } -#endif \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems b/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems index 60ff37b..4a618ff 100644 --- a/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems +++ b/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems @@ -17,6 +17,7 @@ + @@ -93,7 +94,6 @@ - diff --git a/tests/TestGcad2024/GlobalUsings.cs b/tests/TestGcad2024/GlobalUsings.cs new file mode 100644 index 0000000..a4bf204 --- /dev/null +++ b/tests/TestGcad2024/GlobalUsings.cs @@ -0,0 +1,49 @@ +/// 系统引用 +global using System; +global using System.Collections; +global using System.Collections.Generic; +global using System.IO; +global using System.Linq; +global using System.Text; +global using System.Reflection; +global using System.Text.RegularExpressions; +global using Microsoft.Win32; +global using System.ComponentModel; +global using System.Runtime.InteropServices; +global using System.Collections.Specialized; + +global using Exception = System.Exception; + +global using Registry = Microsoft.Win32.Registry; +global using RegistryKey = Microsoft.Win32.RegistryKey; + +/// autocad 引用 +global using Gssoft.Gscad.ApplicationServices; +global using Gssoft.Gscad.EditorInput; +global using Gssoft.Gscad.Colors; +global using Gssoft.Gscad.DatabaseServices; +global using Gssoft.Gscad.Geometry; +global using Gssoft.Gscad.Runtime; +global using Acap = Gssoft.Gscad.ApplicationServices.Application; +global using Acaop = Gssoft.Gscad.ApplicationServices.Core.Application; +global using Acgi = Gssoft.Gscad.GraphicsInterface; + +global using Gssoft.Gscad.DatabaseServices.Filters; +global using Gssoft.Gscad; + +// jig命名空间会引起Viewport/Polyline等等重义,最好逐个引入 using Gssoft.Gscad.GraphicsInterface +global using WorldDraw = Gssoft.Gscad.GraphicsInterface.WorldDraw; +global using Manager = Gssoft.Gscad.GraphicsSystem.Manager; +global using Group = Gssoft.Gscad.DatabaseServices.Group; +global using Viewport = Gssoft.Gscad.DatabaseServices.Viewport; +global using Gssoft.Gscad.GraphicsInterface; +global using Polyline = Gssoft.Gscad.DatabaseServices.Polyline; +global using Cad_DwgFiler = Gssoft.Gscad.DatabaseServices.DwgFiler; +global using Cad_DxfFiler = Gssoft.Gscad.DatabaseServices.DxfFiler; +global using Cad_ErrorStatus = Gssoft.Gscad.Runtime.ErrorStatus; + + +/// ifoxcad +global using IFoxCAD.Cad; +global using IFoxCAD.Basal; + diff --git a/tests/TestGcad2024/TestGcad2024.csproj b/tests/TestGcad2024/TestGcad2024.csproj new file mode 100644 index 0000000..5336ff6 --- /dev/null +++ b/tests/TestGcad2024/TestGcad2024.csproj @@ -0,0 +1,29 @@ + + + preview + enable + + NET48 + true + true + x64 + True + + + + $(Configuration);gcad + + + + + + + + + + + + + + + diff --git a/tests/TestShared/TestMirrorFile.cs b/tests/TestShared/TestMirrorFile.cs index 20503f7..76ac033 100644 --- a/tests/TestShared/TestMirrorFile.cs +++ b/tests/TestShared/TestMirrorFile.cs @@ -1,6 +1,4 @@ -using Autodesk.AutoCAD.DatabaseServices; - -namespace Test; +namespace Test; public class MirrorFile { -- Gitee From 97e8d420d57f5a7546efadc4c631bb58f7e11b40 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 21 Sep 2023 20:40:44 +0800 Subject: [PATCH 197/453] =?UTF-8?q?2023=E5=B9=B49=E6=9C=8821=E6=97=A520:40?= =?UTF-8?q?=20=E5=91=A8=E5=9B=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/CheckFactory.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/CheckFactory.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/CheckFactory.cs index 42bb785..217e7e4 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/CheckFactory.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/CheckFactory.cs @@ -38,7 +38,8 @@ public static void CheckDuplicateCommand(Assembly? assembly = null) } } } - var strings = dic.Where(o => o.Value.Count() > 1).Select(o => o.Key + "命令重复,在类" + string.Join("和", o.Value) + "中"); + var strings = dic.Where(o => o.Value.Count() > 1) + .Select(o => o.Key + "命令重复,在类" + string.Join("和", o.Value) + "中"); string str = string.Join(Environment.NewLine, strings); if (!string.IsNullOrEmpty(str)) MessageBox.Show(str, "错误:重复命令!"); -- Gitee From 28860f48a1c90bb6f05f42cdcd6a154dde33922b Mon Sep 17 00:00:00 2001 From: vicwjb Date: Wed, 27 Sep 2023 15:45:40 +0800 Subject: [PATCH 198/453] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E5=9D=97=E7=9A=84=E6=9C=89=E6=95=88=E5=90=8D=E5=AD=97=E5=87=BD?= =?UTF-8?q?=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/DBObjectEx.cs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBObjectEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBObjectEx.cs index c881ad9..4e06b42 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBObjectEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBObjectEx.cs @@ -5,6 +5,25 @@ /// public static class DBObjectEx { + /// + /// 获取块的有效名字 + /// + /// 块参照 + /// 名字 + public static string GetBlockName(this BlockReference blk) + { + ArgumentNullEx.ThrowIfNull(blk); + if (blk.IsDynamicBlock) + { + var btrid = blk.DynamicBlockTableRecord; + var tr = btrid.Database.TransactionManager.TopTransaction; + ArgumentNullEx.ThrowIfNull(tr); + var btr = (BlockTableRecord)tr.GetObject(btrid); + return btr.Name; + } + return blk.Name; + } + #region Xdata扩展 /// /// 删除扩展数据 -- Gitee From bbe94c50e20328227cef9ab888ce2fe66ec788d0 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Wed, 27 Sep 2023 15:49:23 +0800 Subject: [PATCH 199/453] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=BB=9F=E8=AE=A1?= =?UTF-8?q?=E5=9D=97=E6=95=B0=E9=87=8F=E7=9A=84=E6=B5=8B=E8=AF=95=E5=87=BD?= =?UTF-8?q?=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/TestShared/TestDBTrans.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/TestShared/TestDBTrans.cs b/tests/TestShared/TestDBTrans.cs index 0cb64b3..41eb67d 100644 --- a/tests/TestShared/TestDBTrans.cs +++ b/tests/TestShared/TestDBTrans.cs @@ -186,4 +186,18 @@ public void Test_TopTransaction() var trm = HostApplicationServices.WorkingDatabase.TransactionManager; } + + [CommandMethod(nameof(Test_DBTrans_BlockCount))] + public void Test_DBTrans_BlockCount() + { + using var tr = new DBTrans(); + var i = tr.CurrentSpace + .GetEntities() + .Where(ent => ent.GetBlockName() == "自定义块"); + + var block = i.ToList()[0]; + Env.Print(i.Count()); + } + + } \ No newline at end of file -- Gitee From 0d6815b631c26f2bfe05b6a6c05dbd103490308d Mon Sep 17 00:00:00 2001 From: vicwjb Date: Thu, 28 Sep 2023 16:00:31 +0800 Subject: [PATCH 200/453] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BA=8C=E7=BB=B4ge?= =?UTF-8?q?=E6=9B=B2=E7=BA=BF=E8=BD=AC=E5=9C=86=E5=BC=A7=E5=87=BD=E6=95=B0?= =?UTF-8?q?=E7=9A=84=E9=94=99=E8=AF=AF=E3=80=82fixed=20#I84X1K?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/Curve2dEx.cs | 4 +- tests/TestShared/TestCurve.cs | 160 ++++++++++++++++++ 2 files changed, 162 insertions(+), 2 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Curve2dEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Curve2dEx.cs index 07db654..0b1fe75 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Curve2dEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Curve2dEx.cs @@ -97,8 +97,8 @@ public static Arc ToArc(this CircularArc2d a2d) if (a2d.IsClockWise) { - startangle = -a2d.EndAngle - refangle; - endangle = -a2d.StartAngle - refangle; + startangle = -a2d.EndAngle + refangle; + endangle = -a2d.StartAngle + refangle; } else { diff --git a/tests/TestShared/TestCurve.cs b/tests/TestShared/TestCurve.cs index 01d501d..075bcc9 100644 --- a/tests/TestShared/TestCurve.cs +++ b/tests/TestShared/TestCurve.cs @@ -91,6 +91,166 @@ public void Test_CurveExtend() curve.ForWrite(e => e.Extend(e.EndParam + 1)); } + + + private Arc ToArc1(CircularArc2d a2d) + { + double startangle, endangle; + double refangle = a2d.ReferenceVector.Angle; + + if (a2d.IsClockWise) + { + startangle = -a2d.EndAngle + refangle; + endangle = -a2d.StartAngle + refangle; + } + else + { + startangle = a2d.StartAngle + refangle; + endangle = a2d.EndAngle + refangle; + } + + return + new Arc( + new Point3d(new Plane(), a2d.Center), + Vector3d.ZAxis, + a2d.Radius, + startangle, + endangle); + } + + + [CommandMethod(nameof(Test_Curve_ToArc))] + public void Test_Curve_ToArc() + { + using var tr = new DBTrans(); + var gearc = new CircularArc2d(new Point2d(0,0),new Point2d(0.5,0.5),new Point2d(1,0)); + var dbarc = gearc.ToArc(); + var dbarc1 = ToArc1(gearc); + dbarc.ColorIndex = 1; + tr.CurrentSpace.AddEntity(dbarc); + dbarc1.ColorIndex = 2; + tr.CurrentSpace.AddEntity(dbarc1); + + var gearc3 = new CircularArc3d(new(0,0,0),new(0.5,0.5,0),new Point3d(1,0,0)); + var dbarc3 = (Arc)Curve.CreateFromGeCurve(gearc3); + dbarc3.ColorIndex = 3; + tr.CurrentSpace.AddEntity(dbarc3); + + + + Polyline pl0 = new();//创建有圆弧的多段线 + + pl0.AddVertexAt(0, new(-520, 200), -0.74, 0, 0); + pl0.AddVertexAt(1, new(-100, 140), 0.52, 0, 0); + pl0.AddVertexAt(2, new(16, -120), -0.27, 0, 0); + pl0.AddVertexAt(3, new(400, -130), 0.75, 0, 0); + pl0.AddVertexAt(4, new(450, 200), -0.69, 0, 0); + tr.CurrentSpace.AddEntity(pl0); + + + for (int FFF = 0; FFF < pl0.NumberOfVertices; FFF++) + { + if (pl0.GetSegmentType(FFF) == SegmentType.Arc) + { + var bulge = pl0.GetBulgeAt(FFF); + + //将 CircularArc2d 转为Arc 颜色为红 + CircularArc2d arc2d = pl0.GetArcSegment2dAt(FFF); + + Arc arc = arc2d.ToArc(); + if (bulge < 0) arc.ReverseCurve(); + arc.ColorIndex = 1; + tr.CurrentSpace.AddEntity(arc); + Env.Printl($"arc的ge:ReferenceVector:{MathEx.ConvertRadToDeg(arc2d.ReferenceVector.Angle)}"); + Env.Printl($"arc的ge:顺时针:{arc2d.IsClockWise}"); + Env.Printl($"arc的ge:起点角度:{MathEx.ConvertRadToDeg(arc2d.StartAngle)},终点角度:{MathEx.ConvertRadToDeg(arc2d.EndAngle)}"); + Env.Printl($"arc的db:起点角度:{MathEx.ConvertRadToDeg(arc.StartAngle)},终点角度:{MathEx.ConvertRadToDeg(arc.EndAngle)}"); + + //将 CircularArc2d 转为Arc 颜色为黄 + CircularArc2d arc2d1 = pl0.GetArcSegment2dAt(FFF); + Arc arc1 = ToArc1(arc2d1); + if (bulge < 0) arc1.ReverseCurve(); + arc1.ColorIndex = 2; + tr.CurrentSpace.AddEntity(arc1); + Env.Printl($"arc1的ge:ReferenceVector:{MathEx.ConvertRadToDeg(arc2d1.ReferenceVector.Angle)}"); + Env.Printl($"arc的ge:顺时针:{arc2d1.IsClockWise}"); + Env.Printl($"arc1的ge:起点角度:{MathEx.ConvertRadToDeg(arc2d1.StartAngle)} ,终点角度: {MathEx.ConvertRadToDeg(arc2d1.EndAngle)}"); + Env.Printl($"arc1的db:起点角度:{MathEx.ConvertRadToDeg(arc1.StartAngle)} ,终点角度: {MathEx.ConvertRadToDeg(arc1.EndAngle)}"); + + //将 CircularArc3d 转为Arc 颜色为黄色 + CircularArc3d arc3d = pl0.GetArcSegmentAt(FFF); + Arc arc2 = arc3d.ToArc(); + + arc2.ColorIndex = 3; + tr.CurrentSpace.AddEntity(arc2); + Env.Printl($"arc2的ge:ReferenceVector:{MathEx.ConvertRadToDeg(arc3d.ReferenceVector.AngleOnPlane(new Plane()))}"); + Env.Printl($"arc2的ge:起点角度:{MathEx.ConvertRadToDeg(arc3d.StartAngle)} ,终点角度: {MathEx.ConvertRadToDeg(arc3d.EndAngle)}"); + Env.Printl($"arc2的db:起点角度:{MathEx.ConvertRadToDeg(arc2.StartAngle)} ,终点角度: {MathEx.ConvertRadToDeg(arc2.EndAngle)}"); + +/* + + +arc的ge: ReferenceVector:154.872779886857 +arc的ge: 顺时针:True +arc的ge:起点角度:0,终点角度:146.005764482025 +arc的db: 起点角度:334.872779886857,终点角度:120.878544368882 +arc1的ge: ReferenceVector:154.872779886857 +arc的ge: 顺时针:True +arc1的ge:起点角度:0 ,终点角度: 146.005764482025 +arc1的db: 起点角度:334.872779886857 ,终点角度: 120.878544368882 +arc2的ge: ReferenceVector:154.872779886857 +arc2的ge: 起点角度:0 ,终点角度: 146.005764482025 +arc2的db: 起点角度:25.1272201131434 ,终点角度: 171.132984595169 + + +arc的ge: ReferenceVector:149.095360016814 +arc的ge: 顺时针:False +arc的ge:起点角度:0,终点角度:109.897726505109 +arc的db: 起点角度:149.095360016814,终点角度:258.993086521922 +arc1的ge: ReferenceVector:149.095360016814 +arc的ge: 顺时针:False +arc1的ge:起点角度:0 ,终点角度: 109.897726505109 +arc1的db: 起点角度:149.095360016814 ,终点角度: 258.993086521922 +arc2的ge: ReferenceVector:149.095360016814 +arc2的ge: 起点角度:0 ,终点角度: 109.897726505109 +arc2的db: 起点角度:149.095360016814 ,终点角度: 258.993086521922 + + +arc的ge: ReferenceVector:118.727409809308 +arc的ge: 顺时针:True +arc的ge:起点角度:0,终点角度:60.4383004893619 +arc的db: 起点角度:298.727409809308,终点角度:359.16571029867 +arc1的ge: ReferenceVector:118.727409809308 +arc的ge: 顺时针:True +arc1的ge:起点角度:0 ,终点角度: 60.4383004893619 +arc1的db: 起点角度:298.727409809308 ,终点角度: 359.16571029867 +arc2的ge: ReferenceVector:118.727409809308 +arc2的ge: 起点角度:0 ,终点角度: 60.4383004893619 +arc2的db: 起点角度:61.2725901906918 ,终点角度: 121.710890680054 + + +arc的ge: ReferenceVector:277.644556524148 +arc的ge: 顺时针:False +arc的ge:起点角度:0,终点角度:147.479590583376 +arc的db: 起点角度:277.644556524148,终点角度:65.124147107524 +arc1的ge: ReferenceVector:277.644556524148 +arc的ge: 顺时针:False +arc1的ge:起点角度:0 ,终点角度: 147.479590583376 +arc1的db: 起点角度:277.644556524148 ,终点角度: 65.124147107524 +arc2的ge: ReferenceVector:277.644556524148 +arc2的ge: 起点角度:0 ,终点角度: 147.479590583376 +arc2的db: 起点角度:277.644556524148 ,终点角度: 65.124147107524 + + + + + + +*/ + } + } + + } } -- Gitee From fc10670adc79a16b336d59b862e0c75dbf9a3e8f Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sun, 8 Oct 2023 15:23:33 +0800 Subject: [PATCH 201/453] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=88=B7=E6=96=B0?= =?UTF-8?q?=E5=9B=BE=E5=B1=82=E7=8A=B6=E6=80=81=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../IFox.CAD.Shared/IFox.CAD.Shared.projitems | 1 + src/CAD/IFox.CAD.Shared/Runtime/IFoxUtils.cs | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 src/CAD/IFox.CAD.Shared/Runtime/IFoxUtils.cs diff --git a/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems b/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems index 4a618ff..af053ce 100644 --- a/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems +++ b/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems @@ -81,6 +81,7 @@ + diff --git a/src/CAD/IFox.CAD.Shared/Runtime/IFoxUtils.cs b/src/CAD/IFox.CAD.Shared/Runtime/IFoxUtils.cs new file mode 100644 index 0000000..5b1dc29 --- /dev/null +++ b/src/CAD/IFox.CAD.Shared/Runtime/IFoxUtils.cs @@ -0,0 +1,17 @@ +namespace IFoxCAD.Cad; + +public class IFoxUtils +{ + /// + /// 刷新图层状态,在修改图层的锁定或冻结状态后使用 + /// + /// 图层id集合 + public static void RegenLayers(IEnumerable objectIds) + { + var type = Acap.Version.Major >= 21 ? Assembly.Load("accoremgd")?.GetType("Autodesk.AutoCAD.Internal.CoreLayerUtilities") : Assembly.Load("acmgd")?.GetType("Autodesk.AutoCAD.Internal.LayerUtilities"); + var mi = type?.GetMethods().FirstOrDefault(e => e.Name == "RegenLayers"); + var pi = type?.GetProperties().FirstOrDefault(e => e.Name == "RegenPending"); + var regenPending = (int)(pi?.GetValue(null) ?? 0); + mi?.Invoke(null, new object[] { objectIds.ToArray(), regenPending }); + } +} -- Gitee From 00283d0ae233189bc3702c7da7d1cdb15a4a6d49 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sun, 8 Oct 2023 16:35:37 +0800 Subject: [PATCH 202/453] =?UTF-8?q?=E4=BD=BF=E4=B8=8D=E5=BC=80DBTrans?= =?UTF-8?q?=E6=97=B6CreateDBText=E4=BE=9D=E7=84=B6=E5=8F=AF=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/DBTextEx.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/DBTextEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/DBTextEx.cs index aefb68d..9ae83af 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/DBTextEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/DBTextEx.cs @@ -21,7 +21,7 @@ public static DBText CreateDBText(Point3d position, string text, double height,A if (string.IsNullOrEmpty(text)) throw new ArgumentNullException(nameof(text), "创建文字无内容"); - var workdb = database ?? DBTrans.Top.Database; + var workdb = database ?? HostApplicationServices.WorkingDatabase; using var _ = new SwitchDatabase(workdb); var acText = new DBText(); -- Gitee From 436c3f4a7fb1fe00a29d5fa4567b135d5c3e6dfb Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 12 Oct 2023 00:08:59 +0800 Subject: [PATCH 203/453] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/CheckFactory.cs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/CheckFactory.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/CheckFactory.cs index 217e7e4..685bfc2 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/CheckFactory.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/CheckFactory.cs @@ -1,6 +1,4 @@ #if Debug -using System.Windows.Forms; - namespace IFoxCAD.Cad; public static class CheckFactory { @@ -27,14 +25,13 @@ public static void CheckDuplicateCommand(Assembly? assembly = null) { foreach (Attribute add in method.GetCustomAttributes(typeof(CommandMethodAttribute), false)) { - if (add is CommandMethodAttribute cma) + if (add is not CommandMethodAttribute cma) + continue; + if (!dic.ContainsKey(cma.GlobalName)) { - if (!dic.ContainsKey(cma.GlobalName)) - { - dic.Add(cma.GlobalName, new()); - } - dic[cma.GlobalName].Add(type.Name + "." + method.Name); + dic.Add(cma.GlobalName, new()); } + dic[cma.GlobalName].Add(type.Name + "." + method.Name); } } } @@ -42,7 +39,7 @@ public static void CheckDuplicateCommand(Assembly? assembly = null) .Select(o => o.Key + "命令重复,在类" + string.Join("和", o.Value) + "中"); string str = string.Join(Environment.NewLine, strings); if (!string.IsNullOrEmpty(str)) - MessageBox.Show(str, "错误:重复命令!"); + MessageBox.Show(str, @"错误:重复命令!"); } } #endif \ No newline at end of file -- Gitee From 9abfa5b80b050e1a7df349e4a53161b93327a589 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Fri, 13 Oct 2023 17:27:47 +0800 Subject: [PATCH 204/453] =?UTF-8?q?=E4=BC=98=E5=8C=96id.Erase=E5=87=BD?= =?UTF-8?q?=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs index ebfa130..5670289 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs @@ -130,7 +130,7 @@ public static void Erase(this ObjectId id) { if (id.IsOk()) { - var ent = id.GetObject()!; + var ent = id.GetObject(); using (ent.ForWrite()) { ent.Erase(); -- Gitee From d86af7d2dd12174dafcc516c196f785afe600cb6 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sat, 14 Oct 2023 18:52:38 +0800 Subject: [PATCH 205/453] =?UTF-8?q?=E4=BF=AE=E5=A4=8DErase=E5=87=BD?= =?UTF-8?q?=E6=95=B0=E5=BC=95=E7=94=A8=E9=94=99=E8=AF=AF=E7=9A=84getObject?= =?UTF-8?q?=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs index 5670289..ebfa130 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs @@ -130,7 +130,7 @@ public static void Erase(this ObjectId id) { if (id.IsOk()) { - var ent = id.GetObject(); + var ent = id.GetObject()!; using (ent.ForWrite()) { ent.Erase(); -- Gitee From 3b25e1742e6d8d152705b4cc592a057048993160 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Mon, 16 Oct 2023 11:53:33 +0800 Subject: [PATCH 206/453] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=89=B9=E9=87=8F?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=95=B0=E6=8D=AE=E5=BA=93=E5=AF=B9=E8=B1=A1?= =?UTF-8?q?=E7=9A=84=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/DBObjectEx.cs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBObjectEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBObjectEx.cs index 4e06b42..e684db9 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBObjectEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBObjectEx.cs @@ -24,6 +24,25 @@ public static string GetBlockName(this BlockReference blk) return blk.Name; } + #region Linq + /// + /// 删除数据库对象 + /// + /// 数据库对象列表 + public static void Erase(this IEnumerable dBObjects) + { + foreach (var dbo in dBObjects) + { + if (dbo.IsNewObject || dbo.IsErased) + continue; + using (dbo.ForWrite()) + { + dbo.Erase(); + } + } + } + #endregion + #region Xdata扩展 /// /// 删除扩展数据 -- Gitee From 65b8dead5d383122aab627a0690e5cb7b1fb2bdf Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Wed, 18 Oct 2023 12:10:09 +0800 Subject: [PATCH 207/453] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=88=9B=E5=BB=BA?= =?UTF-8?q?=E6=96=87=E5=AD=97=E7=9A=84=E9=BB=98=E8=AE=A4=E5=AF=B9=E9=BD=90?= =?UTF-8?q?=E6=96=B9=E5=BC=8F=E4=B8=8Ecad=E4=B8=80=E8=87=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/DBTextEx.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/DBTextEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/DBTextEx.cs index 9ae83af..b338566 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/DBTextEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/DBTextEx.cs @@ -16,7 +16,7 @@ public static class DBTextEx /// 文字属性设置委托 /// 文字对象 /// - public static DBText CreateDBText(Point3d position, string text, double height,AttachmentPoint justify = AttachmentPoint.BottomLeft, Database? database = null,Action? action = null) + public static DBText CreateDBText(Point3d position, string text, double height,AttachmentPoint justify = AttachmentPoint.BaseLeft, Database? database = null,Action? action = null) { if (string.IsNullOrEmpty(text)) throw new ArgumentNullException(nameof(text), "创建文字无内容"); -- Gitee From 6ca3547403bd36c74783a40a93a162cb70eaa15d Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 19 Oct 2023 22:12:59 +0800 Subject: [PATCH 208/453] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=BF=AB=E6=8D=B7?= =?UTF-8?q?=E5=8F=91=E9=80=81=E6=B0=94=E6=B3=A1=E9=80=9A=E7=9F=A5=E7=9A=84?= =?UTF-8?q?Utils=E5=B7=A5=E5=85=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/Runtime/IFoxUtils.cs | 50 ++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/src/CAD/IFox.CAD.Shared/Runtime/IFoxUtils.cs b/src/CAD/IFox.CAD.Shared/Runtime/IFoxUtils.cs index 5b1dc29..ecb699c 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/IFoxUtils.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/IFoxUtils.cs @@ -14,4 +14,54 @@ public static void RegenLayers(IEnumerable objectIds) var regenPending = (int)(pi?.GetValue(null) ?? 0); mi?.Invoke(null, new object[] { objectIds.ToArray(), regenPending }); } + /// + /// 发送气泡通知 + /// + /// 显示的秒数,范围1-10为相应秒数,0为常显 + /// 标题 + /// 内容1 + /// 图标样式 + /// 链接 + /// 链接地址 + /// 内容2 + public static void ShowBubbleWindow(int second, string title, string text, IconType iconType = IconType.None, string? hyperText = null, string? hyperLink = null, string? text2 = null) + { + TrayItem? trayItem = null; + const string name = "IFox"; + var num = Acap.StatusBar.TrayItems.Count; + for (int i = 0; i < num; i++) + { + var ti = Acap.StatusBar.TrayItems[i]; + if (ti.ToolTipText == name) + { + trayItem = ti; + break; + } + } + if (trayItem == null) + { + trayItem = new() + { + ToolTipText = name, + Visible = true, + }; + Acap.StatusBar.TrayItems.Add(trayItem); + Acap.StatusBar.Update(); + } + if (second <= 0) second = 0; + else if (second % 10 == 0) second = 10; + else second %= 10; + Acap.SetSystemVariable("TrayTimeOut", second); + var tibw = new TrayItemBubbleWindow(); + tibw.IconType = iconType; + tibw.Title = title; + tibw.Text = text; + tibw.HyperText = hyperText; + tibw.HyperLink = hyperLink; + tibw.Text2 = text2; + Acap.SetSystemVariable("TRAYICONS", 1); + Acap.SetSystemVariable("TRAYNOTIFY", 1); + trayItem.Visible = true; + trayItem.ShowBubbleWindow(tibw); + } } -- Gitee From 9ed4a98c8cc098583c8ac1163177ae5e52c1e451 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sun, 22 Oct 2023 14:33:25 +0800 Subject: [PATCH 209/453] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=B0=94=E6=B3=A1?= =?UTF-8?q?=E9=80=9A=E7=9F=A5ShowBubbleWindow=E6=97=A0=E9=BB=98=E8=AE=A4?= =?UTF-8?q?=E5=BC=95=E7=94=A8=E6=8A=A5=E9=94=99=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/Runtime/IFoxUtils.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/Runtime/IFoxUtils.cs b/src/CAD/IFox.CAD.Shared/Runtime/IFoxUtils.cs index ecb699c..b06b995 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/IFoxUtils.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/IFoxUtils.cs @@ -24,9 +24,9 @@ public static void RegenLayers(IEnumerable objectIds) /// 链接 /// 链接地址 /// 内容2 - public static void ShowBubbleWindow(int second, string title, string text, IconType iconType = IconType.None, string? hyperText = null, string? hyperLink = null, string? text2 = null) + public static void ShowBubbleWindow(int second, string title, string text, Autodesk.AutoCAD.Windows.IconType iconType = Autodesk.AutoCAD.Windows.IconType.None, string? hyperText = null, string? hyperLink = null, string? text2 = null) { - TrayItem? trayItem = null; + Autodesk.AutoCAD.Windows.TrayItem? trayItem = null; const string name = "IFox"; var num = Acap.StatusBar.TrayItems.Count; for (int i = 0; i < num; i++) @@ -52,7 +52,7 @@ public static void ShowBubbleWindow(int second, string title, string text, IconT else if (second % 10 == 0) second = 10; else second %= 10; Acap.SetSystemVariable("TrayTimeOut", second); - var tibw = new TrayItemBubbleWindow(); + var tibw = new Autodesk.AutoCAD.Windows.TrayItemBubbleWindow(); tibw.IconType = iconType; tibw.Title = title; tibw.Text = text; -- Gitee From 3461a2bcda8cd84bdfe28e546473553439161e5c Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Wed, 1 Nov 2023 11:48:50 +0800 Subject: [PATCH 210/453] =?UTF-8?q?=E6=B7=BB=E5=8A=A0IFoxUtils.VetoMouseDo?= =?UTF-8?q?ubleClickEvent();=20=E5=90=A6=E5=86=B3=E5=8F=8C=E5=87=BB?= =?UTF-8?q?=E4=BA=8B=E4=BB=B6=E6=9C=AC=E8=BA=AB=E7=9A=84=E5=90=8E=E7=BB=AD?= =?UTF-8?q?=E6=93=8D=E4=BD=9C=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/Runtime/IFoxUtils.cs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/CAD/IFox.CAD.Shared/Runtime/IFoxUtils.cs b/src/CAD/IFox.CAD.Shared/Runtime/IFoxUtils.cs index b06b995..5511b6b 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/IFoxUtils.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/IFoxUtils.cs @@ -1,6 +1,6 @@ namespace IFoxCAD.Cad; -public class IFoxUtils +public sealed class IFoxUtils { /// /// 刷新图层状态,在修改图层的锁定或冻结状态后使用 @@ -64,4 +64,15 @@ public static void ShowBubbleWindow(int second, string title, string text, Autod trayItem.Visible = true; trayItem.ShowBubbleWindow(tibw); } + + /// + /// 否决双击事件本身的后续操作,在双击事件中使用 + /// + public static void VetoMouseDoubleClickEvent() + { + const string key = "DBLCLKEDIT"; + var value = Acap.GetSystemVariable(key); + Acap.SetSystemVariable(key, 0); + IdleAction.Add(() => Acap.SetSystemVariable(key, value)); + } } -- Gitee From 677ac1aa4655e3d1eab2505e2d67b9dd5ab64e32 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Tue, 14 Nov 2023 17:47:42 +0800 Subject: [PATCH 211/453] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=A3=81=E5=89=AA?= =?UTF-8?q?=E5=9D=97=E6=97=A0=E6=95=88=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/DBDictionaryEx.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBDictionaryEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBDictionaryEx.cs index 0d0c494..68fa999 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBDictionaryEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBDictionaryEx.cs @@ -227,7 +227,7 @@ public static void SetValue(this DataCell cell, CellType type, object value) else { DBDictionary subDict = new(); - dict.SetAt(name, subDict); + dict.SetAt(name, subDict); newdict = subDict; newdict.TreatElementsAsHard = true; } -- Gitee From c11b3c1ce72cd6fa050980497f737f95dad7b850 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 16 Nov 2023 17:56:18 +0800 Subject: [PATCH 212/453] =?UTF-8?q?2023=E5=B9=B411=E6=9C=8816=E6=97=A517:5?= =?UTF-8?q?6=20=E5=91=A8=E5=9B=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs index 24fc3ed..21ebb19 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs @@ -27,7 +27,7 @@ public static void ClipBlockRef(this BlockReference bref, IEnumerable p SpatialFilterDefinition sfd = new(pts, Vector3d.ZAxis, 0.0, 0.0, 0.0, true); using SpatialFilter sf = new() { Definition = sfd }; - var dict = bref.GetXDictionary()!.GetSubDictionary(true, new string[] { filterDictName })!; + var dict = bref.GetXDictionary().GetSubDictionary(true, new string[] { filterDictName })!; dict.SetAt(spatialName, sf); // SetToDictionary(dict, spatialName, sf); } -- Gitee From 3a82c975d96d220e3a06d2701f825d6219f0d61b Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 16 Nov 2023 22:01:12 +0800 Subject: [PATCH 213/453] =?UTF-8?q?=E5=8F=8D=E8=BD=ACRepairSymbolName?= =?UTF-8?q?=E7=9A=84=E9=80=BB=E8=BE=91=EF=BC=8C=E4=B8=BAautocad=E6=97=B6?= =?UTF-8?q?=E8=B0=83=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableEx.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableEx.cs index a182126..5a32cc3 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableEx.cs @@ -186,7 +186,7 @@ public static ObjectId GetBlockFrom(this SymbolTable Date: Wed, 22 Nov 2023 18:38:37 +0800 Subject: [PATCH 214/453] =?UTF-8?q?2023=E5=B9=B411=E6=9C=8822=E6=97=A518:3?= =?UTF-8?q?8=20=E5=91=A8=E4=B8=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Nullable/NullableAttributes.cs | 397 +++++++++--------- 1 file changed, 201 insertions(+), 196 deletions(-) diff --git a/src/Basal/IFox.Basal.Shared/Nullable/NullableAttributes.cs b/src/Basal/IFox.Basal.Shared/Nullable/NullableAttributes.cs index 361f88f..abad9dd 100644 --- a/src/Basal/IFox.Basal.Shared/Nullable/NullableAttributes.cs +++ b/src/Basal/IFox.Basal.Shared/Nullable/NullableAttributes.cs @@ -1,196 +1,201 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -namespace System.Diagnostics.CodeAnalysis -{ -#if !NETSTANDARD2_1 - /// Specifies that null is allowed as an input even if the corresponding type disallows it. - [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)] -#if SYSTEM_PRIVATE_CORELIB - public -#else - internal -#endif - sealed class AllowNullAttribute : Attribute { } - - /// Specifies that null is disallowed as an input even if the corresponding type allows it. - [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)] -#if SYSTEM_PRIVATE_CORELIB - public -#else - internal -#endif - sealed class DisallowNullAttribute : Attribute { } - - /// Specifies that an output may be null even if the corresponding type disallows it. - [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)] -#if SYSTEM_PRIVATE_CORELIB - public -#else - internal -#endif - sealed class MaybeNullAttribute : Attribute { } - - /// Specifies that an output will not be null even if the corresponding type allows it. Specifies that an input argument was not null when the call returns. - [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)] -#if SYSTEM_PRIVATE_CORELIB - public -#else - internal -#endif - sealed class NotNullAttribute : Attribute { } - - /// Specifies that when a method returns , the parameter may be null even if the corresponding type disallows it. - [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] -#if SYSTEM_PRIVATE_CORELIB - public -#else - internal -#endif - sealed class MaybeNullWhenAttribute : Attribute - { - /// Initializes the attribute with the specified return value condition. - /// - /// The return value condition. If the method returns this value, the associated parameter may be null. - /// - public MaybeNullWhenAttribute(bool returnValue) => ReturnValue = returnValue; - - /// Gets the return value condition. - public bool ReturnValue { get; } - } - - /// Specifies that when a method returns , the parameter will not be null even if the corresponding type allows it. - [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] -#if SYSTEM_PRIVATE_CORELIB - public -#else - internal -#endif - sealed class NotNullWhenAttribute : Attribute - { - /// Initializes the attribute with the specified return value condition. - /// - /// The return value condition. If the method returns this value, the associated parameter will not be null. - /// - public NotNullWhenAttribute(bool returnValue) => ReturnValue = returnValue; - - /// Gets the return value condition. - public bool ReturnValue { get; } - } - - /// Specifies that the output will be non-null if the named parameter is non-null. - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, AllowMultiple = true, Inherited = false)] -#if SYSTEM_PRIVATE_CORELIB - public -#else - internal -#endif - sealed class NotNullIfNotNullAttribute : Attribute - { - /// Initializes the attribute with the associated parameter name. - /// - /// The associated parameter name. The output will be non-null if the argument to the parameter specified is non-null. - /// - public NotNullIfNotNullAttribute(string parameterName) => ParameterName = parameterName; - - /// Gets the associated parameter name. - public string ParameterName { get; } - } - - /// Applied to a method that will never return under any circumstance. - [AttributeUsage(AttributeTargets.Method, Inherited = false)] -#if SYSTEM_PRIVATE_CORELIB - public -#else - internal -#endif - sealed class DoesNotReturnAttribute : Attribute { } - - /// Specifies that the method will not return if the associated Boolean parameter is passed the specified value. - [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] -#if SYSTEM_PRIVATE_CORELIB - public -#else - internal -#endif - sealed class DoesNotReturnIfAttribute : Attribute - { - /// Initializes the attribute with the specified parameter value. - /// - /// The condition parameter value. Code after the method will be considered unreachable by diagnostics if the argument to - /// the associated parameter matches this value. - /// - public DoesNotReturnIfAttribute(bool parameterValue) => ParameterValue = parameterValue; - - /// Gets the condition parameter value. - public bool ParameterValue { get; } - } -#endif - - /// Specifies that the method or property will ensure that the listed field and property members have not-null values. - [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] -#if SYSTEM_PRIVATE_CORELIB - public -#else - internal -#endif - sealed class MemberNotNullAttribute : Attribute - { - /// Initializes the attribute with a field or property member. - /// - /// The field or property member that is promised to be not-null. - /// - public MemberNotNullAttribute(string member) => Members = new[] { member }; - - /// Initializes the attribute with the list of field and property members. - /// - /// The list of field and property members that are promised to be not-null. - /// - public MemberNotNullAttribute(params string[] members) => Members = members; - - /// Gets field or property member names. - public string[] Members { get; } - } - - /// Specifies that the method or property will ensure that the listed field and property members have not-null values when returning with the specified return value condition. - [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] -#if SYSTEM_PRIVATE_CORELIB - public -#else - internal -#endif - sealed class MemberNotNullWhenAttribute : Attribute - { - /// Initializes the attribute with the specified return value condition and a field or property member. - /// - /// The return value condition. If the method returns this value, the associated parameter will not be null. - /// - /// - /// The field or property member that is promised to be not-null. - /// - public MemberNotNullWhenAttribute(bool returnValue, string member) - { - ReturnValue = returnValue; - Members = new[] { member }; - } - - /// Initializes the attribute with the specified return value condition and list of field and property members. - /// - /// The return value condition. If the method returns this value, the associated parameter will not be null. - /// - /// - /// The list of field and property members that are promised to be not-null. - /// - public MemberNotNullWhenAttribute(bool returnValue, params string[] members) - { - ReturnValue = returnValue; - Members = members; - } - - /// Gets the return value condition. - public bool ReturnValue { get; } - - /// Gets field or property member names. - public string[] Members { get; } - } -} +//// Licensed to the .NET Foundation under one or more agreements. +//// The .NET Foundation licenses this file to you under the MIT license. + +//namespace System.Diagnostics.CodeAnalysis +//{ +//#if !NETSTANDARD2_1 +// /// Specifies that null is allowed as an input even if the corresponding type disallows it. +// [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)] +//#if SYSTEM_PRIVATE_CORELIB +// public +//#else +// internal +//#endif +// sealed class AllowNullAttribute : Attribute +// { } + +// /// Specifies that null is disallowed as an input even if the corresponding type allows it. +// [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)] +//#if SYSTEM_PRIVATE_CORELIB +// public +//#else +// internal +//#endif +// sealed class DisallowNullAttribute : Attribute +// { } + +// /// Specifies that an output may be null even if the corresponding type disallows it. +// [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)] +//#if SYSTEM_PRIVATE_CORELIB +// public +//#else +// internal +//#endif +// sealed class MaybeNullAttribute : Attribute +// { } + +// /// Specifies that an output will not be null even if the corresponding type allows it. Specifies that an input argument was not null when the call returns. +// [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)] +//#if SYSTEM_PRIVATE_CORELIB +// public +//#else +// internal +//#endif +// sealed class NotNullAttribute : Attribute +// { } + +// /// Specifies that when a method returns , the parameter may be null even if the corresponding type disallows it. +// [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] +//#if SYSTEM_PRIVATE_CORELIB +// public +//#else +// internal +//#endif +// sealed class MaybeNullWhenAttribute : Attribute +// { +// /// Initializes the attribute with the specified return value condition. +// /// +// /// The return value condition. If the method returns this value, the associated parameter may be null. +// /// +// public MaybeNullWhenAttribute(bool returnValue) => ReturnValue = returnValue; + +// /// Gets the return value condition. +// public bool ReturnValue { get; } +// } + +// /// Specifies that when a method returns , the parameter will not be null even if the corresponding type allows it. +// [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] +//#if SYSTEM_PRIVATE_CORELIB +// public +//#else +// internal +//#endif +// sealed class NotNullWhenAttribute : Attribute +// { +// /// Initializes the attribute with the specified return value condition. +// /// +// /// The return value condition. If the method returns this value, the associated parameter will not be null. +// /// +// public NotNullWhenAttribute(bool returnValue) => ReturnValue = returnValue; + +// /// Gets the return value condition. +// public bool ReturnValue { get; } +// } + +// /// Specifies that the output will be non-null if the named parameter is non-null. +// [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, AllowMultiple = true, Inherited = false)] +//#if SYSTEM_PRIVATE_CORELIB +// public +//#else +// internal +//#endif +// sealed class NotNullIfNotNullAttribute : Attribute +// { +// /// Initializes the attribute with the associated parameter name. +// /// +// /// The associated parameter name. The output will be non-null if the argument to the parameter specified is non-null. +// /// +// public NotNullIfNotNullAttribute(string parameterName) => ParameterName = parameterName; + +// /// Gets the associated parameter name. +// public string ParameterName { get; } +// } + +// /// Applied to a method that will never return under any circumstance. +// [AttributeUsage(AttributeTargets.Method, Inherited = false)] +//#if SYSTEM_PRIVATE_CORELIB +// public +//#else +// internal +//#endif +// sealed class DoesNotReturnAttribute : Attribute +// { } + +// /// Specifies that the method will not return if the associated Boolean parameter is passed the specified value. +// [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] +//#if SYSTEM_PRIVATE_CORELIB +// public +//#else +// internal +//#endif +// sealed class DoesNotReturnIfAttribute : Attribute +// { +// /// Initializes the attribute with the specified parameter value. +// /// +// /// The condition parameter value. Code after the method will be considered unreachable by diagnostics if the argument to +// /// the associated parameter matches this value. +// /// +// public DoesNotReturnIfAttribute(bool parameterValue) => ParameterValue = parameterValue; + +// /// Gets the condition parameter value. +// public bool ParameterValue { get; } +// } +//#endif + +// /// Specifies that the method or property will ensure that the listed field and property members have not-null values. +// [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] +//#if SYSTEM_PRIVATE_CORELIB +// public +//#else +// internal +//#endif +// sealed class MemberNotNullAttribute : Attribute +// { +// /// Initializes the attribute with a field or property member. +// /// +// /// The field or property member that is promised to be not-null. +// /// +// public MemberNotNullAttribute(string member) => Members = new[] { member }; + +// /// Initializes the attribute with the list of field and property members. +// /// +// /// The list of field and property members that are promised to be not-null. +// /// +// public MemberNotNullAttribute(params string[] members) => Members = members; + +// /// Gets field or property member names. +// public string[] Members { get; } +// } + +// /// Specifies that the method or property will ensure that the listed field and property members have not-null values when returning with the specified return value condition. +// [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] +//#if SYSTEM_PRIVATE_CORELIB +// public +//#else +// internal +//#endif +// sealed class MemberNotNullWhenAttribute : Attribute +// { +// /// Initializes the attribute with the specified return value condition and a field or property member. +// /// +// /// The return value condition. If the method returns this value, the associated parameter will not be null. +// /// +// /// +// /// The field or property member that is promised to be not-null. +// /// +// public MemberNotNullWhenAttribute(bool returnValue, string member) +// { +// ReturnValue = returnValue; +// Members = new[] { member }; +// } + +// /// Initializes the attribute with the specified return value condition and list of field and property members. +// /// +// /// The return value condition. If the method returns this value, the associated parameter will not be null. +// /// +// /// +// /// The list of field and property members that are promised to be not-null. +// /// +// public MemberNotNullWhenAttribute(bool returnValue, params string[] members) +// { +// ReturnValue = returnValue; +// Members = members; +// } + +// /// Gets the return value condition. +// public bool ReturnValue { get; } + +// /// Gets field or property member names. +// public string[] Members { get; } +// } +//} -- Gitee From 1d19a18baa0f3439f598c01a4ce29309af5437f2 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Wed, 22 Nov 2023 18:43:13 +0800 Subject: [PATCH 215/453] =?UTF-8?q?Revert=20"2023=E5=B9=B411=E6=9C=8822?= =?UTF-8?q?=E6=97=A518:38=20=E5=91=A8=E4=B8=89"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 6986bd7d318c622c993a7d42a6070fc5677b8543. --- .../Nullable/NullableAttributes.cs | 397 +++++++++--------- 1 file changed, 196 insertions(+), 201 deletions(-) diff --git a/src/Basal/IFox.Basal.Shared/Nullable/NullableAttributes.cs b/src/Basal/IFox.Basal.Shared/Nullable/NullableAttributes.cs index abad9dd..361f88f 100644 --- a/src/Basal/IFox.Basal.Shared/Nullable/NullableAttributes.cs +++ b/src/Basal/IFox.Basal.Shared/Nullable/NullableAttributes.cs @@ -1,201 +1,196 @@ -//// Licensed to the .NET Foundation under one or more agreements. -//// The .NET Foundation licenses this file to you under the MIT license. - -//namespace System.Diagnostics.CodeAnalysis -//{ -//#if !NETSTANDARD2_1 -// /// Specifies that null is allowed as an input even if the corresponding type disallows it. -// [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)] -//#if SYSTEM_PRIVATE_CORELIB -// public -//#else -// internal -//#endif -// sealed class AllowNullAttribute : Attribute -// { } - -// /// Specifies that null is disallowed as an input even if the corresponding type allows it. -// [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)] -//#if SYSTEM_PRIVATE_CORELIB -// public -//#else -// internal -//#endif -// sealed class DisallowNullAttribute : Attribute -// { } - -// /// Specifies that an output may be null even if the corresponding type disallows it. -// [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)] -//#if SYSTEM_PRIVATE_CORELIB -// public -//#else -// internal -//#endif -// sealed class MaybeNullAttribute : Attribute -// { } - -// /// Specifies that an output will not be null even if the corresponding type allows it. Specifies that an input argument was not null when the call returns. -// [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)] -//#if SYSTEM_PRIVATE_CORELIB -// public -//#else -// internal -//#endif -// sealed class NotNullAttribute : Attribute -// { } - -// /// Specifies that when a method returns , the parameter may be null even if the corresponding type disallows it. -// [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] -//#if SYSTEM_PRIVATE_CORELIB -// public -//#else -// internal -//#endif -// sealed class MaybeNullWhenAttribute : Attribute -// { -// /// Initializes the attribute with the specified return value condition. -// /// -// /// The return value condition. If the method returns this value, the associated parameter may be null. -// /// -// public MaybeNullWhenAttribute(bool returnValue) => ReturnValue = returnValue; - -// /// Gets the return value condition. -// public bool ReturnValue { get; } -// } - -// /// Specifies that when a method returns , the parameter will not be null even if the corresponding type allows it. -// [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] -//#if SYSTEM_PRIVATE_CORELIB -// public -//#else -// internal -//#endif -// sealed class NotNullWhenAttribute : Attribute -// { -// /// Initializes the attribute with the specified return value condition. -// /// -// /// The return value condition. If the method returns this value, the associated parameter will not be null. -// /// -// public NotNullWhenAttribute(bool returnValue) => ReturnValue = returnValue; - -// /// Gets the return value condition. -// public bool ReturnValue { get; } -// } - -// /// Specifies that the output will be non-null if the named parameter is non-null. -// [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, AllowMultiple = true, Inherited = false)] -//#if SYSTEM_PRIVATE_CORELIB -// public -//#else -// internal -//#endif -// sealed class NotNullIfNotNullAttribute : Attribute -// { -// /// Initializes the attribute with the associated parameter name. -// /// -// /// The associated parameter name. The output will be non-null if the argument to the parameter specified is non-null. -// /// -// public NotNullIfNotNullAttribute(string parameterName) => ParameterName = parameterName; - -// /// Gets the associated parameter name. -// public string ParameterName { get; } -// } - -// /// Applied to a method that will never return under any circumstance. -// [AttributeUsage(AttributeTargets.Method, Inherited = false)] -//#if SYSTEM_PRIVATE_CORELIB -// public -//#else -// internal -//#endif -// sealed class DoesNotReturnAttribute : Attribute -// { } - -// /// Specifies that the method will not return if the associated Boolean parameter is passed the specified value. -// [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] -//#if SYSTEM_PRIVATE_CORELIB -// public -//#else -// internal -//#endif -// sealed class DoesNotReturnIfAttribute : Attribute -// { -// /// Initializes the attribute with the specified parameter value. -// /// -// /// The condition parameter value. Code after the method will be considered unreachable by diagnostics if the argument to -// /// the associated parameter matches this value. -// /// -// public DoesNotReturnIfAttribute(bool parameterValue) => ParameterValue = parameterValue; - -// /// Gets the condition parameter value. -// public bool ParameterValue { get; } -// } -//#endif - -// /// Specifies that the method or property will ensure that the listed field and property members have not-null values. -// [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] -//#if SYSTEM_PRIVATE_CORELIB -// public -//#else -// internal -//#endif -// sealed class MemberNotNullAttribute : Attribute -// { -// /// Initializes the attribute with a field or property member. -// /// -// /// The field or property member that is promised to be not-null. -// /// -// public MemberNotNullAttribute(string member) => Members = new[] { member }; - -// /// Initializes the attribute with the list of field and property members. -// /// -// /// The list of field and property members that are promised to be not-null. -// /// -// public MemberNotNullAttribute(params string[] members) => Members = members; - -// /// Gets field or property member names. -// public string[] Members { get; } -// } - -// /// Specifies that the method or property will ensure that the listed field and property members have not-null values when returning with the specified return value condition. -// [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] -//#if SYSTEM_PRIVATE_CORELIB -// public -//#else -// internal -//#endif -// sealed class MemberNotNullWhenAttribute : Attribute -// { -// /// Initializes the attribute with the specified return value condition and a field or property member. -// /// -// /// The return value condition. If the method returns this value, the associated parameter will not be null. -// /// -// /// -// /// The field or property member that is promised to be not-null. -// /// -// public MemberNotNullWhenAttribute(bool returnValue, string member) -// { -// ReturnValue = returnValue; -// Members = new[] { member }; -// } - -// /// Initializes the attribute with the specified return value condition and list of field and property members. -// /// -// /// The return value condition. If the method returns this value, the associated parameter will not be null. -// /// -// /// -// /// The list of field and property members that are promised to be not-null. -// /// -// public MemberNotNullWhenAttribute(bool returnValue, params string[] members) -// { -// ReturnValue = returnValue; -// Members = members; -// } - -// /// Gets the return value condition. -// public bool ReturnValue { get; } - -// /// Gets field or property member names. -// public string[] Members { get; } -// } -//} +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Diagnostics.CodeAnalysis +{ +#if !NETSTANDARD2_1 + /// Specifies that null is allowed as an input even if the corresponding type disallows it. + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)] +#if SYSTEM_PRIVATE_CORELIB + public +#else + internal +#endif + sealed class AllowNullAttribute : Attribute { } + + /// Specifies that null is disallowed as an input even if the corresponding type allows it. + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)] +#if SYSTEM_PRIVATE_CORELIB + public +#else + internal +#endif + sealed class DisallowNullAttribute : Attribute { } + + /// Specifies that an output may be null even if the corresponding type disallows it. + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)] +#if SYSTEM_PRIVATE_CORELIB + public +#else + internal +#endif + sealed class MaybeNullAttribute : Attribute { } + + /// Specifies that an output will not be null even if the corresponding type allows it. Specifies that an input argument was not null when the call returns. + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)] +#if SYSTEM_PRIVATE_CORELIB + public +#else + internal +#endif + sealed class NotNullAttribute : Attribute { } + + /// Specifies that when a method returns , the parameter may be null even if the corresponding type disallows it. + [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] +#if SYSTEM_PRIVATE_CORELIB + public +#else + internal +#endif + sealed class MaybeNullWhenAttribute : Attribute + { + /// Initializes the attribute with the specified return value condition. + /// + /// The return value condition. If the method returns this value, the associated parameter may be null. + /// + public MaybeNullWhenAttribute(bool returnValue) => ReturnValue = returnValue; + + /// Gets the return value condition. + public bool ReturnValue { get; } + } + + /// Specifies that when a method returns , the parameter will not be null even if the corresponding type allows it. + [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] +#if SYSTEM_PRIVATE_CORELIB + public +#else + internal +#endif + sealed class NotNullWhenAttribute : Attribute + { + /// Initializes the attribute with the specified return value condition. + /// + /// The return value condition. If the method returns this value, the associated parameter will not be null. + /// + public NotNullWhenAttribute(bool returnValue) => ReturnValue = returnValue; + + /// Gets the return value condition. + public bool ReturnValue { get; } + } + + /// Specifies that the output will be non-null if the named parameter is non-null. + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, AllowMultiple = true, Inherited = false)] +#if SYSTEM_PRIVATE_CORELIB + public +#else + internal +#endif + sealed class NotNullIfNotNullAttribute : Attribute + { + /// Initializes the attribute with the associated parameter name. + /// + /// The associated parameter name. The output will be non-null if the argument to the parameter specified is non-null. + /// + public NotNullIfNotNullAttribute(string parameterName) => ParameterName = parameterName; + + /// Gets the associated parameter name. + public string ParameterName { get; } + } + + /// Applied to a method that will never return under any circumstance. + [AttributeUsage(AttributeTargets.Method, Inherited = false)] +#if SYSTEM_PRIVATE_CORELIB + public +#else + internal +#endif + sealed class DoesNotReturnAttribute : Attribute { } + + /// Specifies that the method will not return if the associated Boolean parameter is passed the specified value. + [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] +#if SYSTEM_PRIVATE_CORELIB + public +#else + internal +#endif + sealed class DoesNotReturnIfAttribute : Attribute + { + /// Initializes the attribute with the specified parameter value. + /// + /// The condition parameter value. Code after the method will be considered unreachable by diagnostics if the argument to + /// the associated parameter matches this value. + /// + public DoesNotReturnIfAttribute(bool parameterValue) => ParameterValue = parameterValue; + + /// Gets the condition parameter value. + public bool ParameterValue { get; } + } +#endif + + /// Specifies that the method or property will ensure that the listed field and property members have not-null values. + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] +#if SYSTEM_PRIVATE_CORELIB + public +#else + internal +#endif + sealed class MemberNotNullAttribute : Attribute + { + /// Initializes the attribute with a field or property member. + /// + /// The field or property member that is promised to be not-null. + /// + public MemberNotNullAttribute(string member) => Members = new[] { member }; + + /// Initializes the attribute with the list of field and property members. + /// + /// The list of field and property members that are promised to be not-null. + /// + public MemberNotNullAttribute(params string[] members) => Members = members; + + /// Gets field or property member names. + public string[] Members { get; } + } + + /// Specifies that the method or property will ensure that the listed field and property members have not-null values when returning with the specified return value condition. + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] +#if SYSTEM_PRIVATE_CORELIB + public +#else + internal +#endif + sealed class MemberNotNullWhenAttribute : Attribute + { + /// Initializes the attribute with the specified return value condition and a field or property member. + /// + /// The return value condition. If the method returns this value, the associated parameter will not be null. + /// + /// + /// The field or property member that is promised to be not-null. + /// + public MemberNotNullWhenAttribute(bool returnValue, string member) + { + ReturnValue = returnValue; + Members = new[] { member }; + } + + /// Initializes the attribute with the specified return value condition and list of field and property members. + /// + /// The return value condition. If the method returns this value, the associated parameter will not be null. + /// + /// + /// The list of field and property members that are promised to be not-null. + /// + public MemberNotNullWhenAttribute(bool returnValue, params string[] members) + { + ReturnValue = returnValue; + Members = members; + } + + /// Gets the return value condition. + public bool ReturnValue { get; } + + /// Gets field or property member names. + public string[] Members { get; } + } +} -- Gitee From 0eb753283af35d2ddbb475e7dab4f0a5d1feca15 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Fri, 1 Dec 2023 15:58:05 +0800 Subject: [PATCH 216/453] =?UTF-8?q?=E7=94=A8=E8=BF=87=E7=9A=84=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E5=BA=93=E6=B7=BB=E5=8A=A0using=E5=8F=8A=E6=97=B6disp?= =?UTF-8?q?ose?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableEx.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableEx.cs index 5a32cc3..928f03f 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableEx.cs @@ -193,7 +193,7 @@ public static ObjectId GetBlockFrom(this SymbolTable Date: Fri, 1 Dec 2023 18:19:40 +0800 Subject: [PATCH 217/453] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=88=9B=E5=BB=BA?= =?UTF-8?q?=E9=80=8F=E6=98=8E=E5=BA=A6=E7=9A=84=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/Runtime/IFoxUtils.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/CAD/IFox.CAD.Shared/Runtime/IFoxUtils.cs b/src/CAD/IFox.CAD.Shared/Runtime/IFoxUtils.cs index 5511b6b..20f95f7 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/IFoxUtils.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/IFoxUtils.cs @@ -75,4 +75,13 @@ public static void VetoMouseDoubleClickEvent() Acap.SetSystemVariable(key, 0); IdleAction.Add(() => Acap.SetSystemVariable(key, value)); } + /// + /// 获取透明度 + /// + /// cad特性栏透明度值,范围0-100 + /// cad透明度值 + public Transparency CreateTransparency(int value) + { + return new Transparency(Convert.ToByte(Math.Floor((100 - value) * 2.55))); + } } -- Gitee From 9548038fd9110f38b014d1dd69c5f6bb2b591c58 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 7 Dec 2023 10:26:31 +0800 Subject: [PATCH 218/453] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=97=A0=E6=84=8F?= =?UTF-8?q?=E4=B9=89=E7=9A=84=E6=8A=9B=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/SelectionSetEx.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SelectionSetEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SelectionSetEx.cs index d247364..98a2fd8 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SelectionSetEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SelectionSetEx.cs @@ -79,9 +79,8 @@ public static IEnumerable GetEntities(this SelectionSet ss, bool openErased = false, bool openLockedLayer = false) where T : Entity { - //if (ss is null) - // throw new ArgumentNullException(nameof(ss)); - ArgumentNullEx.ThrowIfNull(ss); + if (ss is null) + return new List(); return ss.GetObjectIds() .Select(id => id.GetObject(openMode, openErased, openLockedLayer)) .OfType(); -- Gitee From 76e2651147c3df90153fa74212abf1b9eabab56b Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 7 Dec 2023 11:12:32 +0800 Subject: [PATCH 219/453] =?UTF-8?q?=E6=B7=B1=E5=BA=A6=E5=85=8B=E9=9A=86?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=B8=80=E7=A7=8D=E5=B8=B8=E8=A7=84=E5=9C=BA?= =?UTF-8?q?=E6=99=AF=E7=9A=84=E5=B8=B8=E7=94=A8=E9=87=8D=E8=BD=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/SymbolTableRecordEx.cs | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs index 7a665b8..f1a6f0c 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs @@ -46,6 +46,31 @@ public static void DeepCloneEx(this BlockTableRecord btr, ObjectIdCollection obj } } } + public static IdMapping DeepCloneEx(this BlockTableRecord btr, ObjectIdCollection objIds) + { + if (objIds is null || objIds.Count == 0) + throw new ArgumentNullException(nameof(objIds)); + + var db = objIds[0].Database; + IdMapping mapOut = new(); + using (btr.ForWrite()) + { + try + { + db.DeepCloneObjects(objIds, btr.ObjectId, mapOut, false); + + // 不在此提取,为了此函数被高频调用 + // 获取克隆键值对(旧块名,新块名) + // foreach (ObjectId item in blockIds) + // result.Add(mapping[item].Value); + } + catch + { + + } + } + return mapOut; + } #endregion -- Gitee From 62fea986a3faf251da449fd2f1951f7570149e11 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Fri, 8 Dec 2023 14:33:27 +0800 Subject: [PATCH 220/453] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=9E=AC=E6=80=81?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E7=B1=BB=E5=9E=8B=E4=B8=BAEntity=E4=B8=BADra?= =?UTF-8?q?wable?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/Jig/JigExTransient.cs | 56 ++++++++++--------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigExTransient.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigExTransient.cs index a657c97..680e5ff 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigExTransient.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigExTransient.cs @@ -1,4 +1,6 @@ -namespace IFoxCAD.Cad; +using Autodesk.AutoCAD.GraphicsInterface; + +namespace IFoxCAD.Cad; /// /// 瞬态容器 @@ -9,19 +11,23 @@ public class JigExTransient : IDisposable // 整数集,暂时不知道有什么意义 readonly IntegerCollection _integerCollection; // 维护集合 - readonly HashSet _entities; + readonly HashSet _drawableSet; readonly TransientManager _manager; #endregion #region 公开属性 /// + /// 图元集合 + /// + public Entity[] Entities => _drawableSet.OfType().ToArray(); + /// /// 对象集合 /// - public Entity[] Entities => _entities.ToArray(); + public Drawable[] Drawables => _drawableSet.ToArray(); /// /// 数量 /// - public int Count => _entities.Count; + public int Count => _drawableSet.Count; #endregion #region 构造函数 @@ -31,7 +37,7 @@ public class JigExTransient : IDisposable public JigExTransient() { _integerCollection = new(); - _entities = new(); + _drawableSet = new(); _manager=TransientManager.CurrentTransientManager; } #endregion @@ -40,11 +46,11 @@ public JigExTransient() /// /// 判断瞬态容器里是否含有对象 /// - /// 对象 + /// 对象 /// 含有返回true - public bool Contains(Entity ent) + public bool Contains(Drawable drawable) { - return _entities.Contains(ent); + return _drawableSet.Contains(drawable); } /// @@ -52,11 +58,11 @@ public bool Contains(Entity ent) /// /// 图元 /// 绘图模式 - public void Add(Entity ent, TransientDrawingMode tdm = TransientDrawingMode.Main) + public void Add(Drawable drawable, TransientDrawingMode tdm = TransientDrawingMode.Main) { - if (_entities.Add(ent)) + if (_drawableSet.Add(drawable)) { - _manager.AddTransient(ent, tdm, 128, _integerCollection); + _manager.AddTransient(drawable, tdm, 128, _integerCollection); } } @@ -64,13 +70,13 @@ public void Add(Entity ent, TransientDrawingMode tdm = TransientDrawingMode.Main /// /// 从瞬态容器中移除图元 /// - /// 已经加入瞬态容器的图元 - public void Remove(Entity ent) + /// 已经加入瞬态容器的图元 + public void Remove(Drawable drawable) { - if (!Contains(ent)) + if (!Contains(drawable)) return; - _manager.EraseTransient(ent, _integerCollection); - _entities.Remove(ent); + _manager.EraseTransient(drawable, _integerCollection); + _drawableSet.Remove(drawable); } /// @@ -78,23 +84,23 @@ public void Remove(Entity ent) /// public void Clear() { - foreach (var ent in _entities) + foreach (var drawable in _drawableSet) { - _manager.EraseTransient(ent, _integerCollection); + _manager.EraseTransient(drawable, _integerCollection); } - _entities.Clear(); + _drawableSet.Clear(); } /// /// 更新单个显示 /// - /// 已经加入瞬态容器的图元 - public void Update(Entity ent) + /// 已经加入瞬态容器的图元 + public void Update(Drawable drawable) { - if (!Contains(ent)) + if (!Contains(drawable)) return; - _manager.UpdateTransient(ent, _integerCollection); + _manager.UpdateTransient(drawable, _integerCollection); } /// @@ -102,8 +108,8 @@ public void Update(Entity ent) /// public void UpdateAll() { - foreach (var ent in _entities) - Update(ent); + foreach (var drawable in _drawableSet) + Update(drawable); } #endregion -- Gitee From dac3cbd2c94a5376de81891251a0fa45ee1fd30a Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Mon, 11 Dec 2023 10:48:08 +0800 Subject: [PATCH 221/453] =?UTF-8?q?=E7=A6=81=E6=AD=A2=E6=9B=B4=E6=94=B9str?= =?UTF-8?q?uct=E5=AD=97=E6=AE=B5=EF=BC=8C=E9=81=BF=E5=85=8Dhashcode?= =?UTF-8?q?=E5=86=B2=E7=AA=81=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Basal/IFox.Basal.Shared/WindowsAPI/WindowsAPI.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Basal/IFox.Basal.Shared/WindowsAPI/WindowsAPI.cs b/src/Basal/IFox.Basal.Shared/WindowsAPI/WindowsAPI.cs index 489f588..ff6afc1 100644 --- a/src/Basal/IFox.Basal.Shared/WindowsAPI/WindowsAPI.cs +++ b/src/Basal/IFox.Basal.Shared/WindowsAPI/WindowsAPI.cs @@ -597,9 +597,9 @@ public struct Point3D : IEquatable private string DebuggerDisplay => $"(X:{X},Y:{Y},Z:{Z})"; /* 由于此类是用来优化,从而实现字段修改,因此直接暴露字段减少栈帧 */ - public double X; - public double Y; - public double Z; + public readonly double X; + public readonly double Y; + public readonly double Z; public Point3D(double x, double y, double z) { -- Gitee From 39feecab4b9485e8a92a9c7e9adc5f7405e2a3f0 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Mon, 11 Dec 2023 16:07:21 +0800 Subject: [PATCH 222/453] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=97=A0=E7=94=A8?= =?UTF-8?q?=E7=9A=84flags=E6=A0=87=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Basal/IFox.Basal.Shared/General/Timer.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Basal/IFox.Basal.Shared/General/Timer.cs b/src/Basal/IFox.Basal.Shared/General/Timer.cs index d489cb5..b92cfe8 100644 --- a/src/Basal/IFox.Basal.Shared/General/Timer.cs +++ b/src/Basal/IFox.Basal.Shared/General/Timer.cs @@ -20,7 +20,6 @@ public class Timer /// /// 时间单位枚举 /// - [Flags] public enum TimeEnum { /// -- Gitee From bd890df0a64fee79f1f670ac9dcc2bdb35119896 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Mon, 11 Dec 2023 16:07:32 +0800 Subject: [PATCH 223/453] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=97=A0=E7=94=A8?= =?UTF-8?q?=E7=9A=84toCharArray=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/SingleKeyWordHook.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SingleKeyWordHook.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SingleKeyWordHook.cs index 91b659c..6127b08 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SingleKeyWordHook.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SingleKeyWordHook.cs @@ -66,7 +66,7 @@ public void AddKeys(KeywordCollection keywordCollection) { if (item.LocalName.Length == 1) { - Keys k = (Keys)item.LocalName.ToCharArray()[0]; + Keys k = (Keys)item.LocalName[0]; _keyWords.Add(k); } } -- Gitee From 6ef5013901eb13cbda09e87ee1531b571fdc1d19 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Fri, 15 Dec 2023 15:31:51 +0800 Subject: [PATCH 224/453] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E6=89=A9=E5=B1=95=E6=95=B0=E6=8D=AE=E9=87=8D=E5=A4=8D=E6=97=A0?= =?UTF-8?q?=E7=94=A8=E5=BE=AA=E7=8E=AF=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../IFox.CAD.Shared/ExtensionMethod/DBObjectEx.cs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBObjectEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBObjectEx.cs index e684db9..f152281 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBObjectEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBObjectEx.cs @@ -77,14 +77,10 @@ public static void RemoveXData(this DBObject obj, string appName) { if (obj.XData == null) return; - foreach (var data in obj.XData) - { - // 直接赋值进去等于清空名称 - using var rb = new ResultBuffer(); - rb.Add(new((int)DxfCode.ExtendedDataRegAppName, appName)); - using (obj.ForWrite()) - obj.XData = rb; - } + + // 直接赋值进去等于清空名称 + using (obj.ForWrite()) + obj.XData = new XDataList() { { 1001, appName } }; } /// /// 克隆对象 -- Gitee From e03955a678f01cfda7ae2204f90562a77a475cfb Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sun, 17 Dec 2023 15:17:59 +0800 Subject: [PATCH 225/453] =?UTF-8?q?Point3d=20xyz=E5=AD=97=E6=AE=B5?= =?UTF-8?q?=E5=88=A0=E9=99=A4readonly=EF=BC=8C=E8=99=BD=E7=84=B6=E6=AD=A4?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=B9=B6=E4=B8=8D=E5=90=88=E7=90=86=EF=BC=8C?= =?UTF-8?q?=E8=BF=9D=E8=83=8C=E4=BA=86hashcode=E5=8E=9F=E5=88=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Basal/IFox.Basal.Shared/WindowsAPI/WindowsAPI.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Basal/IFox.Basal.Shared/WindowsAPI/WindowsAPI.cs b/src/Basal/IFox.Basal.Shared/WindowsAPI/WindowsAPI.cs index ff6afc1..489f588 100644 --- a/src/Basal/IFox.Basal.Shared/WindowsAPI/WindowsAPI.cs +++ b/src/Basal/IFox.Basal.Shared/WindowsAPI/WindowsAPI.cs @@ -597,9 +597,9 @@ public struct Point3D : IEquatable private string DebuggerDisplay => $"(X:{X},Y:{Y},Z:{Z})"; /* 由于此类是用来优化,从而实现字段修改,因此直接暴露字段减少栈帧 */ - public readonly double X; - public readonly double Y; - public readonly double Z; + public double X; + public double Y; + public double Z; public Point3D(double x, double y, double z) { -- Gitee From 8c949371640144e7b74016f64dba24e2a1b12cb8 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sun, 17 Dec 2023 15:18:34 +0800 Subject: [PATCH 226/453] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=9E=AC=E6=80=81?= =?UTF-8?q?=E6=97=A0=E7=94=A8=E5=BC=95=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigExTransient.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigExTransient.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigExTransient.cs index 680e5ff..868e86f 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigExTransient.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigExTransient.cs @@ -1,6 +1,4 @@ -using Autodesk.AutoCAD.GraphicsInterface; - -namespace IFoxCAD.Cad; +namespace IFoxCAD.Cad; /// /// 瞬态容器 -- Gitee From 2914ca71352d635f1b9caa315171639414b5e11c Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sun, 17 Dec 2023 15:18:57 +0800 Subject: [PATCH 227/453] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=A3=80=E6=9F=A5?= =?UTF-8?q?=E9=87=8D=E5=A4=8D=E5=91=BD=E4=BB=A4=E7=BC=BA=E5=B0=91=E5=BC=95?= =?UTF-8?q?=E7=94=A8=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/CheckFactory.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/CheckFactory.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/CheckFactory.cs index 685bfc2..2aea546 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/CheckFactory.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/CheckFactory.cs @@ -39,7 +39,7 @@ public static void CheckDuplicateCommand(Assembly? assembly = null) .Select(o => o.Key + "命令重复,在类" + string.Join("和", o.Value) + "中"); string str = string.Join(Environment.NewLine, strings); if (!string.IsNullOrEmpty(str)) - MessageBox.Show(str, @"错误:重复命令!"); + System.Windows.Forms. MessageBox.Show(str, @"错误:重复命令!"); } } #endif \ No newline at end of file -- Gitee From c782e587f67d121b7907ba62b57c269cba4968c0 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sun, 17 Dec 2023 15:19:19 +0800 Subject: [PATCH 228/453] =?UTF-8?q?IFoxUtils=E9=99=90=E5=AE=9A=E4=B8=BA?= =?UTF-8?q?=E4=BB=85acad=E5=8F=AF=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/Runtime/IFoxUtils.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/CAD/IFox.CAD.Shared/Runtime/IFoxUtils.cs b/src/CAD/IFox.CAD.Shared/Runtime/IFoxUtils.cs index 20f95f7..792f1b3 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/IFoxUtils.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/IFoxUtils.cs @@ -1,5 +1,6 @@ namespace IFoxCAD.Cad; +#if acad public sealed class IFoxUtils { /// @@ -85,3 +86,4 @@ public Transparency CreateTransparency(int value) return new Transparency(Convert.ToByte(Math.Floor((100 - value) * 2.55))); } } +#endif \ No newline at end of file -- Gitee From 9a048656b411f4e8eb21c8cd1ee7ed50e5afaaa9 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Mon, 18 Dec 2023 15:26:56 +0800 Subject: [PATCH 229/453] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=B5=A9=E8=BE=B0?= =?UTF-8?q?=E7=9A=84nuget=E5=8C=85=EF=BC=8C=E5=A2=9E=E5=8A=A0=E4=B8=AD?= =?UTF-8?q?=E6=9C=9B=E7=9A=84=E6=B5=8B=E8=AF=95=E9=A1=B9=E7=9B=AE=EF=BC=8C?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=B8=80=E4=BA=9B=E4=B8=AD=E6=9C=9B=E7=9A=84?= =?UTF-8?q?=E8=8E=AB=E5=90=8D=E5=85=B6=E5=A6=99=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IFoxCAD.sln | 7 ++++ src/CAD/IFox.CAD.GCAD/IFox.CAD.GCAD.csproj | 2 +- src/CAD/IFox.CAD.ZCAD/IFox.CAD.ZCAD.csproj | 2 +- tests/TestShared/TestEnv.cs | 6 +-- tests/TestShared/TestLisp.cs | 3 +- tests/TestShared/TestPoint.cs | 6 ++- tests/TestZcad2024/GlobalUsings.cs | 47 ++++++++++++++++++++++ tests/TestZcad2024/TestZcad2024.csproj | 29 +++++++++++++ 8 files changed, 94 insertions(+), 8 deletions(-) create mode 100644 tests/TestZcad2024/GlobalUsings.cs create mode 100644 tests/TestZcad2024/TestZcad2024.csproj diff --git a/IFoxCAD.sln b/IFoxCAD.sln index e8a3d2c..3480358 100644 --- a/IFoxCAD.sln +++ b/IFoxCAD.sln @@ -62,6 +62,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Docs", "Docs", "{DA8EA8E7-A EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestGcad2024", "tests\TestGcad2024\TestGcad2024.csproj", "{FEC39964-9ECB-4567-8F68-94F80A39FA02}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestZcad2024", "tests\TestZcad2024\TestZcad2024.csproj", "{890D0AA3-1621-47F2-9E47-75D16A51D36E}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -108,6 +110,10 @@ Global {FEC39964-9ECB-4567-8F68-94F80A39FA02}.Debug|Any CPU.Build.0 = Debug|Any CPU {FEC39964-9ECB-4567-8F68-94F80A39FA02}.Release|Any CPU.ActiveCfg = Release|Any CPU {FEC39964-9ECB-4567-8F68-94F80A39FA02}.Release|Any CPU.Build.0 = Release|Any CPU + {890D0AA3-1621-47F2-9E47-75D16A51D36E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {890D0AA3-1621-47F2-9E47-75D16A51D36E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {890D0AA3-1621-47F2-9E47-75D16A51D36E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {890D0AA3-1621-47F2-9E47-75D16A51D36E}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -126,6 +132,7 @@ Global {3D7D095D-EF0A-40B3-9776-5F08C61FD614} = {B2AB7DC7-DBF4-4197-808B-0D2A6613AF5E} {6ED0A677-6621-4493-AF58-71C2BF31DFCE} = {1EE1F817-39D3-43E5-B087-E7AD4D0BEC93} {FEC39964-9ECB-4567-8F68-94F80A39FA02} = {C0BEFC15-6DF7-4636-BC76-4A0B88231470} + {890D0AA3-1621-47F2-9E47-75D16A51D36E} = {C0BEFC15-6DF7-4636-BC76-4A0B88231470} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {31D6C754-CF6B-4AB0-9861-6923DD312350} diff --git a/src/CAD/IFox.CAD.GCAD/IFox.CAD.GCAD.csproj b/src/CAD/IFox.CAD.GCAD/IFox.CAD.GCAD.csproj index fa04e0b..b73c017 100644 --- a/src/CAD/IFox.CAD.GCAD/IFox.CAD.GCAD.csproj +++ b/src/CAD/IFox.CAD.GCAD/IFox.CAD.GCAD.csproj @@ -23,7 +23,7 @@ - + runtime diff --git a/src/CAD/IFox.CAD.ZCAD/IFox.CAD.ZCAD.csproj b/src/CAD/IFox.CAD.ZCAD/IFox.CAD.ZCAD.csproj index b4a31e6..926c3fb 100644 --- a/src/CAD/IFox.CAD.ZCAD/IFox.CAD.ZCAD.csproj +++ b/src/CAD/IFox.CAD.ZCAD/IFox.CAD.ZCAD.csproj @@ -16,7 +16,7 @@ $(Configuration);zcad - + runtime diff --git a/tests/TestShared/TestEnv.cs b/tests/TestShared/TestEnv.cs index 88eb912..1b2d8c5 100644 --- a/tests/TestShared/TestEnv.cs +++ b/tests/TestShared/TestEnv.cs @@ -57,7 +57,7 @@ public void Test_Osmode1() var dim = Env.OSMode; Env.Editor.WriteMessage(dim.ToString()); } - +#if !zcad [CommandMethod(nameof(Test_Cadver))] public void Test_Cadver() { @@ -67,7 +67,7 @@ public void Test_Cadver() 1.Print(); "1".Print(); } - +#endif [CommandMethod(nameof(Test_GetVar))] public void Test_GetVar() { @@ -89,7 +89,7 @@ public void Test_GetVar() //} -#if !NET40 +#if !zcad // 通过此功能获取全部变量,尚不清楚此处如何设置,没有通过测试 [CommandMethod(nameof(Test_GetvarAll))] public static void Test_GetvarAll() diff --git a/tests/TestShared/TestLisp.cs b/tests/TestShared/TestLisp.cs index d7740e4..4bd7b19 100644 --- a/tests/TestShared/TestLisp.cs +++ b/tests/TestShared/TestLisp.cs @@ -46,6 +46,7 @@ public static object LispTest_RunLisp(ResultBuffer rb) [CommandMethod("CmdTest_RunLisp17", CommandFlags.Interruptible)] // 命令不会被记录在命令历史记录 [CommandMethod("CmdTest_RunLisp18", CommandFlags.NoHistory)] +#if (!zcad) // 命令不会被 UNDO取消 [CommandMethod("CmdTest_RunLisp19", CommandFlags.NoUndoMarker)] // 不能在参照块中使用命令 @@ -61,7 +62,7 @@ public static object LispTest_RunLisp(ResultBuffer rb) [CommandMethod("CmdTest_RunLisp23", CommandFlags.NoInferConstraint)] // 命令允许在选择图元时临时显示动态尺寸 [CommandMethod("CmdTest_RunLisp24", CommandFlags.TempShowDynDimension)] - +#endif public static void CmdTest_RunLisp() { // 测试方法1: (command "CmdTest_RunLisp1") diff --git a/tests/TestShared/TestPoint.cs b/tests/TestShared/TestPoint.cs index d6b5f57..f6da535 100644 --- a/tests/TestShared/TestPoint.cs +++ b/tests/TestShared/TestPoint.cs @@ -25,13 +25,15 @@ public void Test_Endtoend() new(1, 1), new(1, 0) }; - foreach (var pt in pts) + + + foreach (Point2d pt in pts) { Env.Printl($"X={pt.X},Y={pt.Y}"); } pts.End2End(); Env.Printl("-------"); - foreach (var pt in pts) + foreach (Point2d pt in pts) { Env.Printl($"X={pt.X},Y={pt.Y}"); } diff --git a/tests/TestZcad2024/GlobalUsings.cs b/tests/TestZcad2024/GlobalUsings.cs new file mode 100644 index 0000000..543b726 --- /dev/null +++ b/tests/TestZcad2024/GlobalUsings.cs @@ -0,0 +1,47 @@ +/// 系统引用 +global using System; +global using System.Collections; +global using System.Collections.Generic; +global using System.IO; +global using System.Linq; +global using System.Text; +global using System.Reflection; +global using System.Text.RegularExpressions; +global using Microsoft.Win32; +global using System.ComponentModel; +global using System.Runtime.InteropServices; +global using System.Collections.Specialized; + +global using Exception = System.Exception; + +global using Registry = Microsoft.Win32.Registry; +global using RegistryKey = Microsoft.Win32.RegistryKey; + +// cad 引用 +global using ZwSoft.ZwCAD.ApplicationServices; +global using ZwSoft.ZwCAD.EditorInput; +global using ZwSoft.ZwCAD.Colors; +global using ZwSoft.ZwCAD.DatabaseServices; +global using ZwSoft.ZwCAD.Geometry; +global using ZwSoft.ZwCAD.Runtime; +global using Acap = ZwSoft.ZwCAD.ApplicationServices.Application; +global using Acaop = ZwSoft.ZwCAD.ApplicationServices.Application; +global using AcException = ZwSoft.ZwCAD.Runtime.Exception; +global using ZwSoft.ZwCAD.DatabaseServices.Filters; +global using Acgi = ZwSoft.ZwCAD.GraphicsInterface; +// jig命名空间会引起Viewport/Polyline等等重义,最好逐个引入 using ZwSoft.ZwCAD.GraphicsInterface +global using ZwSoft.ZwCAD.GraphicsInterface; +global using WorldDraw = ZwSoft.ZwCAD.GraphicsInterface.WorldDraw; +global using Manager = ZwSoft.ZwCAD.GraphicsSystem.Manager; +global using Group = ZwSoft.ZwCAD.DatabaseServices.Group; +global using Viewport = ZwSoft.ZwCAD.DatabaseServices.Viewport; +global using Polyline = ZwSoft.ZwCAD.DatabaseServices.Polyline; +global using Cad_DwgFiler = ZwSoft.ZwCAD.DatabaseServices.DwgFiler; +global using Cad_DxfFiler = ZwSoft.ZwCAD.DatabaseServices.DxfFiler; +global using Cad_ErrorStatus = ZwSoft.ZwCAD.Runtime.ErrorStatus; + + +/// ifoxcad +global using IFoxCAD.Cad; +global using IFoxCAD.Basal; + diff --git a/tests/TestZcad2024/TestZcad2024.csproj b/tests/TestZcad2024/TestZcad2024.csproj new file mode 100644 index 0000000..2dd8650 --- /dev/null +++ b/tests/TestZcad2024/TestZcad2024.csproj @@ -0,0 +1,29 @@ + + + preview + enable + + NET48 + true + true + x64 + True + + + + $(Configuration);zcad + + + + + + + + + + + + + + + -- Gitee From c6de58f77f48b4ee415b8f8dbec8761f66fa6871 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Mon, 18 Dec 2023 17:27:51 +0800 Subject: [PATCH 230/453] =?UTF-8?q?=E5=BF=98=E8=AE=B0using=20jig=E6=97=B6?= =?UTF-8?q?=EF=BC=8Cgc=E8=A7=A6=E5=8F=91=E6=9E=90=E6=9E=84=E5=87=BD?= =?UTF-8?q?=E6=95=B0=EF=BC=8C=E6=AD=A4=E6=97=B6=E5=AF=B9=E8=B1=A1=E5=86=85?= =?UTF-8?q?=E7=9A=84queue=E5=B7=B2=E7=BB=8F=E5=85=88=E8=A2=ABgc=E9=87=8A?= =?UTF-8?q?=E6=94=BE=EF=BC=8C=E4=BC=9A=E8=AE=BF=E9=97=AE=E5=88=B0=E4=B8=8D?= =?UTF-8?q?=E5=AD=98=E5=9C=A8=E7=9A=84=E5=86=85=E5=AD=98=EF=BC=8C=E6=89=80?= =?UTF-8?q?=E4=BB=A5=E5=8F=AA=E6=9C=89=E5=9C=A8=E6=98=BE=E7=A4=BAdispose?= =?UTF-8?q?=E7=9A=84=E6=97=B6=E5=80=99=E6=89=8D=E9=94=80=E6=AF=81queue?= =?UTF-8?q?=E9=87=8C=E7=9A=84=E5=9B=BE=E5=85=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../IFox.CAD.Shared/ExtensionMethod/Jig/JigEx.cs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigEx.cs index 99fc5f2..3b157d2 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigEx.cs @@ -372,12 +372,14 @@ protected virtual void Dispose(bool disposing) // 不重复释放,并设置已经释放 if (IsDisposed) return; IsDisposed = true; - - // 最后一次的图元如果没有加入数据库,就在此销毁,所以JigEx调用的时候加using - _drawEntitys?.ForEach(ent => { - if (ent.Database == null && !ent.IsDisposed) - ent.Dispose(); - }); + if(disposing) + { + // 最后一次的图元如果没有加入数据库,就在此销毁,所以JigEx调用的时候加using + _drawEntitys?.ForEach(ent => { + if (ent.Database == null && !ent.IsDisposed) + ent.Dispose(); + }); + } _drawEntitys?.Clear(); } #endregion -- Gitee From e31770fa03c3428ca20c38e28886e5462f18f79f Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Tue, 19 Dec 2023 14:53:21 +0800 Subject: [PATCH 231/453] =?UTF-8?q?idle=E9=87=8C=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=AF=B9Position=E7=9A=84=E5=A4=84=E7=90=86=EF=BC=8C=E7=94=A8?= =?UTF-8?q?=E4=BA=8E=E5=8F=8A=E6=97=B6=E6=9B=B4=E6=96=B0=E6=98=BE=E7=A4=BA?= =?UTF-8?q?=E6=95=88=E6=9E=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/IdleAction.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/IdleAction.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/IdleAction.cs index 0d1c78e..cc51ccc 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/IdleAction.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/IdleAction.cs @@ -55,5 +55,6 @@ private static void Acap_Idle(object sender, EventArgs e) { _actions.RemoveAt(0); } + System.Windows.Forms.Cursor.Position = System.Windows.Forms.Cursor.Position; } } -- Gitee From 76b43947133ff209c444c418027965766d91771a Mon Sep 17 00:00:00 2001 From: vicwjb Date: Tue, 19 Dec 2023 15:36:34 +0800 Subject: [PATCH 232/453] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=9D=97=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E4=BB=A3=E7=A0=81=EF=BC=8C=E5=8F=91=E5=B8=830.7.2?= =?UTF-8?q?=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Basal/Directory.Build.props | 4 +- src/CAD/Directory.Build.props | 4 +- tests/TestShared/TestBlock.cs | 210 +++++++++++++++++++++++++++----- 3 files changed, 185 insertions(+), 33 deletions(-) diff --git a/src/Basal/Directory.Build.props b/src/Basal/Directory.Build.props index 29ab28e..ae9fb12 100644 --- a/src/Basal/Directory.Build.props +++ b/src/Basal/Directory.Build.props @@ -1,8 +1,8 @@  - 0.7.1 - 发布0.7.1 + 0.7.2 + 发布0.7.2 diff --git a/src/CAD/Directory.Build.props b/src/CAD/Directory.Build.props index 8bbe5a4..aff56da 100644 --- a/src/CAD/Directory.Build.props +++ b/src/CAD/Directory.Build.props @@ -1,8 +1,8 @@  - 0.7.1 - 发布0.7.1 + 0.7.2 + 发布0.7.2 diff --git a/tests/TestShared/TestBlock.cs b/tests/TestShared/TestBlock.cs index 7995ee0..0127329 100644 --- a/tests/TestShared/TestBlock.cs +++ b/tests/TestShared/TestBlock.cs @@ -1,6 +1,4 @@ -using IFoxCAD.Cad; -using System.Data.Common; - + namespace Test; public class TestBlock @@ -37,7 +35,7 @@ public void Test_GetBoundingBoxEx() { var box = item?.GetBoundingBoxEx(); Env.Print("min:" + box?.BottomLeft + ";max" + box?.TopRight); - if (box != null) + if (box != null) tr.CurrentSpace.AddEntity(new Line(box.Value.BottomLeft, box.Value.TopRight)); } } @@ -49,7 +47,8 @@ public void Test_BlockDef() using DBTrans tr = new(); // var line = new Line(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); tr.BlockTable.Add("test", - btr => { + btr => + { btr.Origin = new Point3d(0, 0, 0); }, () => // 图元 @@ -64,10 +63,12 @@ public void Test_BlockDef() // ObjectId objectId = tr.BlockTable.Add("a");// 新建块 // objectId.GetObject().AddEntity();// 测试添加空实体 tr.BlockTable.Add("test1", - btr => { + btr => + { btr.Origin = new Point3d(0, 0, 0); }, - () => { + () => + { var line = new Line(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); var acText = DBTextEx.CreateDBText(Point3d.Origin, "123", 2.5); return new List { line, acText }; @@ -81,7 +82,8 @@ public void Test_BlockDefbehind() using DBTrans tr = new(@"C:\Users\vic\Desktop\test.dwg"); // var line = new Line(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); tr.BlockTable.Add("test", - btr => { + btr => + { btr.Origin = new Point3d(0, 0, 0); }, () => // 图元 @@ -98,13 +100,15 @@ public void Test_BlockDefbehind() // ObjectId objectId = tr.BlockTable.Add("a");// 新建块 // objectId.GetObject().AddEntity();// 测试添加空实体 tr.BlockTable.Add("test1", - btr => { + btr => + { btr.Origin = new Point3d(0, 0, 0); }, - () => { + () => + { var line = new Line(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); var acText = DBTextEx.CreateDBText(Point3d.Origin, "12345", 2.5); - + return new List { line, acText }; }); tr.Database.SaveDwgFile(); @@ -129,7 +133,8 @@ public void Test_BlockDefChange() // }); - tr.BlockTable.Change("test", btr => { + tr.BlockTable.Change("test", btr => + { foreach (var id in btr) { var ent = tr.GetObject(id); @@ -193,7 +198,7 @@ public void Test_InsertBlockDef() { "tagTest4", "" } }; tr.CurrentSpace.InsertBlock(new Point3d(10, 10, 0), "test2", atts: def2); - tr.CurrentSpace.InsertBlock(new Point3d(20,20,0),"test2"); + tr.CurrentSpace.InsertBlock(new Point3d(20, 20, 0), "test2"); tr.CurrentSpace.InsertBlock(new Point3d(-10, 0, 0), "test44"); } @@ -204,14 +209,16 @@ public void Test_InsertBlockWithDoubleDatabase() using var trans = new DBTrans(); tr.BlockTable.Add("test456", - btr => { + btr => + { btr.Origin = new(0, 0, 0); }, - () => { + () => + { var line = new Line(new(0, 0, 0), new(1, 1, 0)); var actext = DBTextEx.CreateDBText(Point3d.Origin, "123", 2.5, database: tr.Database); - return new List { line,actext }; + return new List { line, actext }; }); tr.CurrentSpace.InsertBlock(Point3d.Origin, "test456"); @@ -260,7 +267,8 @@ public void Test_BlockFile() public void Test_ClipBlock() { using DBTrans tr = new(); - tr.BlockTable.Add("test1", btr => { + tr.BlockTable.Add("test1", btr => + { btr.Origin = new Point3d(0, 0, 0); btr.AddEntity(new Line(new Point3d(0, 0, 0), new Point3d(10, 10, 0)), new Line(new Point3d(10, 10, 0), new Point3d(10, 0, 0))); @@ -276,6 +284,22 @@ public void Test_ClipBlock() brf2?.ClipBlockRef(new Point3d(13, 13, 0), new Point3d(17, 17, 0)); } + + [CommandMethod(nameof(Test_ClipBlock1))] + public void Test_ClipBlock1() + { + using DBTrans tr = new(); + var ent = Env.Editor.GetEntity("pick block"); + if (ent.Status != PromptStatus.OK) return; + + var brf1 = tr.GetObject(ent.ObjectId)!; + var pts = new List { new Point3d(3, 3, 0), new Point3d(7, 3, 0), new Point3d(7, 7, 0), new Point3d(3, 7, 0) }; + brf1.ClipBlockRef(pts); + + } + + + // 给用户的测试程序,不知道对错 [CommandMethod(nameof(Test_Block_ej))] public void Test_Block_ej() @@ -300,7 +324,8 @@ public void Test_Block_ej() var blockdef = tr.BlockTable.GetBlockFrom(fullFileName, false); tr.Database.Clayer = tr.LayerTable["0"];// 当前图层切换为0图层 - tr.LayerTable.Change(tr.Database.Clayer, ltr => { + tr.LayerTable.Change(tr.Database.Clayer, ltr => + { ltr.Color = Color.FromColorIndex(ColorMethod.ByAci, 2); // ColorMethod.ByAci可以让我们使用AutoCAD ACI颜色索引……这里为2(表示黄色) }); @@ -325,7 +350,8 @@ public void Test_Block_ej() var btr = tr2.BlockTable[brf2.Name]; - tr2.BlockTable.Change(btr, ltr => { + tr2.BlockTable.Change(btr, ltr => + { foreach (ObjectId oid in ltr) { var ent = tr2.GetObject(oid); @@ -335,12 +361,12 @@ public void Test_Block_ej() switch (mText.Text) { case "$$A": - mText.Contents = "hahaha"; - break; + mText.Contents = "hahaha"; + break; case "$$B": - break; + break; default: - break; + break; } } else if (ent is DBText dBText) @@ -354,11 +380,11 @@ public void Test_Block_ej() switch (dimension.DimensionText) { case "$$pipeLen": - dimension.DimensionText = "350"; - dimension.RecomputeDimensionBlock(true); - break; + dimension.DimensionText = "350"; + dimension.RecomputeDimensionBlock(true); + break; default: - break; + break; } } } @@ -556,18 +582,144 @@ public void Test_Back() } using DBTrans tr = new(dwg); - tr.ModelSpace.GetEntities().ForEach(ent => { + tr.ModelSpace.GetEntities().ForEach(ent => + { ent.ForWrite(e => e.ColorIndex = 3); }); tr.Database.SaveAs(dwg, DwgVersion.Current); - tr.ModelSpace.GetEntities().ForEach(ent => { + tr.ModelSpace.GetEntities().ForEach(ent => + { ent.ForWrite(e => e.ColorIndex = 4); }); tr.Database.SaveAs(dwg, DwgVersion.Current); } + + [CommandMethod(nameof(Test_ExplodeBlock))] + public void Test_ExplodeBlock() + { + var r1 = Env.Editor.GetEntity("pick block"); + if (r1.Status != PromptStatus.OK) + return; + using var tr = new DBTrans(); + if (tr.GetObject(r1.ObjectId, OpenMode.ForWrite) is not BlockReference brf) + return; + var dboc = new DBObjectCollection(); + // brf.Explode(dboc); + brf.ExplodeToOwnerSpace(); + // foreach (Entity item in dboc) + // { + // tr.CurrentSpace.AddEntity(item); + // } + using (brf.ForWrite()) + { + brf.Erase(); + } + } } + + +public static class Blocks +{ + + [CommandMethod("TestExplodeToOwnerSpace3")] + public static void TestExplodeToOwnerSpace3_Method() + { + Editor ed = Application.DocumentManager.MdiActiveDocument.Editor; + try + { + PromptEntityOptions prEntOpt = new PromptEntityOptions("\nSelect an INSERT:"); + prEntOpt.SetRejectMessage("\nIt is not an INSERT!"); + prEntOpt.AddAllowedClass(typeof(BlockReference), true); + PromptEntityResult selRes = ed.GetEntity(prEntOpt); + if (selRes.Status == PromptStatus.OK) + { + ObjectIdCollection ids = ExplodeToOwnerSpace3(selRes.ObjectId); + ed.WriteMessage("{0} entities were added into database.", ids.Count); + } + else + { + ed.WriteMessage("\nEntity Selection failed!"); + } + } + catch (System.Exception ex) + { + ed.WriteMessage(ex.Message); + } + } + + public static void ExplodeToOwnerSpace2(ObjectId id, bool erase = true) + { + ExplodeToOwnerSpace3(id, erase); + } + + public static void ExplodeToOwnerSpace2(this BlockReference br) + { + ExplodeToOwnerSpace3(br); + } + + public static ObjectIdCollection ExplodeToOwnerSpace3(ObjectId id, bool erase = true) + { + ObjectIdCollection ids; + + using (Transaction tr = id.Database.TransactionManager.StartTransaction()) + { + BlockReference br = (BlockReference)tr.GetObject(id, OpenMode.ForRead); + ids = br.ExplodeToOwnerSpace3(); + + if (erase) + { + br.UpgradeOpen(); + br.Erase(); + } + + tr.Commit(); + } + + return ids; + } + + private static ObjectIdCollection idsAdded; + public static ObjectIdCollection ExplodeToOwnerSpace3(this BlockReference br) + { + idsAdded = new ObjectIdCollection(); + + Transaction tr = br.Database.TransactionManager.TopTransaction; + BlockTableRecord spaceBtr = (BlockTableRecord)tr.GetObject(br.BlockId, OpenMode.ForWrite); + LoopThroughInsertAndAddEntity2n3(br.BlockTransform, br, spaceBtr); + + return idsAdded; + } + // 不能用于非等比 + public static void LoopThroughInsertAndAddEntity2n3(Matrix3d mat, BlockReference br, BlockTableRecord space) + { + Transaction tr = space.Database.TransactionManager.TopTransaction; + BlockTableRecord btr = tr.GetObject(br.BlockTableRecord, OpenMode.ForRead) as BlockTableRecord; + + foreach (ObjectId id in btr) + { + DBObject obj = tr.GetObject(id, OpenMode.ForRead); + Entity ent = obj.Clone() as Entity; + if (ent is BlockReference) + { + BlockReference br1 = (BlockReference)ent; + LoopThroughInsertAndAddEntity2n3(br1.BlockTransform.PreMultiplyBy(mat), br1, space); + } + else + { + ent.TransformBy(mat); + space.AppendEntity(ent); + tr.AddNewlyCreatedDBObject(ent, true); + + idsAdded.Add(ent.ObjectId); + } + } + } + +} + + public class BlockImportClass { [CommandMethod(nameof(Test_Cbll))] -- Gitee From ffeef0084beaaa46e299b94e69b031df78fcc510 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 21 Dec 2023 01:05:15 +0800 Subject: [PATCH 233/453] =?UTF-8?q?=E6=9C=BA=E6=98=93=E9=87=8D=E5=90=8D?= =?UTF-8?q?=E7=9A=84=E7=B1=BB=E5=9E=8B=E4=B8=94=E5=B9=BF=E6=B3=9B=E6=97=B6?= =?UTF-8?q?=E9=87=87=E7=94=A8=E5=86=85=E9=83=A8using=20=E5=A3=B0=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Basal/IFox.Basal.Shared/WindowsAPI/MouseHook.cs | 2 ++ src/CAD/IFox.CAD.Shared/Copyclip/TagClipboardInfo.cs | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Basal/IFox.Basal.Shared/WindowsAPI/MouseHook.cs b/src/Basal/IFox.Basal.Shared/WindowsAPI/MouseHook.cs index 89f96fa..8be0253 100644 --- a/src/Basal/IFox.Basal.Shared/WindowsAPI/MouseHook.cs +++ b/src/Basal/IFox.Basal.Shared/WindowsAPI/MouseHook.cs @@ -1,5 +1,7 @@ using System.Drawing; using System.Windows.Forms; +using MouseEventArgs = System.Windows.Forms.MouseEventArgs; +using MouseEventHandler = System.Windows.Forms.MouseEventHandler; namespace IFoxCAD.Basal; diff --git a/src/CAD/IFox.CAD.Shared/Copyclip/TagClipboardInfo.cs b/src/CAD/IFox.CAD.Shared/Copyclip/TagClipboardInfo.cs index 024bb36..acadd08 100644 --- a/src/CAD/IFox.CAD.Shared/Copyclip/TagClipboardInfo.cs +++ b/src/CAD/IFox.CAD.Shared/Copyclip/TagClipboardInfo.cs @@ -353,7 +353,7 @@ public static bool GetClipboard(string clipKey, out T? tag) var clipTypeData = GetClipboardData(clipKeyFormat); // 剪贴板的数据拷贝进去结构体中,会依照数据长度进行拷贝 - locked = WindowsAPI.GlobalLockTask(clipTypeData, ptr => { + locked =IFoxCAD.Basal.WindowsAPI.GlobalLockTask(clipTypeData, ptr => { // 非托管内存块->托管对象 result = (T)Marshal.PtrToStructure(ptr, typeof(T)); }); -- Gitee From 0805b78e36659b555d20aa39abca0b3d53ccfbb0 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Fri, 22 Dec 2023 18:15:44 +0800 Subject: [PATCH 234/453] =?UTF-8?q?=E5=8C=85=E5=9B=B4=E7=9B=92=E8=BD=AC?= =?UTF-8?q?=E5=A4=9A=E6=AE=B5=E7=BA=BF=E9=BB=98=E8=AE=A4=E6=94=B9=E4=B8=BA?= =?UTF-8?q?=E9=97=AD=E5=90=88=E7=9F=A9=E5=BD=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/Entity/PolylineEx.cs | 35 +++++++++---------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/PolylineEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/PolylineEx.cs index 7a48715..9daffa6 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/PolylineEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/PolylineEx.cs @@ -9,6 +9,7 @@ namespace IFoxCAD.Cad; public static class PolylineEx { #region 获取多段线端点 + /// /// 获取二维多段线的端点坐标 /// @@ -24,7 +25,6 @@ public static IEnumerable GetPoints(this Polyline2d pl2d) yield return vertex.Position; } } - } /// @@ -39,7 +39,7 @@ public static IEnumerable GetPoints(this Polyline3d pl3d) { if (tr.GetObject(id) is PolylineVertex3d vertex) yield return vertex.Position; - } + } } /// @@ -51,13 +51,15 @@ public static List GetPoints(this Polyline pl) { return Enumerable - .Range(0, pl.NumberOfVertices) - .Select(pl.GetPoint3dAt) - .ToList(); + .Range(0, pl.NumberOfVertices) + .Select(pl.GetPoint3dAt) + .ToList(); } + #endregion #region 创建多段线 + /// /// 根据点集创建多段线
/// 此多段线无默认全局宽度0,无圆弧段 @@ -69,9 +71,7 @@ public static Polyline CreatePolyline(this IEnumerable points, Action

{ - pl.AddVertexAt(index, pt.Point2d(), 0, 0, 0); - }); + points.ForEach((index, pt) => { pl.AddVertexAt(index, pt.Point2d(), 0, 0, 0); }); action?.Invoke(pl); return pl; } @@ -82,19 +82,21 @@ public static Polyline CreatePolyline(this IEnumerable points, Action

端点表,利用元组(Point3d pt, double bulge, double startWidth, double endWidth) /// 轻多段线属性设置委托 /// 轻多段线对象 - public static Polyline CreatePolyline(this IEnumerable<(Point3d pt, double bulge, double startWidth, double endWidth)> pts, - Action? action = null) + public static Polyline CreatePolyline( + this IEnumerable<(Point3d pt, double bulge, double startWidth, double endWidth)> pts, + Action? action = null) { Polyline pl = new(); pl.SetDatabaseDefaults(); - pts.ForEach((index, vertex) => { + pts.ForEach((index, vertex) => + { pl.AddVertexAt(index, vertex.pt.Point2d(), vertex.bulge, vertex.startWidth, vertex.endWidth); }); action?.Invoke(pl); return pl; } - + ///

/// 根据Extents3d创建多段线
/// 此多段线无默认全局宽度0,无圆弧段,标高为0 @@ -111,15 +113,12 @@ public static Polyline CreatePolyline(this Extents3d points, Action? a points.MaxPoint.Point2d(), new(points.MaxPoint.X, points.MinPoint.Y) }; - Polyline pl = new(); + Polyline pl = new() { Closed = true }; pl.SetDatabaseDefaults(); - pts.ForEach((index, pt) => { - pl.AddVertexAt(index, pt, 0, 0, 0); - }); + pts.ForEach((index, pt) => { pl.AddVertexAt(index, pt, 0, 0, 0); }); action?.Invoke(pl); return pl; - } + } #endregion - } \ No newline at end of file -- Gitee From b0823e1e745cf734b8d3ec4c5c4343e47feb0bda Mon Sep 17 00:00:00 2001 From: vicwjb Date: Tue, 26 Dec 2023 11:22:04 +0800 Subject: [PATCH 235/453] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=89=B9=E9=87=8F?= =?UTF-8?q?=E6=8F=92=E5=85=A5dxf=E5=88=B0=E5=BD=93=E5=89=8D=E7=A9=BA?= =?UTF-8?q?=E9=97=B4=E7=9A=84=E7=A4=BA=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/TestShared/TestBlock.cs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tests/TestShared/TestBlock.cs b/tests/TestShared/TestBlock.cs index 0127329..63d305a 100644 --- a/tests/TestShared/TestBlock.cs +++ b/tests/TestShared/TestBlock.cs @@ -262,6 +262,31 @@ public void Test_BlockFile() tr.CurrentSpace.InsertBlock(Point3d.Origin, id); } + [CommandMethod(nameof(Test_BlockFiledxf))] + public void Test_BlockFiledxf() + { + string [] files; + var folder= new System.Windows.Forms.FolderBrowserDialog(); + if (folder.ShowDialog() == System.Windows.Forms.DialogResult.OK) + { + files = Directory.GetFiles(folder.SelectedPath,"*.dxf",SearchOption.AllDirectories); + using DBTrans tr = new(); + foreach (var item in files) + { + var id = tr.BlockTable.GetBlockFrom(item, false); + var pt = Env.Editor.GetPoint("pick pt"); + if (pt.Status == PromptStatus.OK) + { + tr.CurrentSpace.InsertBlock(pt.Value, id); + Env.Editor.Redraw(); + } + + } + + } + + + } [CommandMethod(nameof(Test_ClipBlock))] public void Test_ClipBlock() -- Gitee From f35e1a3f6e7c28d5073b69e7b4b0a04e10fb35cd Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 4 Jan 2024 18:00:59 +0800 Subject: [PATCH 236/453] =?UTF-8?q?=E5=AD=97=E5=85=B8SetKey=E6=97=B6?= =?UTF-8?q?=E5=BA=94=E5=B0=86=E5=8E=9Fapi=E7=9A=84objectId=E8=BF=94?= =?UTF-8?q?=E5=9B=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/DBDictionaryEx.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBDictionaryEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBDictionaryEx.cs index 68fa999..622b5c8 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBDictionaryEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBDictionaryEx.cs @@ -48,14 +48,16 @@ public static IEnumerable GetAllObjects(this DBDictionary dict) where T : /// 字典 /// 键 /// 值 - public static void SetAt(this DBDictionary dict, string key, T newValue) where T : DBObject + /// 字典项目的id + public static ObjectId SetAt(this DBDictionary dict, string key, T newValue) where T : DBObject { var tr = DBTrans.GetTopTransaction(dict.Database); using (dict.ForWrite()) { - dict.SetAt(key, newValue); + var id = dict.SetAt(key, newValue); tr.AddNewlyCreatedDBObject(newValue, true); + return id; } } -- Gitee From de2da8cfa6ec7f0fe8104745165a0662e3afc014 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sun, 14 Jan 2024 00:21:14 +0800 Subject: [PATCH 237/453] =?UTF-8?q?2024=E5=B9=B41=E6=9C=8814=E6=97=A50:21?= =?UTF-8?q?=20=E5=91=A8=E6=97=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CAD/IFox.CAD.Shared/ExtensionMethod/DatabaseEx.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/DatabaseEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/DatabaseEx.cs index d195d76..6d9a14d 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/DatabaseEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/DatabaseEx.cs @@ -101,7 +101,11 @@ public static void SaveFile(this Database db, DwgVersion version = DwgVersion.AC { var (error, file) = db.GetOrCreateSaveAsFile(); if (echoes && error) - System.Windows.Forms.MessageBox.Show($"错误参数:\n{fileMsg}\n\n它将保存:\n{file}", "错误的文件路径"); + System.Windows.Forms.MessageBox.Show($@"错误参数: +{fileMsg} + +它将保存: +{file}", "错误的文件路径"); saveAsFile = file; } -- Gitee From 1717e37281c99f18bcc56a682155202d4536f71c Mon Sep 17 00:00:00 2001 From: vicwjb Date: Mon, 15 Jan 2024 15:22:10 +0800 Subject: [PATCH 238/453] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E7=BB=93=E6=9E=84=EF=BC=8C=E6=96=B0=E5=A2=9E?= =?UTF-8?q?c#12=E8=AF=AD=E6=B3=95=E5=8F=8A=E7=9B=B8=E5=85=B3=E4=BF=AE?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/DBDictionaryEx.cs | 3 +- .../ExtensionMethod/Entity/CircleEx.cs | 2 +- .../ExtensionMethod/SymbolTableRecordEx.cs | 11 +- tests/TestAcad09plus/TestAcad09plus.csproj | 3 + tests/TestShared/CmdINI.cs | 5 +- tests/TestShared/TestAddEntity.cs | 123 +------------- tests/TestShared/TestEntity/TestAddEntity.cs | 157 ++++++++++++++++++ tests/TestShared/TestShared.projitems | 4 + tests/TestShared/readme.md | 20 +++ 9 files changed, 200 insertions(+), 128 deletions(-) create mode 100644 tests/TestShared/TestEntity/TestAddEntity.cs create mode 100644 tests/TestShared/readme.md diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBDictionaryEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBDictionaryEx.cs index 622b5c8..2a38c6a 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBDictionaryEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBDictionaryEx.cs @@ -96,8 +96,9 @@ public static void SetXRecord(this DBDictionary dict, string key, XRecordDataLis /// 获取扩展字典 ///
/// 对象 + /// 打开模式 /// 扩展字典对象 - public static DBDictionary GetXDictionary(this DBObject obj,OpenMode openMode =OpenMode.ForRead) + public static DBDictionary GetXDictionary(this DBObject obj, OpenMode openMode = OpenMode.ForRead) { var tr = DBTrans.GetTopTransaction(obj.Database); ObjectId id = obj.ExtensionDictionary; diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/CircleEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/CircleEx.cs index 4488f3a..5115ba8 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/CircleEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/CircleEx.cs @@ -51,7 +51,7 @@ public static Circle CreateCircle(Point3d startPoint, Point3d endPoint) /// 法向量的Y /// 法向量的Z /// - public static Circle? CreateCircle(Point3d center, double radius, double vex = 0, double vey = 0, double vez = 1) + public static Circle CreateCircle(Point3d center, double radius, double vex = 0, double vey = 0, double vez = 1) { return new Circle(center, new Vector3d(vex, vey, vez), radius);// 平面法向量XY方向 } diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs index f1a6f0c..9818df1 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs @@ -15,7 +15,7 @@ public static class SymbolTableRecordEx /// 0x02 若为未添加数据库图元,则利用entity.Clone();同时不需要考虑动态块属性,可以使用entity.GetTransformedCopy /// ///
- /// + /// 块表记录 /// /// 克隆到当前块表记录,相当于原地克隆
/// 克隆到目标块表记录内,相当于制作新块 @@ -46,6 +46,12 @@ public static void DeepCloneEx(this BlockTableRecord btr, ObjectIdCollection obj } } } + /// + /// 深度克隆id到块表记录 + /// + /// 块表记录 + /// 图元id集合 + /// id词典 public static IdMapping DeepCloneEx(this BlockTableRecord btr, ObjectIdCollection objIds) { if (objIds is null || objIds.Count == 0) @@ -98,11 +104,10 @@ public static ObjectId AddEntity(this BlockTableRecord btr, Entity entity) /// /// 添加实体集合 /// - /// 实体类型 /// 块表记录 /// 实体集合 /// 对象 id 列表 - public static IEnumerable AddEntity(this BlockTableRecord btr, IEnumerable ents) where T : Entity + public static IEnumerable AddEntity(this BlockTableRecord btr, IEnumerable ents) { var tr = DBTrans.GetTopTransaction(btr.Database); diff --git a/tests/TestAcad09plus/TestAcad09plus.csproj b/tests/TestAcad09plus/TestAcad09plus.csproj index c12c96c..3fe2240 100644 --- a/tests/TestAcad09plus/TestAcad09plus.csproj +++ b/tests/TestAcad09plus/TestAcad09plus.csproj @@ -8,6 +8,9 @@ true x64 True + 1.0.0.* + 1.0.0.0 + false diff --git a/tests/TestShared/CmdINI.cs b/tests/TestShared/CmdINI.cs index 363e360..c296a56 100644 --- a/tests/TestShared/CmdINI.cs +++ b/tests/TestShared/CmdINI.cs @@ -167,7 +167,7 @@ public void Terminate() } } #endif -#endif + public class Init : AutoLoad { @@ -185,4 +185,5 @@ public override void Terminate() // 所以如果不是想要在cad关闭的时候清理某些东西,这里不用写任何的代码。 } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/tests/TestShared/TestAddEntity.cs b/tests/TestShared/TestAddEntity.cs index 2200cac..123ba77 100644 --- a/tests/TestShared/TestAddEntity.cs +++ b/tests/TestShared/TestAddEntity.cs @@ -2,130 +2,11 @@ public partial class Test { - // add entity test - [CommandMethod(nameof(Test_Addent))] - public void Test_Addent() - { - using DBTrans tr = new(); - Line line = new(new(0, 0, 0), new(1, 1, 0)); - tr.CurrentSpace.AddEntity(line); - Line line1 = new(new(10, 10, 0), new(41, 1, 0)); - tr.ModelSpace.AddEntity(line1); - Line line2 = new(new(-10, 10, 0), new(41, 1, 0)); - tr.PaperSpace.AddEntity(line2); - - } - [CommandMethod(nameof(Test_Drawarc))] - public void Test_Drawarc() - { - using DBTrans tr = new(); - Arc arc1 = ArcEx.CreateArcSCE(new Point3d(2, 0, 0), new Point3d(0, 0, 0), new Point3d(0, 2, 0));// 起点,圆心,终点 - Arc arc2 = ArcEx.CreateArc(new Point3d(4, 0, 0), new Point3d(0, 0, 0), Math.PI / 2); // 起点,圆心,弧度 - Arc arc3 = ArcEx.CreateArc(new Point3d(1, 0, 0), new Point3d(0, 0, 0), new Point3d(0, 1, 0)); // 起点,圆上一点,终点 - tr.CurrentSpace.AddEntity(arc1, arc2, arc3); - - } - [CommandMethod(nameof(Test_DrawCircle))] - public void Test_DrawCircle() - { - using DBTrans tr = new(); - var circle1 = CircleEx.CreateCircle(new Point3d(0, 0, 0), new Point3d(1, 0, 0)); // 起点,终点 - var circle2 = CircleEx.CreateCircle(new Point3d(-2, 0, 0), new Point3d(2, 0, 0), new Point3d(0, 2, 0));// 三点画圆,成功 - var circle3 = CircleEx.CreateCircle(new Point3d(-2, 0, 0), new Point3d(0, 0, 0), new Point3d(2, 0, 0));// 起点,圆心,终点,失败 - tr.CurrentSpace.AddEntity(circle1, circle2!); - if (circle3 is not null) - tr.CurrentSpace.AddEntity(circle3); - else - tr.Editor?.WriteMessage("三点画圆失败"); - tr.CurrentSpace.AddEntity(circle3!); - } - - // 添加直线 - [CommandMethod(nameof(Test_AddLine1))] - public void Test_AddLine1() - { - using DBTrans tr = new(); - // tr.ModelSpace.AddEnt(line); - // tr.ModelSpace.AddEnts(line,circle); - - // tr.PaperSpace.AddEnt(line); - // tr.PaperSpace.AddEnts(line,circle); - - // tr.addent(btr,line); - // tr.addents(btr,line,circle); - - - // tr.BlockTable.Add(new BlockTableRecord(), line => - // { - // line. - // }); - Line line1 = new(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); - Line line2 = new(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); - Line line3 = new(new Point3d(1, 1, 0), new Point3d(3, 3, 0)); - Circle circle = new(new Point3d(0, 0, 0), Vector3d.ZAxis, 10); - tr.CurrentSpace.AddEntity(line1); - tr.CurrentSpace.AddEntity(line2, line3, circle); - } - // 增加多段线1 - [CommandMethod(nameof(Test_AddPolyline1))] - public void Test_AddPolyline1() - { - using DBTrans tr = new(); - Polyline pl = new(); - pl.SetDatabaseDefaults(); - pl.AddVertexAt(0, new Point2d(0, 0), 0, 0, 0); - pl.AddVertexAt(1, new Point2d(10, 10), 0, 0, 0); - pl.AddVertexAt(2, new Point2d(20, 20), 0, 0, 0); - pl.AddVertexAt(3, new Point2d(30, 30), 0, 0, 0); - pl.AddVertexAt(4, new Point2d(40, 40), 0, 0, 0); - pl.Closed = true; - pl.Color = Color.FromColorIndex(ColorMethod.ByColor, 6); - tr.CurrentSpace.AddEntity(pl); - } - - // 增加多段线2 - [CommandMethod(nameof(Test_AddPolyline2))] - public void Test_AddPolyline2() - { - var pts = new List<(Point3d, double, double, double)> - { - (new Point3d(0,0,0),0,0,0), - (new Point3d(10,0,0),0,0,0), - (new Point3d(10,10,0),0,0,0), - (new Point3d(0,10,0),0,0,0), - (new Point3d(5,5,0),0,0,0) - }; - using DBTrans tr = new(); - var pl = pts.CreatePolyline(); - tr.CurrentSpace.AddEntity(pl); - } - - [CommandMethod(nameof(Test_AddPolyline3))] - public void Test_AddPolyline3() - { - using var tr = new DBTrans(); - - var pts = new List - { - new(0, 0, 0), - new(0, 1, 0), - new(1, 1, 0), - new(1, 0, 0) - }; - var pline = pts.CreatePolyline(); - tr.CurrentSpace.AddEntity(pline); - - var pline1 = pts.CreatePolyline(p => - { - p.Closed = true; - p.ConstantWidth = 0.2; - p.ColorIndex = 1; - }); - tr.CurrentSpace.AddEntity(pline1); - } + + diff --git a/tests/TestShared/TestEntity/TestAddEntity.cs b/tests/TestShared/TestEntity/TestAddEntity.cs new file mode 100644 index 0000000..920e6e0 --- /dev/null +++ b/tests/TestShared/TestEntity/TestAddEntity.cs @@ -0,0 +1,157 @@ +namespace Test; + +public class TestAddEntity +{ +#region 直线 + [CommandMethod(nameof(Test_AddLinetoCurrentSpace))] + public void Test_AddLinetoCurrentSpace() + { + using DBTrans tr = new(); // 开启事务 + + Line line = new(new(0, 0, 0), new(1, 1, 0)); // 定义一个直线 + tr.CurrentSpace.AddEntity(line); // 将直线添加到当前空间 + } + + [CommandMethod(nameof(Test_AddLinetoModelSpace))] + public void Test_AddLinetoModelSpace() + { + using DBTrans tr = new(); // 开启事务 + + Line line = new(new(0, 0, 0), new(1, 1, 0)); // 定义一个直线 + tr.ModelSpace.AddEntity(line); // 将直线添加到模型空间 + } + + [CommandMethod(nameof(Test_AddLinetoPaperSpace))] + public void Test_AddLinetoPaperSpace() + { + using DBTrans tr = new(); // 开启事务 + + Line line = new(new(0, 0, 0), new(1, 1, 0)); // 定义一个直线 + tr.PaperSpace.AddEntity(line); // 将直线添加到图纸空间 + } + + [CommandMethod(nameof(Test_AddEntities))] + public void Test_AddEntities() + { + // 开启事务 + using DBTrans tr = new(); + // 定义三条直线 + Line line1 = new(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); + Line line2 = new(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); + Line line3 = new(new Point3d(1, 1, 0), new Point3d(3, 3, 0)); + Circle circle = new(); + // 一次性添加到当前空间 + tr.CurrentSpace.AddEntity(line2, line2, line3, circle); + // 或者可以传入个列表 + List lines = [line1, line2, line3]; + tr.CurrentSpace.AddEntity(lines); + // 或者可以传入个数组 + Line[] lines1 = [line1, line2, line3]; + tr.CurrentSpace.AddEntity(lines1); + // 图元数组 + Entity[] lines2 = [line1, line2, line3, circle]; + tr.CurrentSpace.AddEntity(lines2); + // c#12 新语法,集合表达式 + tr.CurrentSpace.AddEntity([line1, line2, circle]); + } +#endregion + +#region 圆 + [CommandMethod(nameof(Test_AddCircle))] + public void Test_AddCircle() + { + var cir = CircleEx.CreateCircle(Point3d.Origin, new(1,0,0)); // 两点创建圆 + var cir1 = CircleEx.CreateCircle(Point3d.Origin, new(1,1,0), new(2,0,0)); //三点创建圆 + var cir2 = CircleEx.CreateCircle(Point3d.Origin, 5); // 圆心半径创建圆 + + using DBTrans tr = new(); + tr.CurrentSpace.AddEntity(cir, cir2); + + // 由于三点不一定能成功创建一个圆,因此返回值是可空的,需要判空 + if (cir1 is not null) + { + tr.CurrentSpace.AddEntity(cir1); + } + } +#endregion + +#region 圆弧 + [CommandMethod(nameof(Test_AddArc))] + public void Test_AddArc() + { + using DBTrans tr = new(); + Arc arc1 = ArcEx.CreateArcSCE(new Point3d(2, 0, 0), new Point3d(0, 0, 0), new Point3d(0, 2, 0));// 起点,圆心,终点 + Arc arc2 = ArcEx.CreateArc(new Point3d(4, 0, 0), new Point3d(0, 0, 0), Math.PI / 2); // 起点,圆心,弧度 + Arc arc3 = ArcEx.CreateArc(new Point3d(1, 0, 0), new Point3d(0, 0, 0), new Point3d(0, 1, 0)); // 起点,圆上一点,终点 + tr.CurrentSpace.AddEntity(arc1, arc2, arc3); + } + +#endregion + + + + + +#region 多段线 + [CommandMethod(nameof(Test_AddPolyline1))] + public void Test_AddPolyline1() + { + using DBTrans tr = new(); + Polyline pl = new(); + pl.SetDatabaseDefaults(); + pl.AddVertexAt(0, new Point2d(0, 0), 0, 0, 0); + pl.AddVertexAt(1, new Point2d(10, 10), 0, 0, 0); + pl.AddVertexAt(2, new Point2d(20, 20), 0, 0, 0); + pl.AddVertexAt(3, new Point2d(30, 30), 0, 0, 0); + pl.AddVertexAt(4, new Point2d(40, 40), 0, 0, 0); + pl.Closed = true; + pl.Color = Color.FromColorIndex(ColorMethod.ByColor, 6); + tr.CurrentSpace.AddEntity(pl); + } + + [CommandMethod(nameof(Test_AddPolyline2))] + public void Test_AddPolyline2() + { + // 集合表达式 + List<(Point3d, double, double, double)> pts = + [ + (new Point3d(0,0,0),0,0,0), + (new Point3d(10,0,0),0,0,0), + (new Point3d(10,10,0),0,0,0), + (new Point3d(0,10,0),0,0,0), + (new Point3d(5,5,0),0,0,0) + ]; + + using DBTrans tr = new(); + var pl = pts.CreatePolyline(); + tr.CurrentSpace.AddEntity(pl); + } + + [CommandMethod(nameof(Test_AddPolyline3))] + public void Test_AddPolyline3() + { + using var tr = new DBTrans(); + + List pts = + [ + new(0, 0, 0), + new(0, 1, 0), + new(1, 1, 0), + new(1, 0, 0) + ]; + var pline = pts.CreatePolyline(); + tr.CurrentSpace.AddEntity(pline); + + // 可以通过委托,一次性的创建多段线并设置属性 + var pline1 = pts.CreatePolyline(p => + { + p.Closed = true; + p.ConstantWidth = 0.2; + p.ColorIndex = 1; + }); + tr.CurrentSpace.AddEntity(pline1); + } + +#endregion + +} diff --git a/tests/TestShared/TestShared.projitems b/tests/TestShared/TestShared.projitems index b29bbf6..28b5f94 100644 --- a/tests/TestShared/TestShared.projitems +++ b/tests/TestShared/TestShared.projitems @@ -21,6 +21,7 @@ + @@ -43,4 +44,7 @@ + + + \ No newline at end of file diff --git a/tests/TestShared/readme.md b/tests/TestShared/readme.md new file mode 100644 index 0000000..81b106f --- /dev/null +++ b/tests/TestShared/readme.md @@ -0,0 +1,20 @@ +# 测试项目文件结构 +- 图元类 - TestEntity + + TestAddEntity.cs + + TestRemoveEntity.cs + + .... +- 事务类 - TestDBtrans +- 符号表类 - TestSymTable + + TestLayer.cs + + TestTextStyle.cs + + ... +- 选择集类 +- 扩展数据类 +- editor类 +- 数据库对象类 +- env类 +- jig类 +- 数据交互类 +- lisp类 +- 算法类 +- \ No newline at end of file -- Gitee From 5bdbfdd1508260f1cfe62076ac2a07a100086367 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Wed, 17 Jan 2024 15:31:11 +0800 Subject: [PATCH 239/453] =?UTF-8?q?=E6=B8=85=E7=90=86=E8=AD=A6=E5=91=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../IFox.CAD.Shared/Algorithms/Graph/Graph.cs | 3 +- .../Algorithms/QuadTree/QuadTree.cs | 2 +- .../Algorithms/QuadTree/QuadTreeNode.cs | 48 +++--- .../Algorithms/QuadTree/Rect.cs | 145 ++++++++++++++++-- src/CAD/IFox.CAD.Shared/AutoReg/AssemInfo.cs | 4 +- .../IFox.CAD.Shared/AutoReg/AutoRegAssem.cs | 10 +- src/CAD/IFox.CAD.Shared/AutoReg/IAutoGo.cs | 65 ++++---- .../IFox.CAD.Shared/CadVersion/AcadVersion.cs | 2 +- src/CAD/IFox.CAD.Shared/Copyclip/EmfTool.cs | 11 +- .../Copyclip/TagClipboardInfo.cs | 14 +- .../ExtensionMethod/BulgeVertexWidth.cs | 13 +- .../ExtensionMethod/CheckFactory.cs | 3 + .../ExtensionMethod/CollectionEx.cs | 12 ++ .../ExtensionMethod/Curve3dEx.cs | 3 +- .../ExtensionMethod/CurveEx.cs | 43 +++--- .../ExtensionMethod/DBTransEx.cs | 3 + .../ExtensionMethod/EditorEx.cs | 13 +- .../Entity/EntityBoundingInfo.cs | 13 +- .../ExtensionMethod/Entity/PolylineEx.cs | 12 +- .../IFox.CAD.Shared/ExtensionMethod/Enums.cs | 33 +++- .../ExtensionMethod/GeometryEx.cs | 16 +- .../ExtensionMethod/Jig/JigEx.cs | 16 +- .../ExtensionMethod/Jig/JigExTransient.cs | 2 +- .../IFox.CAD.Shared/ExtensionMethod/ObjEx.cs | 9 +- .../ExtensionMethod/PointEx.cs | 4 +- .../ExtensionMethod/RedrawEx.cs | 12 +- .../ExtensionMethod/SingleKeyWordHook.cs | 7 + .../IFox.CAD.Shared/ExtensionMethod/Tools.cs | 4 +- .../IFox.CAD.Shared/ExtensionMethod/XrefEx.cs | 55 +++---- .../HatchConverter.cs" | 4 + .../HatchEx.cs" | 4 +- src/CAD/IFox.CAD.Shared/PE/AcadPeInfo.cs | 70 ++++++++- src/CAD/IFox.CAD.Shared/PE/DBmod.cs | 34 +++- src/CAD/IFox.CAD.Shared/PE/PostCmd.cs | 42 ++++- src/CAD/IFox.CAD.Shared/PE/ProgramPE.cs | 13 +- .../IFox.CAD.Shared/ResultData/XdataList.cs | 1 + src/CAD/IFox.CAD.Shared/Runtime/IFoxUtils.cs | 6 +- tests/TestShared/Copyclip.cs | 2 +- tests/TestShared/TestBlock.cs | 18 +-- tests/TestShared/TestConvexHull.cs | 2 +- tests/TestShared/TestExtents.cs | 29 ++-- tests/TestShared/TestJson.cs | 2 +- tests/TestShared/TestQuadTree.cs | 6 +- 43 files changed, 601 insertions(+), 209 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/Algorithms/Graph/Graph.cs b/src/CAD/IFox.CAD.Shared/Algorithms/Graph/Graph.cs index 75bdc5b..6ecb934 100644 --- a/src/CAD/IFox.CAD.Shared/Algorithms/Graph/Graph.cs +++ b/src/CAD/IFox.CAD.Shared/Algorithms/Graph/Graph.cs @@ -241,7 +241,7 @@ public HashSet GetAdjacencyEdge(IGraphVertex vertex) /// 曲线表 public List GetCurves(List graphVertices) { - var curves = new List(); + List curves = []; for (int i = 0; i < graphVertices.Count - 1; i++) { var cur = graphVertices[i]; @@ -696,6 +696,7 @@ static List RotateToSmallest(List lst) /// 将列表反向,并旋转到起点为最小值 ///
/// + /// /// static List Invert(List lst, IGraphVertex vertex) { diff --git a/src/CAD/IFox.CAD.Shared/Algorithms/QuadTree/QuadTree.cs b/src/CAD/IFox.CAD.Shared/Algorithms/QuadTree/QuadTree.cs index 538a620..403cc6c 100644 --- a/src/CAD/IFox.CAD.Shared/Algorithms/QuadTree/QuadTree.cs +++ b/src/CAD/IFox.CAD.Shared/Algorithms/QuadTree/QuadTree.cs @@ -172,7 +172,7 @@ public List Query(Rect rect, QuadTreeSelectMode selectMode = QuadTreeSe { QuadTreeEvn.SelectMode = selectMode; - var results = new List(); + List results = []; // 选择图元 _rootNode.Query(rect, results); // 选择点 diff --git a/src/CAD/IFox.CAD.Shared/Algorithms/QuadTree/QuadTreeNode.cs b/src/CAD/IFox.CAD.Shared/Algorithms/QuadTree/QuadTreeNode.cs index 06bf472..315117f 100644 --- a/src/CAD/IFox.CAD.Shared/Algorithms/QuadTree/QuadTreeNode.cs +++ b/src/CAD/IFox.CAD.Shared/Algorithms/QuadTree/QuadTreeNode.cs @@ -482,7 +482,7 @@ void GetCurrentContents(Rect queryArea, List results) // 再判断图元的与目标的距离,找到最小距离,即为最近 var minPt = new Point2d(queryAreaCenter.X - hw, queryAreaCenter.Y - hh); var maxPt = new Point2d(queryAreaCenter.X + hw, queryAreaCenter.Y + hh); - var ents = new List(); + List ents = []; Query(new Rect(minPt, maxPt), ents); for (int i = 0; i < ents.Count; i++) { @@ -608,7 +608,7 @@ void GetCurrentContents(Rect queryArea, List results) { TEntity? results = default; - var lst = new List(); + List lst = []; var qcent = queryArea.CenterPoint; switch (findMode) @@ -763,30 +763,32 @@ QuadTreeNode GetMinNode(Rect queryArea) #endregion #region 改 + /* /// /// 所有的点归类到最小包围它的空间 /// - // public void PointsToMinNode() - // { - // ForEach(node => - // { - // for (int i = 0; i < node.Contents.Count; i++) - // { - // var ent = node.Contents[i]; - // if (ent.IsPoint) - // { - // // 如果最小包含!=当前,就是没有放在最适合的位置 - // var queryNode = GetMinNode(ent); - // if (queryNode != node) - // { - // node.Remove(ent); - // queryNode.Contents.Add(ent); - // } - // } - // } - // return false; - // }); - // } + public void PointsToMinNode() + { + ForEach(node => + { + for (int i = 0; i < node.Contents.Count; i++) + { + var ent = node.Contents[i]; + if (ent.IsPoint) + { + // 如果最小包含!=当前,就是没有放在最适合的位置 + var queryNode = GetMinNode(ent); + if (queryNode != node) + { + node.Remove(ent); + queryNode.Contents.Add(ent); + } + } + } + return false; + }); + } + */ #endregion #region 方法 diff --git a/src/CAD/IFox.CAD.Shared/Algorithms/QuadTree/Rect.cs b/src/CAD/IFox.CAD.Shared/Algorithms/QuadTree/Rect.cs index 170ebdd..583c07d 100644 --- a/src/CAD/IFox.CAD.Shared/Algorithms/QuadTree/Rect.cs +++ b/src/CAD/IFox.CAD.Shared/Algorithms/QuadTree/Rect.cs @@ -17,7 +17,12 @@ public TolerancePoint2d(double tolerance = 1e-6) { _tolerance = tolerance; } - + /// + /// 比较 + /// + /// + /// + /// public bool Equals(Point2d a, Point2d b)// Point3d是struct不会为null { /*默认规则是==是0容差,Eq是有容差*/ @@ -32,7 +37,11 @@ public bool Equals(Point2d a, Point2d b)// Point3d是struct不会为null // (X86.CPU.FSQRT指令用的牛顿迭代法/软件层面可以使用快速平方根....我还以为CPU会采取快速平方根这样的取表操作) return a.IsEqualTo(b, new Tolerance(_tolerance, _tolerance)); } - + /// + /// 哈希 + /// + /// + /// public int GetHashCode(Point2d obj) { // 结构体直接返回 obj.GetHashCode(); Point3d ToleranceDistinct3d @@ -42,7 +51,9 @@ public int GetHashCode(Point2d obj) } } - +/// +/// 矩形范围类 +/// [Serializable] [StructLayout(LayoutKind.Sequential)] [DebuggerDisplay("{DebuggerDisplay,nq}")] @@ -53,7 +64,13 @@ public class Rect : IEquatable, IComparable private string DebuggerDisplay => ToString("f4"); #pragma warning disable CA2211 // 非常量字段应当不可见 + /// + /// 矩形容差 + /// public static TolerancePoint2d RectTolerance = new(1e-6); + /// + /// cad容差 + /// public static Tolerance CadTolerance = new(1e-6, 1e-6); #pragma warning restore CA2211 // 非常量字段应当不可见 @@ -68,15 +85,41 @@ public class Rect : IEquatable, IComparable #endregion #region 成员 + /// + /// X + /// public double X => _X; + /// + /// Y + /// public double Y => _Y; + /// + /// 左 + /// public double Left => _X; + /// + /// 下 + /// public double Bottom => _Y; + /// + /// 右 + /// public double Right => _Right; + /// + /// 上 + /// public double Top => _Top; - + /// + /// 宽 + /// public double Width => _Right - _X; + /// + /// 高 + /// public double Height => _Top - _Y; + /// + /// 面积 + /// public double Area { get @@ -85,9 +128,17 @@ public double Area return ar < 1e-10 ? 0 : ar; } } - + /// + /// 左下Min + /// public Point2d MinPoint => LeftLower; + /// + /// 右上Max + /// public Point2d MaxPoint => RightUpper; + /// + /// 中间 + /// public Point2d CenterPoint => Midst; /// @@ -143,6 +194,9 @@ public double Area #endregion #region 构造 + /// + /// + /// public Rect() { } @@ -188,18 +242,40 @@ public Rect(Point2d p1, Point2d p3, bool check = false) #endregion #region 重载运算符_比较 + /// + /// + /// + /// + /// public override bool Equals(object? obj) { return this.Equals(obj as Rect); } + /// + /// + /// + /// + /// public bool Equals(Rect? b) { return this.Equals(b, 1e-6);/*默认规则是==是0容差,Eq是有容差*/ } + /// + /// + /// + /// + /// + /// public static bool operator !=(Rect? a, Rect? b) { return !(a == b); } + /// + /// + /// + /// + /// + /// public static bool operator ==(Rect? a, Rect? b) { // 此处地方不允许使用==null,因为此处是定义 @@ -228,7 +304,10 @@ public bool Equals(Rect? b, double tolerance = 1e-6) Math.Abs(_Top - b._Top) < tolerance && Math.Abs(_Y - b._Y) < tolerance; } - + /// + /// + /// + /// public override int GetHashCode() { return (((int)_X ^ (int)_Y).GetHashCode() ^ (int)_Right).GetHashCode() ^ (int)_Top; @@ -236,10 +315,21 @@ public override int GetHashCode() #endregion #region 包含 + /// + /// + /// + /// + /// public bool Contains(Point2d Point2d) { return Contains(Point2d.X, Point2d.Y); } + /// + /// + /// + /// + /// + /// public bool Contains(double x, double y) { return _X <= x && x <= _Right && @@ -279,16 +369,22 @@ public Point2d[] GetCommonPoint(Rect other) { return ToPoints().Intersect(other.ToPoints(), RectTolerance).ToArray(); } - + /// + /// 转换为point2d数组 + /// + /// public Point2d[] ToPoints() { Point2d a = MinPoint;// min Point2d b = new(_Right, _Y); Point2d c = MaxPoint;// max Point2d d = new(_X, _Top); - return new Point2d[] { a, b, c, d }; + return [a, b, c, d]; } - + /// + /// 转换为point2d元组 + /// + /// public (Point2d boxMin, Point2d boxRigthDown, Point2d boxMax, Point2d boxLeftUp) ToPoints4() { Point2d a = MinPoint;// min @@ -311,6 +407,7 @@ public Rect Expand(double d) /// 是否矩形(带角度) /// /// + /// /// public static bool IsRectAngle(List? ptList, double tolerance = 1e-8) { @@ -490,7 +587,7 @@ static bool CrossAclockwise(Point2d o, Point2d a, Point2d b) /// 多段线对象 public Entity ToPolyLine() { - var bv = new List(); + List bv = []; var pts = ToPoints(); Polyline pl = new(); pl.SetDatabaseDefaults(); @@ -566,10 +663,18 @@ public static void XCollision(List box, // { // return new Rect(rect.Left, rect.Bottom, rect.Right, rect.Top); // } + /// + /// + /// + /// public static implicit operator Rect(System.Drawing.RectangleF rect) { return new Rect(rect.Left, rect.Bottom, rect.Right, rect.Top); } + /// + /// + /// + /// public static implicit operator Rect(System.Drawing.Rectangle rect) { return new Rect(rect.Left, rect.Bottom, rect.Right, rect.Top); @@ -577,14 +682,29 @@ public static implicit operator Rect(System.Drawing.Rectangle rect) #endif #region ToString + /// + /// + /// + /// public sealed override string ToString() { return ToString(null, null); } + /// + /// + /// + /// + /// public string ToString(IFormatProvider? provider) { return ToString(null, provider); } + /// + /// + /// + /// + /// + /// public string ToString(string? format = null, IFormatProvider? formatProvider = null) { return $"({_X.ToString(format, formatProvider)},{_Y.ToString(format, formatProvider)})," + @@ -597,6 +717,11 @@ public string ToString(string? format = null, IFormatProvider? formatProvider = } /*为了红黑树,加入这个*/ + /// + /// + /// + /// + /// public int CompareTo(Rect rect) { if (rect == null) diff --git a/src/CAD/IFox.CAD.Shared/AutoReg/AssemInfo.cs b/src/CAD/IFox.CAD.Shared/AutoReg/AssemInfo.cs index 23e5c7d..94827a5 100644 --- a/src/CAD/IFox.CAD.Shared/AutoReg/AssemInfo.cs +++ b/src/CAD/IFox.CAD.Shared/AutoReg/AssemInfo.cs @@ -80,6 +80,8 @@ public enum AutoRegConfig /// 移除教育版 ///
RemoveEMR = 8, - + /// + /// 全部 + /// All = Regedit | ReflectionAttribute | ReflectionInterface | RemoveEMR, } \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/AutoReg/AutoRegAssem.cs b/src/CAD/IFox.CAD.Shared/AutoReg/AutoRegAssem.cs index e07474e..fd3c361 100644 --- a/src/CAD/IFox.CAD.Shared/AutoReg/AutoRegAssem.cs +++ b/src/CAD/IFox.CAD.Shared/AutoReg/AutoRegAssem.cs @@ -82,13 +82,21 @@ public AutoRegAssem(AutoRegConfig autoRegConfig) // 这里的是不会自动执行的 + /// + /// + /// public void Initialize() { } + /// + /// + /// public void Terminate() { } - + /// + /// + /// ~AutoRegAssem() { _autoRef?.Terminate(); diff --git a/src/CAD/IFox.CAD.Shared/AutoReg/IAutoGo.cs b/src/CAD/IFox.CAD.Shared/AutoReg/IAutoGo.cs index 1dbc831..766f721 100644 --- a/src/CAD/IFox.CAD.Shared/AutoReg/IAutoGo.cs +++ b/src/CAD/IFox.CAD.Shared/AutoReg/IAutoGo.cs @@ -9,8 +9,14 @@ namespace IFoxCAD.Cad; [Flags] public enum Sequence : byte { - First,// 最先 - Last, // 最后 + /// + /// 最先 + /// + First, + /// + /// 最后 + /// + Last, } /// @@ -18,11 +24,20 @@ public enum Sequence : byte /// public interface IFoxAutoGo { - // 控制加载顺序 + /// + /// 控制加载顺序 + /// + /// Sequence SequenceId(); - // 关闭cad的时候会自动执行 + + /// + /// 关闭cad的时候会自动执行 + /// void Terminate(); - // 打开cad的时候会自动执行 + + /// + /// 打开cad的时候会自动执行 + /// void Initialize(); } @@ -89,29 +104,26 @@ public void Run() /// 2:接口..(多个) /// ///
-public class AutoReflection +/// +/// 反射执行 +/// +/// 1.特性:
+/// 2.接口: +///
+///
+/// 约束在此dll进行加速 +/// +public class AutoReflection(string dllName, AutoRegConfig configInfo) { - static List _InitializeList = new(); // 储存方法用于初始化 - static List _TerminateList = new(); // 储存方法用于结束释放 + static List _InitializeList = []; // 储存方法用于初始化 + static List _TerminateList = []; // 储存方法用于结束释放 - readonly string _dllName; - readonly AutoRegConfig _autoRegConfig; + readonly string _dllName = dllName; + readonly AutoRegConfig _autoRegConfig = configInfo; /// - /// 反射执行 - /// - /// 1.特性:
- /// 2.接口: - ///
+ /// 启动cad的时候会自动执行 ///
- /// 约束在此dll进行加速 - public AutoReflection(string dllName, AutoRegConfig configInfo) - { - _dllName = dllName; - _autoRegConfig = configInfo; - } - - // 启动cad的时候会自动执行 public void Initialize() { try @@ -232,9 +244,10 @@ public static void AppDomainGetTypes(Action action, string? dllNameWithout /// /// 收集接口下的函数 /// - /// 储存要运行的方法 - /// 查找方法名 - /// + /// + /// + /// + /// void GetInterfaceFunctions(List initializes, string initializeName, List terminates, string terminateName) { diff --git a/src/CAD/IFox.CAD.Shared/CadVersion/AcadVersion.cs b/src/CAD/IFox.CAD.Shared/CadVersion/AcadVersion.cs index 92813b3..4ae8368 100644 --- a/src/CAD/IFox.CAD.Shared/CadVersion/AcadVersion.cs +++ b/src/CAD/IFox.CAD.Shared/CadVersion/AcadVersion.cs @@ -20,7 +20,7 @@ public static List Versions .OpenSubKey(@"SOFTWARE\Autodesk\Hardcopy") .GetValueNames(); - var _versions = new List(); + List _versions = []; for (int i = 0; i < copys.Length; i++) { if (!Regex.IsMatch(copys[i], _pattern)) diff --git a/src/CAD/IFox.CAD.Shared/Copyclip/EmfTool.cs b/src/CAD/IFox.CAD.Shared/Copyclip/EmfTool.cs index b49f08f..98cdd50 100644 --- a/src/CAD/IFox.CAD.Shared/Copyclip/EmfTool.cs +++ b/src/CAD/IFox.CAD.Shared/Copyclip/EmfTool.cs @@ -1,4 +1,5 @@ -namespace IFoxCAD.Cad; +#pragma warning disable CS1591 // 缺少对公共可见类型或成员的 XML 注释 +namespace IFoxCAD.Cad; using System; using System.Diagnostics; @@ -24,7 +25,10 @@ // http://www.cppblog.com/zwp/archive/2012/02/25/60225.html [Serializable] [StructLayout(LayoutKind.Sequential, Pack = 2)] + public struct MetaFilePict + + { public MappingModes mm; public int xExt; @@ -791,7 +795,7 @@ public static void SaveMetaFile(this Metafile file, string emfName) /// /// 矢量图 转换 byte[] /// - /// + /// /// public static byte[]? ToByteArray(this Metafile mf) { @@ -919,4 +923,5 @@ static void Draw(Graphics g) g.DrawString("剖面图", new Font("宋体", 9f), Brushes.Green, 220f, 20f); } #endif -} \ No newline at end of file +} +#pragma warning restore CS1591 // 缺少对公共可见类型或成员的 XML 注释 \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/Copyclip/TagClipboardInfo.cs b/src/CAD/IFox.CAD.Shared/Copyclip/TagClipboardInfo.cs index acadd08..07452fc 100644 --- a/src/CAD/IFox.CAD.Shared/Copyclip/TagClipboardInfo.cs +++ b/src/CAD/IFox.CAD.Shared/Copyclip/TagClipboardInfo.cs @@ -1,4 +1,5 @@ -namespace IFoxCAD.Cad; +#pragma warning disable CS1591 // 缺少对公共可见类型或成员的 XML 注释 +namespace IFoxCAD.Cad; using System; using System.Diagnostics; @@ -556,6 +557,8 @@ public enum ClipboardFormat : uint ///
CF_DIBV5 = 17, + +#pragma warning disable CS1574 // XML 注释中有无法解析的 cref 特性 /// /// Owner-display format. The clipboard owner must display and update the clipboard viewer window, and receive /// the , , @@ -563,6 +566,7 @@ public enum ClipboardFormat : uint /// messages. The hMem parameter must be null. /// CF_OWNERDISPLAY = 0x0080, +#pragma warning restore CS1574 // XML 注释中有无法解析的 cref 特性 /// /// Text display format associated with a private format. The hMem parameter must be a handle to data @@ -601,15 +605,16 @@ public enum ClipboardFormat : uint /// See . /// CF_GDIOBJLAST = 0x03FF, - +#pragma warning disable CS1574 // XML 注释中有无法解析的 cref 特性 /// /// Start of a range of integer values for private clipboard formats. The range ends with /// . Handles associated with private clipboard formats are not freed /// automatically, the clipboard owner must free such handles, typically in response to the /// message. /// + /// CF_PRIVATEFIRST = 0x0200, - +#pragma warning restore CS1574 // XML 注释中有无法解析的 cref 特性 /// /// See . /// @@ -653,4 +658,5 @@ enum eExpandedClipDataTypes kDcSectionViewStyles = 18, kDcDetailViewStyles = 19, }; -#endif \ No newline at end of file +#endif +#pragma warning restore CS1591 // 缺少对公共可见类型或成员的 XML 注释 \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/BulgeVertexWidth.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/BulgeVertexWidth.cs index 1f9e08d..1929dd6 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/BulgeVertexWidth.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/BulgeVertexWidth.cs @@ -26,9 +26,13 @@ public class BulgeVertexWidth /// 尾宽 ///
public double EndWidth; - + /// + /// 顶点 + /// public Point2d Vertex => new(X, Y); - + /// + /// 默认构造 + /// public BulgeVertexWidth() { } /// @@ -77,7 +81,10 @@ public BulgeVertexWidth(Polyline pl, int index) StartWidth = pl.GetStartWidthAt(index); EndWidth = pl.GetEndWidthAt(index); } - + /// + /// 转换为 BulgeVertex + /// + /// public BulgeVertex ToBulgeVertex() { return new BulgeVertex(Vertex, Bulge); diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/CheckFactory.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/CheckFactory.cs index 2aea546..21454a1 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/CheckFactory.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/CheckFactory.cs @@ -1,5 +1,8 @@ #if Debug namespace IFoxCAD.Cad; +/// +/// 命令检查类 +/// public static class CheckFactory { /* diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/CollectionEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/CollectionEx.cs index c0962c7..3dfe440 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/CollectionEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/CollectionEx.cs @@ -163,10 +163,22 @@ public static void ForEach(this IEnumerable source, Action + /// 关键字名字 + /// public enum KeywordName { + /// + /// 全局名字 + /// GlobalName, + /// + /// 本地名字 + /// LocalName, + /// + /// 显示名字 + /// DisplayName, } diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Curve3dEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Curve3dEx.cs index c12275b..f415ea3 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Curve3dEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Curve3dEx.cs @@ -26,11 +26,12 @@ public static bool IsEqualPoint(this Tolerance tol, double d1, double d2) /// 获取三维解析类曲线(自交曲线)的交点参数 ///
/// 三维解析类曲线 + /// 是否排序 /// 曲线参数的列表 public static List GetParamsAtIntersectionPoints(this Curve3d c3d, bool sort = true) { CurveCurveIntersector3d cci = new(c3d, c3d, Vector3d.ZAxis); - List pars = new(); + List pars = []; for (int i = 0; i < cci.NumberOfIntersectionPoints; i++) pars.AddRange(cci.GetIntersectionParameters(i)); if (sort) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/CurveEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/CurveEx.cs index 4ed16e2..295ed1a 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/CurveEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/CurveEx.cs @@ -127,7 +127,7 @@ public static IEnumerable GetAllCycle(this IEnumerable curves) // 查询全部的 闭合环 dfs.FindAll(graph); // 遍历闭合环的列表,将每个闭合环转换为实体曲线 - var res = new List(); + List res = []; foreach (var item in dfs.Curve3ds) { var curve = graph.GetCurves(item.ToList()).ToArray(); @@ -148,8 +148,8 @@ public static List BreakCurve(this List curves) var tol = new Tolerance(0.01, 0.01); - var geCurves = new List(); // 存储曲线转换后的复合曲线 - var paramss = new List>(); // 存储每个曲线的交点参数值 + List geCurves = []; // 存储曲线转换后的复合曲线 + List> paramss = []; // 存储每个曲线的交点参数值 for (int i = 0; i < curves.Count; i++) { @@ -157,12 +157,12 @@ public static List BreakCurve(this List curves) if (cc3d is not null) { geCurves.Add(cc3d); - paramss.Add(new List()); + paramss.Add([]); } } - // var oldCurves = new List(); - var newCurves = new List(); + // List oldCurves = []; + List newCurves = []; var cci3d = new CurveCurveIntersector3d(); for (int i = 0; i < curves.Count; i++) @@ -218,19 +218,19 @@ public static List BreakCurveOnZPlane(this List curves) throw new ArgumentNullException(nameof(curves)); var zPlane = new Plane(Point3d.Origin, Vector3d.ZAxis); var curvesTemp = curves.Select(c => c.GetProjectedCurve(zPlane, Vector3d.ZAxis)).ToList(); - var geCurves = new List(); // 存储曲线转换后的复合曲线 - var paramss = new List>(); // 存储每个曲线的交点参数值 + List geCurves = []; // 存储曲线转换后的复合曲线 + List> paramss = []; // 存储每个曲线的交点参数值 for (int i = 0; i < curvesTemp.Count; i++) { - paramss.Add(new HashSet()); + paramss.Add([]); var cc3d = curvesTemp[i].ToCompositeCurve3d(); if (cc3d is not null) { geCurves.Add(cc3d); } } - var newCurves = new List(); + List newCurves = []; var cci3d = new CurveCurveIntersector3d(); for (int i = 0; i < curvesTemp.Count; i++) @@ -293,8 +293,8 @@ public static List BreakCurve2dByQuadTree(this List sourceCurveLis //var tolerance = new Tolerance(tol, tol); var zPlane = new Plane(Point3d.Origin, Vector3d.ZAxis); List curves = sourceCurveList.Select(c => c.GetOrthoProjectedCurve(zPlane)).ToList(); - var geCurves = new List(); - var xlines = new List(); + List geCurves = []; + List xlines = []; double minX = double.MaxValue; double minY = double.MaxValue; double maxX = double.MinValue; @@ -331,7 +331,7 @@ public static List BreakCurve2dByQuadTree(this List sourceCurveLis var bci = new BreakCurveInfo(maxBox, xl, cc3d); geCurves.Add(bci); }); - var newCurves = new List(); + List newCurves = []; var quadTree = new QuadTree(maxBox); foreach (var bci in geCurves) { @@ -694,9 +694,7 @@ public static NurbCurve3d ToCurve3d(this Spline spl) { NurbCurve3d nc3d; NurbsData ndata = spl.NurbsData; - KnotCollection knots = new(); - foreach (Double knot in ndata.GetKnots()) - knots.Add(knot); + KnotCollection knots = [.. ndata.GetKnots()]; if (ndata.Rational) { @@ -845,7 +843,7 @@ public static PolylineCurve3d ToPolylineCurve3d(this Polyline3d pl) /// 复合曲线对象 public static CompositeCurve3d ToCurve3d(this Polyline pl) { - List c3ds = new(); + List c3ds = []; for (int i = 0; i < pl.NumberOfVertices; i++) { @@ -863,7 +861,7 @@ public static CompositeCurve3d ToCurve3d(this Polyline pl) break; } } - return new CompositeCurve3d(c3ds.ToArray()); + return new CompositeCurve3d([.. c3ds]); } /// @@ -916,11 +914,10 @@ public static void ChamferAt(this Polyline polyline, int index, double radius, b // 获取当前索引号的前后两段直线,并组合为Ge复合曲线 Curve3d[] c3ds = - new Curve3d[] - { - polyline.GetLineSegmentAt(index - 1), - polyline.GetLineSegmentAt(index) - }; + [ + polyline.GetLineSegmentAt(index - 1), + polyline.GetLineSegmentAt(index) + ]; CompositeCurve3d cc3d = new(c3ds); // 试倒直角 diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBTransEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBTransEx.cs index fdd4e91..1131399 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBTransEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBTransEx.cs @@ -3,6 +3,9 @@ namespace IFoxCAD.Cad; #if lack_test +/// +/// 事务类扩展 +/// public static class DBTransEx { /* diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs index 05b90e1..d9a92b0 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs @@ -1010,11 +1010,22 @@ public static PromptResult GetString(this Editor ed, string Message, string Defa [DllImport("accore.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ads_queueexpr")] static extern int Ads_queueexpr(string strExpr); - + /// + /// 执行lisp的方式枚举 + /// public enum RunLispFlag : byte { + /// + /// AdsQueueexpr + /// AdsQueueexpr = 1, + /// + /// AcedEvaluateLisp + /// AcedEvaluateLisp = 2, + /// + /// SendStringToExecute + /// SendStringToExecute = 4, } diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs index e0e693a..2719d18 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs @@ -251,16 +251,5 @@ static bool IsEmptyExt(this Extents3d ext) else return false; } - /// - /// 点偏移 - /// - /// - /// - /// - /// - /// - //static Point3d Offset(this Point3d pt, double x, double y, double z = 0) - //{ - // return new Point3d(pt.X + x, pt.Y + y, pt.Z + z); - //} + } \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/PolylineEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/PolylineEx.cs index 9daffa6..b2a5ba1 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/PolylineEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/PolylineEx.cs @@ -1,7 +1,4 @@ -using System; -using System.Data.SqlTypes; - -namespace IFoxCAD.Cad; +namespace IFoxCAD.Cad; /// /// 多段线扩展类 @@ -106,13 +103,14 @@ public static Polyline CreatePolyline( /// 多段线对象 public static Polyline CreatePolyline(this Extents3d points, Action? action = null) { - var pts = new List() - { + List pts = + [ points.MinPoint.Point2d(), new(points.MinPoint.X, points.MaxPoint.Y), points.MaxPoint.Point2d(), new(points.MaxPoint.X, points.MinPoint.Y) - }; + ]; + Polyline pl = new() { Closed = true }; pl.SetDatabaseDefaults(); pts.ForEach((index, pt) => { pl.AddVertexAt(index, pt, 0, 0, 0); }); diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Enums.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Enums.cs index 5043cad..87f02c3 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Enums.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Enums.cs @@ -37,7 +37,9 @@ public enum XrefModes : byte /// Bind, } - +/// +/// 符号表模式 +/// [Flags] public enum SymModes : ushort { @@ -66,6 +68,9 @@ public enum SymModes : ushort /// 线型表 /// LinetypeTable = 32, + /// + /// 图层|字体|标注|线型|应用 + /// Option1 = LayerTable | TextStyleTable | DimStyleTable | LinetypeTable | RegAppTable, /// @@ -80,9 +85,14 @@ public enum SymModes : ushort /// 视口表 /// ViewportTable = 256, + /// + /// 坐标|视口|视图 + /// Option2 = UcsTable | ViewTable | ViewportTable, - // 全部 + /// + /// 全部 + /// All = BlockTable | Option1 | Option2 } @@ -159,17 +169,34 @@ public enum PointOnRegionType } - +/// +/// ttf字体枚举 +/// public enum FontTTF { + /// + /// 宋体 + /// [Description("宋体.ttf")] 宋体, + /// + /// 仿宋 + /// [Description("simfang.ttf")] 仿宋, + /// + /// 仿宋GB2312 + /// [Description("FSGB2312.ttf")] 仿宋GB2312, + /// + /// Arial + /// [Description("Arial.ttf")] Arial, + /// + /// Romans + /// [Description("Romans")] Romans } \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs index 44689e7..d5e213e 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs @@ -22,7 +22,7 @@ public static PointOnRegionType PointOnRegion(this IEnumerable pts, Poi if (ptlst.Count < 3) return PointOnRegionType.Error; - var ls2ds = new List(); + List ls2ds = []; foreach (var node in ptlst.GetNodes()) { ls2ds.Add(new LineSegment2d(node.Value, node.Next!.Value)); @@ -74,7 +74,7 @@ public static PointOnRegionType PointOnRegion(this IEnumerable pts, Poi if (ptlst.Count < 3) return PointOnRegionType.Error; - var ls3ds = new List(); + List ls3ds = []; foreach (var node in ptlst.GetNodes()) ls3ds.Add(new LineSegment3d(node.Value, node.Next!.Value)); var cc3d = new CompositeCurve3d(ls3ds.ToArray()); @@ -594,6 +594,9 @@ public static void Draw(this Geometry geometry, params Drawable[] drawables) drawables.ForEach(d => geometry.Draw(d)); } } +/// +/// 向量扩展类 +/// public static class VectorEx { /// @@ -661,7 +664,16 @@ public static double AngleOnPlane(this Vector3d vector, Plane? plane = null) /// public static class PlaneEx { + /// + /// X + /// public static readonly Plane X = new (Point3d.Origin, Vector3d.XAxis); + /// + /// Y + /// public static readonly Plane Y = new (Point3d.Origin, Vector3d.YAxis); + /// + /// Z + /// public static readonly Plane Z = new (Point3d.Origin, Vector3d.ZAxis); } \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigEx.cs index 3b157d2..241277b 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigEx.cs @@ -12,8 +12,14 @@ namespace IFoxCAD.Cad; * 作者: 惊惊⎛⎝◕⏝⏝◕。⎠⎞ ⎛⎝≥⏝⏝0⎠⎞ ⎛⎝⓿⏝⏝⓿。⎠⎞ ⎛⎝≥⏝⏝≤⎠⎞ * 博客: https://www.cnblogs.com/JJBox/p/15650770.html */ - +/// +/// 重绘事件 +/// +/// public delegate void WorldDrawEvent(WorldDraw draw); +/// +/// jig扩展类 +/// public class JigEx : DrawJig, IDisposable { #region 成员 @@ -348,6 +354,9 @@ protected override DynamicDimensionDataCollection GetDynamicDimensionData(double #endregion #region IDisposable接口相关函数 + /// + /// + /// public bool IsDisposed { get; private set; } = false; /// @@ -366,7 +375,10 @@ public void Dispose() { Dispose(false); } - + /// + /// + /// + /// protected virtual void Dispose(bool disposing) { // 不重复释放,并设置已经释放 diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigExTransient.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigExTransient.cs index 868e86f..38ed391 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigExTransient.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigExTransient.cs @@ -54,7 +54,7 @@ public bool Contains(Drawable drawable) /// /// 向瞬态容器中添加对象 /// - /// 图元 + /// 图元 /// 绘图模式 public void Add(Drawable drawable, TransientDrawingMode tdm = TransientDrawingMode.Main) { diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjEx.cs index e81eeaf..2a21c3c 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjEx.cs @@ -13,12 +13,5 @@ public static void Print(this object obj) { Acap.DocumentManager.MdiActiveDocument?.Editor.WriteMessage($"\n{obj}\n"); } - /// - /// 系统的打印 - /// - /// - //public static void PrintLine(this object obj) - //{ - // Console.WriteLine(obj.ToString()); - //} + } \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/PointEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/PointEx.cs index 024580a..87fc6bf 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/PointEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/PointEx.cs @@ -1,5 +1,7 @@ namespace IFoxCAD.Cad; - +/// +/// 点 +/// public static class PointEx { /// diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/RedrawEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/RedrawEx.cs index f58f51d..059b2a6 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/RedrawEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/RedrawEx.cs @@ -1,5 +1,7 @@ namespace IFoxCAD.Cad; - +/// +/// 亮显模式 +/// [Flags] public enum BrightEntity : int { @@ -36,7 +38,9 @@ public enum BrightEntity : int /// MoveZero = 128, } - +/// +/// 刷新模式 +/// [Flags] public enum BrightEditor : int { @@ -61,7 +65,9 @@ public enum BrightEditor : int /// ViewportsIn = 16, } - +/// +/// 重绘扩展 +/// public static class RedrawEx { /// diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SingleKeyWordHook.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SingleKeyWordHook.cs index 6127b08..2c9e969 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SingleKeyWordHook.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SingleKeyWordHook.cs @@ -135,6 +135,10 @@ private void Acap_PreTranslateMessage(object sender, PreTranslateMessageEventArg /// 已经销毁 /// public bool IsDisposed => _isDisposed; + /// + /// + /// + /// protected virtual void Dispose(bool disposing) { if (!_isDisposed) @@ -147,6 +151,9 @@ protected virtual void Dispose(bool disposing) _isDisposed = true; } } + /// + /// + /// public void Dispose() { Dispose(disposing: true); diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Tools.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Tools.cs index b5b8f2c..e270233 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Tools.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Tools.cs @@ -1,7 +1,9 @@ using static IFoxCAD.Basal.Timer; namespace IFoxCAD.Cad; - +/// +/// 工具类 +/// public static class Tools { /// diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/XrefEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/XrefEx.cs index e32e943..09e2104 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/XrefEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/XrefEx.cs @@ -1,10 +1,9 @@ -// #define error_demo - - - -namespace IFoxCAD.Cad; +namespace IFoxCAD.Cad; #region 参照工厂 +/// +/// 参照绑定模式接口 +/// public interface IXrefBindModes { /// @@ -24,15 +23,19 @@ public interface IXrefBindModes /// public void Bind(); } - -public class XrefFactory : IXrefBindModes +/// +/// 参照工厂类 +/// +/// +/// 要处理的参照名称,就处理所有 +public class XrefFactory(DBTrans tr, HashSet? xrefNames = null) : IXrefBindModes { #region 私有字段 - readonly DBTrans _tr; + readonly DBTrans _tr = tr; /// - /// 要处理的参照名称,就处理所有 + /// 要处理的参照名称,就处理所有 /// - readonly HashSet? _xrefNames; + readonly HashSet? _xrefNames = xrefNames; #endregion #region 公开字段 @@ -75,22 +78,14 @@ public class XrefFactory : IXrefBindModes /// 其他项有异常:
///
public SymModes SymModesBind = SymModes.LayerTable; - #endregion - #region 构造 - /// - /// 参照工厂 - /// - /// - /// 要处理的参照名称,就处理所有 - public XrefFactory(DBTrans tr, HashSet? xrefNames = null) - { - _tr = tr; - _xrefNames = xrefNames; - } #endregion + #region 重写 + /// + /// 绑定 + /// public void Bind() { // 此功能有绑定出错的问题 @@ -100,7 +95,9 @@ public void Bind() // 此功能修补了上面缺失 DoubleBind(); } - + /// + /// 分离 + /// public void Detach() { using ObjectIdCollection xrefIds = new(); @@ -108,7 +105,9 @@ public void Detach() foreach (ObjectId id in xrefIds) _tr.Database.DetachXref(id); } - + /// + /// 重载 + /// public void Reload() { using ObjectIdCollection xrefIds = new(); @@ -116,7 +115,9 @@ public void Reload() if (xrefIds.Count > 0) _tr.Database.ReloadXrefs(xrefIds); } - + /// + /// 卸载 + /// public void Unload() { using ObjectIdCollection xrefIds = new(); @@ -345,7 +346,9 @@ void DoubleBind() } - +/// +/// 参照扩展 +/// public static class XrefEx { /// diff --git "a/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchConverter.cs" "b/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchConverter.cs" index 9e16d24..a88b970 100644 --- "a/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchConverter.cs" +++ "b/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchConverter.cs" @@ -315,6 +315,10 @@ public void CreateBoundary(List outEnts) }); } } + /// + /// 创建边界 + /// + /// public List CreateBoundary() { List outEnts = new List(); diff --git "a/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchEx.cs" "b/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchEx.cs" index 8bfd043..6bd4b82 100644 --- "a/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchEx.cs" +++ "b/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchEx.cs" @@ -1,5 +1,7 @@ namespace IFoxCAD.Cad; - +/// +/// 充填扩展类 +/// public static class HatchEx { /// diff --git a/src/CAD/IFox.CAD.Shared/PE/AcadPeInfo.cs b/src/CAD/IFox.CAD.Shared/PE/AcadPeInfo.cs index 3957a68..df72756 100644 --- a/src/CAD/IFox.CAD.Shared/PE/AcadPeInfo.cs +++ b/src/CAD/IFox.CAD.Shared/PE/AcadPeInfo.cs @@ -2,30 +2,60 @@ namespace IFoxCAD.Cad; -// 选择模式 +/// +/// 选择模式 +/// [Flags] public enum AcadPeEnum : byte { + /// + /// AcadExe + /// AcadExe = 1, + /// + /// AccoreDll + /// AccoreDll = 2, + /// + /// Acdb + /// Acdb = 4, + /// + /// ExeAndCore + /// ExeAndCore = AcadExe | AccoreDll, } -// 这里的枚举对应 GetMethodException 错误值 +/// +/// 这里的枚举对应 GetMethodException 错误值 +/// [Flags] public enum GetMethodErrorNum : byte { + /// + /// + /// Ok = 0, + /// + /// + /// NoModule = 1, + /// + /// + /// NoFuncName = 2, } -// 自动获取本工程上面的发送命令的接口 +/// +/// 自动获取本工程上面的发送命令的接口 +/// public class AcadPeInfo { #region 静态单例获取exe/dll信息 static PeInfo? _PeForAcadExe; + /// + /// + /// public static PeInfo? PeForAcadExe { get @@ -41,6 +71,9 @@ public static PeInfo? PeForAcadExe } static PeInfo? _PeForAccoreDll; + /// + /// + /// public static PeInfo? PeForAccoreDll { get @@ -58,6 +91,9 @@ public static PeInfo? PeForAccoreDll } static PeInfo? _PeForAcdbDll; + /// + /// + /// public static PeInfo? PeForAcdbDll { get @@ -136,7 +172,7 @@ public AcadPeInfo(string methodName, AcadPeEnum acadPeEnum) #region 方法 /// - /// 储存旧值<去除修饰函数名(查找的),带修饰函数名们> + /// 储存旧值,去除修饰函数名(查找的),带修饰函数名们 /// static Dictionary> _Dict = new(); @@ -311,20 +347,40 @@ public static void Finds(PeInfo peInfo, /// public class GetPeMethodException : ApplicationException { + /// + /// + /// public int ErrorNum; + /// + /// + /// public string? ErrorMsg; + /// + /// + /// public Exception? InnerException1; - + /// + /// + /// + /// public GetPeMethodException(string msg) : base(msg) { ErrorMsg = msg; } - + /// + /// + /// + /// + /// public GetPeMethodException(int errorNum, string msg) : base(msg) { ErrorNum = errorNum; } - + /// + /// + /// + /// + /// public GetPeMethodException(string msg, Exception innerException) : base(msg, innerException) { InnerException1 = innerException; diff --git a/src/CAD/IFox.CAD.Shared/PE/DBmod.cs b/src/CAD/IFox.CAD.Shared/PE/DBmod.cs index 7502e25..b45a033 100644 --- a/src/CAD/IFox.CAD.Shared/PE/DBmod.cs +++ b/src/CAD/IFox.CAD.Shared/PE/DBmod.cs @@ -8,27 +8,55 @@ [Flags] public enum DBmod : short { - [Description("数据库冇修改")] + /// + /// 数据库未修改 + /// + [Description("数据库未修改")] DatabaseNoModifies = 0, + /// + /// 数据库有修改 + /// [Description("数据库有修改")] Database = 1, + /// + /// 变量有修改 + /// [Description("变量有修改")] Value = 4, + /// + /// 窗口有修改 + /// [Description("窗口有修改")] Window = 8, + /// + /// 视图有修改 + /// [Description("视图有修改")] View = 16, + /// + /// 字段有修改 + /// [Description("字段有修改")] Field = 32 } - +/// +/// 图形修改状态 +/// public class DBmodEx { + /// + /// 图形修改状态 + /// public static DBmod DBmod => (DBmod)Env.GetVar("dbmod"); delegate long DelegateAcdbSetDbmod(IntPtr db, DBmod newValue); static DelegateAcdbSetDbmod? acdbSetDbmod;//别改名称 - + /// + /// 设置图形修改状态 + /// + /// 数据库的指针 + /// 修改状态 + /// public static long AcdbSetDbmod(IntPtr db, DBmod newValue) { acdbSetDbmod ??= AcadPeInfo.GetDelegate( diff --git a/src/CAD/IFox.CAD.Shared/PE/PostCmd.cs b/src/CAD/IFox.CAD.Shared/PE/PostCmd.cs index cd0b39e..7e70074 100644 --- a/src/CAD/IFox.CAD.Shared/PE/PostCmd.cs +++ b/src/CAD/IFox.CAD.Shared/PE/PostCmd.cs @@ -1,5 +1,7 @@ namespace IFoxCAD.Cad; - +/// +/// 发送命令 +/// public class PostCmd { /* @@ -122,14 +124,34 @@ static void AsyncCommand(string args) doc?.GetType() .InvokeMember("SendCommand", BindingFlags.InvokeMethod, null, doc, commandArray);// 返回值是null } - + /// + /// 命令模式 + /// public enum RunCmdFlag : byte { + /// + /// 发送命令(同步)如果2015.+这里报错,那么表示vs需要提权测试 + /// AcedCmd = 1, + /// + /// 发送命令(同步) + /// AcedCommand = 2, + /// + /// 发送命令(同步),可以多线程 + /// AcedPostCommand = 4, + /// + /// 发送命令(同步) + /// AcedInvoke = 8, + /// + /// 默认的发送命令 + /// SendStringToExecute = 16, + /// + /// 异步命令 + /// AsyncCommand = 32, } @@ -137,14 +159,30 @@ public enum RunCmdFlag : byte * 发送命令会记录在命令历史 * 发送lisp的(command "xx")就不会 */ + /// + /// 发送命令 + /// + /// + /// public static PromptStatus SendCommand(ResultBuffer args) { return AcedCmd(args); } + /// + /// 发送命令 + /// + /// + /// public static PromptStatus SendCommand(IntPtr args) { return AcedCommand(args); } + /// + /// 发送命令 + /// + /// + /// + /// public static PromptStatus SendCommand(string args, RunCmdFlag flag) { PromptStatus ret = PromptStatus.OK; diff --git a/src/CAD/IFox.CAD.Shared/PE/ProgramPE.cs b/src/CAD/IFox.CAD.Shared/PE/ProgramPE.cs index e1f834a..32208fc 100644 --- a/src/CAD/IFox.CAD.Shared/PE/ProgramPE.cs +++ b/src/CAD/IFox.CAD.Shared/PE/ProgramPE.cs @@ -1,4 +1,5 @@ -namespace IFoxCAD.Cad; +#pragma warning disable CS1591 // 缺少对公共可见类型或成员的 XML 注释 +namespace IFoxCAD.Cad; using System; using System.Collections; @@ -45,7 +46,9 @@ public class PeInfo /// 获取是否正常打开文件 /// public bool OpenFile { get; private set; } = false; + public DosHeader? DosHeader { get; private set; } + public DosStub? DosStub { get; private set; } public PEHeader? PEHeader { get; private set; } public OptionalHeader? OptionalHeader { get; private set; } @@ -75,6 +78,11 @@ public class PeInfo #endregion #region 构造 + /// + /// 构造函数 + /// + /// + /// public PeInfo(string fullName) { if (fullName is null) @@ -1564,4 +1572,5 @@ public class DataEntry public long FileStarIndex = 0; public long FileEndIndex = 0; } -#endregion \ No newline at end of file +#endregion +#pragma warning restore CS1591 // 缺少对公共可见类型或成员的 XML 注释 \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ResultData/XdataList.cs b/src/CAD/IFox.CAD.Shared/ResultData/XdataList.cs index bd0ff99..157571b 100644 --- a/src/CAD/IFox.CAD.Shared/ResultData/XdataList.cs +++ b/src/CAD/IFox.CAD.Shared/ResultData/XdataList.cs @@ -92,6 +92,7 @@ public List GetXdataAppIndex(string appName, DxfCode[] dxfCodes) /// /// 区间任务 /// + /// /// private void RangeTask(string appName, Action action) { diff --git a/src/CAD/IFox.CAD.Shared/Runtime/IFoxUtils.cs b/src/CAD/IFox.CAD.Shared/Runtime/IFoxUtils.cs index 792f1b3..ad49c3e 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/IFoxUtils.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/IFoxUtils.cs @@ -1,5 +1,7 @@ namespace IFoxCAD.Cad; - +/// +/// ifox工具类 +/// #if acad public sealed class IFoxUtils { @@ -81,7 +83,7 @@ public static void VetoMouseDoubleClickEvent() ///
/// cad特性栏透明度值,范围0-100 /// cad透明度值 - public Transparency CreateTransparency(int value) + public static Transparency CreateTransparency(int value) { return new Transparency(Convert.ToByte(Math.Floor((100 - value) * 2.55))); } diff --git a/tests/TestShared/Copyclip.cs b/tests/TestShared/Copyclip.cs index 52377f9..d4f44a2 100644 --- a/tests/TestShared/Copyclip.cs +++ b/tests/TestShared/Copyclip.cs @@ -406,7 +406,7 @@ void Paste(bool isBlock) } // 获取临时文件的图元id - var fileEntityIds = new List(); + List fileEntityIds = []; using (DBTrans fileTr = new(cadClipType.File, commit: false, fileOpenMode: FileOpenMode.OpenForReadAndAllShare)) { diff --git a/tests/TestShared/TestBlock.cs b/tests/TestShared/TestBlock.cs index 63d305a..fc2fdb2 100644 --- a/tests/TestShared/TestBlock.cs +++ b/tests/TestShared/TestBlock.cs @@ -167,7 +167,7 @@ public void Test_InsertBlockDef() tr.BlockTable.Add("test1", line1, line2, att1, att2); - var ents = new List(); + List ents = []; var line5 = new Line(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); var line6 = new Line(new Point3d(0, 0, 0), new Point3d(-1, 1, 0)); ents.Add(line5); @@ -245,7 +245,7 @@ public void Test_BlockNullBug() { using DBTrans tr = new(); - var ents = new List(); + List ents = []; var line5 = new Line(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); var line6 = new Line(new Point3d(0, 0, 0), new Point3d(-1, 1, 0)); ents.Add(line5); @@ -434,7 +434,7 @@ public void Test_QuickBlockDef2() { // SelectionSet ss = rss.Value; // ObjectId[] ids = ss.GetObjectIds(); - // var ents = new List>(); + // List> ents = []; // var extents = new Extents3d(); // foreach (var id in ids) // { @@ -462,7 +462,7 @@ public void Test_QuickBlockDef2() var extents = ents!.GetExtents(); Point3d pt = extents.MinPoint; Matrix3d matrix = Matrix3d.Displacement(Point3d.Origin - pt); - // var newEnts = new List(); + // List newEnts = []; // foreach (var ent in ents) // { // var newEnt = ent.Key; @@ -705,7 +705,7 @@ public static ObjectIdCollection ExplodeToOwnerSpace3(ObjectId id, bool erase = return ids; } - private static ObjectIdCollection idsAdded; + private static ObjectIdCollection idsAdded = []; public static ObjectIdCollection ExplodeToOwnerSpace3(this BlockReference br) { idsAdded = new ObjectIdCollection(); @@ -720,12 +720,12 @@ public static ObjectIdCollection ExplodeToOwnerSpace3(this BlockReference br) public static void LoopThroughInsertAndAddEntity2n3(Matrix3d mat, BlockReference br, BlockTableRecord space) { Transaction tr = space.Database.TransactionManager.TopTransaction; - BlockTableRecord btr = tr.GetObject(br.BlockTableRecord, OpenMode.ForRead) as BlockTableRecord; + BlockTableRecord btr = (BlockTableRecord)tr.GetObject(br.BlockTableRecord, OpenMode.ForRead); foreach (ObjectId id in btr) { DBObject obj = tr.GetObject(id, OpenMode.ForRead); - Entity ent = obj.Clone() as Entity; + Entity? ent = obj.Clone() as Entity; if (ent is BlockReference) { BlockReference br1 = (BlockReference)ent; @@ -733,11 +733,11 @@ public static void LoopThroughInsertAndAddEntity2n3(Matrix3d mat, BlockReference } else { - ent.TransformBy(mat); + ent?.TransformBy(mat); space.AppendEntity(ent); tr.AddNewlyCreatedDBObject(ent, true); - idsAdded.Add(ent.ObjectId); + idsAdded.Add(ent!.ObjectId); } } } diff --git a/tests/TestShared/TestConvexHull.cs b/tests/TestShared/TestConvexHull.cs index 380bc44..03692ae 100644 --- a/tests/TestShared/TestConvexHull.cs +++ b/tests/TestShared/TestConvexHull.cs @@ -7,7 +7,7 @@ public class TestConvexHull public void Test_ConvexHull() { // using DBTrans tr = new(); - // var pts = new List(); + // List pts = []; // var flag = true; // while (flag) // { diff --git a/tests/TestShared/TestExtents.cs b/tests/TestShared/TestExtents.cs index b4916fe..96c04db 100644 --- a/tests/TestShared/TestExtents.cs +++ b/tests/TestShared/TestExtents.cs @@ -16,26 +16,26 @@ public void Test_BlockExtents() if (block != null && block.Bounds.HasValue) { var extent = block.GeometricExtents; - var pts = new List() { + List pts = [ extent.MinPoint, new Point3d(extent.MinPoint.X,extent.MaxPoint.Y,0), extent.MaxPoint, new Point3d(extent.MaxPoint.X,extent.MinPoint.Y,0), - }; + ]; tr.CurrentSpace.AddEntity(pts.CreatePolyline(action: e => e.ColorIndex = 1)); if (block is BlockReference block1) { var extents = block1.GeometryExtentsBestFit(); - var pts1 = new List() - { + List pts1 = + [ extents.MinPoint, new Point3d(extents.MinPoint.X, extents.MaxPoint.Y, 0), extents.MaxPoint, new Point3d(extents.MaxPoint.X, extents.MinPoint.Y, 0), - }; + ]; tr.CurrentSpace.AddEntity(pts.CreatePolyline(action: e => e.ColorIndex = 2)); var extents2 = block1.GetBoundingBoxEx(); @@ -70,22 +70,27 @@ public void Test_entextents() e.Closed = true; })); var ext = e.GetBoundingBoxEx(); - tr.CurrentSpace.AddEntity(ext?.Extents3d.CreatePolyline(action: e => + if (ext.HasValue) { - e.ColorIndex = 5; - e.Closed = true; - })); + tr.CurrentSpace.AddEntity( + ext.Value.Extents3d.CreatePolyline(action: e => + { + e.ColorIndex = 5; + e.Closed = true; + })); + } + if (e is Curve spline) { var ge = spline.GetGeCurve(); var box = ge.BoundBlock; - var lst = new List() - { + List lst = + [ box.BasePoint, box.BasePoint + box.Direction1, box.BasePoint + box.Direction2, box.BasePoint + box.Direction3, - }; + ]; tr.CurrentSpace.AddEntity(lst.CreatePolyline(action: e => { e.ColorIndex = 6; diff --git a/tests/TestShared/TestJson.cs b/tests/TestShared/TestJson.cs index 9205679..9e48561 100644 --- a/tests/TestShared/TestJson.cs +++ b/tests/TestShared/TestJson.cs @@ -12,7 +12,7 @@ public class TestJson [CommandMethod(nameof(JavaScriptSerializer))] public void JavaScriptSerializer() { - var RegisteredUsers = new List(); + List RegisteredUsers = []; RegisteredUsers.Add(0); RegisteredUsers.Add(1); RegisteredUsers.Add(2); diff --git a/tests/TestShared/TestQuadTree.cs b/tests/TestShared/TestQuadTree.cs index 8dad5cc..1c2e2a8 100644 --- a/tests/TestShared/TestQuadTree.cs +++ b/tests/TestShared/TestQuadTree.cs @@ -171,7 +171,7 @@ public void CmdTest_QuadTree20() var ed = doc.Editor; ed.WriteMessage("\n自动加入全图到四叉树"); - var ss = new List(); + List ss = []; int entnum = 0; var time1 = Timer.RunTime(() => { db.Action(tr => { @@ -300,12 +300,12 @@ public void CmdTest_CreateNodesRect() // 需要把事务放在循环体内部 // 报错: 0x6B00500A (msvcr80.dll)处(位于 acad.exe 中)引发的异常: 0xC0000005: 写入位置 0xFFE00000 时发生访问冲突。 // 画出所有的四叉树节点边界,因为事务放在外面引起 - var nodeRects = new List(); + List nodeRects = []; _quadTreeRoot.ForEach(node => { nodeRects.Add(node); return false; }); - var rectIds = new List(); + List rectIds = []; foreach (var item in nodeRects)// Count = 97341 当数量接近这个量级 { db.Action(tr => { -- Gitee From 8639399656f0e864307af757753864e2cd7a67c4 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Thu, 18 Jan 2024 11:04:44 +0800 Subject: [PATCH 240/453] =?UTF-8?q?=E6=B8=85=E7=90=86=E8=AD=A6=E5=91=8A?= =?UTF-8?q?=EF=BC=8C=E5=8D=87=E7=BA=A7c#12?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../IFox.Basal.Shared/General/DebugHelper.cs | 9 +++---- src/Basal/IFox.Basal.Shared/General/DictEx.cs | 26 +++++++++---------- src/Basal/IFox.Basal.Shared/General/EnumEx.cs | 9 ++++--- .../IFox.Basal.Shared/WindowsAPI/Enums.cs | 6 +++-- src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs | 6 ++--- src/CAD/IFox.CAD.Shared/Runtime/IFoxUtils.cs | 3 ++- .../IFox.CAD.Shared/Runtime/SymbolTable.cs | 18 ++++++------- 7 files changed, 39 insertions(+), 38 deletions(-) diff --git a/src/Basal/IFox.Basal.Shared/General/DebugHelper.cs b/src/Basal/IFox.Basal.Shared/General/DebugHelper.cs index 58ae2fc..ca5ced8 100644 --- a/src/Basal/IFox.Basal.Shared/General/DebugHelper.cs +++ b/src/Basal/IFox.Basal.Shared/General/DebugHelper.cs @@ -1,8 +1,7 @@ -using System.Diagnostics; -using System.Threading; - -namespace IFoxCAD.Basal; - +namespace IFoxCAD.Basal; +/// +/// 调试工具 +/// public static class Debugx { /// diff --git a/src/Basal/IFox.Basal.Shared/General/DictEx.cs b/src/Basal/IFox.Basal.Shared/General/DictEx.cs index 296fb16..73619cf 100644 --- a/src/Basal/IFox.Basal.Shared/General/DictEx.cs +++ b/src/Basal/IFox.Basal.Shared/General/DictEx.cs @@ -1,15 +1,15 @@ namespace IFoxCAD.Basal; -public static class DictEx -{ - // public static TKey? GetKey(this IDictionary dict!!, TKey key!!) - // { - // if (dict.ContainsKey(key)) - // { - // foreach (var item in dict.Keys) - // if (key.Equals(item)) - // return item; - // } - // return default; - // } -} +// public static class DictEx +// { +// // public static TKey? GetKey(this IDictionary dict!!, TKey key!!) +// // { +// // if (dict.ContainsKey(key)) +// // { +// // foreach (var item in dict.Keys) +// // if (key.Equals(item)) +// // return item; +// // } +// // return default; +// // } +// } diff --git a/src/Basal/IFox.Basal.Shared/General/EnumEx.cs b/src/Basal/IFox.Basal.Shared/General/EnumEx.cs index 50ab654..3aca683 100644 --- a/src/Basal/IFox.Basal.Shared/General/EnumEx.cs +++ b/src/Basal/IFox.Basal.Shared/General/EnumEx.cs @@ -1,8 +1,8 @@ namespace IFoxCAD.Basal; -using System.ComponentModel; -using System.Linq; - +/// +/// 枚举扩展 +/// public static class EnumEx { /// @@ -14,12 +14,13 @@ public static void CleanCache() } // (类型完整名,描述组合) - static readonly Dictionary> _cache = new(); + static readonly Dictionary> _cache = []; /// /// 打印枚举的特性注释内容 /// /// 枚举 + /// /// 注释内容 public static HashSet? GetAttribute(this Enum e, bool noDescrToString = true) where T : DescriptionAttribute diff --git a/src/Basal/IFox.Basal.Shared/WindowsAPI/Enums.cs b/src/Basal/IFox.Basal.Shared/WindowsAPI/Enums.cs index ed76fd0..059f92c 100644 --- a/src/Basal/IFox.Basal.Shared/WindowsAPI/Enums.cs +++ b/src/Basal/IFox.Basal.Shared/WindowsAPI/Enums.cs @@ -1,4 +1,5 @@ -#if true +#pragma warning disable CS1591 // 缺少对公共可见类型或成员的 XML 注释 +#if true namespace IFoxCAD.Basal; // https://blog.csdn.net/qq_43812868/article/details/108587936 @@ -1068,4 +1069,5 @@ public enum GetWindowCmd : uint /// GW_ENABLEDPOPUP = 6 } -#endif \ No newline at end of file +#endif +#pragma warning restore CS1591 // 缺少对公共可见类型或成员的 XML 注释 diff --git a/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs b/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs index 3fb4a26..b7617b5 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs @@ -601,8 +601,8 @@ private void Dispose(bool disposing) public override string ToString() { - List lines = new() - { + List lines = + [ $"StackCount = {_dBTrans.Count}", $"_fileName = \"{_fileName}\"", $"_commit = {_commit}", @@ -612,7 +612,7 @@ public override string ToString() $"Editor = {Editor != null}", $"Transaction = {Transaction.UnmanagedObject}", $"Database = {Database.Filename}" - }; + ]; return string.Join("\n", lines.ToArray()); } diff --git a/src/CAD/IFox.CAD.Shared/Runtime/IFoxUtils.cs b/src/CAD/IFox.CAD.Shared/Runtime/IFoxUtils.cs index ad49c3e..e87621b 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/IFoxUtils.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/IFoxUtils.cs @@ -1,8 +1,9 @@ namespace IFoxCAD.Cad; + +#if acad /// /// ifox工具类 /// -#if acad public sealed class IFoxUtils { /// diff --git a/src/CAD/IFox.CAD.Shared/Runtime/SymbolTable.cs b/src/CAD/IFox.CAD.Shared/Runtime/SymbolTable.cs index 450f6f3..7a54e7b 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/SymbolTable.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/SymbolTable.cs @@ -116,17 +116,15 @@ public ObjectId Add(TRecord record) /// 对象id public ObjectId Add(string name, Action? action = null) { - ObjectId id = this[name]; - if (id.IsNull) + var id = this[name]; + if (!id.IsNull) return id; + var record = new TRecord() { - var record = new TRecord() - { - Name = name - }; - id = Add(record); - using (record.ForWrite()) - action?.Invoke(record); - } + Name = name + }; + id = Add(record); + using (record.ForWrite()) + action?.Invoke(record); return id; } #endregion -- Gitee From 65ffffbe8ed446b04553d4053e422dadbb567318 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Thu, 18 Jan 2024 11:07:34 +0800 Subject: [PATCH 241/453] =?UTF-8?q?=E6=B8=85=E7=90=86=E6=97=A0=E7=94=A8?= =?UTF-8?q?=E7=9A=84=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Basal/IFox.Basal.Shared/General/DictEx.cs | 15 ---------- src/Basal/IFox.Basal.Shared/General/ListEx.cs | 30 ------------------- .../IFox.Basal.Shared.projitems | 2 -- 3 files changed, 47 deletions(-) delete mode 100644 src/Basal/IFox.Basal.Shared/General/DictEx.cs delete mode 100644 src/Basal/IFox.Basal.Shared/General/ListEx.cs diff --git a/src/Basal/IFox.Basal.Shared/General/DictEx.cs b/src/Basal/IFox.Basal.Shared/General/DictEx.cs deleted file mode 100644 index 73619cf..0000000 --- a/src/Basal/IFox.Basal.Shared/General/DictEx.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace IFoxCAD.Basal; - -// public static class DictEx -// { -// // public static TKey? GetKey(this IDictionary dict!!, TKey key!!) -// // { -// // if (dict.ContainsKey(key)) -// // { -// // foreach (var item in dict.Keys) -// // if (key.Equals(item)) -// // return item; -// // } -// // return default; -// // } -// } diff --git a/src/Basal/IFox.Basal.Shared/General/ListEx.cs b/src/Basal/IFox.Basal.Shared/General/ListEx.cs deleted file mode 100644 index 528b6ad..0000000 --- a/src/Basal/IFox.Basal.Shared/General/ListEx.cs +++ /dev/null @@ -1,30 +0,0 @@ -namespace IFoxCAD.Basal; - - -public static class ListEx -{ - public static bool EqualsAll(this IList a, IList b) - { - return EqualsAll(a, b, null); - // there is a slight performance gain in passing null here. - // It is how it is done in other parts of the framework. - } - - public static bool EqualsAll(this IList a, IList b, IEqualityComparer? comparer) - { - if (a is null) - return b is null; - else if (b is null) - return false; - - if (a.Count != b.Count) - return false; - - comparer ??= EqualityComparer.Default; - - for (int i = 0; i < a.Count; i++) - if (!comparer.Equals(a[i], b[i])) - return false; - return true; - } -} diff --git a/src/Basal/IFox.Basal.Shared/IFox.Basal.Shared.projitems b/src/Basal/IFox.Basal.Shared/IFox.Basal.Shared.projitems index abd241c..52307b1 100644 --- a/src/Basal/IFox.Basal.Shared/IFox.Basal.Shared.projitems +++ b/src/Basal/IFox.Basal.Shared/IFox.Basal.Shared.projitems @@ -18,13 +18,11 @@ - - -- Gitee From 65b1cf820791741b6c761cd1713436aea5175412 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Thu, 18 Jan 2024 16:27:17 +0800 Subject: [PATCH 242/453] =?UTF-8?q?=E6=B8=85=E7=90=86=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExpressionTrees/ParameterRebinder.cs | 39 ++- .../ExpressionTrees/PredicateBuilder.cs | 59 ++--- .../ExpressionTrees/SqlExpressionVisitor.cs | 200 +++++++-------- .../IFox.Basal.Shared/General/ArrayEx.cs | 6 +- .../IFox.Basal.Shared/General/DebugHelper.cs | 8 +- src/Basal/IFox.Basal.Shared/General/EnumEx.cs | 47 ++-- .../General/LinkedHashMap.cs | 90 +++---- .../General/LinkedHashSet.cs | 82 +++---- src/Basal/IFox.Basal.Shared/General/LinqEx.cs | 170 ++++++------- .../IFox.Basal.Shared/General/LoopList.cs | 81 +++--- .../IFox.Basal.Shared/General/LoopState.cs | 81 +++--- .../IFox.Basal.Shared/General/RandomEx.cs | 13 +- src/Basal/IFox.Basal.Shared/General/Timer.cs | 44 ++-- .../IFox.Basal.Shared/WindowsAPI/MouseHook.cs | 4 +- .../WindowsAPI/WindowsAPI.cs | 7 +- .../IFox.CAD.Shared/Algorithms/Graph/Graph.cs | 232 +++++++----------- .../Algorithms/Graph/IGraph.cs | 4 +- src/CAD/IFox.CAD.Shared/AutoReg/IAutoGo.cs | 2 +- .../Copyclip/TagClipboardInfo.cs | 2 +- .../IFox.CAD.Shared/SelectionFilter/OpList.cs | 37 ++- ...53\345\205\205\344\272\213\344\273\266.cs" | 28 +-- tests/TestShared/Copyclip.cs | 4 +- tests/TestShared/TestMarshal.cs | 6 +- tests/TestShared/TestPoint.cs | 6 +- 24 files changed, 564 insertions(+), 688 deletions(-) diff --git a/src/Basal/IFox.Basal.Shared/ExpressionTrees/ParameterRebinder.cs b/src/Basal/IFox.Basal.Shared/ExpressionTrees/ParameterRebinder.cs index b0098bc..217b375 100644 --- a/src/Basal/IFox.Basal.Shared/ExpressionTrees/ParameterRebinder.cs +++ b/src/Basal/IFox.Basal.Shared/ExpressionTrees/ParameterRebinder.cs @@ -1,35 +1,29 @@ -#if NET45_OR_GREATER -namespace IFoxCAD.Basal; +namespace IFoxCAD.Basal; /// -/// ذ +/// 参数重绑定 /// -public class ParameterRebinder : SqlExpressionVisitor +/// +/// 参数重绑定 +/// +/// 字典 +public class ParameterRebinder(Dictionary map) : SqlExpressionVisitor { - private readonly Dictionary map; /// - /// ذ + /// 替换参数 /// - /// ֵ - public ParameterRebinder(Dictionary map) - { - this.map = map ?? new Dictionary(); - } - /// - /// 滻 - /// - /// ֵ - /// ʽ - /// ʽ - public static Expression? ReplaceParameters(Dictionary map, Expression expression) + /// 字典 + /// 表达式 + /// 表达式 + public static Expression ReplaceParameters(Dictionary map, Expression expression) { return new ParameterRebinder(map).Visit(expression); } /// - /// ʲ + /// 访问参数 /// - /// ʽ - /// ʽ + /// 参数表达式 + /// 表达式 protected override Expression VisitParameter(ParameterExpression expression) { if (map.TryGetValue(expression, out var parameterExpression)) @@ -37,5 +31,4 @@ protected override Expression VisitParameter(ParameterExpression expression) return base.VisitParameter(expression); } -} -#endif \ No newline at end of file +} \ No newline at end of file diff --git a/src/Basal/IFox.Basal.Shared/ExpressionTrees/PredicateBuilder.cs b/src/Basal/IFox.Basal.Shared/ExpressionTrees/PredicateBuilder.cs index 11ae2d3..a0c7ac0 100644 --- a/src/Basal/IFox.Basal.Shared/ExpressionTrees/PredicateBuilder.cs +++ b/src/Basal/IFox.Basal.Shared/ExpressionTrees/PredicateBuilder.cs @@ -1,67 +1,67 @@ - + #if NET45_OR_GREATER namespace IFoxCAD.Basal; /// -/// Predicateίй +/// Predicate委托构造器 /// public static class PredicateBuilder { /// - /// ίбʽ + /// 返回真的委托表达式 /// - /// ķ - /// + /// 传入参数的泛型 + /// public static Expression> True() { return param => true; } /// - /// ؼٵίбʽ + /// 返回假的委托表达式 /// - /// ķ - /// + /// 传入参数的泛型 + /// public static Expression> False() { return param => false; } /// - /// predicateί + /// 创建predicate委托 /// - /// - /// ίбʽ - /// ίбʽ + /// 传入参数类型 + /// 委托表达式 + /// 委托表达式 public static Expression> Create(Expression> predicate) { return predicate; } /// - /// ʾıʽ + /// 表示并的表达式 /// - /// - /// һ - /// ڶ - /// ʽ + /// 传入参数类型 + /// 第一个参数 + /// 第二个 + /// 表达式 public static Expression> And(this Expression> first, Expression> second) { return first.Compose(second, Expression.AndAlso); } /// - /// ʾıʽ + /// 表示或的表达式 /// - /// - /// һ - /// ڶ - /// ʽ + /// 传入参数类型 + /// 第一个参数 + /// 第二个 + /// 表达式 public static Expression> Or(this Expression> first, Expression> second) { return first.Compose(second, Expression.OrElse); } /// - /// Ƿıʽ + /// 表是否的表达式 /// - /// - /// ʽ - /// ʽ + /// 传入参数类型 + /// 表达式 + /// 表达式 public static Expression> Not(this Expression> expression) { return Expression.Lambda>(Expression.Not(expression.Body), expression.Parameters); @@ -71,12 +71,7 @@ private static Expression Compose(this Expression first, Expression { var map = first.Parameters.Select((f, i) => new{f,s = second.Parameters[i]}).ToDictionary(p => p.s, p => p.f); var expression = ParameterRebinder.ReplaceParameters(map, second.Body); - if (expression != null) - { - return Expression.Lambda(merge(first.Body, expression), first.Parameters); - } - return first; - + return Expression.Lambda(merge(first.Body, expression), first.Parameters); } } diff --git a/src/Basal/IFox.Basal.Shared/ExpressionTrees/SqlExpressionVisitor.cs b/src/Basal/IFox.Basal.Shared/ExpressionTrees/SqlExpressionVisitor.cs index 1fb88be..8d61105 100644 --- a/src/Basal/IFox.Basal.Shared/ExpressionTrees/SqlExpressionVisitor.cs +++ b/src/Basal/IFox.Basal.Shared/ExpressionTrees/SqlExpressionVisitor.cs @@ -1,23 +1,18 @@ -#if NET45_OR_GREATER - -namespace IFoxCAD.Basal; +namespace IFoxCAD.Basal; /// -/// sqlʽ +/// sql表达式访问者类 /// public abstract class SqlExpressionVisitor { /// - /// + /// 访问 /// - /// ʽ - /// ʽ + /// 表达式 + /// 表达式 /// - protected virtual Expression? Visit(Expression expression) + protected virtual Expression Visit(Expression expression) { - if (expression is null) - return null; - return expression.NodeType switch { ExpressionType.Add => VisitBinary((BinaryExpression)expression), @@ -68,10 +63,10 @@ public abstract class SqlExpressionVisitor }; } /// - /// ߰ + /// 访问者绑定 /// - /// 󶨵 - /// 󶨵 + /// 绑定的类 + /// 绑定的类 /// protected virtual MemberBinding VisitBinding(MemberBinding binding) { @@ -84,10 +79,10 @@ protected virtual MemberBinding VisitBinding(MemberBinding binding) }; } /// - /// ʼϳʼ趨 + /// 访问集合初始设定项 /// - /// ϳʼ趨 - /// ϳʼ趨 + /// 集合初始设定项 + /// 集合初始设定项 protected virtual ElementInit VisitElementInitializer(ElementInit initializer) { var arguments = VisitExpressionList(initializer.Arguments); @@ -98,43 +93,39 @@ protected virtual ElementInit VisitElementInitializer(ElementInit initializer) return initializer; } /// - /// һԪ + /// 访问一元运算符 /// - /// һԪ - /// ʽ + /// 一元运算符 + /// 表达式 protected virtual Expression VisitUnary(UnaryExpression unary) { var operand = Visit(unary.Operand); - if (operand != unary.Operand) - return Expression.MakeUnary(unary.NodeType, operand, unary.Type, unary.Method); - - return unary; + return operand != unary.Operand ? Expression.MakeUnary(unary.NodeType, operand, unary.Type, unary.Method) : unary; } /// - /// ʶ + /// 访问二进制运算符 /// - /// - /// ʽ + /// 二进制运算符 + /// 表达式 protected virtual Expression VisitBinary(BinaryExpression binary) { var left = Visit(binary.Left); var right = Visit(binary.Right); - var conversion = Visit(binary.Conversion); + var conversion = Visit(binary.Conversion!); if (left == binary.Left && right == binary.Right && conversion == binary.Conversion) return binary; - if (binary.NodeType == ExpressionType.Coalesce && binary.Conversion != null) - return Expression.Coalesce(left, right, conversion as LambdaExpression); - - return Expression.MakeBinary(binary.NodeType, left, right, binary.IsLiftedToNull, binary.Method); + return binary is { NodeType: ExpressionType.Coalesce, Conversion: not null } + ? Expression.Coalesce(left, right, conversion as LambdaExpression) + : Expression.MakeBinary(binary.NodeType, left, right, binary.IsLiftedToNull, binary.Method); } /// - /// + /// 访问类型 /// - /// - /// ʽ + /// 类型 + /// 表达式 protected virtual Expression VisitTypeIs(TypeBinaryExpression typeBinary) { var expression = Visit(typeBinary.Expression); @@ -145,19 +136,19 @@ protected virtual Expression VisitTypeIs(TypeBinaryExpression typeBinary) return typeBinary; } /// - /// ʳֵ + /// 访问常数值 /// - /// ֵ - /// ʽ + /// 常数值 + /// 表达式 protected virtual Expression VisitConstant(ConstantExpression constant) { return constant; } /// - /// + /// 访问条件运算符 /// - /// - /// ʽ + /// 条件运算符 + /// 表达式 protected virtual Expression VisitConditional(ConditionalExpression conditional) { var test = Visit(conditional.Test); @@ -176,19 +167,19 @@ protected virtual Expression VisitConditional(ConditionalExpression conditional) return conditional; } /// - /// ʲ + /// 访问参数 /// - /// - /// ʽ + /// 参数 + /// 表达式 protected virtual Expression VisitParameter(ParameterExpression parameter) { return parameter; } /// - /// ʳԱ + /// 访问成员 /// - /// Ա - /// ʽ + /// 成员 + /// 表达式 protected virtual Expression VisitMemberAccess(MemberExpression member) { var expression = Visit(member.Expression); @@ -199,13 +190,13 @@ protected virtual Expression VisitMemberAccess(MemberExpression member) return member; } /// - /// ʷ + /// 访问方法调用 /// - /// - /// ʽ + /// 方法调用 + /// 表达式 protected virtual Expression VisitMethodCall(MethodCallExpression methodCall) { - var instance = Visit(methodCall.Object); + var instance = Visit(methodCall.Object!); var arguments = (IEnumerable)VisitExpressionList(methodCall.Arguments); if (instance != methodCall.Object || !Equals(arguments, methodCall.Arguments)) @@ -214,10 +205,10 @@ protected virtual Expression VisitMethodCall(MethodCallExpression methodCall) return methodCall; } /// - /// ʱʽ + /// 访问表达式集合 /// - /// ʽ - /// ʽֻ + /// 表达式集合 + /// 表达式只读集合 protected virtual ReadOnlyCollection VisitExpressionList(ReadOnlyCollection original) { var index1 = 0; @@ -226,32 +217,29 @@ protected virtual ReadOnlyCollection VisitExpressionList(ReadOnlyCol for (var count = original.Count; index1 < count; ++index1) { var expression = Visit(original[index1]); - if (expression != null) + if (expressions != null) { - if (expressions != null) - { - expressions.Add(expression); - } + expressions.Add(expression); + } - else if (expression != original[index1]) - { - expressions = new List(count); + else if (expression != original[index1]) + { + expressions = new List(count); - for (var index2 = 0; index2 < index1; ++index2) - expressions.Add(original[index2]); + for (var index2 = 0; index2 < index1; ++index2) + expressions.Add(original[index2]); - expressions.Add(expression); - } + expressions.Add(expression); } - + } return expressions != null ? expressions.AsReadOnly() : original; } /// - /// ʳԱֵ + /// 访问成员赋值 /// - /// Աֵ + /// 成员赋值 /// protected virtual MemberAssignment VisitMemberAssignment(MemberAssignment assignment) { @@ -263,10 +251,10 @@ protected virtual MemberAssignment VisitMemberAssignment(MemberAssignment assign return assignment; } /// - /// ¶ԱijԱ + /// 访问新对象成员的成员 /// - /// ¶ԱijԱ - /// ¶ԱijԱ + /// 新对象成员的成员 + /// 新对象成员的成员 protected virtual MemberMemberBinding VisitMemberMemberBinding(MemberMemberBinding binding) { var bindings = VisitBindingList(binding.Bindings); @@ -277,10 +265,10 @@ protected virtual MemberMemberBinding VisitMemberMemberBinding(MemberMemberBindi return binding; } /// - /// ʳԱʼ + /// 访问成员初始化 /// - /// Աʼ - /// Աʼ + /// 成员初始化 + /// 成员初始化 protected virtual MemberListBinding VisitMemberListBinding(MemberListBinding binding) { var initializers = VisitElementInitializerList(binding.Initializers); @@ -291,10 +279,10 @@ protected virtual MemberListBinding VisitMemberListBinding(MemberListBinding bin return binding; } /// - /// ʳԱʼб + /// 访问成员初始化列表 /// - /// Աʼб - /// Աʼб + /// 成员初始化列表 + /// 成员初始化列表 protected virtual IEnumerable VisitBindingList(ReadOnlyCollection original) { var index1 = 0; @@ -320,13 +308,13 @@ protected virtual IEnumerable VisitBindingList(ReadOnlyCollection } } - return (IEnumerable)bindings! ?? original; + return bindings!; } /// - /// ʼ趨 + /// 访问集合设定项集合 /// - /// 趨 - /// 趨 + /// 集合设定项集合 + /// 集合设定项集合 protected virtual IEnumerable VisitElementInitializerList(ReadOnlyCollection original) { var index1 = 0; @@ -352,13 +340,13 @@ protected virtual IEnumerable VisitElementInitializerList(ReadOnlyC } } - return (IEnumerable)initializers! ?? original; + return initializers!; } /// - /// lambdaʽ + /// 访问lambda表达式 /// - /// lambdaʽ - /// ʽ + /// lambda表达式 + /// 表达式 protected virtual Expression VisitLambda(LambdaExpression lambda) { var body = Visit(lambda.Body); @@ -369,10 +357,10 @@ protected virtual Expression VisitLambda(LambdaExpression lambda) return lambda; } /// - /// ʹ캯 + /// 访问构造函数 /// - /// 캯 - /// + /// 构造函数 + /// 构造函数 protected virtual NewExpression VisitNew(NewExpression expression) { var arguments = VisitExpressionList(expression.Arguments); @@ -386,10 +374,10 @@ protected virtual NewExpression VisitNew(NewExpression expression) return Expression.New(expression.Constructor, arguments); } /// - /// ʳԱʼ + /// 访问成员初始化 /// - /// Աʼ - /// ʽ + /// 成员初始化 + /// 表达式 protected virtual Expression VisitMemberInit(MemberInitExpression memberInit) { var expression = VisitNew(memberInit.NewExpression); @@ -401,10 +389,10 @@ protected virtual Expression VisitMemberInit(MemberInitExpression memberInit) return memberInit; } /// - /// ʼϳʼ + /// 访问集合初始化 /// - /// ϳʼ - /// ʽ + /// 集合初始化 + /// 表达式 protected virtual Expression VisitListInit(ListInitExpression listInit) { var expression = VisitNew(listInit.NewExpression); @@ -416,10 +404,10 @@ protected virtual Expression VisitListInit(ListInitExpression listInit) return listInit; } /// - /// + /// 访问新数组 /// - /// - /// ʽ + /// 新数组 + /// 表达式 protected virtual Expression VisitNewArray(NewArrayExpression newArray) { var expressions = VisitExpressionList(newArray.Expressions); @@ -427,16 +415,15 @@ protected virtual Expression VisitNewArray(NewArrayExpression newArray) if (Equals(expressions, newArray.Expressions)) return newArray; - if (newArray.NodeType == ExpressionType.NewArrayInit) - return Expression.NewArrayInit(newArray.Type.GetElementType(), expressions); - - return Expression.NewArrayBounds(newArray.Type.GetElementType(), expressions); + return newArray.NodeType == ExpressionType.NewArrayInit + ? Expression.NewArrayInit(newArray.Type.GetElementType()!, expressions) + : Expression.NewArrayBounds(newArray.Type.GetElementType()!, expressions); } /// - /// ίеñʽ + /// 访问委托调用表达式 /// - /// ίеñʽ - /// ʽ + /// 委托调用表达式 + /// 表达式 protected virtual Expression VisitInvocation(InvocationExpression invocation) { var arguments = VisitExpressionList(invocation.Arguments); @@ -447,5 +434,4 @@ protected virtual Expression VisitInvocation(InvocationExpression invocation) return invocation; } -} -#endif \ No newline at end of file +} \ No newline at end of file diff --git a/src/Basal/IFox.Basal.Shared/General/ArrayEx.cs b/src/Basal/IFox.Basal.Shared/General/ArrayEx.cs index 5b0e2cd..36bf8e7 100644 --- a/src/Basal/IFox.Basal.Shared/General/ArrayEx.cs +++ b/src/Basal/IFox.Basal.Shared/General/ArrayEx.cs @@ -40,14 +40,14 @@ public static T[] Combine2(this T[] a, T[] b) /// 传出参数2:数组结尾
/// 返回值比较结尾为就移除
/// - [System.Diagnostics.DebuggerStepThrough] + [DebuggerStepThrough] public static void Deduplication(List lst, Func func) { // 头和尾比较,满足条件移除尾巴 - for (int i = 0; i < lst.Count; i++) + for (var i = 0; i < lst.Count; i++) { var first = lst[i]; - for (int j = lst.Count - 1; j > i/*符号是 >= 而且是i*/; j--) + for (var j = lst.Count - 1; j > i/*符号是 >= 而且是i*/; j--) { var last = lst[j]; if (func(first, last)) diff --git a/src/Basal/IFox.Basal.Shared/General/DebugHelper.cs b/src/Basal/IFox.Basal.Shared/General/DebugHelper.cs index ca5ced8..b956094 100644 --- a/src/Basal/IFox.Basal.Shared/General/DebugHelper.cs +++ b/src/Basal/IFox.Basal.Shared/General/DebugHelper.cs @@ -2,7 +2,7 @@ /// /// 调试工具 /// -public static class Debugx +public static class DebugEx { /// /// cad命令切换: Debugx @@ -13,17 +13,17 @@ public static class Debugx public static void Printl(object message, bool time = true) { var flag = Environment.GetEnvironmentVariable("debugx", EnvironmentVariableTarget.User); - if (flag == null || flag == "0") + if (flag is null or "0") return; if (time) //message = $"{DateTime.Now.ToLongDateString() + DateTime.Now.TimeOfDay}\n" + - message = $"{DateTime.Now.TimeOfDay} ThreadId:{Thread.CurrentThread.ManagedThreadId}\n" + + message = $"{DateTime.Now.TimeOfDay} ThreadId:{Environment.CurrentManagedThreadId}\n" + $"\t\t{message}"; //System.Diagnostics.Debug.Indent(); #if DEBUG - System.Diagnostics.Debug.WriteLine(message); + Debug.WriteLine(message); #else System.Diagnostics.Trace.WriteLine(message); #endif diff --git a/src/Basal/IFox.Basal.Shared/General/EnumEx.cs b/src/Basal/IFox.Basal.Shared/General/EnumEx.cs index 3aca683..158c5bd 100644 --- a/src/Basal/IFox.Basal.Shared/General/EnumEx.cs +++ b/src/Basal/IFox.Basal.Shared/General/EnumEx.cs @@ -10,11 +10,11 @@ public static class EnumEx /// public static void CleanCache() { - _cache.Clear(); + Cache.Clear(); } // (类型完整名,描述组合) - static readonly Dictionary> _cache = []; + private static readonly Dictionary> Cache = []; /// /// 打印枚举的特性注释内容 @@ -26,10 +26,10 @@ public static void CleanCache() where T : DescriptionAttribute { var eType = e.GetType(); - string eFullName = eType.FullName + "." + e.ToString(); + var eFullName = eType.FullName + "." + e; - if (_cache.ContainsKey(eFullName)) - return _cache[eFullName]; + if (Cache.TryGetValue(eFullName, out var attribute1)) + return attribute1; var fieldInfo = eType.GetField(Enum.GetName(eType, e)); if (fieldInfo == null) @@ -40,30 +40,26 @@ public static void CleanCache() if (Attribute.GetCustomAttribute(fieldInfo, typeof(T)) is T attribute) { nodes.Add(attribute.Description); - _cache.Add(eFullName, nodes); + Cache.Add(eFullName, nodes); return nodes; } // 通常到这里的就是 ALL = A | B | C // 遍历所有的枚举,组合每个注释 - List enumHas = new(); + List enumHas = []; + enumHas.AddRange(Enum.GetValues(eType).Cast().Where(em => + (e.GetHashCode() & em.GetHashCode()) == em.GetHashCode() && e.GetHashCode() != em.GetHashCode())); // 遍历这个枚举类型,获取枚举按位包含的成员 - foreach (Enum em in Enum.GetValues(eType)) - if ((e.GetHashCode() & em.GetHashCode()) == em.GetHashCode() && - e.GetHashCode() != em.GetHashCode()) - enumHas.Add(em); // 采取的行为是:注释的行为是特殊的,就按照注释的,否则,遍历子元素提取注释 // 大的在前面才能判断是否按位包含后面的,后面的就是要移除的 - enumHas = enumHas.OrderByDescending(a => a.GetHashCode()).ToList(); - ArrayEx.Deduplication(enumHas, (a, b) => { - return (a.GetHashCode() & b.GetHashCode()) == b.GetHashCode(); - }); + enumHas = [.. enumHas.OrderByDescending(a => a.GetHashCode())]; + ArrayEx.Deduplication(enumHas, (a, b) => (a.GetHashCode() & b.GetHashCode()) == b.GetHashCode()); // 逆序仅仅为排序后处理,不一定和书写顺序一样,尤其是递归可能存在重复的元素 - for (int i = enumHas.Count - 1; i >= 0; i--) + for (var i = enumHas.Count - 1; i >= 0; i--) { var atts = GetAttribute(enumHas[i], noDescrToString);// 递归 if (atts == null) @@ -75,7 +71,7 @@ public static void CleanCache() if (nodes.Count == 0 && noDescrToString) nodes.Add(e.ToString()); - _cache.Add(eFullName, nodes); + Cache.Add(eFullName, nodes); return nodes; } @@ -85,12 +81,15 @@ public static void CleanCache() public static string? PrintNote(this Enum e, bool noDescToString = true) { var hash = GetAttribute(e, noDescToString); - if (hash != null) - return string.Join("|", hash.ToArray()); - return null; + return hash == null ? null : string.Join("|", [.. hash]); } - - // 不按位运算的情况下,直接获取比较快捷 + + /// + /// 获取枚举的描述内容 + /// + /// 不按位运算的情况下,直接获取比较快捷 + /// + /// public static string GetDesc(this Enum e) { return GetDesc(e.GetType(), e.ToString()); @@ -107,8 +106,6 @@ public static string GetDesc(this Type type, string field) var memberInfo = type.GetMember(field); var attributes = memberInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false); // 如果没有定义描述,就把当前枚举值的对应名称返回 - if (attributes is null || attributes.Length != 1) - return field; - return ((DescriptionAttribute)attributes.Single()).Description; + return attributes.Length != 1 ? field : ((DescriptionAttribute)attributes.Single()).Description; } } \ No newline at end of file diff --git a/src/Basal/IFox.Basal.Shared/General/LinkedHashMap.cs b/src/Basal/IFox.Basal.Shared/General/LinkedHashMap.cs index 0e6232c..2cbfd43 100644 --- a/src/Basal/IFox.Basal.Shared/General/LinkedHashMap.cs +++ b/src/Basal/IFox.Basal.Shared/General/LinkedHashMap.cs @@ -14,34 +14,26 @@ /// Derived from https://stackoverflow.com/a/3719378/240845 /// https://stackoverflow.com/users/240845/mheyman /// -public class LinkedHashMap +/// +/// Initializes a new instance of the +/// class. +/// +/// +/// Maximum number of elements to cache. +/// +/// +/// When elements cycle out of the cache, disposes them. May be null. +/// +public class LinkedHashMap(int capacity, Action? dispose = null) { - private readonly Dictionary> cacheMap = new(); + private readonly Dictionary> _cacheMap = []; - private readonly LinkedList lruList = new(); - - private readonly Action? dispose; - - /// - /// Initializes a new instance of the - /// class. - /// - /// - /// Maximum number of elements to cache. - /// - /// - /// When elements cycle out of the cache, disposes them. May be null. - /// - public LinkedHashMap(int capacity, Action? dispose = null) - { - this.Capacity = capacity; - this.dispose = dispose; - } + private readonly LinkedList _lruList = []; /// /// Gets the capacity of the cache. /// - public int Capacity { get; } + public int Capacity { get; } = capacity; /// Gets the value associated with the specified key. /// @@ -59,13 +51,13 @@ public LinkedHashMap(int capacity, Action? dispose = null) /// public bool TryGetValue(TKey key, out TValue? value) { - lock (this.cacheMap) + lock (_cacheMap) { - if (this.cacheMap.TryGetValue(key, out LinkedListNode.MapItem> node)) + if (_cacheMap.TryGetValue(key, out var node)) { value = node.Value.Value; - this.lruList.Remove(node); - this.lruList.AddLast(node); + _lruList.Remove(node); + _lruList.AddLast(node); return true; } @@ -90,27 +82,27 @@ public bool TryGetValue(TKey key, out TValue? value) /// public TValue Get(TKey key, Func valueGenerator) { - lock (this.cacheMap) + lock (_cacheMap) { TValue value; - if (this.cacheMap.TryGetValue(key, out LinkedListNode.MapItem> node)) + if (_cacheMap.TryGetValue(key, out var node)) { value = node.Value.Value; - this.lruList.Remove(node); - this.lruList.AddLast(node); + _lruList.Remove(node); + _lruList.AddLast(node); } else { value = valueGenerator(); - if (this.cacheMap.Count >= this.Capacity) + if (_cacheMap.Count >= Capacity) { - this.RemoveFirst(); + RemoveFirst(); } MapItem cacheItem = new(key, value); node = new LinkedListNode(cacheItem); - this.lruList.AddLast(node); - this.cacheMap.Add(key, node); + _lruList.AddLast(node); + _cacheMap.Add(key, node); } return value; @@ -128,44 +120,38 @@ public TValue Get(TKey key, Func valueGenerator) /// public void Add(TKey key, TValue value) { - lock (this.cacheMap) + lock (_cacheMap) { - if (this.cacheMap.Count >= this.Capacity) + if (_cacheMap.Count >= Capacity) { - this.RemoveFirst(); + RemoveFirst(); } MapItem cacheItem = new(key, value); LinkedListNode node = new(cacheItem); - this.lruList.AddLast(node); - this.cacheMap.Add(key, node); + _lruList.AddLast(node); + _cacheMap.Add(key, node); } } private void RemoveFirst() { // Remove from LRUPriority - LinkedListNode node = this.lruList.First; - this.lruList.RemoveFirst(); + var node = _lruList.First; + _lruList.RemoveFirst(); // Remove from cache - this.cacheMap.Remove(node.Value.Key); + _cacheMap.Remove(node.Value.Key); // dispose - this.dispose?.Invoke(node.Value.Value); + dispose?.Invoke(node.Value.Value); } - private class MapItem + private class MapItem(TKey k, TValue v) { - public MapItem(TKey k, TValue v) - { - this.Key = k; - this.Value = v; - } - - public TKey Key { get; } + public TKey Key { get; } = k; - public TValue Value { get; } + public TValue Value { get; } = v; } } diff --git a/src/Basal/IFox.Basal.Shared/General/LinkedHashSet.cs b/src/Basal/IFox.Basal.Shared/General/LinkedHashSet.cs index 6efaa04..a4ad211 100644 --- a/src/Basal/IFox.Basal.Shared/General/LinkedHashSet.cs +++ b/src/Basal/IFox.Basal.Shared/General/LinkedHashSet.cs @@ -1,28 +1,22 @@ namespace IFoxCAD.Basal; - -public class LinkedHashSet : ICollection where T : IComparable +#pragma warning disable CS1591 // 缺少对公共可见类型或成员的 XML 注释 +public sealed class LinkedHashSet : ICollection where T : IComparable { - private readonly IDictionary> m_Dictionary; - private readonly LoopList m_LinkedList; - - public LinkedHashSet() - { - m_Dictionary = new Dictionary>(); - m_LinkedList = new LoopList(); - } + private readonly IDictionary> _mDictionary = new Dictionary>(); + private readonly LoopList _mLinkedList = []; - public LoopListNode? First => m_LinkedList.First; + public LoopListNode? First => _mLinkedList.First; - public LoopListNode? Last => m_LinkedList.Last; + public LoopListNode? Last => _mLinkedList.Last; - public LoopListNode? MinNode { get; set; } + public LoopListNode? MinNode { get; private set; } public bool Add(T item) { - if (m_Dictionary.ContainsKey(item)) + if (_mDictionary.ContainsKey(item)) return false; - var node = m_LinkedList.AddLast(item); - m_Dictionary.Add(item, node); + var node = _mLinkedList.AddLast(item); + _mDictionary.Add(item, node); if (MinNode is null) { @@ -48,12 +42,12 @@ void ICollection.Add(T item) public LoopListNode AddFirst(T value) { - if (m_Dictionary.ContainsKey(value)) + if (_mDictionary.TryGetValue(value, out var first)) { - return m_Dictionary[value]; + return first; } - var node = m_LinkedList.AddFirst(value); - m_Dictionary.Add(value, node); + var node = _mLinkedList.AddFirst(value); + _mDictionary.Add(value, node); if (MinNode is null) { MinNode = node; @@ -79,31 +73,27 @@ public void AddRange(IEnumerable collection) public void Clear() { - m_LinkedList.Clear(); - m_Dictionary.Clear(); + _mLinkedList.Clear(); + _mDictionary.Clear(); } public bool Remove(T item) { - bool found = m_Dictionary.TryGetValue(item, out LoopListNode node); + var found = _mDictionary.TryGetValue(item, out var node); if (!found) return false; - m_Dictionary.Remove(item); - m_LinkedList.Remove(node); + _mDictionary.Remove(item); + _mLinkedList.Remove(node!); return true; } - public int Count - { - get { return m_Dictionary.Count; } - } + public int Count => _mDictionary.Count; public void For(LoopListNode from, Action action) { var first = from; var last = from; - if (first is null) return; - for (int i = 0; i < Count; i++) + for (var i = 0; i < Count; i++) { action.Invoke(i, first!.Value, last!.Value); first = first.Next; @@ -113,16 +103,16 @@ public void For(LoopListNode from, Action action) public List ToList() { - return m_LinkedList.ToList(); + return [.. _mLinkedList]; } - [System.Diagnostics.DebuggerStepThrough] + [DebuggerStepThrough] public IEnumerator GetEnumerator() { - return m_LinkedList.GetEnumerator(); + return _mLinkedList.GetEnumerator(); } - [System.Diagnostics.DebuggerStepThrough] + [DebuggerStepThrough] IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); @@ -131,38 +121,35 @@ IEnumerator IEnumerable.GetEnumerator() public bool Contains(T item) { - return m_Dictionary.ContainsKey(item); + return _mDictionary.ContainsKey(item); } public void CopyTo(T[] array, int arrayIndex) { // m_LinkedList.CopyTo(array, arrayIndex); - return; + } public bool SetFirst(LoopListNode node) { - return m_LinkedList.SetFirst(node); + return _mLinkedList.SetFirst(node); } public LinkedHashSet Clone() { - var newset = new LinkedHashSet(); + var newSet = new LinkedHashSet(); foreach (var item in this) { - newset.Add(item); + newSet.Add(item); } - return newset; + return newSet; } - public virtual bool IsReadOnly - { - get { return m_Dictionary.IsReadOnly; } - } + public bool IsReadOnly => _mDictionary.IsReadOnly; public override string ToString() { - return m_LinkedList.ToString(); + return _mLinkedList.ToString(); } public void UnionWith(IEnumerable other) @@ -219,4 +206,5 @@ private static Exception GetNotSupportedDueToSimplification() { return new NotSupportedException("This method is not supported due to simplification of example code."); } -} \ No newline at end of file +} +#pragma warning restore CS1591 // 缺少对公共可见类型或成员的 XML 注释 \ No newline at end of file diff --git a/src/Basal/IFox.Basal.Shared/General/LinqEx.cs b/src/Basal/IFox.Basal.Shared/General/LinqEx.cs index 8112e63..746bacf 100644 --- a/src/Basal/IFox.Basal.Shared/General/LinqEx.cs +++ b/src/Basal/IFox.Basal.Shared/General/LinqEx.cs @@ -18,21 +18,19 @@ public static class LinqEx public static TValue FindByMax(this IEnumerable source, Func func) where TKey : IComparable { - var itor = source.GetEnumerator(); - if (!itor.MoveNext()) + using var itr = source.GetEnumerator(); + if (!itr.MoveNext()) throw new ArgumentNullException(nameof(source), "对象为 null"); - TValue value = itor.Current; - TKey key = func(value); + var value = itr.Current; + var key = func(value); - while (itor.MoveNext()) + while (itr.MoveNext()) { - TKey tkey = func(itor.Current); - if (tkey.CompareTo(key) > 0) - { - key = tkey; - value = itor.Current; - } + var tKey = func(itr.Current); + if (tKey.CompareTo(key) <= 0) continue; + key = tKey; + value = itr.Current; } return value; } @@ -49,21 +47,19 @@ public static TValue FindByMax(this IEnumerable source, Fu public static TValue FindByMax(this IEnumerable source, out TKey maxResult, Func func) where TKey : IComparable { - var itor = source.GetEnumerator(); - if (!itor.MoveNext()) + using var itr = source.GetEnumerator(); + if (!itr.MoveNext()) throw new ArgumentNullException(nameof(source), "对象为 null"); - TValue value = itor.Current; - TKey key = func(value); + var value = itr.Current; + var key = func(value); - while (itor.MoveNext()) + while (itr.MoveNext()) { - TKey tkey = func(itor.Current); - if (tkey.CompareTo(key) > 0) - { - key = tkey; - value = itor.Current; - } + var tKey = func(itr.Current); + if (tKey.CompareTo(key) <= 0) continue; + key = tKey; + value = itr.Current; } maxResult = key; return value; @@ -78,16 +74,16 @@ public static TValue FindByMax(this IEnumerable source, ou /// 最大键值的对应值 public static TValue FindByMax(this IEnumerable source, Comparison comparison) { - var itor = source.GetEnumerator(); - if (!itor.MoveNext()) + using var itr = source.GetEnumerator(); + if (!itr.MoveNext()) throw new ArgumentNullException(nameof(source), "对象为 null"); - TValue value = itor.Current; + var value = itr.Current; - while (itor.MoveNext()) + while (itr.MoveNext()) { - if (comparison(itor.Current, value) > 0) - value = itor.Current; + if (comparison(itr.Current, value) > 0) + value = itr.Current; } return value; } @@ -108,21 +104,19 @@ public static TValue FindByMax(this IEnumerable source, Comparis public static TValue FindByMin(this IEnumerable source, out TKey minKey, Func func) where TKey : IComparable { - var itor = source.GetEnumerator(); - if (!itor.MoveNext()) + using var itr = source.GetEnumerator(); + if (!itr.MoveNext()) throw new ArgumentNullException(nameof(source), "对象为 null"); - TValue value = itor.Current; - TKey key = func(value); + var value = itr.Current; + var key = func(value); - while (itor.MoveNext()) + while (itr.MoveNext()) { - TKey tkey = func(itor.Current); - if (tkey.CompareTo(key) < 0) - { - key = tkey; - value = itor.Current; - } + var tKey = func(itr.Current); + if (tKey.CompareTo(key) >= 0) continue; + key = tKey; + value = itr.Current; } minKey = key; return value; @@ -139,21 +133,19 @@ public static TValue FindByMin(this IEnumerable source, ou public static TValue FindByMin(this IEnumerable source, Func func) where TKey : IComparable { - var itor = source.GetEnumerator(); - if (!itor.MoveNext()) + using var itr = source.GetEnumerator(); + if (!itr.MoveNext()) throw new ArgumentNullException(nameof(source), "对象为 null"); - TValue value = itor.Current; - TKey key = func(value); + var value = itr.Current; + var key = func(value); - while (itor.MoveNext()) + while (itr.MoveNext()) { - TKey tkey = func(itor.Current); - if (tkey.CompareTo(key) < 0) - { - key = tkey; - value = itor.Current; - } + var tKey = func(itr.Current); + if (tKey.CompareTo(key) >= 0) continue; + key = tKey; + value = itr.Current; } return value; } @@ -167,16 +159,16 @@ public static TValue FindByMin(this IEnumerable source, Fu /// 最小键值的对应值 public static TValue FindByMin(this IEnumerable source, Comparison comparison) { - var itor = source.GetEnumerator(); - if (!itor.MoveNext()) + using var itr = source.GetEnumerator(); + if (!itr.MoveNext()) throw new ArgumentNullException(nameof(source), "对象为 null"); - TValue value = itor.Current; + var value = itr.Current; - while (itor.MoveNext()) + while (itr.MoveNext()) { - if (comparison(itor.Current, value) < 0) - value = itor.Current; + if (comparison(itr.Current, value) < 0) + value = itr.Current; } return value; } @@ -196,28 +188,28 @@ public static TValue FindByMin(this IEnumerable source, Comparis public static TValue[] FindByExt(this IEnumerable source, Func func) where TKey : IComparable { - var itor = source.GetEnumerator(); - if (!itor.MoveNext()) + using var itr = source.GetEnumerator(); + if (!itr.MoveNext()) throw new ArgumentNullException(nameof(source), "对象为 null"); - TValue[] values = new TValue[2]; - values[0] = values[1] = itor.Current; + var values = new TValue[2]; + values[0] = values[1] = itr.Current; - TKey[] keys = new TKey[2]; - keys[0] = keys[1] = func(itor.Current); + var keys = new TKey[2]; + keys[0] = keys[1] = func(itr.Current); - while (itor.MoveNext()) + while (itr.MoveNext()) { - TKey tkey = func(itor.Current); - if (tkey.CompareTo(keys[0]) < 0) + var tKey = func(itr.Current); + if (tKey.CompareTo(keys[0]) < 0) { - keys[0] = tkey; - values[0] = itor.Current; + keys[0] = tKey; + values[0] = itr.Current; } - else if (tkey.CompareTo(keys[1]) > 0) + else if (tKey.CompareTo(keys[1]) > 0) { - keys[1] = tkey; - values[1] = itor.Current; + keys[1] = tKey; + values[1] = itr.Current; } } return values; @@ -232,19 +224,19 @@ public static TValue[] FindByExt(this IEnumerable source, /// 最(小/大)键值的对应值 public static TValue[] FindByExt(this IEnumerable source, Comparison comparison) { - var itor = source.GetEnumerator(); - if (!itor.MoveNext()) + using var itr = source.GetEnumerator(); + if (!itr.MoveNext()) throw new ArgumentNullException(nameof(source), "对象为 null"); - TValue[] values = new TValue[2]; - values[0] = values[1] = itor.Current; + var values = new TValue[2]; + values[0] = values[1] = itr.Current; - while (itor.MoveNext()) + while (itr.MoveNext()) { - if (comparison(itor.Current, values[0]) < 0) - values[0] = itor.Current; - else if (comparison(itor.Current, values[1]) > 0) - values[1] = itor.Current; + if (comparison(itr.Current, values[0]) < 0) + values[0] = itr.Current; + else if (comparison(itr.Current, values[1]) > 0) + values[1] = itr.Current; } return values; } @@ -260,20 +252,20 @@ public static TValue[] FindByExt(this IEnumerable source, Compar public static TKey[] FindExt(this IEnumerable source, Func func) where TKey : IComparable { - var itor = source.GetEnumerator(); - if (!itor.MoveNext()) + using var itr = source.GetEnumerator(); + if (!itr.MoveNext()) throw new ArgumentNullException(nameof(source), "对象为 null"); - TKey[] keys = new TKey[2]; - keys[0] = keys[1] = func(itor.Current); + var keys = new TKey[2]; + keys[0] = keys[1] = func(itr.Current); - while (itor.MoveNext()) + while (itr.MoveNext()) { - TKey tkey = func(itor.Current); - if (tkey.CompareTo(keys[0]) < 0) - keys[0] = tkey; - else if (tkey.CompareTo(keys[1]) > 0) - keys[1] = tkey; + var tKey = func(itr.Current); + if (tKey.CompareTo(keys[0]) < 0) + keys[0] = tKey; + else if (tKey.CompareTo(keys[1]) > 0) + keys[1] = tKey; } return keys; } diff --git a/src/Basal/IFox.Basal.Shared/General/LoopList.cs b/src/Basal/IFox.Basal.Shared/General/LoopList.cs index 243ced6..da1e258 100644 --- a/src/Basal/IFox.Basal.Shared/General/LoopList.cs +++ b/src/Basal/IFox.Basal.Shared/General/LoopList.cs @@ -35,6 +35,7 @@ public class LoopListNode /// 环链表节点构造函数 /// /// 节点值 + /// 环链表 public LoopListNode(T value, LoopList ts) { Value = value; @@ -104,10 +105,10 @@ public LoopList() { } /// 环链表构造函数 ///
/// 节点迭代器 - [System.Diagnostics.DebuggerStepThrough] + [DebuggerStepThrough] public LoopList(IEnumerable values) { - var ge = values.GetEnumerator(); + using var ge = values.GetEnumerator(); while (ge.MoveNext()) Add(ge.Current); } @@ -210,7 +211,7 @@ public void For(Func, bool> action) /// public bool Contains(LoopListNode node) { - return node is not null && node.List == this; + return node.List == this; } /// @@ -220,14 +221,11 @@ public bool Contains(LoopListNode node) /// public bool Contains(T value) { - bool result = false; + var result = false; ForEach(node => { - if (node.Value!.Equals(value)) - { - result = true; - return true; - } - return false; + if (!node.Value!.Equals(value)) return false; + result = true; + return true; }); return result; } @@ -235,7 +233,7 @@ public bool Contains(T value) /// /// 查找第一个出现的节点 /// - /// + /// /// public LoopListNode? Find(T value) { @@ -284,7 +282,7 @@ public bool Contains(T value) /// public IEnumerable>? Finds(T value) { - LoopListNode? node = First; + var node = First; if (node is null) return null; @@ -390,7 +388,7 @@ public LoopListNode Add(T value) /// /// /// - [System.Diagnostics.DebuggerStepThrough] + [DebuggerStepThrough] public LoopListNode AddLast(T value) { return Add(value); @@ -400,10 +398,10 @@ public LoopListNode AddLast(T value) /// 容器内容全部加入到末尾 ///
/// - [System.Diagnostics.DebuggerStepThrough] + [DebuggerStepThrough] public void AddRange(IEnumerable list) { - var ge = list.GetEnumerator(); + using var ge = list.GetEnumerator(); while (ge.MoveNext()) Add(ge.Current); } @@ -419,13 +417,13 @@ public LoopListNode AddBefore(LoopListNode node, T value) if (node == First) return AddFirst(value); - var tnode = new LoopListNode(value, this); - node.Previous!.Next = tnode; - tnode.Previous = node.Previous; - node.Previous = tnode; - tnode.Next = node; + var tNode = new LoopListNode(value, this); + node.Previous!.Next = tNode; + tNode.Previous = node.Previous; + node.Previous = tNode; + tNode.Next = node; Count++; - return tnode; + return tNode; } /// @@ -436,13 +434,13 @@ public LoopListNode AddBefore(LoopListNode node, T value) /// public LoopListNode AddAfter(LoopListNode node, T value) { - var tnode = new LoopListNode(value, this); - node.Next!.Previous = tnode; - tnode.Next = node.Next; - node.Next = tnode; - tnode.Previous = node; + var tNode = new LoopListNode(value, this); + node.Next!.Previous = tNode; + tNode.Next = node.Next; + node.Next = tNode; + tNode.Previous = node; Count++; - return tnode; + return tNode; } #endregion @@ -524,9 +522,10 @@ public bool Remove(T value) if (lst is null) return false; - var ge = lst!.GetEnumerator(); + using var ge = lst.GetEnumerator(); while (ge.MoveNext()) - InternalRemove(ge.Current); + if (ge.Current != null) + InternalRemove(ge.Current); return true; } @@ -633,7 +632,7 @@ public void LinkTo(LoopListNode from, LoopListNode to, int number, bool is /// /// /// - [System.Diagnostics.DebuggerStepThrough] + [DebuggerStepThrough] public IEnumerable> GetNodes(LoopListNode from) { var node = from; @@ -648,7 +647,7 @@ public IEnumerable> GetNodes(LoopListNode from) /// 获取节点的查询器 ///
/// - [System.Diagnostics.DebuggerStepThrough] + [DebuggerStepThrough] public IEnumerable> GetNodes() { LoopListNode node = First!; @@ -663,7 +662,7 @@ public IEnumerable> GetNodes() /// 获取节点值的查询器 ///
/// - [System.Diagnostics.DebuggerStepThrough] + [DebuggerStepThrough] public IEnumerator GetEnumerator() { LoopListNode node = First!; @@ -674,12 +673,12 @@ public IEnumerator GetEnumerator() } } - [System.Diagnostics.DebuggerStepThrough] + [DebuggerStepThrough] IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); #region IEnumerable 成员 - [System.Diagnostics.DebuggerStepThrough] + [DebuggerStepThrough] IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); #endregion IEnumerable 成员 @@ -704,7 +703,7 @@ string IFormattable.ToString(string? format, IFormatProvider? formatProvider) /// public override string ToString() { - return ToString(null, null); + return ToString(null); } /// @@ -715,13 +714,11 @@ public string ToString(string? format, IFormatProvider? formatProvider = null) { var s = new StringBuilder(); s.Append($"Count = {Count};"); - if (format is null) - { - s.Append("{ "); - foreach (T value in this) - s.Append($"{value} "); - s.Append(" }"); - } + if (format is not null) return s.ToString(); + s.Append("{ "); + foreach (var value in this) + s.Append($"{value} "); + s.Append(" }"); return s.ToString(); } #endregion diff --git a/src/Basal/IFox.Basal.Shared/General/LoopState.cs b/src/Basal/IFox.Basal.Shared/General/LoopState.cs index 76ff63f..c758c48 100644 --- a/src/Basal/IFox.Basal.Shared/General/LoopState.cs +++ b/src/Basal/IFox.Basal.Shared/General/LoopState.cs @@ -1,4 +1,5 @@ -namespace IFoxCAD.Basal; +#pragma warning disable CS1591 // 缺少对公共可见类型或成员的 XML 注释 +namespace IFoxCAD.Basal; #line hidden // 调试的时候跳过它 /// @@ -6,29 +7,29 @@ /// public class LoopState { - const int PLS_NONE = 0; - const int PLS_EXCEPTIONAL = 1; - const int PLS_BROKEN = 2; - const int PLS_STOPPED = 4; - const int PLS_CANCELED = 8; + private const int PlsNone = 0; + private const int PlsExceptional = 1; + private const int PlsBroken = 2; + private const int PlsStopped = 4; + private const int PlsCanceled = 8; - private volatile int _flag = PLS_NONE; + private volatile int _flag = PlsNone; - public bool IsRun => _flag == PLS_NONE; - public bool IsExceptional => (_flag & PLS_EXCEPTIONAL) == PLS_EXCEPTIONAL; - public bool IsBreak => (_flag & PLS_BROKEN) == PLS_BROKEN; - public bool IsStop => (_flag & PLS_STOPPED) == PLS_STOPPED; - public bool IsCancel => (_flag & PLS_CANCELED) == PLS_CANCELED; + public bool IsRun => _flag == PlsNone; + public bool IsExceptional => (_flag & PlsExceptional) == PlsExceptional; + public bool IsBreak => (_flag & PlsBroken) == PlsBroken; + public bool IsStop => (_flag & PlsStopped) == PlsStopped; + public bool IsCancel => (_flag & PlsCanceled) == PlsCanceled; public void Exceptional() { - if ((_flag & PLS_EXCEPTIONAL) != PLS_EXCEPTIONAL) - _flag |= PLS_EXCEPTIONAL; + if ((_flag & PlsExceptional) != PlsExceptional) + _flag |= PlsExceptional; } - public void Break() => _flag = PLS_BROKEN; - public void Stop() => _flag = PLS_STOPPED; - public void Cancel() => _flag = PLS_CANCELED; - public void Reset() => _flag = PLS_NONE; + public void Break() => _flag = PlsBroken; + public void Stop() => _flag = PlsStopped; + public void Cancel() => _flag = PlsCanceled; + public void Reset() => _flag = PlsNone; } #line default @@ -37,31 +38,33 @@ public void Exceptional() /// public class ProState { - const int PLS_NONE = 0; // 初始化(构造就立马运行,将导致构造函数中也被检测,这是浪费性能及挖坑给自己的) - const int PLS_RUN = 1; // 运行 - const int PLS_BROKEN = 2; - const int PLS_STOPPED = 4; - const int PLS_CANCELED = 8; - const int PLS_EXCEPTIONAL = 16; // 异常 用于附加状态 + private const int PlsNone = 0; // 初始化(构造就立马运行,将导致构造函数中也被检测,这是浪费性能及挖坑给自己的) + private const int PlsRun = 1; // 运行 + private const int PlsBroken = 2; + private const int PlsStopped = 4; + private const int PlsCanceled = 8; + private const int PlsExceptional = 16; // 异常 用于附加状态 - private volatile int _flag = PLS_NONE; + private volatile int _flag = PlsNone; - public bool IsNone => _flag == PLS_NONE; - public bool IsRun => (_flag & PLS_RUN) == PLS_RUN; - public bool IsBreak => (_flag & PLS_BROKEN) == PLS_BROKEN; - public bool IsStop => (_flag & PLS_STOPPED) == PLS_STOPPED; - public bool IsCancel => (_flag & PLS_CANCELED) == PLS_CANCELED; - public bool IsExceptional => (_flag & PLS_EXCEPTIONAL) == PLS_EXCEPTIONAL; + public bool IsNone => _flag == PlsNone; + public bool IsRun => (_flag & PlsRun) == PlsRun; + public bool IsBreak => (_flag & PlsBroken) == PlsBroken; + public bool IsStop => (_flag & PlsStopped) == PlsStopped; + public bool IsCancel => (_flag & PlsCanceled) == PlsCanceled; + public bool IsExceptional => (_flag & PlsExceptional) == PlsExceptional; public void Exceptional() { - if ((_flag & PLS_EXCEPTIONAL) != PLS_EXCEPTIONAL) - _flag |= PLS_EXCEPTIONAL; + if ((_flag & PlsExceptional) != PlsExceptional) + _flag |= PlsExceptional; } - public void Break() => _flag = PLS_BROKEN; - public void Stop() => _flag = PLS_STOPPED; - public void Cancel() => _flag = PLS_CANCELED; - public void Start() => _flag = PLS_RUN; - public void None() => _flag = PLS_NONE; + public void Break() => _flag = PlsBroken; + public void Stop() => _flag = PlsStopped; + public void Cancel() => _flag = PlsCanceled; + public void Start() => _flag = PlsRun; + public void None() => _flag = PlsNone; } -#line default \ No newline at end of file +#line default + +#pragma warning restore CS1591 // 缺少对公共可见类型或成员的 XML 注释 \ No newline at end of file diff --git a/src/Basal/IFox.Basal.Shared/General/RandomEx.cs b/src/Basal/IFox.Basal.Shared/General/RandomEx.cs index 4d74324..119bd2b 100644 --- a/src/Basal/IFox.Basal.Shared/General/RandomEx.cs +++ b/src/Basal/IFox.Basal.Shared/General/RandomEx.cs @@ -72,8 +72,7 @@ public static string NextString(string[] arr) /// public static string NextString(Random ran, string[] arr) { - ran ??= GetRandom(); - int n = ran.Next(arr.Length - 1); + var n = ran.Next(arr.Length - 1); return arr[n]; } /// @@ -93,7 +92,6 @@ public static double NextDouble(double[] arr) /// public static double NextDouble(Random ran, double[] arr) { - ran ??= GetRandom(); int n = ran.Next(arr.Length - 1); return arr[n]; } @@ -114,7 +112,6 @@ public static int NextInt(int max) /// public static int NextInt(Random ran, int max) { - ran ??= GetRandom(); return ran.Next(max); } /// @@ -136,7 +133,6 @@ public static int NextInt(int min, int max) /// 返回一个介于之间的整数 public static int NextInt(Random ran, int min, int max) { - ran ??= GetRandom(); return ran.Next(min, max); } @@ -154,10 +150,9 @@ public static System.Drawing.Color NextColor() /// public static System.Drawing.Color NextColor(Random ran) { - ran ??= GetRandom(); - int R = ran.Next(255); - int G = ran.Next(255); - int B = ran.Next(255); + var R = ran.Next(255); + var G = ran.Next(255); + var B = ran.Next(255); B = (R + G > 400) ? R + G - 400 : B;// 0 : 380 - R - G; B = (B > 255) ? 255 : B; return System.Drawing.Color.FromArgb(R, G, B); diff --git a/src/Basal/IFox.Basal.Shared/General/Timer.cs b/src/Basal/IFox.Basal.Shared/General/Timer.cs index b92cfe8..78b1abb 100644 --- a/src/Basal/IFox.Basal.Shared/General/Timer.cs +++ b/src/Basal/IFox.Basal.Shared/General/Timer.cs @@ -41,7 +41,7 @@ public enum TimeEnum } [DllImport("Kernel32.dll")] - static extern bool QueryPerformanceCounter(out long lpPerformanceCount); + private static extern bool QueryPerformanceCounter(out long lpPerformanceCount); /// /// 这个函数会检索性能计数器的频率. @@ -52,10 +52,10 @@ public enum TimeEnum /// /// [DllImport("Kernel32.dll")] - static extern bool QueryPerformanceFrequency(out long lpFrequency); + private static extern bool QueryPerformanceFrequency(out long lpFrequency); - long _startTime, _stopTime; - readonly long _freq; + private long _startTime, _stopTime; + private readonly long _freq; /// /// 构造函数 /// @@ -74,7 +74,7 @@ public Timer() /// public void Start() { - System.Threading.Thread.Sleep(0); + Thread.Sleep(0); QueryPerformanceCounter(out _startTime); } @@ -84,27 +84,27 @@ public void Start() public void Stop() { QueryPerformanceCounter(out _stopTime); - _Second = (double)(_stopTime - _startTime) / _freq; + Second = (double)(_stopTime - _startTime) / _freq; } - double _Second = 0; // 返回计时器经过时间 /// /// 秒 /// - public double Second => _Second; + public double Second { get; private set; } + /// /// 毫秒 /// - public double Millisecond => _Second * 1000.0; + public double Millisecond => Second * 1000.0; /// /// 微秒 /// - public double Microsecond => _Second * 1000000.0; + public double Microsecond => Second * 1000000.0; /// /// 纳秒 /// - public double Nanosecond => _Second * 1000000000.0; + public double Nanosecond => Second * 1000000000.0; /// /// 计算执行委托的时间 /// @@ -119,22 +119,14 @@ public static double RunTime(Action action, action(); nanoSecond.Stop(); - var time = 0.0; - switch (timeEnum) + var time = timeEnum switch { - case TimeEnum.Second: - time = nanoSecond.Second; - break; - case TimeEnum.Millisecond: - time = nanoSecond.Millisecond; - break; - case TimeEnum.Microsecond: - time = nanoSecond.Microsecond; - break; - case TimeEnum.Nanosecond: - time = nanoSecond.Nanosecond; - break; - } + TimeEnum.Second => nanoSecond.Second, + TimeEnum.Millisecond => nanoSecond.Millisecond, + TimeEnum.Microsecond => nanoSecond.Microsecond, + TimeEnum.Nanosecond => nanoSecond.Nanosecond, + _ => 0.0 + }; //string timeNameZn = ""; //switch (timeEnum) //{ diff --git a/src/Basal/IFox.Basal.Shared/WindowsAPI/MouseHook.cs b/src/Basal/IFox.Basal.Shared/WindowsAPI/MouseHook.cs index 8be0253..29cbca7 100644 --- a/src/Basal/IFox.Basal.Shared/WindowsAPI/MouseHook.cs +++ b/src/Basal/IFox.Basal.Shared/WindowsAPI/MouseHook.cs @@ -2,6 +2,7 @@ using System.Windows.Forms; using MouseEventArgs = System.Windows.Forms.MouseEventArgs; using MouseEventHandler = System.Windows.Forms.MouseEventHandler; +#pragma warning disable CS1591 // 缺少对公共可见类型或成员的 XML 注释 namespace IFoxCAD.Basal; @@ -311,4 +312,5 @@ protected virtual void Dispose(bool disposing) UnHook(); } #endregion -} \ No newline at end of file +} +#pragma warning restore CS1591 // 缺少对公共可见类型或成员的 XML 注释 \ No newline at end of file diff --git a/src/Basal/IFox.Basal.Shared/WindowsAPI/WindowsAPI.cs b/src/Basal/IFox.Basal.Shared/WindowsAPI/WindowsAPI.cs index 489f588..3e6fd0a 100644 --- a/src/Basal/IFox.Basal.Shared/WindowsAPI/WindowsAPI.cs +++ b/src/Basal/IFox.Basal.Shared/WindowsAPI/WindowsAPI.cs @@ -1,4 +1,5 @@ -#define Marshal +#pragma warning disable CS1591 // 缺少对公共可见类型或成员的 XML 注释 +#define Marshal namespace IFoxCAD.Basal; public partial class WindowsAPI @@ -654,4 +655,6 @@ public override int GetHashCode() } #endregion } -} \ No newline at end of file +} + +#pragma warning restore CS1591 // 缺少对公共可见类型或成员的 XML 注释 \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/Algorithms/Graph/Graph.cs b/src/CAD/IFox.CAD.Shared/Algorithms/Graph/Graph.cs index 6ecb934..43e09bc 100644 --- a/src/CAD/IFox.CAD.Shared/Algorithms/Graph/Graph.cs +++ b/src/CAD/IFox.CAD.Shared/Algorithms/Graph/Graph.cs @@ -1,7 +1,5 @@ namespace IFoxCAD.Cad; -using Exception = System.Exception; - /// /// 无权无向图实现 /// IEnumerable 枚举所有顶点; @@ -13,19 +11,19 @@ public sealed class Graph : IGraph, IEnumerable /// 存储所有节点的字典,key为顶点的类型,value为邻接表,类型是hashset,不可重复添加点 /// /// - readonly Dictionary> vertices = new(); + private readonly Dictionary> _vertices = []; /// /// 邻接边表,key为顶点的类型,value为邻接边表,类型是hashset,不可重复添加边 /// - readonly Dictionary> edges = new(); + private readonly Dictionary> _edges = []; /// /// 为加快索引,引入hash检索 /// - readonly Dictionary vertexs = new(); + private readonly Dictionary _vertexStr = []; /// /// 节点数量 /// - public int VerticesCount => vertices.Count; + public int VerticesCount => _vertices.Count; /// /// Returns a reference vertex. @@ -35,22 +33,15 @@ private IGraphVertex? ReferenceVertex { get { - using (var enumerator = vertexs.GetEnumerator()) - { - if (enumerator.MoveNext()) - { - return enumerator.Current.Value; - } - } - - return null; + using var enumerator = _vertexStr.GetEnumerator(); + return enumerator.MoveNext() ? enumerator.Current.Value : null; } } IGraphVertex? IGraph.ReferenceVertex => ReferenceVertex; /// /// 目前点增加点的顺序号,这个点号不随删点而减少的 /// - private int insertCount; + private int _insertCount; #endregion #region 构造函数 @@ -59,7 +50,7 @@ private IGraphVertex? ReferenceVertex /// public Graph() { - insertCount = 0; // 每次新建对象就将顶点顺序号归零 + _insertCount = 0; // 每次新建对象就将顶点顺序号归零 } #endregion @@ -72,14 +63,14 @@ public Graph() public IGraphVertex AddVertex(Point3d pt) { var str = pt.GetHashString(); - if (vertexs.ContainsKey(str)) - return vertexs[str]; + if (_vertexStr.TryGetValue(str, out var addVertex)) + return addVertex; - var vertex = new GraphVertex(pt, insertCount++); - vertices.Add(vertex, new HashSet()); - edges.Add(vertex, new HashSet()); + var vertex = new GraphVertex(pt, _insertCount++); + _vertices.Add(vertex, []); + _edges.Add(vertex, []); - vertexs[str] = vertex; + _vertexStr[str] = vertex; return vertex; } @@ -98,16 +89,16 @@ public void AddEdge(Curve3d curve) var end = AddVertex(curve.EndPoint); // 添加起点的邻接表和邻接边 - vertices[start].Add(end); - edges[start].Add(new GraphEdge(end, curve)); + _vertices[start].Add(end); + _edges[start].Add(new GraphEdge(end, curve)); // 为了保证点顺序,每个点的邻接边必须按起点-终点,所以添加曲线终点时,将添加一个方向的曲线 - var curtmp = (Curve3d)curve.Clone(); - curtmp = curtmp.GetReverseParameterCurve(); + var curTmp = (Curve3d)curve.Clone(); + curTmp = curTmp.GetReverseParameterCurve(); // 添加终点的邻接表和邻接边 - vertices[end].Add(start); - edges[end].Add(new GraphEdge(start, curtmp)); + _vertices[end].Add(start); + _edges[end].Add(new GraphEdge(start, curTmp)); } #endregion @@ -119,22 +110,22 @@ public void AddEdge(Curve3d curve) public void RemoveVertex(Point3d pt) { var str = pt.GetHashString(); - if (vertexs.ContainsKey(str)) + if (_vertexStr.ContainsKey(str)) { - var vertex = vertexs[str]; + var vertex = _vertexStr[str]; // 删除邻接表里的vertex点,先删除后面的遍历可以少一轮 - vertices.Remove(vertex!); + _vertices.Remove(vertex!); // 删除其他顶点的邻接表里的vertex点 - foreach (var item in vertices.Values) + foreach (var item in _vertices.Values) item.Remove(vertex!); // 删除邻接边表里的vertex点,先删除后面的遍历可以少一轮 - edges.Remove(vertex!); + _edges.Remove(vertex!); // 删除其他顶点的邻接边表的指向vertex的边 - foreach (var item in edges.Values) + foreach (var item in _edges.Values) { item.RemoveWhere(x => vertex.Equals(x.TargetVertex)); // foreach (var edge in item) @@ -143,7 +134,7 @@ public void RemoveVertex(Point3d pt) // item.Remove(edge); // } } - vertexs.Remove(str); + _vertexStr.Remove(str); } } @@ -171,15 +162,10 @@ public void RemoveEdge(Curve3d curve) /// 有边返回 ,反之返回 public bool HasEdge(IGraphVertex source, IGraphVertex dest) { - if (!vertices.ContainsKey(source) || !vertices.ContainsKey(dest)) + if (!_vertices.ContainsKey(source) || !_vertices.ContainsKey(dest)) throw new ArgumentException("源或目标不在此图中;"); - foreach (var item in edges[source]) - { - if (item.TargetVertex == dest) - return true; - } - return false; + return _edges[source].Any(item => Equals(item.TargetVertex, dest)); } /// @@ -191,15 +177,10 @@ public bool HasEdge(IGraphVertex source, IGraphVertex dest) /// 传入的点不在图中时抛出参数异常 public IEdge? GetEdge(IGraphVertex source, IGraphVertex dest) { - if (!vertices.ContainsKey(source) || !vertices.ContainsKey(dest)) + if (!_vertices.ContainsKey(source) || !_vertices.ContainsKey(dest)) throw new ArgumentException("源或目标不在此图中;"); - foreach (var item in edges[source]) - { - if (item.TargetVertex.Equals(dest)) - return item; - } - return null; + return _edges[source].FirstOrDefault(item => item.TargetVertex.Equals(dest)); } /// @@ -209,7 +190,7 @@ public bool HasEdge(IGraphVertex source, IGraphVertex dest) /// 存在顶点返回 ,反之返回 public bool ContainsVertex(IGraphVertex value) { - return vertices.ContainsKey(value); + return _vertices.ContainsKey(value); } #endregion @@ -221,7 +202,7 @@ public bool ContainsVertex(IGraphVertex value) /// 邻接表 public HashSet GetAdjacencyList(IGraphVertex vertex) { - return vertices[vertex]; + return _vertices[vertex]; } /// @@ -231,7 +212,7 @@ public HashSet GetAdjacencyList(IGraphVertex vertex) /// 邻接边表 public HashSet GetAdjacencyEdge(IGraphVertex vertex) { - return edges[vertex]; + return _edges[vertex]; } /// @@ -250,9 +231,9 @@ public List GetCurves(List graphVertices) if (edge is not null) curves.Add(edge.TargetEdge); } - var lastedge = GetEdge(graphVertices[^1], graphVertices[0]); - if (lastedge is not null) - curves.Add(lastedge.TargetEdge); + var lastEdge = GetEdge(graphVertices[^1], graphVertices[0]); + if (lastEdge is not null) + curves.Add(lastEdge.TargetEdge); return curves; } @@ -267,9 +248,8 @@ public Graph Clone() { var newGraph = new Graph(); - foreach (var vertex in edges.Values) - foreach (var item in vertex) - newGraph.AddEdge(item.TargetEdge); + foreach (var item in _edges.Values.SelectMany(vertex => vertex)) + newGraph.AddEdge(item.TargetEdge); return newGraph; } @@ -286,19 +266,19 @@ IGraph IGraph.Clone() [System.Diagnostics.DebuggerStepThrough] public IEnumerator GetEnumerator() { - return VerticesAsEnumberable.GetEnumerator(); + return VerticesEnumberable.GetEnumerator(); } [System.Diagnostics.DebuggerStepThrough] - IEnumerator? IEnumerable.GetEnumerator() + IEnumerator IEnumerable.GetEnumerator() { - return GetEnumerator() as IEnumerator; + return (IEnumerator)GetEnumerator(); } /// /// 节点迭代器 /// - public IEnumerable VerticesAsEnumberable => - vertices.Select(x => x.Key); + public IEnumerable VerticesEnumberable => + _vertices.Select(x => x.Key); #endregion #region 方法 @@ -308,21 +288,21 @@ public IEnumerator GetEnumerator() /// public string ToReadable() { - int i = 1; - string output = string.Empty; - foreach (var node in vertices) + var i = 1; + var output = string.Empty; + foreach (var node in _vertices) { var adjacents = string.Empty; output = string.Format("{1}\r\n{0}-{2}: [", i, output, node.Key.Data.ToString()); - foreach (var adjacentNode in node.Value) - adjacents = string.Format("{0}{1},", adjacents, adjacentNode.Data.ToString()); + adjacents = node.Value.Aggregate(adjacents, + (current, adjacentNode) => $"{current}{adjacentNode.Data},"); if (adjacents.Length > 0) - adjacents = adjacents.TrimEnd(new char[] { ',', ' ' }); + adjacents = adjacents.TrimEnd([',', ' ']); - output = string.Format("{0}{1}]", output, adjacents); + output = $"{output}{adjacents}]"; i++; } return output; @@ -335,30 +315,23 @@ public string ToReadable() /// 邻接表图实现的顶点; /// IEnumerable 枚举所有邻接点; /// -public sealed class GraphVertex : IGraphVertex, IEquatable, IComparable, IComparable +/// +/// 邻接表图实现的顶点 +/// +/// 点 +/// 所在节点索引 +public sealed class GraphVertex(Point3d value, int index) : IGraphVertex, IEquatable, IComparable { #region 属性 /// /// 数据 /// - public Point3d Data { get; set; } + public Point3d Data => value; /// /// 索引 /// - public int Index { get; set; } - #endregion + public int Index => index; - #region 构造 - /// - /// 邻接表图实现的顶点 - /// - /// 点 - /// 所在节点索引 - public GraphVertex(Point3d value, int index) - { - Data = value; - Index = index; - } #endregion #region 重载运算符_比较 @@ -376,14 +349,11 @@ public bool Equals(IGraphVertex other) /// /// /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (obj is null) return false; - if (obj is not IGraphVertex vertex) - return false; - else - return Equals(vertex); + return obj is IGraphVertex vertex && Equals(vertex); } /// /// 计算hashcode @@ -419,7 +389,7 @@ int IComparable.CompareTo(IGraphVertex other) /// /// /// - public int CompareTo(object obj) + public int CompareTo(object? obj) { if (obj is null) return 1; @@ -440,12 +410,9 @@ public int CompareTo(object obj) /// /// /// - public static bool operator ==(GraphVertex person1, GraphVertex person2) + public static bool operator ==(GraphVertex person1, GraphVertex? person2) { - if (person1 is null || person2 is null) - return Equals(person1, person2); - - return person1.Equals(person2); + return person2 is null ? Equals(person1, person2) : person1.Equals(person2); } /// /// 不相等 @@ -453,9 +420,9 @@ public int CompareTo(object obj) /// /// /// - public static bool operator !=(GraphVertex person1, GraphVertex person2) + public static bool operator !=(GraphVertex person1, GraphVertex? person2) { - if (person1 is null || person2 is null) + if (person2 is null) return !Equals(person1, person2); return !person1.Equals(person2); @@ -467,30 +434,23 @@ public int CompareTo(object obj) /// /// 无向图中边的定义 /// -public sealed class GraphEdge : IEdge, IEquatable +/// +/// 无向图中边的定义 +/// +/// 下一点 +/// 下一点之间的曲线 +public sealed class GraphEdge(IGraphVertex target, Curve3d edge) : IEdge, IEquatable { #region 属性 /// /// 顶点 /// - public IGraphVertex TargetVertex { get; set; } + public IGraphVertex TargetVertex { get; } = target; /// /// 边 /// - public Curve3d TargetEdge { get; set; } - #endregion + public Curve3d TargetEdge { get; } = edge; - #region 构造 - /// - /// 无向图中边的定义 - /// - /// 下一点 - /// 下一点之间的曲线 - public GraphEdge(IGraphVertex target, Curve3d edge) - { - TargetVertex = target; - TargetEdge = edge; - } #endregion #region 重载运算符_比较 @@ -501,9 +461,7 @@ public GraphEdge(IGraphVertex target, Curve3d edge) /// public bool Equals(GraphEdge other) { - if (other is null) - return false; - return TargetVertex == other.TargetVertex && + return Equals(TargetVertex, other.TargetVertex) && TargetEdge == other.TargetEdge; } /// @@ -511,14 +469,11 @@ public bool Equals(GraphEdge other) /// /// /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (obj is null) return false; - if (obj is not GraphEdge personObj) - return false; - else - return Equals(personObj); + return obj is GraphEdge personObj && Equals(personObj); } /// /// 获取hashcode @@ -534,12 +489,9 @@ public override int GetHashCode() /// /// /// - public static bool operator ==(GraphEdge person1, GraphEdge person2) + public static bool operator ==(GraphEdge person1, GraphEdge? person2) { - if (person1 is null || person2 is null) - return Equals(person1, person2); - - return person1.Equals(person2); + return person2 is null ? Equals(person1, person2) : person1.Equals(person2); } /// /// 不相等 @@ -547,9 +499,9 @@ public override int GetHashCode() /// /// /// - public static bool operator !=(GraphEdge person1, GraphEdge person2) + public static bool operator !=(GraphEdge person1, GraphEdge? person2) { - if (person1 is null || person2 is null) + if (person2 is null) return !Equals(person1, person2); return !person1.Equals(person2); @@ -583,9 +535,9 @@ public void FindAll(IGraph graph) { var total = new HashSet(); // var graphtmp = graph.Clone(); - foreach (var item in graph.VerticesAsEnumberable) + foreach (var item in graph.VerticesEnumberable) { - Dfs(graph, new LinkedHashSet { item }, total); + Dfs(graph, [item], total); total.Add(item); } } @@ -599,7 +551,7 @@ public void FindAll(IGraph graph) /// 已经遍历的路径 /// #if true - void Dfs(IGraph graph, LinkedHashSet visited, HashSet totalVisited) + private void Dfs(IGraph graph, LinkedHashSet visited, HashSet totalVisited) { var adjlist = graph.GetAdjacencyList(/*startNode*/ visited.First!.Value); // O(1) foreach (var nextNode in adjlist) // O(n) @@ -620,8 +572,8 @@ void Dfs(IGraph graph, LinkedHashSet visited, HashSet 2 && nextNode.Equals(visited.Last!.Value)) { // 将重复的路径进行过滤,并把新的路径存入结果 - var curstr = Gethashstring(visited); // O(n) - if (Isnew(curstr)) // O(1) + var curstr = GetHashString(visited); // O(n) + if (IsNew(curstr)) // O(1) { Curve3ds.Add(visited); Curved.Add(curstr.Item1); @@ -686,7 +638,7 @@ void Dfs(IGraph graph, List visited) /// /// /// - static List RotateToSmallest(List lst) + private static List RotateToSmallest(List lst) { var index = lst.IndexOf(lst.Min()); return lst.Skip(index).Concat(lst.Take(index)).ToList(); @@ -698,7 +650,7 @@ static List RotateToSmallest(List lst) /// /// /// - static List Invert(List lst, IGraphVertex vertex) + private static List Invert(List lst, IGraphVertex vertex) { var tmp = lst.ToList(); tmp.Reverse(); @@ -706,11 +658,11 @@ static List Invert(List lst, IGraphVertex vertex) return tmp.Skip(index).Concat(lst.Take(index)).ToList(); } - static (string, string) Gethashstring(List pathone, List pathtwo) + private static (string, string) GetHashString(List pathone, List pathtwo) { var one = new string[pathone.Count]; var two = new string[pathtwo.Count]; - for (int i = 0; i < pathone.Count; i++) + for (var i = 0; i < pathone.Count; i++) { one[i] = pathone[i].Index.ToString(); two[i] = pathtwo[i].Index.ToString(); @@ -718,7 +670,7 @@ static List Invert(List lst, IGraphVertex vertex) return (string.Join("-", one), string.Join("-", two)); } - static (string, string) Gethashstring(LinkedHashSet path) + private static (string, string) GetHashString(LinkedHashSet path) { var one = new string[path.Count]; var two = new string[path.Count]; @@ -730,7 +682,7 @@ static List Invert(List lst, IGraphVertex vertex) } - bool Isnew((string, string) path) + private bool IsNew((string, string) path) { return !Curved.Contains(path.Item1) && !Curved.Contains(path.Item2); } diff --git a/src/CAD/IFox.CAD.Shared/Algorithms/Graph/IGraph.cs b/src/CAD/IFox.CAD.Shared/Algorithms/Graph/IGraph.cs index a3a5aec..b0726c8 100644 --- a/src/CAD/IFox.CAD.Shared/Algorithms/Graph/IGraph.cs +++ b/src/CAD/IFox.CAD.Shared/Algorithms/Graph/IGraph.cs @@ -22,7 +22,7 @@ public interface IGraph /// 顶点的迭代器 /// /// - IEnumerable VerticesAsEnumberable { get; } + IEnumerable VerticesEnumberable { get; } /// /// 是否有边 @@ -81,7 +81,7 @@ public interface IGraphVertex : IComparable /// 顶点的键 /// /// - int Index { get; set; } + int Index { get; } /// /// 顶点的数据 diff --git a/src/CAD/IFox.CAD.Shared/AutoReg/IAutoGo.cs b/src/CAD/IFox.CAD.Shared/AutoReg/IAutoGo.cs index 766f721..3cd31af 100644 --- a/src/CAD/IFox.CAD.Shared/AutoReg/IAutoGo.cs +++ b/src/CAD/IFox.CAD.Shared/AutoReg/IAutoGo.cs @@ -232,7 +232,7 @@ public static void AppDomainGetTypes(Action action, string? dllNameWithout #if DEBUG catch (System.Exception e) { - Debugx.Printl($"出错:{nameof(AppDomainGetTypes)};计数{error};错误信息:{e.Message}"); + DebugEx.Printl($"出错:{nameof(AppDomainGetTypes)};计数{error};错误信息:{e.Message}"); Debugger.Break(); #else catch diff --git a/src/CAD/IFox.CAD.Shared/Copyclip/TagClipboardInfo.cs b/src/CAD/IFox.CAD.Shared/Copyclip/TagClipboardInfo.cs index 07452fc..91cdcd9 100644 --- a/src/CAD/IFox.CAD.Shared/Copyclip/TagClipboardInfo.cs +++ b/src/CAD/IFox.CAD.Shared/Copyclip/TagClipboardInfo.cs @@ -328,7 +328,7 @@ public static bool OpenClipboardTask(bool isWrite, Action action) catch (Exception e) { Debugger.Break(); - Debugx.Printl(e.Message); + DebugEx.Printl(e.Message); } finally { diff --git a/src/CAD/IFox.CAD.Shared/SelectionFilter/OpList.cs b/src/CAD/IFox.CAD.Shared/SelectionFilter/OpList.cs index 5870be9..0eb2350 100644 --- a/src/CAD/IFox.CAD.Shared/SelectionFilter/OpList.cs +++ b/src/CAD/IFox.CAD.Shared/SelectionFilter/OpList.cs @@ -8,7 +8,7 @@ public abstract class OpList : OpLogi /// /// 过滤器列表 /// - protected List _lst = new(); + protected readonly List Lst = []; /// /// 添加过滤器条件的虚函数,子类可以重写 @@ -35,7 +35,7 @@ public abstract class OpList : OpLogi /// 过滤器对象 public virtual void Add(OpFilter value) { - _lst.Add(value); + Lst.Add(value); } /// @@ -47,7 +47,7 @@ public virtual void Add(OpFilter value) public void Add(string speccode, int code, object value) { if (speccode == "~") - _lst.Add(new OpEqual(code, value).Not); + Lst.Add(new OpEqual(code, value).Not); } /// @@ -57,7 +57,7 @@ public void Add(string speccode, int code, object value) /// 组码值 public void Add(int code, object value) { - _lst.Add(new OpEqual(code, value)); + Lst.Add(new OpEqual(code, value)); } /// @@ -67,7 +67,7 @@ public void Add(int code, object value) /// 组码值 public void Add(DxfCode code, object value) { - _lst.Add(new OpEqual(code, value)); + Lst.Add(new OpEqual(code, value)); } /// @@ -78,7 +78,7 @@ public void Add(DxfCode code, object value) /// 比较运算符 public void Add(int code, object value, string comp) { - _lst.Add(new OpComp(comp, code, value)); + Lst.Add(new OpComp(comp, code, value)); } /// @@ -89,7 +89,7 @@ public void Add(int code, object value, string comp) /// 比较运算符 public void Add(DxfCode code, object value, string comp) { - _lst.Add(new OpComp(comp, code, value)); + Lst.Add(new OpComp(comp, code, value)); } /// @@ -99,8 +99,9 @@ public void Add(DxfCode code, object value, string comp) [System.Diagnostics.DebuggerStepThrough] public override IEnumerator GetEnumerator() { - foreach (var value in _lst) - yield return value; + // foreach (var value in Lst) + // yield return value; + return Lst.GetEnumerator(); } } @@ -112,10 +113,7 @@ public class OpAnd : OpList /// /// 符号名 /// - public override string Name - { - get { return "And"; } - } + public override string Name => "And"; /// /// 添加过滤条件 @@ -126,11 +124,11 @@ public override void Add(OpFilter value) if (value is OpAnd opand) { foreach (var item in opand) - _lst.Add(item); + Lst.Add(item); } else { - _lst.Add(value); + Lst.Add(value); } } } @@ -143,10 +141,7 @@ public class OpOr : OpList /// /// 符号名 /// - public override string Name - { - get { return "Or"; } - } + public override string Name => "Or"; /// /// 添加过滤条件 @@ -157,11 +152,11 @@ public override void Add(OpFilter value) if (value is OpOr opor) { foreach (var item in opor) - _lst.Add(item); + Lst.Add(item); } else { - _lst.Add(value); + Lst.Add(value); } } } \ No newline at end of file diff --git "a/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/02.\346\213\211\344\274\270\345\241\253\345\205\205\344\272\213\344\273\266.cs" "b/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/02.\346\213\211\344\274\270\345\241\253\345\205\205\344\272\213\344\273\266.cs" index 2d0bfc1..8fed9c2 100644 --- "a/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/02.\346\213\211\344\274\270\345\241\253\345\205\205\344\272\213\344\273\266.cs" +++ "b/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/02.\346\213\211\344\274\270\345\241\253\345\205\205\344\272\213\344\273\266.cs" @@ -56,14 +56,14 @@ public static void Dm_VetoCommand(object sender, DocumentLockModeChangedEventArg HatchPick.MapDocHatchPickEvent[e.Document].SetPropertiesInfoTask(); if (_vetoProperties) { - Debugx.Printl("Dm_VetoCommand 否决了"); + DebugEx.Printl("Dm_VetoCommand 否决了"); e.Veto(); _vetoProperties = false; // 发送编辑填充命令 SendCommand("_hatchedit ", RunCmdFlag.AcedPostCommand); return; } - Debugx.Printl("Dm_VetoCommand 没否决"); + DebugEx.Printl("Dm_VetoCommand 没否决"); } break; } @@ -126,7 +126,7 @@ void Md_CommandWillStart(object sender, CommandEventArgs e) // 此处无法使用文档锁,否则将导致文档锁无法释放,然后ctrl+z失败 var cmdup = e.GlobalCommandName.ToUpper(); - Debugx.Printl("Md_CommandWillStart::" + cmdup); + DebugEx.Printl("Md_CommandWillStart::" + cmdup); switch (cmdup) { @@ -155,8 +155,8 @@ void Md_CommandWillStart(object sender, CommandEventArgs e) { var mp = HatchHook.MouseStartPoint; var mouseStart = Screen.ScreenToCad(mp); - Debugx.Printl("mouseStart,屏幕点::" + mp); - Debugx.Printl("mouseStart,cad点::" + mouseStart); + DebugEx.Printl("mouseStart,屏幕点::" + mp); + DebugEx.Printl("mouseStart,cad点::" + mouseStart); // 获取当前选择的对象,然后提取所有的夹点 var prompt = Env.Editor.SelectImplied(); @@ -169,7 +169,7 @@ void Md_CommandWillStart(object sender, CommandEventArgs e) // TODO 屏幕像素点转cad点的误差,要随着视口高度而动态计算....这里的计算可能不太正确 var tol = (double)Env.GetVar("viewsize") / 10; - Debugx.Printl("tol::" + tol); + DebugEx.Printl("tol::" + tol); // 0x01 移动了矩形填充中间的夹点,删除边界,并且重新生成填充和边界 // 0x02 移动了填充边界上的夹点,不处理,然后它会通过关联进行自己修改 @@ -250,9 +250,9 @@ void Md_CommandWillStart(object sender, CommandEventArgs e) // 点在边界上:就不处理了,它会通过cad的关联填充反应器自动修改 if (_pickInBo) - Debugx.Printl("夹点在边界上"); + DebugEx.Printl("夹点在边界上"); else - Debugx.Printl("夹点不在边界上"); + DebugEx.Printl("夹点不在边界上"); } } } @@ -287,7 +287,7 @@ void Md_CommandEnded(object sender, CommandEventArgs e) { case "REFEDIT": { - Debugx.Printl("Md_CommandEnded:: REFEDIT"); + DebugEx.Printl("Md_CommandEnded:: REFEDIT"); // 在位编辑命令,执行后,获取当前空间所有填充 var prompt = Env.Editor.SelectAll(FilterForHatch); @@ -311,7 +311,7 @@ void Md_CommandEnded(object sender, CommandEventArgs e) break; case "REFSET": // 加减在位编辑图元 { - Debugx.Printl("Md_CommandEnded:: REFSET"); + DebugEx.Printl("Md_CommandEnded:: REFSET"); // 命令历史的最后一行是:添加/删除 var last = Env.GetVar("lastprompt").ToString(); @@ -350,7 +350,7 @@ void Md_CommandEnded(object sender, CommandEventArgs e) break; case "REFCLOSE":// 保存块,清空集合 { - Debugx.Printl("Md_CommandEnded:: REFCLOSE"); + DebugEx.Printl("Md_CommandEnded:: REFCLOSE"); _refeditSsgeted.Clear(); _refeditSsgeting.Clear(); } @@ -457,7 +457,7 @@ void Md_ImpliedSelectionChanged(object sender, EventArgs e) _selectChangedStop = false; return; } - Debugx.Printl("Md_ImpliedSelectionChanged"); + DebugEx.Printl("Md_ImpliedSelectionChanged"); using DBTrans tr = new(doclock: true); var prompt = Env.Editor.SelectImplied(); @@ -509,7 +509,7 @@ void CreatHatchConverter(Hatch hatch, HashSet outSsgetIds) // 那就不创建新的,然后选中它们 if (hc.BoundaryIds.Count != 0) { - Debugx.Printl("CreatHatchConverter:: 加入了现有边界到选择集"); + DebugEx.Printl("CreatHatchConverter:: 加入了现有边界到选择集"); // 加入选择集 foreach (var item in hc.BoundaryIds) @@ -519,7 +519,7 @@ void CreatHatchConverter(Hatch hatch, HashSet outSsgetIds) } else { - Debugx.Printl("CreatHatchConverter:: 创建新填充和边界"); + DebugEx.Printl("CreatHatchConverter:: 创建新填充和边界"); // 创建新填充和边界 hc.GetBoundarysData(); diff --git a/tests/TestShared/Copyclip.cs b/tests/TestShared/Copyclip.cs index d4f44a2..96aaf81 100644 --- a/tests/TestShared/Copyclip.cs +++ b/tests/TestShared/Copyclip.cs @@ -592,13 +592,13 @@ void Paste(bool isBlock) catch (Exception e) { Debugger.Break(); - Debugx.Printl(e); + DebugEx.Printl(e); } } catch (Exception e)//{"剪贴板上的数据无效 (异常来自 HRESULT:0x800401D3 (CLIPBRD_E_BAD_DATA))"} { Debugger.Break(); - Debugx.Printl(e); + DebugEx.Printl(e); } finally { diff --git a/tests/TestShared/TestMarshal.cs b/tests/TestShared/TestMarshal.cs index 834fe12..7beb84b 100644 --- a/tests/TestShared/TestMarshal.cs +++ b/tests/TestShared/TestMarshal.cs @@ -58,11 +58,11 @@ public void Test_ImplicitPoint3D() { Point3d pt1 = new(1, 56, 89); var a1 = (Point3D*)&pt1; - Debugx.Printl("指针类型转换,获取x::" + a1->X); + DebugEx.Printl("指针类型转换,获取x::" + a1->X); var pt2 = Point3D.Create(new IntPtr(&pt1)); - Debugx.Printl("pt1地址::" + (int)&pt1); - Debugx.Printl("pt2地址::" + (int)&pt2); + DebugEx.Printl("pt1地址::" + (int)&pt1); + DebugEx.Printl("pt2地址::" + (int)&pt2); Debug.Assert(&pt1 == &pt2);//不相等,是申请了新内存 } } diff --git a/tests/TestShared/TestPoint.cs b/tests/TestShared/TestPoint.cs index f6da535..9431873 100644 --- a/tests/TestShared/TestPoint.cs +++ b/tests/TestShared/TestPoint.cs @@ -82,7 +82,7 @@ public void Test_PtSortedSet() foreach (var item in ss1) { if (item.X > 3 && item.X < 7) - Debugx.Printl(item); + DebugEx.Printl(item); else if (item.X >= 7) break; } @@ -151,9 +151,9 @@ public void Test_ListEqualspeed() { var lst1 = new List { 1, 2, 3, 4 }; var lst2 = new List { 1, 2, 3, 4 }; - lst1.EqualsAll(null!); + lst1.SequenceEqual(null!); Tools.TestTimes2(1000000, "eqaulspeed:", () => { - lst1.EqualsAll(lst2); + lst1.SequenceEqual(lst2); }); } -- Gitee From 1969c408db0e6fc4371b984168b697cdfb7f2138 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Fri, 19 Jan 2024 15:32:51 +0800 Subject: [PATCH 243/453] =?UTF-8?q?=E6=B8=85=E7=90=86=E6=97=A0=E7=94=A8?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=EF=BC=8C=E4=BC=98=E5=8C=96=E9=80=89=E6=8B=A9?= =?UTF-8?q?=E9=9B=86=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/SelectionSetEx.cs | 53 +++++-------------- tests/TestShared/TestSelectfilter.cs | 26 +++++++++ 2 files changed, 39 insertions(+), 40 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SelectionSetEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SelectionSetEx.cs index 98a2fd8..a43b803 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SelectionSetEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SelectionSetEx.cs @@ -8,29 +8,6 @@ namespace IFoxCAD.Cad; public static class SelectionSetEx { #region 获取对象id - /// - /// 获取已选择的对象 - /// - /// 选择集 - /// 已选择的对象集合 - [System.Diagnostics.DebuggerStepThrough] - public static IEnumerable GetSelectedObjects(this SelectionSet ss) - { - return ss.Cast(); - } - - /// - /// 获取已选择的对象 - /// - /// 已选择的对象泛型 - /// 选择集 - /// 已选择的对象集合 - [System.Diagnostics.DebuggerStepThrough] - public static IEnumerable GetSelectObjects(this SelectionSet ss) where T : SelectedObject - { - return ss.Cast().OfType(); - } - /// /// 从选择集中获取对象id /// @@ -40,11 +17,10 @@ public static IEnumerable GetSelectObjects(this SelectionSet ss) where T : [System.Diagnostics.DebuggerStepThrough] public static IEnumerable GetObjectIds(this SelectionSet ss) where T : Entity { - string dxfName = RXClass.GetClass(typeof(T)).DxfName; - return - ss - .GetObjectIds() - .Where(id => id.ObjectClass.DxfName == dxfName); + var rxc = RXObject.GetClass(typeof(T)); + + return ss.GetObjectIds() + .Where(id => id.ObjectClass.IsDerivedFrom(rxc)); } /// @@ -55,10 +31,8 @@ public static IEnumerable GetObjectIds(this SelectionSet ss) where [System.Diagnostics.DebuggerStepThrough] public static IEnumerable> GetObjectIdGroup(this SelectionSet ss) { - return - ss - .GetObjectIds() - .GroupBy(id => id.ObjectClass.DxfName); + return ss.GetObjectIds() + .GroupBy(id => id.ObjectClass.DxfName); } #endregion @@ -74,16 +48,14 @@ public static IEnumerable> GetObjectIdGroup(this Sel /// 是否打开锁定图层对象,默认为不打开 /// 图元集合 [System.Diagnostics.DebuggerStepThrough] - public static IEnumerable GetEntities(this SelectionSet ss, + public static IEnumerable GetEntities(this SelectionSet? ss, OpenMode openMode = OpenMode.ForRead, bool openErased = false, bool openLockedLayer = false) where T : Entity { - if (ss is null) - return new List(); - return ss.GetObjectIds() - .Select(id => id.GetObject(openMode, openErased, openLockedLayer)) - .OfType(); + return ss?.GetObjectIds() + .Select(id => id.GetObject(openMode, openErased, openLockedLayer)) + .OfType() ?? []; } #endregion @@ -104,7 +76,8 @@ public static void ForEach(this SelectionSet ss, bool openErased = false, bool openLockedLayer = false) where T : Entity { - ForEach(ss, (ent, state) => { + ForEach(ss, (ent, _) => + { action.Invoke(ent); }, openMode, openErased, openLockedLayer); } @@ -121,7 +94,7 @@ public static void ForEach(this SelectionSet ss, /// [System.Diagnostics.DebuggerStepThrough] public static void ForEach(this SelectionSet ss, - Action action, + Action action, OpenMode openMode = OpenMode.ForRead, bool openErased = false, bool openLockedLayer = false) where T : Entity diff --git a/tests/TestShared/TestSelectfilter.cs b/tests/TestShared/TestSelectfilter.cs index ff47d00..cab6c92 100644 --- a/tests/TestShared/TestSelectfilter.cs +++ b/tests/TestShared/TestSelectfilter.cs @@ -29,4 +29,30 @@ public void Test_Selectanpoint() var sel2 = Env.Editor.SelectAtPoint(new Point3d(0, 0, 0)); Env.Editor.WriteMessage(""); } +} + +public class TestSelectObjectType +{ + [CommandMethod(nameof(Test_Select_type))] + public void Test_Select_type() + { + var sel = Env.Editor.SSGet(); + if (sel.Status != PromptStatus.OK) return; + var ids = sel.Value.GetObjectIds(); + foreach (var item in ids) + { + item.Print(); + } + + var dxfName = RXObject.GetClass(typeof(Dimension)).DxfName; + dxfName.Print(); + var idss = sel.Value.GetObjectIds(); + foreach (var item in idss) + { + item.Print(); + item.ObjectClass.DxfName.Print(); + } + + } + } \ No newline at end of file -- Gitee From 3af7e731b2202585f6b4d8f4d1c28de3cde5d417 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Sun, 21 Jan 2024 19:16:19 +0800 Subject: [PATCH 244/453] =?UTF-8?q?=E5=B0=86IFoxUtils=E7=9A=84=E5=86=85?= =?UTF-8?q?=E5=AE=B9=E5=85=A8=E9=83=A8=E7=A7=BB=E8=87=B3Tools=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E9=87=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../IFox.CAD.Shared/ExtensionMethod/Tools.cs | 126 ++++++++++++++---- .../IFox.CAD.Shared/IFox.CAD.Shared.projitems | 1 - src/CAD/IFox.CAD.Shared/Runtime/IFoxUtils.cs | 92 ------------- 3 files changed, 102 insertions(+), 117 deletions(-) delete mode 100644 src/CAD/IFox.CAD.Shared/Runtime/IFoxUtils.cs diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Tools.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Tools.cs index e270233..17846f6 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Tools.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Tools.cs @@ -1,5 +1,4 @@ using static IFoxCAD.Basal.Timer; - namespace IFoxCAD.Cad; /// /// 工具类 @@ -14,12 +13,12 @@ public static void TestTimes2(int count, string message, Action action) { System.Diagnostics.Stopwatch watch = new(); watch.Start(); // 开始监视代码运行时间 - for (int i = 0; i < count; i++) + for (var i = 0; i < count; i++) action.Invoke();// 需要测试的代码 watch.Stop(); // 停止监视 - TimeSpan timespan = watch.Elapsed; // 获取当前实例测量得出的总时间 - double time = timespan.TotalMilliseconds; - string name = "毫秒"; + var timespan = watch.Elapsed; // 获取当前实例测量得出的总时间 + var time = timespan.TotalMilliseconds; + var name = "毫秒"; if (timespan.TotalMilliseconds > 1000) { time = timespan.TotalSeconds; @@ -36,12 +35,12 @@ public static void TestTimes3(int count, string message, Action action) { System.Diagnostics.Stopwatch watch = new(); watch.Start(); // 开始监视代码运行时间 - for (int i = 0; i < count; i++) + for (var i = 0; i < count; i++) action.Invoke(i);// 需要测试的代码 watch.Stop(); // 停止监视 - TimeSpan timespan = watch.Elapsed; // 获取当前实例测量得出的总时间 - double time = timespan.TotalMilliseconds; - string name = "毫秒"; + var timespan = watch.Elapsed; // 获取当前实例测量得出的总时间 + var time = timespan.TotalMilliseconds; + var name = "毫秒"; if (timespan.TotalMilliseconds > 1000) { time = timespan.TotalSeconds; @@ -60,27 +59,106 @@ public static void TestTimes(int count, string message, Action action, TimeEnum timeEnum = TimeEnum.Millisecond) { var time = RunTime(() => { - for (int i = 0; i < count; i++) + for (var i = 0; i < count; i++) action.Invoke(); }, timeEnum); - string timeNameZn = ""; - switch (timeEnum) + var timeNameZn = timeEnum switch { - case TimeEnum.Second: - timeNameZn = " 秒"; - break; - case TimeEnum.Millisecond: - timeNameZn = " 毫秒"; - break; - case TimeEnum.Microsecond: - timeNameZn = " 微秒"; - break; - case TimeEnum.Nanosecond: - timeNameZn = " 纳秒"; + TimeEnum.Millisecond => " 毫秒", + TimeEnum.Microsecond => " 微秒", + TimeEnum.Nanosecond => " 纳秒", + _ => " 秒" + }; + + Env.Print($"{message} 代码执行 {count} 次的时间:{time} ({timeNameZn})"); + } + +#if acad + /// + /// 刷新图层状态,在修改图层的锁定或冻结状态后使用 + /// + /// 图层id集合 + public static void RegenLayers(IEnumerable objectIds) + { + var type = Acaop.Version.Major >= 21 + ? Assembly.Load("accoremgd")?.GetType("Autodesk.AutoCAD.Internal.CoreLayerUtilities") + : Assembly.Load("acmgd")?.GetType("Autodesk.AutoCAD.Internal.LayerUtilities"); + var mi = type?.GetMethods().FirstOrDefault(e => e.Name == "RegenLayers"); + var pi = type?.GetProperties().FirstOrDefault(e => e.Name == "RegenPending"); + var regenPending = (int)(pi?.GetValue(null) ?? 0); + mi?.Invoke(null, new object[] { objectIds.ToArray(), regenPending }); + } + + /// + /// 发送气泡通知 + /// + /// 显示的秒数,范围1-10为相应秒数,0为常显 + /// 标题 + /// 内容1 + /// 图标样式 + /// 链接 + /// 链接地址 + /// 内容2 + public static void ShowBubbleWindow(int second, string title, string text, Autodesk.AutoCAD.Windows.IconType iconType = Autodesk.AutoCAD.Windows.IconType.None, string? hyperText = null, string? hyperLink = null, string? text2 = null) + { + Autodesk.AutoCAD.Windows.TrayItem? trayItem = null; + const string name = "IFox"; + var num = Acap.StatusBar.TrayItems.Count; + for (var i = 0; i < num; i++) + { + var ti = Acap.StatusBar.TrayItems[i]; + if (ti.ToolTipText != name) continue; + trayItem = ti; break; } + if (trayItem == null) + { + trayItem = new() + { + ToolTipText = name, + Visible = true, + }; + Acap.StatusBar.TrayItems.Add(trayItem); + Acap.StatusBar.Update(); + } + if (second <= 0) second = 0; + else if (second % 10 == 0) second = 10; + else second %= 10; + Acaop.SetSystemVariable("TrayTimeOut", second); + var tibw = new Autodesk.AutoCAD.Windows.TrayItemBubbleWindow + { + IconType = iconType, + Title = title, + Text = text, + HyperText = hyperText, + HyperLink = hyperLink, + Text2 = text2 + }; + Acaop.SetSystemVariable("TRAYICONS", 1); + Acaop.SetSystemVariable("TRAYNOTIFY", 1); + trayItem.Visible = true; + trayItem.ShowBubbleWindow(tibw); + } - Env.Print($"{message} 代码执行 {count} 次的时间:{time} ({timeNameZn})"); + /// + /// 否决双击事件本身的后续操作,在双击事件中使用 + /// + public static void VetoMouseDoubleClickEvent() + { + const string key = "DBLCLKEDIT"; + var value = Acaop.GetSystemVariable(key); + Acaop.SetSystemVariable(key, 0); + IdleAction.Add(() => Acaop.SetSystemVariable(key, value)); + } + /// + /// 获取透明度 + /// + /// cad特性栏透明度值,范围0-100 + /// cad透明度值 + public static Transparency CreateTransparency(int value) + { + return new Transparency(Convert.ToByte(Math.Floor((100 - value) * 2.55))); } +#endif } \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems b/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems index af053ce..4a618ff 100644 --- a/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems +++ b/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems @@ -81,7 +81,6 @@ - diff --git a/src/CAD/IFox.CAD.Shared/Runtime/IFoxUtils.cs b/src/CAD/IFox.CAD.Shared/Runtime/IFoxUtils.cs deleted file mode 100644 index e87621b..0000000 --- a/src/CAD/IFox.CAD.Shared/Runtime/IFoxUtils.cs +++ /dev/null @@ -1,92 +0,0 @@ -namespace IFoxCAD.Cad; - -#if acad -/// -/// ifox工具类 -/// -public sealed class IFoxUtils -{ - /// - /// 刷新图层状态,在修改图层的锁定或冻结状态后使用 - /// - /// 图层id集合 - public static void RegenLayers(IEnumerable objectIds) - { - var type = Acap.Version.Major >= 21 ? Assembly.Load("accoremgd")?.GetType("Autodesk.AutoCAD.Internal.CoreLayerUtilities") : Assembly.Load("acmgd")?.GetType("Autodesk.AutoCAD.Internal.LayerUtilities"); - var mi = type?.GetMethods().FirstOrDefault(e => e.Name == "RegenLayers"); - var pi = type?.GetProperties().FirstOrDefault(e => e.Name == "RegenPending"); - var regenPending = (int)(pi?.GetValue(null) ?? 0); - mi?.Invoke(null, new object[] { objectIds.ToArray(), regenPending }); - } - /// - /// 发送气泡通知 - /// - /// 显示的秒数,范围1-10为相应秒数,0为常显 - /// 标题 - /// 内容1 - /// 图标样式 - /// 链接 - /// 链接地址 - /// 内容2 - public static void ShowBubbleWindow(int second, string title, string text, Autodesk.AutoCAD.Windows.IconType iconType = Autodesk.AutoCAD.Windows.IconType.None, string? hyperText = null, string? hyperLink = null, string? text2 = null) - { - Autodesk.AutoCAD.Windows.TrayItem? trayItem = null; - const string name = "IFox"; - var num = Acap.StatusBar.TrayItems.Count; - for (int i = 0; i < num; i++) - { - var ti = Acap.StatusBar.TrayItems[i]; - if (ti.ToolTipText == name) - { - trayItem = ti; - break; - } - } - if (trayItem == null) - { - trayItem = new() - { - ToolTipText = name, - Visible = true, - }; - Acap.StatusBar.TrayItems.Add(trayItem); - Acap.StatusBar.Update(); - } - if (second <= 0) second = 0; - else if (second % 10 == 0) second = 10; - else second %= 10; - Acap.SetSystemVariable("TrayTimeOut", second); - var tibw = new Autodesk.AutoCAD.Windows.TrayItemBubbleWindow(); - tibw.IconType = iconType; - tibw.Title = title; - tibw.Text = text; - tibw.HyperText = hyperText; - tibw.HyperLink = hyperLink; - tibw.Text2 = text2; - Acap.SetSystemVariable("TRAYICONS", 1); - Acap.SetSystemVariable("TRAYNOTIFY", 1); - trayItem.Visible = true; - trayItem.ShowBubbleWindow(tibw); - } - - /// - /// 否决双击事件本身的后续操作,在双击事件中使用 - /// - public static void VetoMouseDoubleClickEvent() - { - const string key = "DBLCLKEDIT"; - var value = Acap.GetSystemVariable(key); - Acap.SetSystemVariable(key, 0); - IdleAction.Add(() => Acap.SetSystemVariable(key, value)); - } - /// - /// 获取透明度 - /// - /// cad特性栏透明度值,范围0-100 - /// cad透明度值 - public static Transparency CreateTransparency(int value) - { - return new Transparency(Convert.ToByte(Math.Floor((100 - value) * 2.55))); - } -} -#endif \ No newline at end of file -- Gitee From 4af1fb4158287f546ce4c88c3a5add670fdff16f Mon Sep 17 00:00:00 2001 From: vicwjb Date: Wed, 24 Jan 2024 21:35:48 +0800 Subject: [PATCH 245/453] =?UTF-8?q?=E8=AE=B2=E5=A4=8D=E6=9D=82=E7=9A=84?= =?UTF-8?q?=E5=88=A4=E6=96=AD=E8=AF=AD=E5=8F=A5=E6=94=B9=E5=86=99,?= =?UTF-8?q?=E4=BB=A5=E5=8F=8A=E5=85=B6=E4=BB=96=E7=9A=84=E5=86=99=E6=B3=95?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/SymbolTableEx.cs | 63 +++++++++++-------- 1 file changed, 38 insertions(+), 25 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableEx.cs index 928f03f..7db088c 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableEx.cs @@ -34,17 +34,17 @@ public static ObjectId Add(this SymbolTable table, /// 更改图层名 /// /// 图层符号表 - /// 旧图层名 - /// 新图层名 - public static ObjectId Rename(this SymbolTable table, string Oldname, string NewName) + /// 旧图层名 + /// 新图层名 + public static ObjectId Rename(this SymbolTable table, string oldName, string newName) { - if (!table.Has(Oldname)) + if (!table.Has(oldName)) return ObjectId.Null; - table.Change(Oldname, layer => { - layer.Name = NewName; + table.Change(oldName, layer => { + layer.Name = newName; }); - return table[NewName]; + return table[newName]; } /// /// 删除图层 @@ -129,7 +129,7 @@ public static ObjectId Add(this SymbolTable table, /// public static ObjectId Add(this SymbolTable table, string name, params Entity[] ents) { - return table.Add(name, null, () => { return ents; }); + return table.Add(name, null, () => ents); } /// @@ -142,15 +142,14 @@ public static void AddAttsToBlocks(this SymbolTable atts) { - List attTags = new(); - table.Change(id, btr => { - + List attTags = []; + table.Change(id, btr => + { btr.GetEntities() .ForEach(def => attTags.Add(def.Tag.ToUpper())); - for (int i = 0; i < atts.Count; i++) - if (!attTags.Contains(atts[i].Tag.ToUpper())) - btr.AddEntity(atts[i]); + foreach (var t in atts.Where(t => !attTags.Contains(t.Tag.ToUpper()))) + btr.AddEntity(t); }); } /// @@ -163,15 +162,14 @@ public static void AddAttsToBlocks(this SymbolTable atts) { - List attTags = new(); - table.Change(name, btr => { - + List attTags = []; + table.Change(name, btr => + { btr.GetEntities() .ForEach(def => attTags.Add(def.Tag.ToUpper())); - for (int i = 0; i < atts.Count; i++) - if (!attTags.Contains(atts[i].Tag.ToUpper())) - btr.AddEntity(atts[i]); + foreach (var t in atts.Where(t => !attTags.Contains(t.Tag.ToUpper()))) + btr.AddEntity(t); }); } @@ -185,20 +183,35 @@ public static void AddAttsToBlocks(this SymbolTable table, string fileName, bool over) { - string blkdefname = SymbolUtilityServices.GetSymbolNameFromPathName(fileName, "dwg"); + var blkdefname = SymbolUtilityServices.GetSymbolNameFromPathName(fileName, "dwg"); #if acad blkdefname = SymbolUtilityServices.RepairSymbolName(blkdefname, false); #endif - ObjectId id = table[blkdefname]; - bool has = id != ObjectId.Null; - if ((has && over) || !has) + var id = table[blkdefname]; + var has = id != ObjectId.Null; + + /* 每次看这里都要反应一阵 + 如果已经有这个id,并且要覆盖,或者没有这个id就执行下面的语句,不然就直接返回id + 其实就是如果有这个id,并且不覆盖,就直接返回,其他的情况都需要重新插入 + 所以原代码可以修改 + if (has && over || !has) { using Database db = new(false, true); db.ReadDwgFile(fileName, FileShare.Read, true, null); db.CloseInput(true); id = table.Database.Insert(BlockTableRecord.ModelSpace, blkdefname, db, false); - } + return id; + } */ + + if (has is true && over is false) + { + return id; + } + using Database db = new(false, true); + db.ReadDwgFile(fileName, FileShare.Read, true, null); + db.CloseInput(true); + id = table.Database.Insert(BlockTableRecord.ModelSpace, blkdefname, db, false); return id; } -- Gitee From b735595e78ffb1814711bb2d07fbd9ab1ec1f864 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Mon, 22 Jan 2024 16:30:31 +0800 Subject: [PATCH 246/453] =?UTF-8?q?=E7=BB=A7=E7=BB=AD=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../IFox.Basal.Shared/WindowsAPI/MouseHook.cs | 24 +++--- .../WindowsAPI/WindowsAPI.cs | 2 +- .../IFox.CAD.Shared/Algorithms/Graph/Graph.cs | 2 +- .../Algorithms/QuadTree/QuadTree.cs | 6 +- src/CAD/IFox.CAD.Shared/AutoReg/AcadEMR.cs | 2 - src/CAD/IFox.CAD.Shared/AutoReg/AssemInfo.cs | 1 + src/CAD/IFox.CAD.Shared/AutoReg/AutoLoad.cs | 13 ++- src/CAD/IFox.CAD.Shared/AutoReg/AutoReg.cs | 52 +++++------- .../IFox.CAD.Shared/AutoReg/AutoRegAssem.cs | 27 +++--- src/CAD/IFox.CAD.Shared/AutoReg/IAutoGo.cs | 83 ++++++++----------- .../AutoReg/MethodInfoHelper.cs | 4 +- .../IFox.CAD.Shared/CadVersion/AcadVersion.cs | 46 ++++------ 12 files changed, 109 insertions(+), 153 deletions(-) diff --git a/src/Basal/IFox.Basal.Shared/WindowsAPI/MouseHook.cs b/src/Basal/IFox.Basal.Shared/WindowsAPI/MouseHook.cs index 29cbca7..46f1725 100644 --- a/src/Basal/IFox.Basal.Shared/WindowsAPI/MouseHook.cs +++ b/src/Basal/IFox.Basal.Shared/WindowsAPI/MouseHook.cs @@ -34,7 +34,7 @@ public class MouseHook public event EventHandler? DoubleClick; - bool _isHookBreak = false; + private bool _isHookBreak; /// /// 否决本次输入:设置不向下回调 /// @@ -52,7 +52,8 @@ public void Vote() [DllImport("user32.dll", EntryPoint = "GetDoubleClickTime")] public extern static int GetDoubleClickTime(); - static readonly Stopwatch _watch = new(); + + private static readonly Stopwatch _watch = new(); /// /// 安装鼠标钩子 @@ -66,7 +67,7 @@ public MouseHook(int setLowLevel = 25000) _watch.Start(); } - void UnHook() + private void UnHook() { if (_NextHookProc != IntPtr.Zero) { @@ -109,14 +110,13 @@ public void SetHook(bool processHook = false) } - - MouseButtons _button; - int _clickCount = 0; - bool _down = false; - bool _up = false; - bool _ck = false; - bool _wheel = false; - bool _move = false; + private MouseButtons _button; + private int _clickCount = 0; + private bool _down = false; + private bool _up = false; + private bool _ck = false; + private bool _wheel = false; + private bool _move = false; /// /// 钩子的消息处理 @@ -125,7 +125,7 @@ public void SetHook(bool processHook = false) /// /// /// false不终止回调,true终止回调 - bool HookTask(int nCode, int wParam, IntPtr lParam) + private bool HookTask(int nCode, int wParam, IntPtr lParam) { if (MouseDown is null && MouseUp is null diff --git a/src/Basal/IFox.Basal.Shared/WindowsAPI/WindowsAPI.cs b/src/Basal/IFox.Basal.Shared/WindowsAPI/WindowsAPI.cs index 3e6fd0a..986a7f9 100644 --- a/src/Basal/IFox.Basal.Shared/WindowsAPI/WindowsAPI.cs +++ b/src/Basal/IFox.Basal.Shared/WindowsAPI/WindowsAPI.cs @@ -342,7 +342,7 @@ public partial class WindowsAPI /// /// 窗口标识符 /// 窗口文字 - /// 文字长度 + /// 文字长度 /// [DllImport("User32.dll", CharSet = CharSet.Auto)] public static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int nMaxCount); diff --git a/src/CAD/IFox.CAD.Shared/Algorithms/Graph/Graph.cs b/src/CAD/IFox.CAD.Shared/Algorithms/Graph/Graph.cs index 43e09bc..7b0097a 100644 --- a/src/CAD/IFox.CAD.Shared/Algorithms/Graph/Graph.cs +++ b/src/CAD/IFox.CAD.Shared/Algorithms/Graph/Graph.cs @@ -658,7 +658,7 @@ private static List Invert(List lst, IGraphVertex ve return tmp.Skip(index).Concat(lst.Take(index)).ToList(); } - private static (string, string) GetHashString(List pathone, List pathtwo) + private static (string, string) GetHashString(IReadOnlyList pathone, IReadOnlyList pathtwo) { var one = new string[pathone.Count]; var two = new string[pathtwo.Count]; diff --git a/src/CAD/IFox.CAD.Shared/Algorithms/QuadTree/QuadTree.cs b/src/CAD/IFox.CAD.Shared/Algorithms/QuadTree/QuadTree.cs index 403cc6c..2872540 100644 --- a/src/CAD/IFox.CAD.Shared/Algorithms/QuadTree/QuadTree.cs +++ b/src/CAD/IFox.CAD.Shared/Algorithms/QuadTree/QuadTree.cs @@ -176,7 +176,7 @@ public List Query(Rect rect, QuadTreeSelectMode selectMode = QuadTreeSe // 选择图元 _rootNode.Query(rect, results); // 选择点 - var ptge = _points.GetEnumerator(); + using var ptge = _points.GetEnumerator(); switch (selectMode) { case QuadTreeSelectMode.IntersectsWith: @@ -190,12 +190,12 @@ public List Query(Rect rect, QuadTreeSelectMode selectMode = QuadTreeSe while (ptge.MoveNext()) { var ptEnt = ptge.Current; - if (rect._X <= ptEnt._X && ptEnt._X <= rect._Right) + if (ptEnt != null && rect._X <= ptEnt._X && ptEnt._X <= rect._Right) { if (rect._Y <= ptEnt._Y && ptEnt._Y <= rect.Top) results.Add(ptEnt); } - else if (ptEnt._X > rect._Right) + else if (ptEnt != null && ptEnt._X > rect._Right) break;// 超过后面范围就break,因为红黑树已经排序 } break; diff --git a/src/CAD/IFox.CAD.Shared/AutoReg/AcadEMR.cs b/src/CAD/IFox.CAD.Shared/AutoReg/AcadEMR.cs index 0d4fe6c..6cde870 100644 --- a/src/CAD/IFox.CAD.Shared/AutoReg/AcadEMR.cs +++ b/src/CAD/IFox.CAD.Shared/AutoReg/AcadEMR.cs @@ -1,8 +1,6 @@ #if true namespace IFoxCAD.Cad; -using System.Diagnostics; - // 作者: [VB.net]福萝卜 莱昂纳多·胖子 // Email:oneeshine@163.com // QQ: 461884072 diff --git a/src/CAD/IFox.CAD.Shared/AutoReg/AssemInfo.cs b/src/CAD/IFox.CAD.Shared/AutoReg/AssemInfo.cs index 94827a5..f200e4d 100644 --- a/src/CAD/IFox.CAD.Shared/AutoReg/AssemInfo.cs +++ b/src/CAD/IFox.CAD.Shared/AutoReg/AssemInfo.cs @@ -58,6 +58,7 @@ public enum AssemLoadType /// /// 注册中心配置信息 /// +[Flags] public enum AutoRegConfig { /// diff --git a/src/CAD/IFox.CAD.Shared/AutoReg/AutoLoad.cs b/src/CAD/IFox.CAD.Shared/AutoReg/AutoLoad.cs index 934f40a..7c84a04 100644 --- a/src/CAD/IFox.CAD.Shared/AutoReg/AutoLoad.cs +++ b/src/CAD/IFox.CAD.Shared/AutoReg/AutoLoad.cs @@ -5,7 +5,7 @@ /// public abstract class AutoLoad : IExtensionApplication { - private AssemInfo _info = new(); + private readonly AssemInfo _info; /// /// 程序集的路径 @@ -15,19 +15,16 @@ public abstract class AutoLoad : IExtensionApplication /// /// 程序集的目录 /// - public static DirectoryInfo CurrentDirectory => Location.Directory; + public static DirectoryInfo? CurrentDirectory => Location.Directory; /// /// 获取程序集的目录 /// /// 程序集 /// 路径对象 - public static DirectoryInfo GetDirectory(Assembly assem) + public static DirectoryInfo? GetDirectory(Assembly assem) { - if (assem == null) - { - throw new(nameof(assem)); - } + ArgumentNullEx.ThrowIfNull(assem); return new FileInfo(assem.Location).Directory; } @@ -36,7 +33,7 @@ public static DirectoryInfo GetDirectory(Assembly assem) /// public AutoLoad() { - Assembly assem = Assembly.GetCallingAssembly(); + var assem = Assembly.GetCallingAssembly(); _info.Loader = assem.Location; _info.Fullname = assem.FullName; _info.Name = assem.GetName().Name; diff --git a/src/CAD/IFox.CAD.Shared/AutoReg/AutoReg.cs b/src/CAD/IFox.CAD.Shared/AutoReg/AutoReg.cs index 32e28db..0588d12 100644 --- a/src/CAD/IFox.CAD.Shared/AutoReg/AutoReg.cs +++ b/src/CAD/IFox.CAD.Shared/AutoReg/AutoReg.cs @@ -3,17 +3,17 @@ /// /// 自动加载辅助类 /// -public class AutoReg +public static class AutoReg { /// /// 获取自动加载注册表位置节点 /// /// 注册表节点 - public static RegistryKey GetAcAppKey() + public static RegistryKey? GetAcAppKey() { - string key = HostApplicationServices.Current.UserRegistryProductRootKey; - RegistryKey ackey = Registry.CurrentUser.OpenSubKey(key, true); - return ackey.CreateSubKey("Applications"); + var key = HostApplicationServices.Current.UserRegistryProductRootKey; + var ackey = Registry.CurrentUser.OpenSubKey(key, true); + return ackey?.CreateSubKey("Applications"); } /// /// 是否已经自动加载 @@ -24,17 +24,14 @@ public static bool SearchForReg(AssemInfo info) { // 在使用netloadx的时候,此处注册表是失效的,具体原因要进行netloadx测试 var appkey = GetAcAppKey(); - if (appkey.SubKeyCount == 0) + if (appkey?.SubKeyCount == 0) return false; - var regApps = appkey.GetSubKeyNames(); - if (regApps.Contains(info.Name)) - { - // 20220409 bug:文件名相同,路径不同,需要判断路径 - var subkey = appkey.OpenSubKey(info.Name); - return subkey.GetValue("LOADER")?.ToString().ToLower() == info.Loader.ToLower(); - } - return false; + var regApps = appkey?.GetSubKeyNames(); + if (regApps == null || !regApps.Contains(info.Name)) return false; + // 20220409 bug:文件名相同,路径不同,需要判断路径 + var subkey = appkey?.OpenSubKey(info.Name); + return string.Equals(subkey?.GetValue("LOADER")?.ToString(), info.Loader, StringComparison.CurrentCultureIgnoreCase); } /// @@ -43,13 +40,13 @@ public static bool SearchForReg(AssemInfo info) /// 程序集信息 public static void RegApp(AssemInfo info) { - RegistryKey appkey = GetAcAppKey(); - RegistryKey rk = appkey.CreateSubKey(info.Name); - rk.SetValue("DESCRIPTION", info.Fullname, RegistryValueKind.String); - rk.SetValue("LOADCTRLS", info.LoadType, RegistryValueKind.DWord); - rk.SetValue("LOADER", info.Loader, RegistryValueKind.String); - rk.SetValue("MANAGED", 1, RegistryValueKind.DWord); - appkey.Close(); + var appkey = GetAcAppKey(); + var rk = appkey?.CreateSubKey(info.Name); + rk?.SetValue("DESCRIPTION", info.Fullname, RegistryValueKind.String); + rk?.SetValue("LOADCTRLS", info.LoadType, RegistryValueKind.DWord); + rk?.SetValue("LOADER", info.Loader, RegistryValueKind.String); + rk?.SetValue("MANAGED", 1, RegistryValueKind.DWord); + appkey?.Close(); } /// @@ -58,15 +55,12 @@ public static void RegApp(AssemInfo info) public static bool UnRegApp(AssemInfo info) { var appkey = GetAcAppKey(); - if (appkey.SubKeyCount == 0) + if (appkey is { SubKeyCount: 0 }) return false; - var regApps = appkey.GetSubKeyNames(); - if (regApps.Contains(info.Name)) - { - appkey.DeleteSubKey(info.Name, false); - return true; - } - return false; + var regApps = appkey?.GetSubKeyNames(); + if (regApps != null && !regApps.Contains(info.Name)) return false; + appkey?.DeleteSubKey(info.Name, false); + return true; } } diff --git a/src/CAD/IFox.CAD.Shared/AutoReg/AutoRegAssem.cs b/src/CAD/IFox.CAD.Shared/AutoReg/AutoRegAssem.cs index fd3c361..32bf875 100644 --- a/src/CAD/IFox.CAD.Shared/AutoReg/AutoRegAssem.cs +++ b/src/CAD/IFox.CAD.Shared/AutoReg/AutoRegAssem.cs @@ -14,8 +14,8 @@ public abstract class AutoRegAssem : IExtensionApplication { #region 字段 - readonly AssemInfo _info; - readonly AutoReflection? _autoRef; + + private readonly AutoReflection? _autoRef; #endregion #region 静态方法 @@ -26,16 +26,15 @@ public abstract class AutoRegAssem : IExtensionApplication /// /// 程序集的目录 /// - public static DirectoryInfo CurrDirectory => Location.Directory; + public static DirectoryInfo? CurrDirectory => Location.Directory; /// /// 获取程序集的目录 /// /// 程序集 /// 路径对象 - public static DirectoryInfo GetDirectory(Assembly? assem) + public static DirectoryInfo? GetDirectory(Assembly? assem) { - if (assem is null) - throw new(nameof(assem)); + ArgumentNullEx.ThrowIfNull(assem); return new FileInfo(assem.Location).Directory; } #endregion @@ -48,7 +47,7 @@ public static DirectoryInfo GetDirectory(Assembly? assem) public AutoRegAssem(AutoRegConfig autoRegConfig) { var assem = Assembly.GetCallingAssembly(); - _info = new() + var info = new AssemInfo { Loader = assem.Location, Fullname = assem.FullName, @@ -58,8 +57,8 @@ public AutoRegAssem(AutoRegConfig autoRegConfig) if ((autoRegConfig & AutoRegConfig.Regedit) == AutoRegConfig.Regedit) { - if (!AutoReg.SearchForReg(_info)) - AutoReg.RegApp(_info); + if (!AutoReg.SearchForReg(info)) + AutoReg.RegApp(info); } if ((autoRegConfig & AutoRegConfig.RemoveEMR) == AutoRegConfig.RemoveEMR) @@ -68,12 +67,10 @@ public AutoRegAssem(AutoRegConfig autoRegConfig) // 实例化了 AutoClass 之后会自动执行 IFoxAutoGo 接口下面的类, // 以及自动执行特性 [IFoxInitialize] // 类库用户不在此处进行其他代码,而是实现特性 - if ((autoRegConfig & AutoRegConfig.ReflectionInterface) == AutoRegConfig.ReflectionInterface || - (autoRegConfig & AutoRegConfig.ReflectionAttribute) == AutoRegConfig.ReflectionAttribute) - { - _autoRef = new AutoReflection(_info.Name, autoRegConfig); - _autoRef.Initialize(); - } + if ((autoRegConfig & AutoRegConfig.ReflectionInterface) != AutoRegConfig.ReflectionInterface && + (autoRegConfig & AutoRegConfig.ReflectionAttribute) != AutoRegConfig.ReflectionAttribute) return; + _autoRef = new AutoReflection(info.Name, autoRegConfig); + _autoRef.Initialize(); } #endregion diff --git a/src/CAD/IFox.CAD.Shared/AutoReg/IAutoGo.cs b/src/CAD/IFox.CAD.Shared/AutoReg/IAutoGo.cs index 3cd31af..e9bb446 100644 --- a/src/CAD/IFox.CAD.Shared/AutoReg/IAutoGo.cs +++ b/src/CAD/IFox.CAD.Shared/AutoReg/IAutoGo.cs @@ -1,6 +1,6 @@ namespace IFoxCAD.Cad; -using System.Collections.ObjectModel; + using System.Diagnostics; /// @@ -44,55 +44,42 @@ public interface IFoxAutoGo /// /// 加载时自动执行特性 /// +/// +/// 用于初始化和结束回收 +/// +/// 优先级 +/// 用于初始化;用于结束回收 [AttributeUsage(AttributeTargets.Method)] -public class IFoxInitialize : Attribute +public class IFoxInitialize(Sequence sequence = Sequence.Last, bool isInitialize = true) : Attribute { /// /// 优先级 /// - internal Sequence SequenceId; + internal Sequence SequenceId = sequence; /// /// 用于初始化;用于结束回收 /// - internal bool IsInitialize; - /// - /// 用于初始化和结束回收 - /// - /// 优先级 - /// 用于初始化;用于结束回收 - public IFoxInitialize(Sequence sequence = Sequence.Last, bool isInitialize = true) - { - SequenceId = sequence; - IsInitialize = isInitialize; - } + internal bool IsInitialize = isInitialize; } // 为了解决IExtensionApplication在一个dll内无法多次实现接口的关系 // 所以在这里反射加载所有的 IAutoGo ,以达到能分开写"启动运行"函数的目的 -class RunClass +/// +/// 执行此方法 +/// +/// +/// +/// 已经创建的对象 +internal class RunClass(MethodInfo method, Sequence sequence, object? instance = null) { - public Sequence Sequence { get; } - readonly MethodInfo _methodInfo; - object? _instance; - /// - /// 执行此方法 - /// - /// - /// - /// 已经创建的对象 - public RunClass(MethodInfo method, Sequence sequence, object? instance = null) - { - _methodInfo = method; - Sequence = sequence; - _instance = instance; - } + public Sequence Sequence { get; } = sequence; /// /// 运行方法 /// public void Run() { - _methodInfo.Invoke(ref _instance); + method.Invoke(ref instance); } } @@ -115,8 +102,8 @@ public void Run() /// public class AutoReflection(string dllName, AutoRegConfig configInfo) { - static List _InitializeList = []; // 储存方法用于初始化 - static List _TerminateList = []; // 储存方法用于结束释放 + private static List _InitializeList = []; // 储存方法用于初始化 + private static List _TerminateList = []; // 储存方法用于结束释放 readonly string _dllName = dllName; readonly AutoRegConfig _autoRegConfig = configInfo; @@ -137,12 +124,10 @@ public void Initialize() GetInterfaceFunctions(_InitializeList, nameof(Initialize), _TerminateList, nameof(Terminate)); } - if (_InitializeList.Count > 0) - { - // 按照 SequenceId 排序_升序 - _InitializeList = _InitializeList.OrderBy(runClass => runClass.Sequence).ToList(); - RunFunctions(_InitializeList); - } + if (_InitializeList.Count <= 0) return; + // 按照 SequenceId 排序_升序 + _InitializeList = _InitializeList.OrderBy(runClass => runClass.Sequence).ToList(); + RunFunctions(_InitializeList); } catch { @@ -160,14 +145,12 @@ public void Terminate() //if ((_autoRegConfig & AutoRegConfig.ReflectionInterface) == AutoRegConfig.ReflectionInterface) // GetInterfaceFunctions(_TerminateList, nameof(Terminate)); - if (_TerminateList.Count > 0) - { - // 按照 SequenceId 排序_降序 - _TerminateList = _TerminateList.OrderByDescending(runClass => runClass.Sequence).ToList(); - RunFunctions(_TerminateList); - } + if (_TerminateList.Count <= 0) return; + // 按照 SequenceId 排序_降序 + _TerminateList = [.. _TerminateList.OrderByDescending(runClass => runClass.Sequence)]; + RunFunctions(_TerminateList); } - catch (System.Exception e) + catch (Exception e) { Env.Printl(e.Message); Debugger.Break(); @@ -182,7 +165,7 @@ public void Terminate() public static void AppDomainGetTypes(Action action, string? dllNameWithoutExtension = null) { #if DEBUG - int error = 0; + var error = 0; #endif try { @@ -194,7 +177,7 @@ public static void AppDomainGetTypes(Action action, string? dllNameWithout assemblies = Array.FindAll(assemblies, p => !p.IsDynamic); // 主程序域 - for (int ii = 0; ii < assemblies.Length; ii++) + for (var ii = 0; ii < assemblies.Length; ii++) { var assembly = assemblies[ii]; @@ -216,7 +199,7 @@ public static void AppDomainGetTypes(Action action, string? dllNameWithout if (types is null) continue; - for (int jj = 0; jj < types.Length; jj++) + for (var jj = 0; jj < types.Length; jj++) { var type = types[jj]; if (type is not null) @@ -230,7 +213,7 @@ public static void AppDomainGetTypes(Action action, string? dllNameWithout } } #if DEBUG - catch (System.Exception e) + catch (Exception e) { DebugEx.Printl($"出错:{nameof(AppDomainGetTypes)};计数{error};错误信息:{e.Message}"); Debugger.Break(); diff --git a/src/CAD/IFox.CAD.Shared/AutoReg/MethodInfoHelper.cs b/src/CAD/IFox.CAD.Shared/AutoReg/MethodInfoHelper.cs index 31be527..7aa9579 100644 --- a/src/CAD/IFox.CAD.Shared/AutoReg/MethodInfoHelper.cs +++ b/src/CAD/IFox.CAD.Shared/AutoReg/MethodInfoHelper.cs @@ -22,9 +22,9 @@ internal static class MethodInfoHelper // 新函数指针进入此处 // 参数数量一定要匹配,为null则参数个数不同导致报错, // 参数为stirng[],则可以传入object[]代替,其他参数是否还可以实现默认构造? - var args = new List { }; + var args = new List(); var paramInfos = methodInfo.GetParameters(); - for (int i = 0; i < paramInfos.Length; i++) + for (var i = 0; i < paramInfos.Length; i++) args.Add(null!); result = methodInfo.Invoke(null, args.ToArray());// 静态调用 } diff --git a/src/CAD/IFox.CAD.Shared/CadVersion/AcadVersion.cs b/src/CAD/IFox.CAD.Shared/CadVersion/AcadVersion.cs index 4ae8368..bfaa57d 100644 --- a/src/CAD/IFox.CAD.Shared/CadVersion/AcadVersion.cs +++ b/src/CAD/IFox.CAD.Shared/CadVersion/AcadVersion.cs @@ -1,6 +1,4 @@ - - -namespace IFoxCAD.Cad; +namespace IFoxCAD.Cad; /// /// cad版本号类 @@ -17,30 +15,22 @@ public static List Versions get { string[] copys = Registry.LocalMachine - .OpenSubKey(@"SOFTWARE\Autodesk\Hardcopy") + .OpenSubKey(@"SOFTWARE\Autodesk\Hardcopy")! .GetValueNames(); List _versions = []; - for (int i = 0; i < copys.Length; i++) - { - if (!Regex.IsMatch(copys[i], _pattern)) - continue; - - var gs = Regex.Match(copys[i], _pattern).Groups; - var ver = new CadVersion + _versions.AddRange(from t in copys + where Regex.IsMatch(t, _pattern) + let gs = Regex.Match(t, _pattern).Groups + select new CadVersion { - ProductRootKey = copys[i], - ProductName = Registry.LocalMachine - .OpenSubKey("SOFTWARE") - .OpenSubKey(copys[i]) - .GetValue("ProductName") - .ToString(), - + ProductRootKey = t, + ProductName = Registry.LocalMachine.OpenSubKey("SOFTWARE")!.OpenSubKey(t) + ?.GetValue("ProductName") + .ToString(), Major = int.Parse(gs[1].Value), Minor = int.Parse(gs[2].Value), - }; - _versions.Add(ver); - } + }); return _versions; } } @@ -52,20 +42,16 @@ public static List Versions { ArgumentNullEx.ThrowIfNull(app); - string acver = app.GetType() + var acver = app.GetType() .InvokeMember( "Version", BindingFlags.GetProperty, null, - app, - new object[0]).ToString(); + app, []).ToString(); var gs = Regex.Match(acver, @"(\d+)\.(\d+).*?").Groups; - int major = int.Parse(gs[1].Value); - int minor = int.Parse(gs[2].Value); - for (int i = 0; i < Versions.Count; i++) - if (Versions[i].Major == major && Versions[i].Minor == minor) - return Versions[i]; - return null; + var major = int.Parse(gs[1].Value); + var minor = int.Parse(gs[2].Value); + return Versions.FirstOrDefault(t => t.Major == major && t.Minor == minor); } } \ No newline at end of file -- Gitee From 2e52cbd0342e6331767cc48860263043ed1f5315 Mon Sep 17 00:00:00 2001 From: zhinanheshang Date: Fri, 26 Jan 2024 11:37:58 +0800 Subject: [PATCH 247/453] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=96=B0new=E7=9A=84?= =?UTF-8?q?dim=E5=AE=9E=E4=BD=93=E8=8E=B7=E5=8F=96=E5=8C=85=E5=9B=B4?= =?UTF-8?q?=E7=9B=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/Entity/EntityBoundingInfo.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs index 2719d18..32562a8 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs @@ -45,12 +45,18 @@ public static class EntityBoundingInfo else if (ent is Table table) { + if(table.IsNewObject) + table.GenerateLayout(); + table.RecomputeTableBlock(true); return table.GeometricExtents; } else if (ent is Dimension dim) { + if(dim.IsNewObject) + dim.GenerateLayout(); // 新new的实体生成布局,即可获取包围盒 + dim.RecomputeDimensionBlock(true); return dim.GeometricExtents; } -- Gitee From 5f6b62186f5a99be6f17e79484eeae6732c0f4b8 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Fri, 26 Jan 2024 18:23:17 +0800 Subject: [PATCH 248/453] =?UTF-8?q?2024=E5=B9=B41=E6=9C=8826=E6=97=A518:23?= =?UTF-8?q?=20=E5=91=A8=E4=BA=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../IFox.Basal.Shared.projitems | 70 ++-- .../ExtensionMethod/IdleAction.cs | 37 +- .../IFox.CAD.Shared/IFox.CAD.Shared.projitems | 194 +++++----- src/CAD/IFox.CAD.Shared/Runtime/Env.cs | 352 ++++++++++-------- .../EventEx/SystemVariableChangedEvent.cs | 4 +- .../IFox.Event.Shared.projitems | 36 +- 6 files changed, 371 insertions(+), 322 deletions(-) diff --git a/src/Basal/IFox.Basal.Shared/IFox.Basal.Shared.projitems b/src/Basal/IFox.Basal.Shared/IFox.Basal.Shared.projitems index 52307b1..3025783 100644 --- a/src/Basal/IFox.Basal.Shared/IFox.Basal.Shared.projitems +++ b/src/Basal/IFox.Basal.Shared/IFox.Basal.Shared.projitems @@ -1,38 +1,38 @@  - - $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - true - c823514a-2bc2-45c2-aced-18924a7b80bf - - - IFox.Basal.Shared - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + true + c823514a-2bc2-45c2-aced-18924a7b80bf + + + IFox.Basal.Shared + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/IdleAction.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/IdleAction.cs index cc51ccc..95284f1 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/IdleAction.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/IdleAction.cs @@ -1,27 +1,31 @@ -namespace IFoxCAD.Cad; +using Cursor = System.Windows.Forms.Cursor; + +namespace IFoxCAD.Cad; /// -/// 空闲执行 -/// by DYH -/// 20230114 +/// 空闲执行 +/// by DYH +/// 20230114 /// public static class IdleAction { /// - /// 是否已经加载 + /// 是否已经加载 /// - private static bool alreadyLoad = false; + private static bool alreadyLoad; + /// - /// 委托列表 + /// 委托列表 /// private static readonly List _actions = new(); + /// - /// 未处理的委托数量 + /// 未处理的委托数量 /// public static int Count => _actions.Count; /// - /// 添加空闲执行委托 + /// 添加空闲执行委托 /// /// 委托 public static void Add(Action action) @@ -29,13 +33,14 @@ public static void Add(Action action) _actions.Add(action); if (!alreadyLoad) { - Acap.Idle -= Acap_Idle; - Acap.Idle += Acap_Idle; + Acaop.Idle -= Acap_Idle; + Acaop.Idle += Acap_Idle; alreadyLoad = true; } } + /// - /// 空闲处理事件 + /// 空闲处理事件 /// /// Acap /// 事件参数 @@ -44,9 +49,10 @@ private static void Acap_Idle(object sender, EventArgs e) if (Count == 0) { alreadyLoad = false; - Acap.Idle -= Acap_Idle; + Acaop.Idle -= Acap_Idle; return; } + try { _actions[0]?.Invoke(); @@ -55,6 +61,7 @@ private static void Acap_Idle(object sender, EventArgs e) { _actions.RemoveAt(0); } - System.Windows.Forms.Cursor.Position = System.Windows.Forms.Cursor.Position; + + Cursor.Position = Cursor.Position; } -} +} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems b/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems index 4a618ff..1f3aa51 100644 --- a/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems +++ b/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems @@ -1,100 +1,100 @@  - - $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - true - 20f254f7-aee5-42ae-a9b3-149bbdc7397f - - - IFox.CAD.Shared - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + true + 20f254f7-aee5-42ae-a9b3-149bbdc7397f + + + IFox.CAD.Shared + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/Runtime/Env.cs b/src/CAD/IFox.CAD.Shared/Runtime/Env.cs index 645734f..9ec9a77 100644 --- a/src/CAD/IFox.CAD.Shared/Runtime/Env.cs +++ b/src/CAD/IFox.CAD.Shared/Runtime/Env.cs @@ -1,36 +1,36 @@ - +using System.Security; namespace IFoxCAD.Cad; /// -/// 系统管理类 -/// -/// 封装了一些系统 osmode;cmdecho;dimblk 系统变量
-/// 封装了常用的 文档 编辑器 数据库等对象为静态变量
-/// 封装了配置页面的注册表信息获取函数 -///
+/// 系统管理类 +/// +/// 封装了一些系统 osmode;cmdecho;dimblk 系统变量
+/// 封装了常用的 文档 编辑器 数据库等对象为静态变量
+/// 封装了配置页面的注册表信息获取函数 +///
///
public static class Env { #region Goal /// - /// 当前的数据库 + /// 当前的数据库 /// public static Database Database => HostApplicationServices.WorkingDatabase; /// - /// 当前文档 + /// 当前文档 /// public static Document Document => Acaop.DocumentManager.MdiActiveDocument; /// - /// 编辑器对象 + /// 编辑器对象 /// public static Editor Editor => Document.Editor; /// - /// 图形管理器 + /// 图形管理器 /// public static Manager GsManager => Document.GraphicsManager; @@ -40,70 +40,75 @@ public static class Env #if !zcad // 中望官方的问题 /// - /// 获取当前配置的数据 + /// 获取当前配置的数据 /// /// 小节名 /// 数据名 /// 对象 public static object GetCurrentProfileProperty(string subSectionName, string propertyName) { - UserConfigurationManager ucm = Acaop.UserConfigurationManager; - IConfigurationSection cpf = ucm.OpenCurrentProfile(); - IConfigurationSection ss = cpf.OpenSubsection(subSectionName); + var ucm = Acaop.UserConfigurationManager; + var cpf = ucm.OpenCurrentProfile(); + var ss = cpf.OpenSubsection(subSectionName); return ss.ReadProperty(propertyName, ""); } /// - /// 获取对话框配置的数据 + /// 获取对话框配置的数据 /// /// 对话框对象 /// 配置项 public static IConfigurationSection GetDialogSection(object dialog) { - UserConfigurationManager ucm = Acaop.UserConfigurationManager; - IConfigurationSection ds = ucm.OpenDialogSection(dialog); + var ucm = Acaop.UserConfigurationManager; + var ds = ucm.OpenDialogSection(dialog); return ds; } /// - /// 获取公共配置的数据 + /// 获取公共配置的数据 /// /// 数据名 /// 配置项 public static IConfigurationSection GetGlobalSection(string propertyName) { - UserConfigurationManager ucm = Acaop.UserConfigurationManager; - IConfigurationSection gs = ucm.OpenGlobalSection(); - IConfigurationSection ss = gs.OpenSubsection(propertyName); + var ucm = Acaop.UserConfigurationManager; + var gs = ucm.OpenGlobalSection(); + var ss = gs.OpenSubsection(propertyName); return ss; } #endif + #endregion Preferences #region Enum + /// - /// 控制在AutoLISP的command函数运行时AutoCAD是否回显提示和输入, 为显示, 为不显示 + /// 控制在AutoLISP的command函数运行时AutoCAD是否回显提示和输入, 为显示, 为不显示 /// public static bool CmdEcho { get => Convert.ToInt16(Acaop.GetSystemVariable("cmdecho")) == 1; set => Acaop.SetSystemVariable("cmdecho", Convert.ToInt16(value)); } + /// - /// 获取Cad当前是否有活动命令 + /// 获取Cad当前是否有活动命令 /// public static bool CmdActive => Convert.ToBoolean(Acaop.GetSystemVariable("CMDACTIVE")); + /// - /// 控制在光标是否为正交模式, 为打开正交, 为关闭正交 + /// 控制在光标是否为正交模式, 为打开正交, 为关闭正交 /// public static bool OrthoMode { get => Convert.ToInt16(Acaop.GetSystemVariable("ORTHOMODE")) == 1; set => Acaop.SetSystemVariable("ORTHOMODE", Convert.ToInt16(value)); } + /// - /// 读写系统变量LastPoint的坐标(UCS) + /// 读写系统变量LastPoint的坐标(UCS) /// public static Point3d LastPoint { @@ -114,107 +119,107 @@ public static Point3d LastPoint #region Dimblk /// - /// 标注箭头类型 + /// 标注箭头类型 /// public enum DimblkType { /// - /// 实心闭合 + /// 实心闭合 /// Defult, /// - /// 点 + /// 点 /// Dot, /// - /// 小点 + /// 小点 /// DotSmall, /// - /// 空心点 + /// 空心点 /// DotBlank, /// - /// 原点标记 + /// 原点标记 /// Origin, /// - /// 原点标记2 + /// 原点标记2 /// Origin2, /// - /// 打开 + /// 打开 /// Open, /// - /// 直角 + /// 直角 /// Open90, /// - /// 30度角 + /// 30度角 /// Open30, /// - /// 闭合 + /// 闭合 /// Closed, /// - /// 空心小点 + /// 空心小点 /// Small, /// - /// 无 + /// 无 /// None, /// - /// 倾斜 + /// 倾斜 /// Oblique, /// - /// 实心框 + /// 实心框 /// BoxFilled, /// - /// 方框 + /// 方框 /// BoxBlank, /// - /// 空心闭合 + /// 空心闭合 /// ClosedBlank, /// - /// 实心基准三角形 + /// 实心基准三角形 /// DatumFilled, /// - /// 基准三角形 + /// 基准三角形 /// DatumBlank, /// - /// 完整标记 + /// 完整标记 /// Integral, /// - /// 建筑标记 + /// 建筑标记 /// ArchTick } @@ -261,19 +266,18 @@ public enum DimblkType { "_DATUMFILLED", DimblkType.DatumFilled }, { "_DATUMBLANK", DimblkType.DatumBlank }, { "_INTEGRAL", DimblkType.Integral }, - { "_ARCHTICK", DimblkType.ArchTick }, + { "_ARCHTICK", DimblkType.ArchTick } }; - /// - /// 标注箭头属性 + /// 标注箭头属性 /// public static DimblkType Dimblk { get { - string s = ((string)Acaop.GetSystemVariable("dimblk")).ToUpper(); + var s = ((string)Acaop.GetSystemVariable("dimblk")).ToUpper(); // if (string.IsNullOrEmpty(s)) // { // return DimblkType.Defult; @@ -291,13 +295,13 @@ public static DimblkType Dimblk } set { - string s = GetDimblkName(value); + var s = GetDimblkName(value); Acaop.SetSystemVariable("dimblk", s); } } /// - /// 获取标注箭头名 + /// 获取标注箭头名 /// /// 标注箭头类型 /// 箭头名 @@ -305,22 +309,20 @@ public static string GetDimblkName(DimblkType dimblk) { return dimblk == DimblkType.Defult - ? - "." - : - "_" + dimblk.GetName(); + ? "." + : "_" + dimblk.GetName(); } /// - /// 获取标注箭头ID + /// 获取标注箭头ID /// /// 标注箭头类型 /// 箭头ID public static ObjectId GetDimblkId(DimblkType dimblk) { - DimblkType oldDimblk = Dimblk; + var oldDimblk = Dimblk; Dimblk = dimblk; - ObjectId id = HostApplicationServices.WorkingDatabase.Dimblk; + var id = HostApplicationServices.WorkingDatabase.Dimblk; Dimblk = oldDimblk; return id; } @@ -330,105 +332,107 @@ public static ObjectId GetDimblkId(DimblkType dimblk) #region OsMode /// - /// 捕捉模式系统变量类型 + /// 捕捉模式系统变量类型 /// [Flags] public enum OSModeType { /// - /// 无 + /// 无 /// None = 0, /// - /// 端点 + /// 端点 /// End = 1, /// - /// 中点 + /// 中点 /// Middle = 2, /// - /// 圆心 + /// 圆心 /// Center = 4, /// - /// 节点 + /// 节点 /// Node = 8, /// - /// 象限点 + /// 象限点 /// Quadrant = 16, /// - /// 交点 + /// 交点 /// Intersection = 32, /// - /// 插入点 + /// 插入点 /// Insert = 64, /// - /// 垂足 + /// 垂足 /// Pedal = 128, /// - /// 切点 + /// 切点 /// Tangent = 256, /// - /// 最近点 + /// 最近点 /// Nearest = 512, /// - /// 几何中心 + /// 几何中心 /// Quick = 1024, /// - /// 外观交点 + /// 外观交点 /// Appearance = 2048, /// - /// 延伸 + /// 延伸 /// Extension = 4096, /// - /// 平行 + /// 平行 /// Parallel = 8192 } /// - /// 捕捉模式系统变量 + /// 捕捉模式系统变量 /// public static OSModeType OSMode { get => (OSModeType)Convert.ToInt16(Acaop.GetSystemVariable("osmode")); set => Acaop.SetSystemVariable("osmode", (int)value); } + /// - /// 捕捉模式osm1是否包含osm2 + /// 捕捉模式osm1是否包含osm2 /// /// 原模式 /// 要比较的模式 - /// 包含时返回 ,不包含时返回 + /// 包含时返回 ,不包含时返回 public static bool Include(this OSModeType osm1, OSModeType osm2) { return (osm1 & osm2) == osm2; } + #endregion OsMode @@ -440,8 +444,9 @@ public static bool Include(this OSModeType osm1, OSModeType osm2) #endregion Enum #region 系统变量 + /// - /// 获取cad系统变量 + /// 获取cad系统变量 /// /// 变量名 /// 变量值 @@ -449,11 +454,12 @@ public static object GetVar(string varName) { return Acaop.GetSystemVariable(varName); } + /// - /// 设置cad系统变量
- /// 0x01 建议先获取现有变量值和设置的是否相同,否则直接设置会发生异常
- /// 0x02 建议锁文档,否则 Psltscale 设置发生异常
- /// 发生异常的时候vs输出窗口会打印一下,但是如果不介意也没啥问题 + /// 设置cad系统变量
+ /// 0x01 建议先获取现有变量值和设置的是否相同,否则直接设置会发生异常
+ /// 0x02 建议锁文档,否则 Psltscale 设置发生异常
+ /// 发生异常的时候vs输出窗口会打印一下,但是如果不介意也没啥问题 ///
/// 变量名 /// 变量值 @@ -470,46 +476,54 @@ public static void SetVar(string varName, object value, bool echo = true) Print($"{varName} 是不存在的变量!"); } } + #endregion #region 环境变量 -#if acad - [System.Security.SuppressUnmanagedCodeSecurity] - [DllImport("accore.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, EntryPoint = "acedGetEnv")] - static extern int AcedGetEnv(string? envName, StringBuilder ReturnValue); - [System.Security.SuppressUnmanagedCodeSecurity] - [DllImport("accore.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, EntryPoint = "acedSetEnv")] - static extern int AcedSetEnv(string? envName, StringBuilder NewValue); +#if acad + [SuppressUnmanagedCodeSecurity] + [DllImport("accore.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, + EntryPoint = "acedGetEnv")] + private static extern int AcedGetEnv(string? envName, StringBuilder ReturnValue); + + [SuppressUnmanagedCodeSecurity] + [DllImport("accore.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, + EntryPoint = "acedSetEnv")] + private static extern int AcedSetEnv(string? envName, StringBuilder NewValue); #endif #if gcad [System.Security.SuppressUnmanagedCodeSecurity] - [DllImport("gced.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, EntryPoint = "gcedGetEnv")] + [DllImport("gced.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, EntryPoint = + "gcedGetEnv")] static extern int AcedGetEnv(string? envName, StringBuilder ReturnValue); [System.Security.SuppressUnmanagedCodeSecurity] - [DllImport("gced.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, EntryPoint = "gcedSetEnv")] + [DllImport("gced.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, EntryPoint = + "gcedSetEnv")] static extern int AcedSetEnv(string? envName, StringBuilder NewValue); #endif // TODO: 中望没有测试,此处仅为不报错;本工程所有含有"中望"均存在问题 #if zcad [System.Security.SuppressUnmanagedCodeSecurity] - [DllImport("zced.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, EntryPoint = "zcedGetEnv")] + [DllImport("zced.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, EntryPoint = + "zcedGetEnv")] static extern int AcedGetEnv(string? envName, StringBuilder ReturnValue); [System.Security.SuppressUnmanagedCodeSecurity] - [DllImport("zced.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, EntryPoint = "zcedSetEnv")] + [DllImport("zced.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, EntryPoint = + "zcedSetEnv")] static extern int AcedSetEnv(string? envName, StringBuilder NewValue); #endif /// - /// 读取acad环境变量
- /// 也能获取win环境变量 + /// 读取acad环境变量
+ /// 也能获取win环境变量 ///
/// 变量名 - /// 返回值从不为null,需判断 + /// 返回值从不为null,需判断 public static string GetEnv(string name) { // 它将混合查询以下路径: @@ -527,9 +541,9 @@ public static string GetEnv(string name) } /// - /// 设置acad环境变量
- /// 它是不会报错的,但是直接设置会写入注册表的,
- /// 如果是设置高低版本cad不同的变量,建议先读取判断再设置
+ /// 设置acad环境变量
+ /// 它是不会报错的,但是直接设置会写入注册表的,
+ /// 如果是设置高低版本cad不同的变量,建议先读取判断再设置
///
/// 变量名 /// 变量值 @@ -538,9 +552,11 @@ public static int SetEnv(string name, string var) { return AcedSetEnv(name, new StringBuilder(var)); } + #endregion #region win环境变量/由于 Aced的 能够同时获取此变量与cad内的,所以废弃 + // /// // /// 获取系统环境变量 // /// @@ -563,18 +579,19 @@ public static int SetEnv(string name, string var) // // 创建、修改或删除当前进程中或者为当前用户或本地计算机保留的 Windows 操作系统注册表项中存储的环境变量 // Environment.SetEnvironmentVariable(var, value); // } + #endregion #region 支持文件目录 /// - /// 添加目录至CAD支持搜索的路径 + /// 添加目录至CAD支持搜索的路径 /// /// 目录 public static void AppendSupportPath(params string[] folders) { if (!folders.Any()) return; - var acadPath = Env.GetEnv("ACAD"); + var acadPath = GetEnv("ACAD"); var acadPathLowerArr = acadPath .ToLower() @@ -583,103 +600,123 @@ public static void AppendSupportPath(params string[] folders) .Select(item => item[^1] == '\\' ? item.Remove(item.Length - 1) : item) .ToHashSet(); - foreach (var folder in folders) { + foreach (var folder in folders) + { if (!Directory.Exists(folder)) continue; - var folderLower = + var folderLower = folder[^1] == '\\' ? folder.Remove(folder.Length - 1).ToLower() : folder.ToLower(); if (!acadPathLowerArr.Contains(folderLower)) - acadPath = folder + ";" + acadPath; //加到前面方便检查 + acadPath = folder + ";" + acadPath; //加到前面方便检查 } + SetEnv("ACAD", acadPath); } - + /// - /// 删除支持搜索文件目录 + /// 删除支持搜索文件目录 /// /// 目录 public static void RemoveSupportPath(params string[] folders) { if (!folders.Any()) return; var acadPathArr = GetEnv("ACAD").Split(';').ToList(); - foreach (var folder in folders) { - var folderLower = + foreach (var folder in folders) + { + var folderLower = folder[^1] == '\\' ? folder.Remove(folder.Length - 1).ToLower() : folder.ToLower(); - acadPathArr.RemoveAll(item => + acadPathArr.RemoveAll(item => (item[^1] == '\\' ? item.Remove(item.Length - 1).ToLower() : item.ToLower()) == folderLower); } + SetEnv("ACAD", string.Join(";", acadPathArr)); } /// - /// 添加目录至CAD受信任的位置 + /// 添加目录至CAD受信任的位置 /// /// 目录 public static void AppendTrustedPath(params string[] folders) { if (!folders.Any()) return; - var trustedPath = Env.GetVar("TRUSTEDPATHS").ToString(); + var trustedPath = GetVar("TRUSTEDPATHS").ToString(); var trustedPathLowerArr = trustedPath .ToLower() .Split(';') .Where(item => item != "") - .Select(item => + .Select(item => item[^1] == '\\' ? item.Remove(item.Length - 1) : item) .ToHashSet(); - foreach (var folder in folders) { + foreach (var folder in folders) + { if (!Directory.Exists(folder)) continue; - var folderLower = + var folderLower = folder[^1] == '\\' ? folder.Remove(folder.Length - 1).ToLower() : folder.ToLower(); if (!trustedPathLowerArr.Contains(folderLower)) trustedPath = folder + ";" + trustedPath; //加到前面方便检查 } + SetVar("TRUSTEDPATHS", trustedPath); } + /// - /// 移除信任目录 + /// 移除信任目录 /// /// 目录 public static void RemoveTrustedPath(params string[] folders) { if (!folders.Any()) return; var trustedPathArr = GetVar("TRUSTEDPATHS").ToString().Split(';').ToList(); - foreach (var folder in folders) { - var folderLower = + foreach (var folder in folders) + { + var folderLower = folder[^1] == '\\' ? folder.Remove(folder.Length - 1).ToLower() : folder.ToLower(); - trustedPathArr.RemoveAll(item => + trustedPathArr.RemoveAll(item => (item[^1] == '\\' ? item.Remove(item.Length - 1).ToLower() : item.ToLower()) == folderLower); } + SetVar("TRUSTEDPATHS", string.Join(";", trustedPathArr)); } #endregion /// - /// 命令行打印,会自动调用对象的toString函数 + /// 命令行打印,会自动调用对象的toString函数 /// /// 要打印的对象 - public static void Print(object message) => Editor.WriteMessage($"{message}\n"); + public static void Print(object message) + { + Editor.WriteMessage($"{message}\n"); + } + /// - /// 命令行打印,会自动调用对象的toString函数,在打印内容前添加换行 + /// 命令行打印,会自动调用对象的toString函数,在打印内容前添加换行 /// /// 要打印的对象 - public static void Printl(object message) => Editor.WriteMessage($"{Environment.NewLine}{message}\n"); + public static void Printl(object message) + { + Editor.WriteMessage($"{Environment.NewLine}{message}\n"); + } /// - /// 判断当前是否在UCS坐标下 + /// 判断当前是否在UCS坐标下 /// /// Bool - public static bool IsUcs() => (short)GetVar("WORLDUCS") == 0; + public static bool IsUcs() + { + return (short)GetVar("WORLDUCS") == 0; + } #region dwg版本号/cad版本号/年份 + /// - /// 获取当前配置文件的保存版本 + /// 获取当前配置文件的保存版本 /// /// public static DwgVersion GetDefaultDwgVersion() { - var ffs = Env.GetEnv("DefaultFormatForSave"); + var ffs = GetEnv("DefaultFormatForSave"); var version = ffs switch { "1" => DwgVersion.AC1009, // R12/LT12 dxf @@ -698,13 +735,13 @@ public static DwgVersion GetDefaultDwgVersion() "61" => (DwgVersion)32, // 2013 dxf "64" => (DwgVersion)33, // 2018 dwg DwgVersion.AC1032 "65" => (DwgVersion)34, // 2018 dxf - _ => throw new NotImplementedException(), // 提醒维护 + _ => throw new NotImplementedException() // 提醒维护 }; return version; } /// - /// 是否为dxf版本号 + /// 是否为dxf版本号 /// /// /// @@ -712,26 +749,26 @@ public static bool IsDxfVersion(this DwgVersion dwgVersion) { var result = (int)dwgVersion switch { - 16 => true,// R12/LT12 dxf - 24 => true,// 2000 dxf - 26 => true,// 2004 dxf - 28 => true,// 2007 dxf - 30 => true,// 2010 dxf - 32 => true,// 2013 dxf - 34 => true,// 2018 dxf - _ => false, + 16 => true, // R12/LT12 dxf + 24 => true, // 2000 dxf + 26 => true, // 2004 dxf + 28 => true, // 2007 dxf + 30 => true, // 2010 dxf + 32 => true, // 2013 dxf + 34 => true, // 2018 dxf + _ => false }; return result; } /// - /// 获取cad年份 + /// 获取cad年份 /// /// 超出年份就报错 public static int GetAcadVersion() { var ver = Acaop.Version.Major + "." + Acaop.Version.Minor; - int acarVarNum = ver switch + var acarVarNum = ver switch { "16.2" => 2006, "17.0" => 2007, @@ -751,12 +788,13 @@ public static int GetAcadVersion() "24.0" => 2021, "24.1" => 2022, "24.2" => 2023, - _ => throw new NotImplementedException(), + _ => throw new NotImplementedException() }; return acarVarNum; } + /// - /// 获取带cad版本号的dll + /// 获取带cad版本号的dll /// /// dll名字 /// dll的前面 @@ -764,15 +802,17 @@ public static string GetAcapVersionDll(string str = "acdb") { return str + Acaop.Version.Major + ".dll"; } + #endregion #region cad变量功能延伸 + /// - /// 设置cad系统变量
- /// 提供一个反序列化后,无cad异常输出的功能
- /// 注意,您需要再此执行时候设置文档锁
- /// 否则也将导致修改数据库异常
+ /// 设置cad系统变量
+ /// 提供一个反序列化后,无cad异常输出的功能
+ /// 注意,您需要再此执行时候设置文档锁
+ /// 否则也将导致修改数据库异常
///
/// /// @@ -780,7 +820,6 @@ public static string GetAcapVersionDll(string str = "acdb") /// public static object SetVarEx(string key, string value) { - var currentVar = GetVar(key); object valueType = currentVar.GetType().Name switch @@ -789,18 +828,18 @@ public static object SetVarEx(string key, string value) "Double" => double.Parse(value), "Int16" => short.Parse(value), "Int32" => int.Parse(value), - _ => throw new NotImplementedException(), + _ => throw new NotImplementedException() }; // 相同的参数进行设置会发生一次异常 if (!string.Equals(currentVar.ToString(), valueType.ToString(), StringComparison.CurrentCultureIgnoreCase)) - Env.SetVar(key, valueType); + SetVar(key, valueType); return currentVar; } /// - /// 设置新系统变量,返回现有系统变量 + /// 设置新系统变量,返回现有系统变量 /// /// 设置的变量词典 /// 返回现有变量词典,然后下次就可以利用它进行设置回来了 @@ -821,25 +860,28 @@ public static Dictionary SaveCadVar(Dictionary a } // 判断是否为系统变量 - var envstr = Env.GetEnv(item.Key); + var envstr = GetEnv(item.Key); if (!string.IsNullOrEmpty(envstr)) { - Env.SetEnv(item.Key, item.Value); + SetEnv(item.Key, item.Value); dict.Add(item.Key, envstr); } } + return dict; } + /// - /// 延迟更新图层锁定淡显状态 - /// 在有锁定或解锁图层的命令的末尾使用 + /// 延迟更新图层锁定淡显状态 + /// 在有锁定或解锁图层的命令的末尾使用 /// public static void DelayUpdateLayLockFade() { const string lfName = "LAYLOCKFADECTL"; - int lf = Convert.ToInt32(Acaop.GetSystemVariable(lfName).ToString()); + var lf = Convert.ToInt32(Acaop.GetSystemVariable(lfName).ToString()); Acaop.SetSystemVariable(lfName, -lf); IdleAction.Add(() => Acaop.SetSystemVariable(lfName, lf)); } + #endregion } \ No newline at end of file diff --git a/src/Event/IFox.Event.Shared/EventEx/SystemVariableChangedEvent.cs b/src/Event/IFox.Event.Shared/EventEx/SystemVariableChangedEvent.cs index 798e35f..f65f7a5 100644 --- a/src/Event/IFox.Event.Shared/EventEx/SystemVariableChangedEvent.cs +++ b/src/Event/IFox.Event.Shared/EventEx/SystemVariableChangedEvent.cs @@ -102,8 +102,8 @@ private static void Acap_SystemVariableChanged(object sender, SystemVariableChan public class SystemVariableChangedAttribute : Attribute { /// s - /// ϵͳ޸ʱǵĺ\n - /// \nֵӦΪvoid + /// ϵͳ޸ʱǵĺ + /// ֵӦΪvoid /// 2ֻΪobjectSystemVariableChangedEventArgs /// /// ϵͳ diff --git a/src/Event/IFox.Event.Shared/IFox.Event.Shared.projitems b/src/Event/IFox.Event.Shared/IFox.Event.Shared.projitems index 137e275..53ffa13 100644 --- a/src/Event/IFox.Event.Shared/IFox.Event.Shared.projitems +++ b/src/Event/IFox.Event.Shared/IFox.Event.Shared.projitems @@ -1,21 +1,21 @@  - - $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - true - c4f9a0cf-920e-41d0-bf51-0a59df660ad9 - - - IFox.Event.Shared - - - - - - - - - - - + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + true + c4f9a0cf-920e-41d0-bf51-0a59df660ad9 + + + IFox.Event.Shared + + + + + + + + + + + \ No newline at end of file -- Gitee From 6cd063c1d6433d7c2e42f3c9ac382bde5ed91d2c Mon Sep 17 00:00:00 2001 From: yupeng_dyp Date: Thu, 1 Feb 2024 04:28:55 +0000 Subject: [PATCH 249/453] =?UTF-8?q?update=20src/CAD/IFox.CAD.Shared/Extens?= =?UTF-8?q?ionMethod/=E6=96=B0=E5=BB=BA=E5=A1=AB=E5=85=85/HatchEx.cs.=20?= =?UTF-8?q?=E5=B0=86=20HatchConvert=20=E7=B1=BB=E7=9A=84=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E8=B0=83=E6=95=B4=E8=87=B3=E6=89=A9=E5=B1=95=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E4=B8=AD=E4=BB=A5=E4=BC=98=E5=8C=96=E4=BD=BF=E7=94=A8=E6=96=B9?= =?UTF-8?q?=E4=BE=BF=E6=80=A7=EF=BC=88=E5=BB=BA=E8=AE=AE=E5=88=A0=E9=99=A4?= =?UTF-8?q?=20HatchConvert=20=E7=B1=BB=EF=BC=89=EF=BC=8C=E5=90=8C=E6=97=B6?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BA=86=E4=B8=8D=E8=83=BD=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E4=B8=8E=E5=88=9B=E5=BB=BA=E6=A4=AD=E5=9C=86=E7=BA=BF=E3=80=81?= =?UTF-8?q?=E8=BE=B9=E7=95=8C=E7=8E=AF=E4=B8=AD=E5=8F=AA=E8=83=BD=E5=8C=85?= =?UTF-8?q?=E5=90=AB=E4=B8=80=E6=9D=A1=E5=A4=9A=E6=AE=B5=E7=BA=BF=E7=AD=89?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: yupeng_dyp --- .../HatchEx.cs" | 343 +++++++++++++++++- 1 file changed, 342 insertions(+), 1 deletion(-) diff --git "a/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchEx.cs" "b/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchEx.cs" index 6bd4b82..51d2c65 100644 --- "a/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchEx.cs" +++ "b/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchEx.cs" @@ -1,4 +1,5 @@ -namespace IFoxCAD.Cad; +namespace IFoxCAD.Cad; + /// /// 充填扩展类 /// @@ -14,4 +15,344 @@ public static void ForEach(this Hatch hatch, Action action) for (int i = 0; i < hatch.NumberOfLoops; i++) action.Invoke(hatch.GetLoopAt(i)); } + + /// + /// 提取已存在的关联边界(一个边界环里所有的对象 id 组成一个 ObjectIdCollection) + /// + /// + /// + /// + public static List? GetAssociatedBoundaryIds(this Hatch hatch) + { + if (!hatch.Id.IsOk()) + throw new ArgumentException("填充未加入或不存在于数据库"); + + if (!hatch.Associative) + return null; + + var listObjIdColl = new List(); + + for (var i = 0; i < hatch.NumberOfLoops; i++) + { + var assIds = hatch.GetAssociatedObjectIdsAt(i); + if (assIds != null) + { + var objIds = new ObjectIdCollection(); + foreach (ObjectId id in assIds) + { + if (id.IsOk()) + objIds.Add(id); + } + + if (objIds.Count == 0) + { + throw new ArgumentException("关联的填充边界被删除后没有清理反应器,请调用:" + + "\n hatch.RemoveAssociatedObjectIds()" + + "\n hatch.Associative = false"); + } + + listObjIdColl.Add(objIds); + } + } + + return listObjIdColl; + } + + /// + /// 创建边界(仅创建于内存中,未加入数据库) + /// + /// + /// 边界环列表(一个边界环里所有的对象组成一个 DBObjectCollection) + public static List CreateBoundarys(this Hatch hatch) + { + if (!hatch.Id.IsOk()) + throw new ArgumentException("填充未加入或不存在于数据库"); + + var listDbObjColl = new List(); + + for (int i = 0; i < hatch.NumberOfLoops; i++) + { + var objColl = new DBObjectCollection(); + var loop = hatch.GetLoopAt(i); + bool isCurve2d = true; + + if (loop.IsPolyline) + { + // 边界是多段线 + HatchLoopIsPolyline(loop, objColl); + isCurve2d = false; + } + else + { + // 1是不可能的,大于2的是曲线; + if (loop.Curves.Count == 2) + { + // 边界是曲线,过滤可能是圆形的情况 + var circle = TwoArcFormOneCircle(loop, objColl); + if (circle is not null) + { + objColl.Add(circle); + isCurve2d = false; + } + } + } + + // 边界是曲线 + if (isCurve2d) + HatchLoopIsCurve2d(loop, objColl); + + listDbObjColl.Add(objColl); + }; + + return listDbObjColl; + } + + /// + /// 对已存在于数据库的填充重新设置边界并计算 + /// + /// + /// 边界对象(一个边界环里所有的对象 id 组成一个 ObjectIdCollection) + ///
边界必需是封闭的环, 可以是一条线围合而成也可以是多条线首尾相连围合而成
+ ///
多个外边界的时候, 建议顺序为(外边界,外边界,外边界,普通边界....), 或(外边界, 普通边界.....外边界, 普通边界....)
+ /// + /// 关联边界(默认保持原样) + public static void ResetBoundarys(this Hatch hatch, List boundaryIds, bool? associative = null) + { + if (!hatch.Id.IsOk()) + throw new ArgumentException("填充未加入或不存在于数据库"); + + boundaryIds.ForEach(ids => + { + foreach (ObjectId id in ids) + { + if (!id.IsOk()) + throw new ArgumentException("边界未加入或不存在于数据库"); + } + }); + + using (hatch.ForWrite()) + { + while (hatch.NumberOfLoops > 0) + hatch.RemoveLoopAt(0); + + if (associative != null) + hatch.Associative = associative == true; + + var isOutermost = true; + + boundaryIds.ForEach(ids => + { + try + { + // 要先添加最外面的边界 + if (isOutermost) + { + isOutermost = false; + hatch.AppendLoop(HatchLoopTypes.Outermost, ids); + } + else + { + // HatchLoopTypes.External 比 HatchLoopTypes.Default 似乎更不容易出问题 + hatch.AppendLoop(HatchLoopTypes.External, ids); + } + } + catch (Exception ex) + { + Env.Editor.WriteMessage(Environment.NewLine + + "发生错误,传入的边界不符合要求,请核实传入的边界是否为封闭的"); + throw new Exception(ex.Message); + } + }); + + hatch.EvaluateHatch(true); + } + } + + #region 私有方法 + /// + /// 处理边界多段线 + /// + /// 填充边界 + /// 收集边界图元 + private static void HatchLoopIsPolyline(HatchLoop loop, DBObjectCollection objColl) + { + // 判断为圆形: + // 上下两个圆弧,然后填充,就会生成此种填充 + // 顶点数是3,凸度是半圆,两个半圆就是一个圆形 + if (loop.Polyline.Count == 3 && loop.Polyline[0].Bulge == 1 && loop.Polyline[1].Bulge == 1 + || loop.Polyline.Count == 3 && loop.Polyline[0].Bulge == -1 && loop.Polyline[1].Bulge == -1) + { + var center = PointEx.GetMidPointTo(loop.Polyline[0].Vertex, loop.Polyline[1].Vertex); + var radius = loop.Polyline[0].Vertex.GetDistanceTo(loop.Polyline[1].Vertex) * 0.5; + var circle = new Circle(center.Point3d(), Vector3d.ZAxis, radius); + objColl.Add(circle); + } + else + { + // 遍历多段线信息 + var bvc = loop.Polyline; + var pl = new Polyline(); + pl.SetDatabaseDefaults(); + for (int j = 0; j < bvc.Count; j++) + { + var bvw = new BulgeVertexWidth(bvc[j]); + pl.AddVertexAt(j, bvw.Vertex, bvw.Bulge, bvw.StartWidth, bvw.EndWidth); + } + objColl.Add(pl); + } + } + + /// + /// 两个圆弧组成圆形 + /// + /// 填充边界 + /// 收集边界图元 + private static Circle? TwoArcFormOneCircle(HatchLoop loop, DBObjectCollection objColl) + { + if (loop.Curves.Count != 2) + { + throw new ArgumentException( + "边界非多段线,而且点数!=2,点数为:" + nameof(loop.Curves.Count) + ";两个矩形交集的时候会出现此情况."); + } + + Circle? circle = null; + + // 判断为圆形: + // 用一条(不是两条)多段线画出两条圆弧为正圆,就会生成此种填充 + // 边界为曲线,数量为2,可能是两个半圆曲线,如果是,就加入圆形数据中 + + // 第一段 + var getCurves1Pts = loop.Curves[0].GetSamplePoints(3); // 曲线取样点分两份(3点) + var mid1Pt = getCurves1Pts[1]; // 腰点 + double bulge1 = loop.Curves[0].StartPoint.GetArcBulge(mid1Pt, loop.Curves[0].EndPoint); + + // 第二段 + var getCurves2Pts = loop.Curves[1].GetSamplePoints(3); + var mid2Pt = getCurves2Pts[1]; + double bulge2 = loop.Curves[1].StartPoint.GetArcBulge(mid2Pt, loop.Curves[1].EndPoint); + + // 第一段上弧&&第二段反弧 || 第一段反弧&&第二段上弧 + if (bulge1 == -1 && bulge2 == -1 || bulge1 == 1 && bulge2 == 1) + { + var center = PointEx.GetMidPointTo(loop.Curves[0].StartPoint, loop.Curves[1].StartPoint); + var radius = loop.Curves[0].StartPoint.GetDistanceTo(loop.Curves[1].StartPoint) * 0.5; + circle = new Circle(center.Point3d(), Vector3d.ZAxis, radius); + } + + return circle; + } + + /// + /// 处理边界曲线 + /// + /// 填充边界 + /// 收集边界图元 + private static void HatchLoopIsCurve2d(HatchLoop loop, DBObjectCollection objColl) + { + int pLineCount = 0; //记录多段线数量 + int curveIsClosed = 0; // 取每一段曲线,曲线可能是直线来的,但是圆弧会按照顶点来分段 + bool newPline = true; // 是否开始新的多段线(一个边界中可能有多条多段线) + bool firstIsPline = false; //遍历边界的第一个子段为多段线(遍历时不一定从多段线的首段开始) + List? polyLineVertexs = null; + List> polyLineData = new(); + + // 遍历边界的多个子段 + foreach (Curve2d curve in loop.Curves) + { + // 计数用于实现闭合 + curveIsClosed++; + + if (curve is CircularArc2d or LineSegment2d) + { + var pts = curve.GetSamplePoints(3); + var midPt = pts[1]; + + // 判断为多段线圆: + // 首尾相同,就是圆形 + if (curve.StartPoint.IsEqualTo(curve.EndPoint, new Tolerance(1e-6, 1e-6))) + { + // 获取起点,然后采样三点,中间就是对称点(直径点) + var center = PointEx.GetMidPointTo(curve.StartPoint, midPt); + var radius = curve.StartPoint.GetDistanceTo(midPt) * 0.5; + var circle = new Circle(center.Point3d(), Vector3d.ZAxis, radius); + objColl.Add(circle); + // 添加在中部的多段线末尾点 + if (curveIsClosed > 1 && !newPline) + polyLineVertexs?.Add(new BulgeVertexWidth(curve.StartPoint, 0)); + // 开始新的多段线 + newPline = true; + continue; + } + + if (curveIsClosed == 1) + firstIsPline = true; + + if (newPline) + { + polyLineVertexs = new(); + polyLineData.Add(polyLineVertexs); + newPline = false; + pLineCount++; + } + + // 判断为多段线,圆弧或直线: + double bulge = curve.StartPoint.GetArcBulge(midPt, curve.EndPoint); + polyLineVertexs?.Add(new BulgeVertexWidth(curve.StartPoint, bulge)); + + // 末尾点,不闭合的情况下就要获取这个 + if (curveIsClosed == loop.Curves.Count) + { + if (firstIsPline && pLineCount > 1) + { + // 连接首尾多段线 + polyLineData[0].ForEach(bvw => polyLineData[^1].Add(bvw)); + polyLineData.RemoveAt(0); + } + else + polyLineVertexs?.Add(new BulgeVertexWidth(curve.EndPoint, 0)); + } + + continue; + } + + // 判断为样条曲线: + if (curve is NurbCurve2d spl) + objColl.Add(spl.ToCurve()); + + // 判断为椭圆: + if (curve is EllipticalArc2d eArc2d) + { + var startParam = eArc2d.IsClockWise ? -eArc2d.EndAngle : eArc2d.StartAngle; + var endParam = eArc2d.IsClockWise ? -eArc2d.StartAngle : eArc2d.EndAngle; + var ellipse = new Ellipse( + eArc2d.Center.Point3d(), + Vector3d.ZAxis, + eArc2d.MajorAxis.Convert3d() * eArc2d.MajorRadius, + eArc2d.MinorRadius / eArc2d.MajorRadius, + Math.Atan2(Math.Sin(startParam) * eArc2d.MinorRadius, + Math.Cos(startParam) * eArc2d.MajorRadius), + Math.Atan2(Math.Sin(endParam) * eArc2d.MinorRadius, + Math.Cos(endParam) * eArc2d.MajorRadius)); + objColl.Add(ellipse); + } + + // 添加在中部的多段线末尾点 + if (curveIsClosed > 1 && !newPline) + polyLineVertexs?.Add(new BulgeVertexWidth(curve.StartPoint, 0)); + // 开始新的多段线 + newPline = true; + } + + // 生成多段线 + polyLineData.ForEach(bvws => + { + if (bvws.Count == 0) return; + var pl = new Polyline(); + pl.SetDatabaseDefaults(); + for (int j = 0; j < bvws.Count; j++) + pl.AddVertexAt(j, bvws[j].Vertex, bvws[j].Bulge, bvws[j].StartWidth, bvws[j].EndWidth); + objColl.Add(pl); + }); + } + #endregion } \ No newline at end of file -- Gitee From 31b3bb9cb8963c6130f808cf572e9933d994e35e Mon Sep 17 00:00:00 2001 From: yupeng_dyp Date: Thu, 1 Feb 2024 04:37:05 +0000 Subject: [PATCH 250/453] =?UTF-8?q?update=20src/CAD/IFox.CAD.Shared/Extens?= =?UTF-8?q?ionMethod/Curve2dEx.cs.=20=E5=B0=86=20NurbCurve2d=20=E7=9A=84?= =?UTF-8?q?=20ToCurve=20=E6=89=A9=E5=B1=95=E6=96=B9=E6=B3=95=E8=BD=AC?= =?UTF-8?q?=E6=8D=A2=E4=B8=BA=E6=A0=B7=E6=9D=A1=E6=9B=B2=E7=BA=BF=E7=9A=84?= =?UTF-8?q?=E6=8E=A7=E5=88=B6=E7=B1=BB=E5=9E=8B=E7=94=B1=20=E6=8E=A7?= =?UTF-8?q?=E5=88=B6=E7=82=B9=20=E6=94=B9=E4=B8=BA=E9=BB=98=E8=AE=A4?= =?UTF-8?q?=E7=9A=84=20=E6=8B=9F=E5=90=88=EF=BC=8C=E4=BF=9D=E6=8C=81?= =?UTF-8?q?=E4=B8=8E=E7=94=A8CAD=E6=89=8B=E7=BB=98=E6=97=B6=E7=9A=84?= =?UTF-8?q?=E6=8E=A7=E5=88=B6=E7=B1=BB=E5=9E=8B=E4=B8=80=E8=87=B4=EF=BC=8C?= =?UTF-8?q?=E4=BB=A5=E6=96=B9=E4=BE=BF=E5=90=8E=E7=BB=AD=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: yupeng_dyp --- src/CAD/IFox.CAD.Shared/ExtensionMethod/Curve2dEx.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Curve2dEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Curve2dEx.cs index 0b1fe75..cd18835 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Curve2dEx.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Curve2dEx.cs @@ -1,4 +1,4 @@ -namespace IFoxCAD.Cad; +namespace IFoxCAD.Cad; /// /// 二维解析类曲线转换为二维实体曲线扩展类 @@ -289,7 +289,7 @@ public static Spline ToCurve(this NurbCurve2d nc2d) knots, weights, 0, - nc2d.Knots.Tolerance); + nc2d.Knots.Tolerance) { Type = SplineType.FitPoints }; } #endregion NurbCurve2d -- Gitee From 04b450392b36ee726227c934e06b79c5f690e4e4 Mon Sep 17 00:00:00 2001 From: Ps <376313736@qq.com> Date: Sun, 4 Feb 2024 18:34:10 +0800 Subject: [PATCH 251/453] =?UTF-8?q?=E4=BC=98=E5=8C=96EntityBoundingInfo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Entity/EntityBoundingInfo.cs | 121 +++++++----------- 1 file changed, 44 insertions(+), 77 deletions(-) diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs index 32562a8..be4b770 100644 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs +++ b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs @@ -15,81 +15,17 @@ public static class EntityBoundingInfo { return new(ext); } - - // 包围盒外扩 - //public static BoundingInfo? GetBoundingInfo(this Extents3d ext, double dist = 0) - //{ - // var p1 = ext.MinPoint.Offset(-dist, -dist); - // var p2 = ext.MaxPoint.Offset(dist, dist); - // var e = new Extents3d(p1, p2); - // return new(e); - //} - - /// - /// 获取实体包围盒 - /// - /// 实体 - /// 包围盒 - static Extents3d? GetEntityBox(this Entity ent) - { - if (!ent.Bounds.HasValue) - return null; - //if (ent is BlockReference brf) - // ext = brf.GeometryExtentsBestFit(); - - if (ent is Spline spl) - return spl.ToPolyline().GeometricExtents; - - else if (ent is MText mtext) - return GetMTextBox(mtext); - - else if (ent is Table table) - { - if(table.IsNewObject) - table.GenerateLayout(); - - table.RecomputeTableBlock(true); - return table.GeometricExtents; - } - - else if (ent is Dimension dim) - { - if(dim.IsNewObject) - dim.GenerateLayout(); // 新new的实体生成布局,即可获取包围盒 - - dim.RecomputeDimensionBlock(true); - return dim.GeometricExtents; - } - else - return ent.GeometricExtents; - - } - /// /// 获取多行文本的正交包围盒 /// /// 多行文本 /// 包围盒 static Extents3d GetMTextBox(MText mText) - { - return mText.GetMTextBoxCorners().ToExtents3D(); - } - - /// - /// 获取点集包围盒 - /// - /// Point3d点集 - /// 包围盒 - static Extents3d ToExtents3D(this IEnumerable pts) { var ext = new Extents3d(); - foreach (Point3d pt in pts) - { - ext.AddPoint(pt); - } + GetMTextBoxCorners(mText).ForEach(p=>ext.AddPoint(p)); return ext; } - /// /// 获取块的包围盒 /// @@ -133,13 +69,15 @@ static void GetBlockBox(this Entity en, ref Extents3d ext, ref Matrix3d mat) { if (ext.IsEmptyExt()) { - var e = ent1.GetEntityBox(); + //var e = ent1.GetEntityBox(); + var e = GetEntityBoxEx(ent1); if (e.HasValue) ext = e.Value; } else { - var e = ent1.GetEntityBox(); + //var e = ent1.GetEntityBox(); + var e = GetEntityBoxEx(ent1); if (e.HasValue) ext.AddExtents(e.Value); } @@ -147,7 +85,8 @@ static void GetBlockBox(this Entity en, ref Extents3d ext, ref Matrix3d mat) } else { - var e = en.GetEntityBox(); + //var e = en.GetEntityBox(); + var e = GetEntityBoxEx(en); if (e.HasValue) { Extents3d entext = e.Value; @@ -167,7 +106,7 @@ static void GetBlockBox(this Entity en, ref Extents3d ext, ref Matrix3d mat) /// /// 多行文本 /// 最小包围盒4点坐标 - public static Point3d[] GetMTextBoxCorners(this MText mtext) + public static Point3d[] GetMTextBoxCorners(MText mtext) { double width = mtext.ActualWidth; double height = mtext.ActualHeight; @@ -233,16 +172,44 @@ public static Point3d[] GetMTextBoxCorners(this MText mtext) /// 包围盒 public static Extents3d? GetEntityBoxEx(Entity ent) { - if (ent is BlockReference block) + Extents3d? ext = null; + switch (ent) { - Extents3d blockExt = default; - var mat = Matrix3d.Identity; - block!.GetBlockBox(ref blockExt, ref mat); - if (blockExt.IsEmptyExt()) - return null; - return blockExt; + case Spline spl: + ext = spl.ToPolyline().GeometricExtents; + break; + case MText mtext: + ext = GetMTextBox(mtext); + break; + case Table table: + if (table.IsNewObject) + table.GenerateLayout(); + table.RecomputeTableBlock(true); + ext = table.GeometricExtents; + break; + case Dimension dim: + if (dim.IsNewObject) + dim.GenerateLayout(); // 新new的实体生成布局,即可获取包围盒 + dim.RecomputeDimensionBlock(true); + ext = dim.GeometricExtents; + break; + case BlockReference block: + Extents3d blockExt = default; + var mat = Matrix3d.Identity; + block!.GetBlockBox(ref blockExt, ref mat); + if (!blockExt.IsEmptyExt()) + ext = blockExt; + break; + default: + if (ent.Bounds.HasValue) + ext = ent.GeometricExtents; + break; } - return GetEntityBox(ent); + if (ext != null) + //实体不是点时,pass + if (ent is not DBPoint && ext.Value.MinPoint.IsEqualTo(ext.Value.MaxPoint)) + return null; + return ext; } /// -- Gitee From 7e696707b43bc0d4250c94de32aa8ad2723adcea Mon Sep 17 00:00:00 2001 From: liuqihong <540762622@qq.com> Date: Sun, 17 Mar 2024 10:47:56 +0000 Subject: [PATCH 252/453] update tests/TestShared/TestJig.cs. Signed-off-by: liuqihong <540762622@qq.com> --- tests/TestShared/TestJig.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/TestShared/TestJig.cs b/tests/TestShared/TestJig.cs index c0bf411..e5711c9 100644 --- a/tests/TestShared/TestJig.cs +++ b/tests/TestShared/TestJig.cs @@ -1,4 +1,4 @@ -namespace Test; +namespace Test; using System.Windows.Forms; @@ -69,7 +69,7 @@ public void Test_Jig44() // 不要这样做: jig.SetOptions(closestPt) 而是使用底层暴露 options!.BasePoint = closestPt; - // 需要避免重复加入同一个关键字 + // 允许在循环中替换关键字,需要避免重复加入同一个关键字 if (!options.Keywords.Contains("A")) options.Keywords.Add("A"); @@ -82,10 +82,13 @@ public void Test_Jig44() }); options = jig.SetOptions(per.PickedPoint); - + + // 在这里加入关键字 // 如果没有这个,那么空格只会是 PromptStatus.None 而不是 PromptStatus.Keyword // options.Keywords.Add(" ", " ", "空格结束啊"); // jig.SetSpaceIsKeyword(); + options.Keywords.Add("A","A","A"); + bool flag = true; while (flag) -- Gitee From efed9f450ca37fa56bda345b44632b325a2f4723 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Fri, 22 Mar 2024 18:24:25 +0800 Subject: [PATCH 253/453] =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E5=88=9D=E5=A7=8B?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IFoxCAD.sln | 142 +- src/Basal/Directory.Build.props | 37 - src/Basal/IFox.Basal.Shared/CLS/Index.cs | 151 -- src/Basal/IFox.Basal.Shared/CLS/Range.cs | 105 -- .../IFox.Basal.Shared/CLS/RuntimeHelpers.cs | 58 - .../CLS/TupleElementNamesAttribute.cs | 51 - .../ExpressionTrees/ParameterRebinder.cs | 34 - .../ExpressionTrees/PredicateBuilder.cs | 78 - .../ExpressionTrees/SqlExpressionVisitor.cs | 437 ----- .../IFox.Basal.Shared/General/ArrayEx.cs | 58 - .../IFox.Basal.Shared/General/DebugHelper.cs | 32 - src/Basal/IFox.Basal.Shared/General/EnumEx.cs | 111 -- .../General/IsExternalInit.cs | 19 - .../General/LinkedHashMap.cs | 157 -- .../General/LinkedHashSet.cs | 210 --- src/Basal/IFox.Basal.Shared/General/LinqEx.cs | 327 ---- .../IFox.Basal.Shared/General/LoopList.cs | 745 -------- .../IFox.Basal.Shared/General/LoopState.cs | 70 - src/Basal/IFox.Basal.Shared/General/MathEx.cs | 22 - .../IFox.Basal.Shared/General/RandomEx.cs | 196 -- src/Basal/IFox.Basal.Shared/General/Timer.cs | 148 -- .../IFox.Basal.Shared.projitems | 38 - .../IFox.Basal.Shared.shproj | 13 - .../Nullable/ArgumentNullEx.cs | 39 - .../CallerArgumentExpressionAttribute.cs | 22 - .../Nullable/NullableAttributes.cs | 196 -- .../IFox.Basal.Shared/WindowsAPI/Enums.cs | 1073 ----------- .../IFox.Basal.Shared/WindowsAPI/MouseHook.cs | 316 ---- .../WindowsAPI/WindowsAPI.cs | 660 ------- .../IFox.Basal.Source.csproj | 49 - src/Basal/IFox.Basal/GlobalUsings.cs | 16 - src/Basal/IFox.Basal/IFox.Basal.csproj | 22 - src/CAD/Directory.Build.props | 34 - src/CAD/IFox.CAD.ACAD/GlobalUsings.cs | 41 - src/CAD/IFox.CAD.ACAD/IFox.CAD.ACAD.csproj | 41 - src/CAD/IFox.CAD.GCAD/GlobalUsings.cs | 41 - src/CAD/IFox.CAD.GCAD/IFox.CAD.GCAD.csproj | 42 - .../IFox.CAD.Shared/Algorithms/Graph/Graph.cs | 692 -------- .../Algorithms/Graph/IGraph.cs | 107 -- .../Algorithms/QuadTree/QuadEntity.cs | 25 - .../Algorithms/QuadTree/QuadTree.cs | 260 --- .../Algorithms/QuadTree/QuadTreeEvn.cs | 28 - .../Algorithms/QuadTree/QuadTreeNode.cs | 818 --------- .../Algorithms/QuadTree/QuadTreeSelectMode.cs | 39 - .../Algorithms/QuadTree/Rect.cs | 742 -------- src/CAD/IFox.CAD.Shared/AutoReg/AcadEMR.cs | 150 -- src/CAD/IFox.CAD.Shared/AutoReg/AssemInfo.cs | 88 - src/CAD/IFox.CAD.Shared/AutoReg/AutoLoad.cs | 62 - src/CAD/IFox.CAD.Shared/AutoReg/AutoReg.cs | 66 - .../IFox.CAD.Shared/AutoReg/AutoRegAssem.cs | 102 -- src/CAD/IFox.CAD.Shared/AutoReg/IAutoGo.cs | 404 ----- .../AutoReg/MethodInfoHelper.cs | 64 - .../IFox.CAD.Shared/CadVersion/AcadVersion.cs | 57 - .../IFox.CAD.Shared/CadVersion/CadVersion.cs | 41 - .../IFox.CAD.Shared/Copyclip/BitmapTool.cs | 165 -- src/CAD/IFox.CAD.Shared/Copyclip/EmfTool.cs | 927 ---------- .../Copyclip/TagClipboardInfo.cs | 662 ------- .../ExtensionMethod/AttachmentPointHelper.cs | 56 - .../ExtensionMethod/BulgeVertexWidth.cs | 92 - .../ExtensionMethod/CheckFactory.cs | 48 - .../ExtensionMethod/CollectionEx.cs | 307 ---- .../ExtensionMethod/Curve2dEx.cs | 296 ---- .../ExtensionMethod/Curve3dEx.cs | 557 ------ .../ExtensionMethod/CurveEx.cs | 989 ----------- .../ExtensionMethod/DBDictionaryEx.cs | 377 ---- .../ExtensionMethod/DBObjectEx.cs | 195 -- .../ExtensionMethod/DBTransEx.cs | 94 - .../ExtensionMethod/DatabaseEx.cs | 201 --- .../ExtensionMethod/DwgMark.cs | 63 - .../ExtensionMethod/EditorEx.cs | 1184 ------------- .../ExtensionMethod/Entity/ArcEx.cs | 86 - .../Entity/BlockReferenceEx.cs | 236 --- .../ExtensionMethod/Entity/BoundingInfo.cs | 179 -- .../ExtensionMethod/Entity/CircleEx.cs | 59 - .../ExtensionMethod/Entity/DBTextEx.cs | 59 - .../Entity/EntityBoundingInfo.cs | 228 --- .../ExtensionMethod/Entity/EntityEx.cs | 166 -- .../ExtensionMethod/Entity/MTextEx.cs | 76 - .../ExtensionMethod/Entity/PolylineEx.cs | 122 -- .../IFox.CAD.Shared/ExtensionMethod/Enums.cs | 202 --- .../ExtensionMethod/ErrorInfoEx.cs | 421 ----- .../ExtensionMethod/Filer/DwgFiler.cs | 496 ------ .../ExtensionMethod/Filer/DwgFilerEx.cs | 91 - .../ExtensionMethod/Filer/DxfFiler.cs | 225 --- .../ExtensionMethod/GeometryEx.cs | 679 ------- .../ExtensionMethod/IdleAction.cs | 67 - .../ExtensionMethod/Jig/JigEx.cs | 419 ----- .../ExtensionMethod/Jig/JigExTransient.cs | 148 -- .../ExtensionMethod/JsonConverter.cs | 120 -- .../IFox.CAD.Shared/ExtensionMethod/ObjEx.cs | 17 - .../ExtensionMethod/ObjectIdEx.cs | 141 -- .../ExtensionMethod/PointEx.cs | 247 --- .../ExtensionMethod/RedrawEx.cs | 200 --- .../ExtensionMethod/SelectionSetEx.cs | 114 -- .../ExtensionMethod/SingleKeyWordHook.cs | 180 -- .../ExtensionMethod/SymbolTableEx.cs | 368 ---- .../ExtensionMethod/SymbolTableRecordEx.cs | 354 ---- .../IFox.CAD.Shared/ExtensionMethod/Tools.cs | 164 -- .../ExtensionMethod/TransactionEx.cs | 41 - .../IFox.CAD.Shared/ExtensionMethod/XrefEx.cs | 643 ------- .../HatchConverter.cs" | 454 ----- .../HatchEx.cs" | 358 ---- .../HatchInfo.cs" | 354 ---- .../IFox.CAD.Shared/IFox.CAD.Shared.projitems | 100 -- .../IFox.CAD.Shared/IFox.CAD.Shared.shproj | 13 - src/CAD/IFox.CAD.Shared/PE/AcadPeInfo.cs | 389 ---- src/CAD/IFox.CAD.Shared/PE/DBmod.cs | 120 -- src/CAD/IFox.CAD.Shared/PE/PostCmd.cs | 237 --- src/CAD/IFox.CAD.Shared/PE/ProgramPE.cs | 1576 ----------------- .../ResultData/LispDottedPair.cs | 68 - .../IFox.CAD.Shared/ResultData/LispList.cs | 194 -- .../ResultData/TypedValueList.cs | 64 - .../ResultData/XRecordDataList.cs | 67 - .../IFox.CAD.Shared/ResultData/XdataList.cs | 146 -- src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs | 620 ------- src/CAD/IFox.CAD.Shared/Runtime/Env.cs | 887 ---------- .../IFox.CAD.Shared/Runtime/SymbolTable.cs | 408 ----- .../IFox.CAD.Shared/SelectionFilter/OpComp.cs | 79 - .../SelectionFilter/OpEqual.cs | 86 - .../SelectionFilter/OpFilter.cs | 341 ---- .../IFox.CAD.Shared/SelectionFilter/OpList.cs | 162 -- .../IFox.CAD.Shared/SelectionFilter/OpLogi.cs | 133 -- .../IFox.CAD.Source/IFox.CAD.Source.csproj | 49 - src/CAD/IFox.CAD.ZCAD/GlobalUsings.cs | 42 - src/CAD/IFox.CAD.ZCAD/IFox.CAD.ZCAD.csproj | 44 - src/Event/EVENT/.keep | 0 .../EventEx/BeginDoubleClickEvent.cs | 108 -- .../EventEx/DocumentActivatedEvent.cs | 108 -- .../EventEx/DocumentLockModeChangedEvent.cs | 122 -- .../EventEx/SystemVariableChangedEvent.cs | 122 -- .../EventFactory/CadEvent.cs | 30 - .../EventFactory/EventFactory.cs | 100 -- .../EventFactory/EventMethodInfo.cs | 22 - .../EventTemporaryShutdownManager.cs | 40 - .../IFox.Event.Shared.projitems | 21 - .../IFox.Event.Shared.shproj | 13 - src/WPF/BindingErrorTraceListener.cs | 84 - src/WPF/Converter.cs | 98 - src/WPF/DependencyObjectExtensions.cs | 36 - src/WPF/EnumSelection.cs | 80 - src/WPF/EventBindingExtension.cs | 190 -- src/WPF/GlobalUsings.cs | 18 - src/WPF/IFox.WPF.csproj | 44 - src/WPF/RelayCommand.cs | 181 -- src/WPF/ViewModelBase.cs | 58 - tests/TestAcad09plus/GlobalUsings.cs | 50 - tests/TestAcad09plus/TestAcad09plus.csproj | 43 - tests/TestAcad09plus/wpf/Cmd.cs | 11 - tests/TestAcad09plus/wpf/TestView.xaml | 24 - tests/TestAcad09plus/wpf/TestView.xaml.cs | 28 - tests/TestAcad09plus/wpf/TestViewModel.cs | 82 - ...63\351\224\256\350\217\234\345\215\225.cs" | 184 -- ...53\345\205\205\344\272\213\344\273\266.cs" | 1030 ----------- .../HatchHelper.cs" | 124 -- ...350\275\254cad\345\235\220\346\240\207.cs" | 120 -- ...06\347\232\204\344\276\213\345\255\220.cs" | 94 - ...3\345\205\205\350\276\271\347\225\214.txt" | 104 -- ...71\347\202\271\344\276\213\345\255\220.cs" | 99 -- tests/TestConsole/GlobalUsings.cs | 15 - tests/TestConsole/Info.cs | 43 - tests/TestConsole/Program.cs | 218 --- tests/TestConsole/RuntimeHelpers.cs | 47 - tests/TestConsole/TestConsole.csproj | 22 - tests/TestConsole/TestSerialize.cs | 48 - ...50\350\276\276\345\274\217\346\240\221.cs" | 142 -- tests/TestGcad2024/GlobalUsings.cs | 49 - tests/TestGcad2024/TestGcad2024.csproj | 29 - tests/TestShared/CmdINI.cs | 189 -- tests/TestShared/Copyclip.cs | 879 --------- tests/TestShared/TestAddEntity.cs | 109 -- tests/TestShared/TestBlock.cs | 864 --------- tests/TestShared/TestCadFilePath.cs | 30 - tests/TestShared/TestConvexHull.cs | 76 - tests/TestShared/TestCurve.cs | 319 ---- tests/TestShared/TestDBTrans.cs | 203 --- tests/TestShared/TestDBobject.cs | 27 - tests/TestShared/TestDwgFilerEx.cs | 161 -- tests/TestShared/TestDwgMark.cs | 11 - tests/TestShared/TestEditor.cs | 87 - tests/TestShared/TestEntity/TestAddEntity.cs | 157 -- tests/TestShared/TestEnv.cs | 184 -- tests/TestShared/TestExtents.cs | 108 -- tests/TestShared/TestFileDatabase.cs | 28 - tests/TestShared/TestHatchinfo.cs | 18 - tests/TestShared/TestId.cs | 72 - tests/TestShared/TestJig.cs | 313 ---- tests/TestShared/TestJigExTransient.cs | 88 - tests/TestShared/TestJson.cs | 25 - tests/TestShared/TestLayer.cs | 66 - tests/TestShared/TestLisp.cs | 122 -- tests/TestShared/TestLoop.cs | 25 - tests/TestShared/TestMarshal.cs | 123 -- tests/TestShared/TestMirrorFile.cs | 73 - tests/TestShared/TestPoint.cs | 202 --- tests/TestShared/TestQuadTree.cs | 457 ----- tests/TestShared/TestSelectfilter.cs | 58 - tests/TestShared/TestShared.projitems | 50 - tests/TestShared/TestShared.shproj | 13 - tests/TestShared/TestSingleKeyWordHook.cs | 48 - tests/TestShared/TestText.cs | 49 - tests/TestShared/TestXRecord.cs | 252 --- tests/TestShared/TestXdata.cs | 132 -- tests/TestShared/TestXrefEx.cs | 24 - tests/TestShared/readme.md | 20 - tests/TestZcad2024/GlobalUsings.cs | 47 - tests/TestZcad2024/TestZcad2024.csproj | 29 - 206 files changed, 4 insertions(+), 39143 deletions(-) delete mode 100644 src/Basal/Directory.Build.props delete mode 100644 src/Basal/IFox.Basal.Shared/CLS/Index.cs delete mode 100644 src/Basal/IFox.Basal.Shared/CLS/Range.cs delete mode 100644 src/Basal/IFox.Basal.Shared/CLS/RuntimeHelpers.cs delete mode 100644 src/Basal/IFox.Basal.Shared/CLS/TupleElementNamesAttribute.cs delete mode 100644 src/Basal/IFox.Basal.Shared/ExpressionTrees/ParameterRebinder.cs delete mode 100644 src/Basal/IFox.Basal.Shared/ExpressionTrees/PredicateBuilder.cs delete mode 100644 src/Basal/IFox.Basal.Shared/ExpressionTrees/SqlExpressionVisitor.cs delete mode 100644 src/Basal/IFox.Basal.Shared/General/ArrayEx.cs delete mode 100644 src/Basal/IFox.Basal.Shared/General/DebugHelper.cs delete mode 100644 src/Basal/IFox.Basal.Shared/General/EnumEx.cs delete mode 100644 src/Basal/IFox.Basal.Shared/General/IsExternalInit.cs delete mode 100644 src/Basal/IFox.Basal.Shared/General/LinkedHashMap.cs delete mode 100644 src/Basal/IFox.Basal.Shared/General/LinkedHashSet.cs delete mode 100644 src/Basal/IFox.Basal.Shared/General/LinqEx.cs delete mode 100644 src/Basal/IFox.Basal.Shared/General/LoopList.cs delete mode 100644 src/Basal/IFox.Basal.Shared/General/LoopState.cs delete mode 100644 src/Basal/IFox.Basal.Shared/General/MathEx.cs delete mode 100644 src/Basal/IFox.Basal.Shared/General/RandomEx.cs delete mode 100644 src/Basal/IFox.Basal.Shared/General/Timer.cs delete mode 100644 src/Basal/IFox.Basal.Shared/IFox.Basal.Shared.projitems delete mode 100644 src/Basal/IFox.Basal.Shared/IFox.Basal.Shared.shproj delete mode 100644 src/Basal/IFox.Basal.Shared/Nullable/ArgumentNullEx.cs delete mode 100644 src/Basal/IFox.Basal.Shared/Nullable/CallerArgumentExpressionAttribute.cs delete mode 100644 src/Basal/IFox.Basal.Shared/Nullable/NullableAttributes.cs delete mode 100644 src/Basal/IFox.Basal.Shared/WindowsAPI/Enums.cs delete mode 100644 src/Basal/IFox.Basal.Shared/WindowsAPI/MouseHook.cs delete mode 100644 src/Basal/IFox.Basal.Shared/WindowsAPI/WindowsAPI.cs delete mode 100644 src/Basal/IFox.Basal.Source/IFox.Basal.Source.csproj delete mode 100644 src/Basal/IFox.Basal/GlobalUsings.cs delete mode 100644 src/Basal/IFox.Basal/IFox.Basal.csproj delete mode 100644 src/CAD/Directory.Build.props delete mode 100644 src/CAD/IFox.CAD.ACAD/GlobalUsings.cs delete mode 100644 src/CAD/IFox.CAD.ACAD/IFox.CAD.ACAD.csproj delete mode 100644 src/CAD/IFox.CAD.GCAD/GlobalUsings.cs delete mode 100644 src/CAD/IFox.CAD.GCAD/IFox.CAD.GCAD.csproj delete mode 100644 src/CAD/IFox.CAD.Shared/Algorithms/Graph/Graph.cs delete mode 100644 src/CAD/IFox.CAD.Shared/Algorithms/Graph/IGraph.cs delete mode 100644 src/CAD/IFox.CAD.Shared/Algorithms/QuadTree/QuadEntity.cs delete mode 100644 src/CAD/IFox.CAD.Shared/Algorithms/QuadTree/QuadTree.cs delete mode 100644 src/CAD/IFox.CAD.Shared/Algorithms/QuadTree/QuadTreeEvn.cs delete mode 100644 src/CAD/IFox.CAD.Shared/Algorithms/QuadTree/QuadTreeNode.cs delete mode 100644 src/CAD/IFox.CAD.Shared/Algorithms/QuadTree/QuadTreeSelectMode.cs delete mode 100644 src/CAD/IFox.CAD.Shared/Algorithms/QuadTree/Rect.cs delete mode 100644 src/CAD/IFox.CAD.Shared/AutoReg/AcadEMR.cs delete mode 100644 src/CAD/IFox.CAD.Shared/AutoReg/AssemInfo.cs delete mode 100644 src/CAD/IFox.CAD.Shared/AutoReg/AutoLoad.cs delete mode 100644 src/CAD/IFox.CAD.Shared/AutoReg/AutoReg.cs delete mode 100644 src/CAD/IFox.CAD.Shared/AutoReg/AutoRegAssem.cs delete mode 100644 src/CAD/IFox.CAD.Shared/AutoReg/IAutoGo.cs delete mode 100644 src/CAD/IFox.CAD.Shared/AutoReg/MethodInfoHelper.cs delete mode 100644 src/CAD/IFox.CAD.Shared/CadVersion/AcadVersion.cs delete mode 100644 src/CAD/IFox.CAD.Shared/CadVersion/CadVersion.cs delete mode 100644 src/CAD/IFox.CAD.Shared/Copyclip/BitmapTool.cs delete mode 100644 src/CAD/IFox.CAD.Shared/Copyclip/EmfTool.cs delete mode 100644 src/CAD/IFox.CAD.Shared/Copyclip/TagClipboardInfo.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/AttachmentPointHelper.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/BulgeVertexWidth.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/CheckFactory.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/CollectionEx.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/Curve2dEx.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/Curve3dEx.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/CurveEx.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/DBDictionaryEx.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/DBObjectEx.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/DBTransEx.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/DatabaseEx.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/DwgMark.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/ArcEx.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BoundingInfo.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/CircleEx.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/DBTextEx.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityEx.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/MTextEx.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/PolylineEx.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/Enums.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/ErrorInfoEx.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/Filer/DwgFiler.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/Filer/DwgFilerEx.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/Filer/DxfFiler.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/IdleAction.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigEx.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigExTransient.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/JsonConverter.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjEx.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/PointEx.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/RedrawEx.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/SelectionSetEx.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/SingleKeyWordHook.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableEx.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/Tools.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/TransactionEx.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ExtensionMethod/XrefEx.cs delete mode 100644 "src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchConverter.cs" delete mode 100644 "src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchEx.cs" delete mode 100644 "src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchInfo.cs" delete mode 100644 src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems delete mode 100644 src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.shproj delete mode 100644 src/CAD/IFox.CAD.Shared/PE/AcadPeInfo.cs delete mode 100644 src/CAD/IFox.CAD.Shared/PE/DBmod.cs delete mode 100644 src/CAD/IFox.CAD.Shared/PE/PostCmd.cs delete mode 100644 src/CAD/IFox.CAD.Shared/PE/ProgramPE.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ResultData/LispDottedPair.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ResultData/LispList.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ResultData/TypedValueList.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ResultData/XRecordDataList.cs delete mode 100644 src/CAD/IFox.CAD.Shared/ResultData/XdataList.cs delete mode 100644 src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs delete mode 100644 src/CAD/IFox.CAD.Shared/Runtime/Env.cs delete mode 100644 src/CAD/IFox.CAD.Shared/Runtime/SymbolTable.cs delete mode 100644 src/CAD/IFox.CAD.Shared/SelectionFilter/OpComp.cs delete mode 100644 src/CAD/IFox.CAD.Shared/SelectionFilter/OpEqual.cs delete mode 100644 src/CAD/IFox.CAD.Shared/SelectionFilter/OpFilter.cs delete mode 100644 src/CAD/IFox.CAD.Shared/SelectionFilter/OpList.cs delete mode 100644 src/CAD/IFox.CAD.Shared/SelectionFilter/OpLogi.cs delete mode 100644 src/CAD/IFox.CAD.Source/IFox.CAD.Source.csproj delete mode 100644 src/CAD/IFox.CAD.ZCAD/GlobalUsings.cs delete mode 100644 src/CAD/IFox.CAD.ZCAD/IFox.CAD.ZCAD.csproj delete mode 100644 src/Event/EVENT/.keep delete mode 100644 src/Event/IFox.Event.Shared/EventEx/BeginDoubleClickEvent.cs delete mode 100644 src/Event/IFox.Event.Shared/EventEx/DocumentActivatedEvent.cs delete mode 100644 src/Event/IFox.Event.Shared/EventEx/DocumentLockModeChangedEvent.cs delete mode 100644 src/Event/IFox.Event.Shared/EventEx/SystemVariableChangedEvent.cs delete mode 100644 src/Event/IFox.Event.Shared/EventFactory/CadEvent.cs delete mode 100644 src/Event/IFox.Event.Shared/EventFactory/EventFactory.cs delete mode 100644 src/Event/IFox.Event.Shared/EventFactory/EventMethodInfo.cs delete mode 100644 src/Event/IFox.Event.Shared/EventFactory/EventTemporaryShutdownManager.cs delete mode 100644 src/Event/IFox.Event.Shared/IFox.Event.Shared.projitems delete mode 100644 src/Event/IFox.Event.Shared/IFox.Event.Shared.shproj delete mode 100644 src/WPF/BindingErrorTraceListener.cs delete mode 100644 src/WPF/Converter.cs delete mode 100644 src/WPF/DependencyObjectExtensions.cs delete mode 100644 src/WPF/EnumSelection.cs delete mode 100644 src/WPF/EventBindingExtension.cs delete mode 100644 src/WPF/GlobalUsings.cs delete mode 100644 src/WPF/IFox.WPF.csproj delete mode 100644 src/WPF/RelayCommand.cs delete mode 100644 src/WPF/ViewModelBase.cs delete mode 100644 tests/TestAcad09plus/GlobalUsings.cs delete mode 100644 tests/TestAcad09plus/TestAcad09plus.csproj delete mode 100644 tests/TestAcad09plus/wpf/Cmd.cs delete mode 100644 tests/TestAcad09plus/wpf/TestView.xaml delete mode 100644 tests/TestAcad09plus/wpf/TestView.xaml.cs delete mode 100644 tests/TestAcad09plus/wpf/TestViewModel.cs delete mode 100644 "tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/01.\346\213\211\344\274\270\345\241\253\345\205\205\345\217\263\351\224\256\350\217\234\345\215\225.cs" delete mode 100644 "tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/02.\346\213\211\344\274\270\345\241\253\345\205\205\344\272\213\344\273\266.cs" delete mode 100644 "tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/HatchHelper.cs" delete mode 100644 "tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/\345\261\217\345\271\225\345\235\220\346\240\207\350\275\254cad\345\235\220\346\240\207.cs" delete mode 100644 "tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/\350\277\207\347\250\213\346\226\207\344\273\266/\344\270\200\344\270\252\346\227\240\346\263\225\347\247\273\345\212\250\347\272\242\350\211\262\345\234\206\347\232\204\344\276\213\345\255\220.cs" delete mode 100644 "tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/\350\277\207\347\250\213\346\226\207\344\273\266/\350\207\252\345\256\232\344\271\211\345\233\276\345\205\203\345\241\253\345\205\205\350\276\271\347\225\214.txt" delete mode 100644 "tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/\350\277\207\347\250\213\346\226\207\344\273\266/\350\216\267\345\217\226\345\244\271\347\202\271\344\276\213\345\255\220.cs" delete mode 100644 tests/TestConsole/GlobalUsings.cs delete mode 100644 tests/TestConsole/Info.cs delete mode 100644 tests/TestConsole/Program.cs delete mode 100644 tests/TestConsole/RuntimeHelpers.cs delete mode 100644 tests/TestConsole/TestConsole.csproj delete mode 100644 tests/TestConsole/TestSerialize.cs delete mode 100644 "tests/TestConsole/\350\241\250\350\276\276\345\274\217\346\240\221.cs" delete mode 100644 tests/TestGcad2024/GlobalUsings.cs delete mode 100644 tests/TestGcad2024/TestGcad2024.csproj delete mode 100644 tests/TestShared/CmdINI.cs delete mode 100644 tests/TestShared/Copyclip.cs delete mode 100644 tests/TestShared/TestAddEntity.cs delete mode 100644 tests/TestShared/TestBlock.cs delete mode 100644 tests/TestShared/TestCadFilePath.cs delete mode 100644 tests/TestShared/TestConvexHull.cs delete mode 100644 tests/TestShared/TestCurve.cs delete mode 100644 tests/TestShared/TestDBTrans.cs delete mode 100644 tests/TestShared/TestDBobject.cs delete mode 100644 tests/TestShared/TestDwgFilerEx.cs delete mode 100644 tests/TestShared/TestDwgMark.cs delete mode 100644 tests/TestShared/TestEditor.cs delete mode 100644 tests/TestShared/TestEntity/TestAddEntity.cs delete mode 100644 tests/TestShared/TestEnv.cs delete mode 100644 tests/TestShared/TestExtents.cs delete mode 100644 tests/TestShared/TestFileDatabase.cs delete mode 100644 tests/TestShared/TestHatchinfo.cs delete mode 100644 tests/TestShared/TestId.cs delete mode 100644 tests/TestShared/TestJig.cs delete mode 100644 tests/TestShared/TestJigExTransient.cs delete mode 100644 tests/TestShared/TestJson.cs delete mode 100644 tests/TestShared/TestLayer.cs delete mode 100644 tests/TestShared/TestLisp.cs delete mode 100644 tests/TestShared/TestLoop.cs delete mode 100644 tests/TestShared/TestMarshal.cs delete mode 100644 tests/TestShared/TestMirrorFile.cs delete mode 100644 tests/TestShared/TestPoint.cs delete mode 100644 tests/TestShared/TestQuadTree.cs delete mode 100644 tests/TestShared/TestSelectfilter.cs delete mode 100644 tests/TestShared/TestShared.projitems delete mode 100644 tests/TestShared/TestShared.shproj delete mode 100644 tests/TestShared/TestSingleKeyWordHook.cs delete mode 100644 tests/TestShared/TestText.cs delete mode 100644 tests/TestShared/TestXRecord.cs delete mode 100644 tests/TestShared/TestXdata.cs delete mode 100644 tests/TestShared/TestXrefEx.cs delete mode 100644 tests/TestShared/readme.md delete mode 100644 tests/TestZcad2024/GlobalUsings.cs delete mode 100644 tests/TestZcad2024/TestZcad2024.csproj diff --git a/IFoxCAD.sln b/IFoxCAD.sln index 3480358..90d5280 100644 --- a/IFoxCAD.sln +++ b/IFoxCAD.sln @@ -1,151 +1,17 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 -VisualStudioVersion = 17.1.32113.165 +VisualStudioVersion = 17.8.34309.116 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Config", "Config", "{786E7347-B116-4F26-9AEF-33EB0AB88D58}" - ProjectSection(SolutionItems) = preProject - .gitattributes = .gitattributes - .gitignore = .gitignore - EndProjectSection -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestConsole", "tests\TestConsole\TestConsole.csproj", "{E2873F0B-CAD2-45E8-8FF0-C05C0C6AD955}" -EndProject -Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "TestShared", "tests\TestShared\TestShared.shproj", "{CED63D2D-0AF6-4831-806D-5E8E9B0D0A07}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestAcad09plus", "tests\TestAcad09plus\TestAcad09plus.csproj", "{5F478F68-19BC-4A3A-AF39-8728F8D396DD}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Test", "Test", "{C0BEFC15-6DF7-4636-BC76-4A0B88231470}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Basal", "Basal", "{1A5C27C1-FEF3-40A0-A1EE-3BC7BF2BD67A}" - ProjectSection(SolutionItems) = preProject - src\Basal\Directory.Build.props = src\Basal\Directory.Build.props - EndProjectSection -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IFox.Basal", "src\Basal\IFox.Basal\IFox.Basal.csproj", "{FF4E1CDE-EEB3-4BE8-8C1D-6B5B17A299C7}" -EndProject -Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "IFox.Basal.Shared", "src\Basal\IFox.Basal.Shared\IFox.Basal.Shared.shproj", "{C823514A-2BC2-45C2-ACED-18924A7B80BF}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IFox.Basal.Source", "src\Basal\IFox.Basal.Source\IFox.Basal.Source.csproj", "{D0C6824C-53A3-4C16-AE7B-3227F18C5039}" -EndProject -Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "IFox.CAD.Shared", "src\CAD\IFox.CAD.Shared\IFox.CAD.Shared.shproj", "{20F254F7-AEE5-42AE-A9B3-149BBDC7397F}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CAD", "CAD", "{B2AB7DC7-DBF4-4197-808B-0D2A6613AF5E}" - ProjectSection(SolutionItems) = preProject - src\CAD\Directory.Build.props = src\CAD\Directory.Build.props - EndProjectSection -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IFox.CAD.Source", "src\CAD\IFox.CAD.Source\IFox.CAD.Source.csproj", "{88F3CF78-23F5-494B-9D8F-2C6B4467E0B4}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IFox.CAD.ACAD", "src\CAD\IFox.CAD.ACAD\IFox.CAD.ACAD.csproj", "{EF20E632-70A9-40EB-8C9A-539FD85FAFAD}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IFox.CAD.GCAD", "src\CAD\IFox.CAD.GCAD\IFox.CAD.GCAD.csproj", "{F388F4B9-F636-414A-9BC9-2B008517B441}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IFox.CAD.ZCAD", "src\CAD\IFox.CAD.ZCAD\IFox.CAD.ZCAD.csproj", "{3D7D095D-EF0A-40B3-9776-5F08C61FD614}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WPF", "WPF", "{1EE1F817-39D3-43E5-B087-E7AD4D0BEC93}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IFox.WPF", "src\WPF\IFox.WPF.csproj", "{6ED0A677-6621-4493-AF58-71C2BF31DFCE}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Docs", "Docs", "{DA8EA8E7-A98E-4565-A3BF-97855988DB8E}" - ProjectSection(SolutionItems) = preProject - docs\0x01代码规范.md = docs\0x01代码规范.md - docs\DBTrans.md = docs\DBTrans.md - LICENSE = LICENSE - README.md = README.md - docs\SelectionFilter.md = docs\SelectionFilter.md - docs\SymbolTable.md = docs\SymbolTable.md - docs\WPF.md = docs\WPF.md - docs\关于IFoxCAD的架构说明.md = docs\关于IFoxCAD的架构说明.md - docs\关于扩展函数的说明.md = docs\关于扩展函数的说明.md - EndProjectSection -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestGcad2024", "tests\TestGcad2024\TestGcad2024.csproj", "{FEC39964-9ECB-4567-8F68-94F80A39FA02}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestZcad2024", "tests\TestZcad2024\TestZcad2024.csproj", "{890D0AA3-1621-47F2-9E47-75D16A51D36E}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IFoxCAD.CAD", "IFoxCAD.CAD\IFoxCAD.CAD.csproj", "{6B29955A-5796-4035-9297-210FA15D3846}" EndProject Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {E2873F0B-CAD2-45E8-8FF0-C05C0C6AD955}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E2873F0B-CAD2-45E8-8FF0-C05C0C6AD955}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E2873F0B-CAD2-45E8-8FF0-C05C0C6AD955}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E2873F0B-CAD2-45E8-8FF0-C05C0C6AD955}.Release|Any CPU.Build.0 = Release|Any CPU - {5F478F68-19BC-4A3A-AF39-8728F8D396DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5F478F68-19BC-4A3A-AF39-8728F8D396DD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5F478F68-19BC-4A3A-AF39-8728F8D396DD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5F478F68-19BC-4A3A-AF39-8728F8D396DD}.Release|Any CPU.Build.0 = Release|Any CPU - {FF4E1CDE-EEB3-4BE8-8C1D-6B5B17A299C7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FF4E1CDE-EEB3-4BE8-8C1D-6B5B17A299C7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FF4E1CDE-EEB3-4BE8-8C1D-6B5B17A299C7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FF4E1CDE-EEB3-4BE8-8C1D-6B5B17A299C7}.Release|Any CPU.Build.0 = Release|Any CPU - {D0C6824C-53A3-4C16-AE7B-3227F18C5039}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D0C6824C-53A3-4C16-AE7B-3227F18C5039}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D0C6824C-53A3-4C16-AE7B-3227F18C5039}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D0C6824C-53A3-4C16-AE7B-3227F18C5039}.Release|Any CPU.Build.0 = Release|Any CPU - {88F3CF78-23F5-494B-9D8F-2C6B4467E0B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {88F3CF78-23F5-494B-9D8F-2C6B4467E0B4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {88F3CF78-23F5-494B-9D8F-2C6B4467E0B4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {88F3CF78-23F5-494B-9D8F-2C6B4467E0B4}.Release|Any CPU.Build.0 = Release|Any CPU - {EF20E632-70A9-40EB-8C9A-539FD85FAFAD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EF20E632-70A9-40EB-8C9A-539FD85FAFAD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EF20E632-70A9-40EB-8C9A-539FD85FAFAD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EF20E632-70A9-40EB-8C9A-539FD85FAFAD}.Release|Any CPU.Build.0 = Release|Any CPU - {F388F4B9-F636-414A-9BC9-2B008517B441}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F388F4B9-F636-414A-9BC9-2B008517B441}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F388F4B9-F636-414A-9BC9-2B008517B441}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F388F4B9-F636-414A-9BC9-2B008517B441}.Release|Any CPU.Build.0 = Release|Any CPU - {3D7D095D-EF0A-40B3-9776-5F08C61FD614}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3D7D095D-EF0A-40B3-9776-5F08C61FD614}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3D7D095D-EF0A-40B3-9776-5F08C61FD614}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3D7D095D-EF0A-40B3-9776-5F08C61FD614}.Release|Any CPU.Build.0 = Release|Any CPU - {6ED0A677-6621-4493-AF58-71C2BF31DFCE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6ED0A677-6621-4493-AF58-71C2BF31DFCE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6ED0A677-6621-4493-AF58-71C2BF31DFCE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6ED0A677-6621-4493-AF58-71C2BF31DFCE}.Release|Any CPU.Build.0 = Release|Any CPU - {FEC39964-9ECB-4567-8F68-94F80A39FA02}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FEC39964-9ECB-4567-8F68-94F80A39FA02}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FEC39964-9ECB-4567-8F68-94F80A39FA02}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FEC39964-9ECB-4567-8F68-94F80A39FA02}.Release|Any CPU.Build.0 = Release|Any CPU - {890D0AA3-1621-47F2-9E47-75D16A51D36E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {890D0AA3-1621-47F2-9E47-75D16A51D36E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {890D0AA3-1621-47F2-9E47-75D16A51D36E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {890D0AA3-1621-47F2-9E47-75D16A51D36E}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {E2873F0B-CAD2-45E8-8FF0-C05C0C6AD955} = {C0BEFC15-6DF7-4636-BC76-4A0B88231470} - {CED63D2D-0AF6-4831-806D-5E8E9B0D0A07} = {C0BEFC15-6DF7-4636-BC76-4A0B88231470} - {5F478F68-19BC-4A3A-AF39-8728F8D396DD} = {C0BEFC15-6DF7-4636-BC76-4A0B88231470} - {FF4E1CDE-EEB3-4BE8-8C1D-6B5B17A299C7} = {1A5C27C1-FEF3-40A0-A1EE-3BC7BF2BD67A} - {C823514A-2BC2-45C2-ACED-18924A7B80BF} = {1A5C27C1-FEF3-40A0-A1EE-3BC7BF2BD67A} - {D0C6824C-53A3-4C16-AE7B-3227F18C5039} = {1A5C27C1-FEF3-40A0-A1EE-3BC7BF2BD67A} - {20F254F7-AEE5-42AE-A9B3-149BBDC7397F} = {B2AB7DC7-DBF4-4197-808B-0D2A6613AF5E} - {88F3CF78-23F5-494B-9D8F-2C6B4467E0B4} = {B2AB7DC7-DBF4-4197-808B-0D2A6613AF5E} - {EF20E632-70A9-40EB-8C9A-539FD85FAFAD} = {B2AB7DC7-DBF4-4197-808B-0D2A6613AF5E} - {F388F4B9-F636-414A-9BC9-2B008517B441} = {B2AB7DC7-DBF4-4197-808B-0D2A6613AF5E} - {3D7D095D-EF0A-40B3-9776-5F08C61FD614} = {B2AB7DC7-DBF4-4197-808B-0D2A6613AF5E} - {6ED0A677-6621-4493-AF58-71C2BF31DFCE} = {1EE1F817-39D3-43E5-B087-E7AD4D0BEC93} - {FEC39964-9ECB-4567-8F68-94F80A39FA02} = {C0BEFC15-6DF7-4636-BC76-4A0B88231470} - {890D0AA3-1621-47F2-9E47-75D16A51D36E} = {C0BEFC15-6DF7-4636-BC76-4A0B88231470} - EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {31D6C754-CF6B-4AB0-9861-6923DD312350} + SolutionGuid = {57CA0128-08DE-436F-B9F1-82C64F49BF67} EndGlobalSection - GlobalSection(SharedMSBuildProjectFiles) = preSolution - src\CAD\IFox.CAD.Shared\IFox.CAD.Shared.projitems*{20f254f7-aee5-42ae-a9b3-149bbdc7397f}*SharedItemsImports = 13 - src\CAD\IFox.CAD.Shared\IFox.CAD.Shared.projitems*{3d7d095d-ef0a-40b3-9776-5f08c61fd614}*SharedItemsImports = 5 - tests\TestShared\TestShared.projitems*{5f478f68-19bc-4a3a-af39-8728f8d396dd}*SharedItemsImports = 5 - src\Basal\IFox.Basal.Shared\IFox.Basal.Shared.projitems*{c823514a-2bc2-45c2-aced-18924a7b80bf}*SharedItemsImports = 13 - tests\TestShared\TestShared.projitems*{ced63d2d-0af6-4831-806d-5e8e9b0d0a07}*SharedItemsImports = 13 - src\CAD\IFox.CAD.Shared\IFox.CAD.Shared.projitems*{ef20e632-70a9-40eb-8c9a-539fd85fafad}*SharedItemsImports = 5 - src\CAD\IFox.CAD.Shared\IFox.CAD.Shared.projitems*{f388f4b9-f636-414a-9bc9-2b008517b441}*SharedItemsImports = 5 - tests\TestShared\TestShared.projitems*{fec39964-9ecb-4567-8f68-94f80a39fa02}*SharedItemsImports = 5 - src\Basal\IFox.Basal.Shared\IFox.Basal.Shared.projitems*{ff4e1cde-eeb3-4be8-8c1d-6b5b17a299c7}*SharedItemsImports = 5 + GlobalSection(ProjectConfigurationPlatforms) = postSolution EndGlobalSection EndGlobal diff --git a/src/Basal/Directory.Build.props b/src/Basal/Directory.Build.props deleted file mode 100644 index ae9fb12..0000000 --- a/src/Basal/Directory.Build.props +++ /dev/null @@ -1,37 +0,0 @@ - - - - 0.7.2 - 发布0.7.2 - - - - preview - enable - true - ..\..\..\bin\$(Configuration)\ - true - true - True - True - - - - - - InspireFunction - xsfhlzh;vicwjb;liuqihong;DYH - InspireFunction - 基于.NET的二次开发基本类库. - MIT - true - https://gitee.com/inspirefunction/ifoxcad - https://gitee.com/inspirefunction/ifoxcad.git - git - IFox;C#;NET;Common;Basal - - - - - - \ No newline at end of file diff --git a/src/Basal/IFox.Basal.Shared/CLS/Index.cs b/src/Basal/IFox.Basal.Shared/CLS/Index.cs deleted file mode 100644 index ae562f8..0000000 --- a/src/Basal/IFox.Basal.Shared/CLS/Index.cs +++ /dev/null @@ -1,151 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. -#if !NOINDEX -namespace System; - - - - - -/// Represent a type can be used to index a collection either from the start or the end. -/// -/// Index is used by the C# compiler to support the new index syntax -/// -/// int[] someArray = new int[5] { 1, 2, 3, 4, 5 } ; -/// int lastElement = someArray[^1]; // lastElement = 5 -/// -/// -public readonly struct Index : IEquatable -{ - private readonly int _value; - - /// Construct an Index using a value and indicating if the index is from the start or from the end. - /// The index value. it has to be zero or positive number. - /// Indicating if the index is from the start or from the end. - /// - /// If the Index constructed from the end, index value 1 means pointing at the last element and index value 0 means pointing at beyond last element. - /// -#if NET45_OR_GREATER - [MethodImpl(MethodImplOptions.AggressiveInlining)] -#endif - public Index(int value, bool fromEnd = false) - { - if (value < 0) - { - throw new ArgumentOutOfRangeException(nameof(value), "value must be non-negative"); - } - - if (fromEnd) - _value = ~value; - else - _value = value; - } - - // The following private constructors mainly created for perf reason to avoid the checks - private Index(int value) - { - _value = value; - } - - /// Create an Index pointing at first element. - public static Index Start => new(0); - - /// Create an Index pointing at beyond last element. - public static Index End => new(~0); - - /// Create an Index from the start at the position indicated by the value. - /// The index value from the start. -#if NET45_OR_GREATER - [MethodImpl(MethodImplOptions.AggressiveInlining)] -#endif - public static Index FromStart(int value) - { - if (value < 0) - { - throw new ArgumentOutOfRangeException(nameof(value), "value must be non-negative"); - } - - return new Index(value); - } - - /// Create an Index from the end at the position indicated by the value. - /// The index value from the end. -#if NET45_OR_GREATER - [MethodImpl(MethodImplOptions.AggressiveInlining)] -#endif - public static Index FromEnd(int value) - { - if (value < 0) - { - throw new ArgumentOutOfRangeException(nameof(value), "value must be non-negative"); - } - - return new Index(~value); - } - - /// Returns the index value. - public int Value - { - get - { - if (_value < 0) - return ~_value; - else - return _value; - } - } - - /// Indicates whether the index is from the start or the end. - public bool IsFromEnd => _value < 0; - - /// Calculate the offset from the start using the giving collection length. - /// The length of the collection that the Index will be used with. length has to be a positive value - /// - /// For performance reason, we don't validate the input length parameter and the returned offset value against negative values. - /// we don't validate either the returned offset is greater than the input length. - /// It is expected Index will be used with collections which always have non negative length/count. If the returned offset is negative and - /// then used to index a collection will get out of range exception which will be same affect as the validation. - /// -#if NET45_OR_GREATER - [MethodImpl(MethodImplOptions.AggressiveInlining)] -#endif - public int GetOffset(int length) - { - int offset = _value; - if (IsFromEnd) - { - // offset = length - (~value) - // offset = length + (~(~value) + 1) - // offset = length + value + 1 - - offset += length + 1; - } - return offset; - } - - /// Indicates whether the current Index object is equal to another object of the same type. - /// An object to compare with this object - public override bool Equals(object? value) => value is Index index && _value == index._value; - - /// Indicates whether the current Index object is equal to another Index object. - /// An object to compare with this object - public bool Equals(Index other) => _value == other._value; - - /// Returns the hash code for this instance. - public override int GetHashCode() => _value; - - /// Converts integer number to an Index. - public static implicit operator Index(int value) => FromStart(value); - - /// Converts the value of the current Index object to its equivalent string representation. - public override string ToString() - { - if (IsFromEnd) - return "^" + ((uint)Value).ToString(); - - return ((uint)Value).ToString(); - } -} - -#endif \ No newline at end of file diff --git a/src/Basal/IFox.Basal.Shared/CLS/Range.cs b/src/Basal/IFox.Basal.Shared/CLS/Range.cs deleted file mode 100644 index 0da227e..0000000 --- a/src/Basal/IFox.Basal.Shared/CLS/Range.cs +++ /dev/null @@ -1,105 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. -#if !NORANGE -namespace System; - - - - - -/// Represent a range has start and end indexes. -/// -/// Range is used by the C# compiler to support the range syntax. -/// -/// int[] someArray = new int[5] { 1, 2, 3, 4, 5 }; -/// int[] subArray1 = someArray[0..2]; // { 1, 2 } -/// int[] subArray2 = someArray[1..^0]; // { 2, 3, 4, 5 } -/// -/// -public readonly struct Range : IEquatable -{ - /// Represent the inclusive start index of the Range. - public Index Start { get; } - - /// Represent the exclusive end index of the Range. - public Index End { get; } - - /// Construct a Range object using the start and end indexes. - /// Represent the inclusive start index of the range. - /// Represent the exclusive end index of the range. - public Range(Index start, Index end) - { - Start = start; - End = end; - } - - /// Indicates whether the current Range object is equal to another object of the same type. - /// An object to compare with this object - public override bool Equals(object? value) => - value is Range r && - r.Start.Equals(Start) && - r.End.Equals(End); - - /// Indicates whether the current Range object is equal to another Range object. - /// An object to compare with this object - public bool Equals(Range other) => other.Start.Equals(Start) && other.End.Equals(End); - - /// Returns the hash code for this instance. - public override int GetHashCode() - { - return Start.GetHashCode() * 31 + End.GetHashCode(); - } - - /// Converts the value of the current Range object to its equivalent string representation. - public override string ToString() - { - return Start + ".." + End; - } - - /// Create a Range object starting from start index to the end of the collection. - public static Range StartAt(Index start) => new(start, Index.End); - - /// Create a Range object starting from first element in the collection to the end Index. - public static Range EndAt(Index end) => new(Index.Start, end); - - /// Create a Range object starting from first element to the end. - public static Range All => new(Index.Start, Index.End); - - /// Calculate the start offset and length of range object using a collection length. - /// The length of the collection that the range will be used with. length has to be a positive value. - /// - /// For performance reason, we don't validate the input length parameter against negative values. - /// It is expected Range will be used with collections which always have non negative length/count. - /// We validate the range is inside the length scope though. - /// -#if NET45_OR_GREATER - [MethodImpl(MethodImplOptions.AggressiveInlining)] -#endif - // [CLSCompliant(false)] - public (int Offset, int Length) GetOffsetAndLength(int length) - { - int start; - Index startIndex = Start; - if (startIndex.IsFromEnd) - start = length - startIndex.Value; - else - start = startIndex.Value; - - int end; - Index endIndex = End; - if (endIndex.IsFromEnd) - end = length - endIndex.Value; - else - end = endIndex.Value; - - if ((uint)end > (uint)length || (uint)start > (uint)end) - { - throw new ArgumentOutOfRangeException(nameof(length)); - } - - return (start, end - start); - } -} - -#endif \ No newline at end of file diff --git a/src/Basal/IFox.Basal.Shared/CLS/RuntimeHelpers.cs b/src/Basal/IFox.Basal.Shared/CLS/RuntimeHelpers.cs deleted file mode 100644 index 6dcdb89..0000000 --- a/src/Basal/IFox.Basal.Shared/CLS/RuntimeHelpers.cs +++ /dev/null @@ -1,58 +0,0 @@ -#if false -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using IFoxCAD.Basal; - -namespace System.Runtime.CompilerServices; - -/* - * 1.编译提示多个程序集中定义,屏蔽不了,但是不影响编译 - * 2.发现可以通过定义一个条件编译常量来进行屏蔽。 - * 3.普通包会提示编译器缺少GetSubArray函数,但是源码包不会。所以解决方案就是使用普通包的时候安装TA.System.Runtime.CompilerServices.RuntimeHelpers.GetSubArray nuget包来解决,此包为一个符号包,不会生成多余的dll - */ - - -#if !NORuntimeHelpers -/// -/// -/// -internal static class RuntimeHelpers - -{ - /// - /// Slices the specified array using the specified range. - /// - public static T[] GetSubArray(T[] array, Range range) - { - //if (array == null) - // throw new ArgumentNullException(nameof(array)); - array.NotNull(nameof(array)); - - (int offset, int length) = range.GetOffsetAndLength(array.Length); - - if (default(T)! != null || typeof(T[]) == array.GetType()) // NULLABLE: default(T) == null warning (https://github.com/dotnet/roslyn/issues/34757) - { - // We know the type of the array to be exactly T[]. - if (length == 0) - { - // return Array.Empty(); - return new T[0]; - } - - var dest = new T[length]; - Array.Copy(array, offset, dest, 0, length); - return dest; - } - else - { - // The array is actually a U[] where U:T. - T[] dest = (T[])Array.CreateInstance(array.GetType().GetElementType()!, length); - Array.Copy(array, offset, dest, 0, length); - return dest; - } - } -} -#endif -#endif \ No newline at end of file diff --git a/src/Basal/IFox.Basal.Shared/CLS/TupleElementNamesAttribute.cs b/src/Basal/IFox.Basal.Shared/CLS/TupleElementNamesAttribute.cs deleted file mode 100644 index 747ae51..0000000 --- a/src/Basal/IFox.Basal.Shared/CLS/TupleElementNamesAttribute.cs +++ /dev/null @@ -1,51 +0,0 @@ -#if false -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -namespace System.Runtime.CompilerServices; - -/// -/// Indicates that the use of on a member is meant to be treated as a tuple with element names. -/// -[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Event)] -public sealed class TupleElementNamesAttribute : Attribute -{ - private readonly string[] _transformNames; - - /// - /// Initializes a new instance of the class. - /// - /// - /// Specifies, in a pre-order depth-first traversal of a type's - /// construction, which occurrences are - /// meant to carry element names. - /// - /// - /// This constructor is meant to be used on types that contain an - /// instantiation of that contains - /// element names. For instance, if C is a generic type with - /// two type parameters, then a use of the constructed type C{, might be intended to - /// treat the first type argument as a tuple with element names and the - /// second as a tuple without element names. In which case, the - /// appropriate attribute specification should use a - /// transformNames value of { "name1", "name2", null, null, - /// null }. - /// - public TupleElementNamesAttribute(string[] transformNames) - { - _transformNames = transformNames ?? throw new ArgumentNullException(nameof(transformNames)); - } - - /// - /// Specifies, in a pre-order depth-first traversal of a type's - /// construction, which elements are - /// meant to carry element names. - /// - public IList TransformNames => _transformNames; -} - -#endif \ No newline at end of file diff --git a/src/Basal/IFox.Basal.Shared/ExpressionTrees/ParameterRebinder.cs b/src/Basal/IFox.Basal.Shared/ExpressionTrees/ParameterRebinder.cs deleted file mode 100644 index 217b375..0000000 --- a/src/Basal/IFox.Basal.Shared/ExpressionTrees/ParameterRebinder.cs +++ /dev/null @@ -1,34 +0,0 @@ -namespace IFoxCAD.Basal; - -/// -/// 参数重绑定 -/// -/// -/// 参数重绑定 -/// -/// 字典 -public class ParameterRebinder(Dictionary map) : SqlExpressionVisitor -{ - /// - /// 替换参数 - /// - /// 字典 - /// 表达式 - /// 表达式 - public static Expression ReplaceParameters(Dictionary map, Expression expression) - { - return new ParameterRebinder(map).Visit(expression); - } - /// - /// 访问参数 - /// - /// 参数表达式 - /// 表达式 - protected override Expression VisitParameter(ParameterExpression expression) - { - if (map.TryGetValue(expression, out var parameterExpression)) - expression = parameterExpression; - - return base.VisitParameter(expression); - } -} \ No newline at end of file diff --git a/src/Basal/IFox.Basal.Shared/ExpressionTrees/PredicateBuilder.cs b/src/Basal/IFox.Basal.Shared/ExpressionTrees/PredicateBuilder.cs deleted file mode 100644 index a0c7ac0..0000000 --- a/src/Basal/IFox.Basal.Shared/ExpressionTrees/PredicateBuilder.cs +++ /dev/null @@ -1,78 +0,0 @@ - -#if NET45_OR_GREATER -namespace IFoxCAD.Basal; -/// -/// Predicate委托构造器 -/// -public static class PredicateBuilder -{ - /// - /// 返回真的委托表达式 - /// - /// 传入参数的泛型 - /// - public static Expression> True() - { - return param => true; - } - /// - /// 返回假的委托表达式 - /// - /// 传入参数的泛型 - /// - public static Expression> False() - { - return param => false; - } - /// - /// 创建predicate委托 - /// - /// 传入参数类型 - /// 委托表达式 - /// 委托表达式 - public static Expression> Create(Expression> predicate) - { - return predicate; - } - /// - /// 表示并的表达式 - /// - /// 传入参数类型 - /// 第一个参数 - /// 第二个 - /// 表达式 - public static Expression> And(this Expression> first, Expression> second) - { - return first.Compose(second, Expression.AndAlso); - } - /// - /// 表示或的表达式 - /// - /// 传入参数类型 - /// 第一个参数 - /// 第二个 - /// 表达式 - public static Expression> Or(this Expression> first, Expression> second) - { - return first.Compose(second, Expression.OrElse); - } - /// - /// 表是否的表达式 - /// - /// 传入参数类型 - /// 表达式 - /// 表达式 - public static Expression> Not(this Expression> expression) - { - return Expression.Lambda>(Expression.Not(expression.Body), expression.Parameters); - } - - private static Expression Compose(this Expression first, Expression second, Func merge) - { - var map = first.Parameters.Select((f, i) => new{f,s = second.Parameters[i]}).ToDictionary(p => p.s, p => p.f); - var expression = ParameterRebinder.ReplaceParameters(map, second.Body); - return Expression.Lambda(merge(first.Body, expression), first.Parameters); - } -} - -#endif \ No newline at end of file diff --git a/src/Basal/IFox.Basal.Shared/ExpressionTrees/SqlExpressionVisitor.cs b/src/Basal/IFox.Basal.Shared/ExpressionTrees/SqlExpressionVisitor.cs deleted file mode 100644 index 8d61105..0000000 --- a/src/Basal/IFox.Basal.Shared/ExpressionTrees/SqlExpressionVisitor.cs +++ /dev/null @@ -1,437 +0,0 @@ -namespace IFoxCAD.Basal; - -/// -/// sql表达式访问者类 -/// -public abstract class SqlExpressionVisitor -{ - /// - /// 访问 - /// - /// 表达式 - /// 表达式 - /// - protected virtual Expression Visit(Expression expression) - { - return expression.NodeType switch - { - ExpressionType.Add => VisitBinary((BinaryExpression)expression), - ExpressionType.AddChecked => VisitBinary((BinaryExpression)expression), - ExpressionType.And => VisitBinary((BinaryExpression)expression), - ExpressionType.AndAlso => VisitBinary((BinaryExpression)expression), - ExpressionType.ArrayIndex => VisitBinary((BinaryExpression)expression), - ExpressionType.Coalesce => VisitBinary((BinaryExpression)expression), - ExpressionType.Divide => VisitBinary((BinaryExpression)expression), - ExpressionType.Equal => VisitBinary((BinaryExpression)expression), - ExpressionType.ExclusiveOr => VisitBinary((BinaryExpression)expression), - ExpressionType.GreaterThan => VisitBinary((BinaryExpression)expression), - ExpressionType.GreaterThanOrEqual => VisitBinary((BinaryExpression)expression), - ExpressionType.LeftShift => VisitBinary((BinaryExpression)expression), - ExpressionType.LessThan => VisitBinary((BinaryExpression)expression), - ExpressionType.LessThanOrEqual => VisitBinary((BinaryExpression)expression), - ExpressionType.Modulo => VisitBinary((BinaryExpression)expression), - ExpressionType.Multiply => VisitBinary((BinaryExpression)expression), - ExpressionType.MultiplyChecked => VisitBinary((BinaryExpression)expression), - ExpressionType.NotEqual => VisitBinary((BinaryExpression)expression), - ExpressionType.Or => VisitBinary((BinaryExpression)expression), - ExpressionType.OrElse => VisitBinary((BinaryExpression)expression), - ExpressionType.RightShift => VisitBinary((BinaryExpression)expression), - ExpressionType.Subtract => VisitBinary((BinaryExpression)expression), - ExpressionType.SubtractChecked => VisitBinary((BinaryExpression)expression), - ExpressionType.ArrayLength => VisitUnary((UnaryExpression)expression), - ExpressionType.Convert => VisitUnary((UnaryExpression)expression), - ExpressionType.ConvertChecked => VisitUnary((UnaryExpression)expression), - ExpressionType.Negate => VisitUnary((UnaryExpression)expression), - ExpressionType.NegateChecked => VisitUnary((UnaryExpression)expression), - ExpressionType.Not => VisitUnary((UnaryExpression)expression), - ExpressionType.Quote => VisitUnary((UnaryExpression)expression), - ExpressionType.TypeAs => VisitUnary((UnaryExpression)expression), - ExpressionType.Call => VisitMethodCall((MethodCallExpression)expression), - ExpressionType.Conditional => VisitConditional((ConditionalExpression)expression), - ExpressionType.Constant => VisitConstant((ConstantExpression)expression), - ExpressionType.Invoke => VisitInvocation((InvocationExpression)expression), - ExpressionType.Lambda => VisitLambda((LambdaExpression)expression), - ExpressionType.ListInit => VisitListInit((ListInitExpression)expression), - ExpressionType.MemberAccess => VisitMemberAccess((MemberExpression)expression), - ExpressionType.MemberInit => VisitMemberInit((MemberInitExpression)expression), - ExpressionType.New => VisitNew((NewExpression)expression), - ExpressionType.NewArrayInit => VisitNewArray((NewArrayExpression)expression), - ExpressionType.NewArrayBounds => VisitNewArray((NewArrayExpression)expression), - ExpressionType.Parameter => VisitParameter((ParameterExpression)expression), - ExpressionType.TypeIs => VisitTypeIs((TypeBinaryExpression)expression), - _ => throw new RuntimeBinderException(nameof(expression.NodeType)) - }; - } - /// - /// 访问者绑定 - /// - /// 绑定的类 - /// 绑定的类 - /// - protected virtual MemberBinding VisitBinding(MemberBinding binding) - { - return binding.BindingType switch - { - MemberBindingType.Assignment => VisitMemberAssignment((MemberAssignment)binding), - MemberBindingType.MemberBinding => VisitMemberMemberBinding((MemberMemberBinding)binding), - MemberBindingType.ListBinding => VisitMemberListBinding((MemberListBinding)binding), - _ => throw new RuntimeBinderException(nameof(binding.BindingType)) - }; - } - /// - /// 访问集合初始设定项 - /// - /// 集合初始设定项 - /// 集合初始设定项 - protected virtual ElementInit VisitElementInitializer(ElementInit initializer) - { - var arguments = VisitExpressionList(initializer.Arguments); - - if (arguments != initializer.Arguments) - return Expression.ElementInit(initializer.AddMethod, arguments); - - return initializer; - } - /// - /// 访问一元运算符 - /// - /// 一元运算符 - /// 表达式 - protected virtual Expression VisitUnary(UnaryExpression unary) - { - var operand = Visit(unary.Operand); - - return operand != unary.Operand ? Expression.MakeUnary(unary.NodeType, operand, unary.Type, unary.Method) : unary; - } - /// - /// 访问二进制运算符 - /// - /// 二进制运算符 - /// 表达式 - protected virtual Expression VisitBinary(BinaryExpression binary) - { - var left = Visit(binary.Left); - var right = Visit(binary.Right); - var conversion = Visit(binary.Conversion!); - - if (left == binary.Left && right == binary.Right && conversion == binary.Conversion) - return binary; - - return binary is { NodeType: ExpressionType.Coalesce, Conversion: not null } - ? Expression.Coalesce(left, right, conversion as LambdaExpression) - : Expression.MakeBinary(binary.NodeType, left, right, binary.IsLiftedToNull, binary.Method); - } - /// - /// 访问类型 - /// - /// 类型 - /// 表达式 - protected virtual Expression VisitTypeIs(TypeBinaryExpression typeBinary) - { - var expression = Visit(typeBinary.Expression); - - if (expression != typeBinary.Expression) - return Expression.TypeIs(expression, typeBinary.TypeOperand); - - return typeBinary; - } - /// - /// 访问常数值 - /// - /// 常数值 - /// 表达式 - protected virtual Expression VisitConstant(ConstantExpression constant) - { - return constant; - } - /// - /// 访问条件运算符 - /// - /// 条件运算符 - /// 表达式 - protected virtual Expression VisitConditional(ConditionalExpression conditional) - { - var test = Visit(conditional.Test); - var ifTrue = Visit(conditional.IfTrue); - var ifFalse = Visit(conditional.IfFalse); - - if (test != conditional.Test) - return Expression.Condition(test, ifTrue, ifFalse); - - if (ifTrue != conditional.IfTrue) - return Expression.Condition(test, ifTrue, ifFalse); - - if (ifFalse != conditional.IfFalse) - return Expression.Condition(test, ifTrue, ifFalse); - - return conditional; - } - /// - /// 访问参数 - /// - /// 参数 - /// 表达式 - protected virtual Expression VisitParameter(ParameterExpression parameter) - { - return parameter; - } - /// - /// 访问成员 - /// - /// 成员 - /// 表达式 - protected virtual Expression VisitMemberAccess(MemberExpression member) - { - var expression = Visit(member.Expression); - - if (expression != member.Expression) - return Expression.MakeMemberAccess(expression, member.Member); - - return member; - } - /// - /// 访问方法调用 - /// - /// 方法调用 - /// 表达式 - protected virtual Expression VisitMethodCall(MethodCallExpression methodCall) - { - var instance = Visit(methodCall.Object!); - var arguments = (IEnumerable)VisitExpressionList(methodCall.Arguments); - - if (instance != methodCall.Object || !Equals(arguments, methodCall.Arguments)) - return Expression.Call(instance, methodCall.Method, arguments); - - return methodCall; - } - /// - /// 访问表达式集合 - /// - /// 表达式集合 - /// 表达式只读集合 - protected virtual ReadOnlyCollection VisitExpressionList(ReadOnlyCollection original) - { - var index1 = 0; - var expressions = default(List); - - for (var count = original.Count; index1 < count; ++index1) - { - var expression = Visit(original[index1]); - if (expressions != null) - { - expressions.Add(expression); - } - - else if (expression != original[index1]) - { - expressions = new List(count); - - for (var index2 = 0; index2 < index1; ++index2) - expressions.Add(original[index2]); - - expressions.Add(expression); - } - - } - - return expressions != null ? expressions.AsReadOnly() : original; - } - /// - /// 访问成员赋值 - /// - /// 成员赋值 - /// - protected virtual MemberAssignment VisitMemberAssignment(MemberAssignment assignment) - { - var expression = Visit(assignment.Expression); - - if (expression != assignment.Expression) - return Expression.Bind(assignment.Member, expression); - - return assignment; - } - /// - /// 访问新对象成员的成员 - /// - /// 新对象成员的成员 - /// 新对象成员的成员 - protected virtual MemberMemberBinding VisitMemberMemberBinding(MemberMemberBinding binding) - { - var bindings = VisitBindingList(binding.Bindings); - - if (!Equals(bindings, binding.Bindings)) - return Expression.MemberBind(binding.Member, bindings); - - return binding; - } - /// - /// 访问成员初始化 - /// - /// 成员初始化 - /// 成员初始化 - protected virtual MemberListBinding VisitMemberListBinding(MemberListBinding binding) - { - var initializers = VisitElementInitializerList(binding.Initializers); - - if (!Equals(initializers, binding.Initializers)) - return Expression.ListBind(binding.Member, initializers); - - return binding; - } - /// - /// 访问成员初始化列表 - /// - /// 成员初始化列表 - /// 成员初始化列表 - protected virtual IEnumerable VisitBindingList(ReadOnlyCollection original) - { - var index1 = 0; - var bindings = default(List); - - for (var count = original.Count; index1 < count; ++index1) - { - var memberBinding = VisitBinding(original[index1]); - - if (bindings != null) - { - bindings.Add(memberBinding); - } - - else if (memberBinding != original[index1]) - { - bindings = new List(count); - - for (var index2 = 0; index2 < index1; ++index2) - bindings.Add(original[index2]); - - bindings.Add(memberBinding); - } - } - - return bindings!; - } - /// - /// 访问集合设定项集合 - /// - /// 集合设定项集合 - /// 集合设定项集合 - protected virtual IEnumerable VisitElementInitializerList(ReadOnlyCollection original) - { - var index1 = 0; - var initializers = default(List); - - for (var count = original.Count; index1 < count; ++index1) - { - var initializer = VisitElementInitializer(original[index1]); - - if (initializers != null) - { - initializers.Add(initializer); - } - - else if (initializer != original[index1]) - { - initializers = new List(count); - - for (var index2 = 0; index2 < index1; ++index2) - initializers.Add(original[index2]); - - initializers.Add(initializer); - } - } - - return initializers!; - } - /// - /// 访问lambda表达式 - /// - /// lambda表达式 - /// 表达式 - protected virtual Expression VisitLambda(LambdaExpression lambda) - { - var body = Visit(lambda.Body); - - if (body != lambda.Body) - return Expression.Lambda(lambda.Type, body, lambda.Parameters); - - return lambda; - } - /// - /// 访问构造函数 - /// - /// 构造函数 - /// 构造函数 - protected virtual NewExpression VisitNew(NewExpression expression) - { - var arguments = VisitExpressionList(expression.Arguments); - - if (Equals(arguments, expression.Arguments)) - return expression; - - if (expression.Members != null) - return Expression.New(expression.Constructor, arguments, expression.Members); - - return Expression.New(expression.Constructor, arguments); - } - /// - /// 访问成员初始化 - /// - /// 成员初始化 - /// 表达式 - protected virtual Expression VisitMemberInit(MemberInitExpression memberInit) - { - var expression = VisitNew(memberInit.NewExpression); - var bindings = VisitBindingList(memberInit.Bindings); - - if (expression != memberInit.NewExpression || !Equals(bindings, memberInit.Bindings)) - return Expression.MemberInit(expression, bindings); - - return memberInit; - } - /// - /// 访问集合初始化 - /// - /// 集合初始化 - /// 表达式 - protected virtual Expression VisitListInit(ListInitExpression listInit) - { - var expression = VisitNew(listInit.NewExpression); - var initializers = VisitElementInitializerList(listInit.Initializers); - - if (expression != listInit.NewExpression || !Equals(initializers, listInit.Initializers)) - return Expression.ListInit(expression, initializers); - - return listInit; - } - /// - /// 访问新数组 - /// - /// 新数组 - /// 表达式 - protected virtual Expression VisitNewArray(NewArrayExpression newArray) - { - var expressions = VisitExpressionList(newArray.Expressions); - - if (Equals(expressions, newArray.Expressions)) - return newArray; - - return newArray.NodeType == ExpressionType.NewArrayInit - ? Expression.NewArrayInit(newArray.Type.GetElementType()!, expressions) - : Expression.NewArrayBounds(newArray.Type.GetElementType()!, expressions); - } - /// - /// 访问委托调用表达式 - /// - /// 委托调用表达式 - /// 表达式 - protected virtual Expression VisitInvocation(InvocationExpression invocation) - { - var arguments = VisitExpressionList(invocation.Arguments); - var expression = Visit(invocation.Expression); - - if (arguments != invocation.Arguments || expression != invocation.Expression) - return Expression.Invoke(expression, arguments); - - return invocation; - } -} \ No newline at end of file diff --git a/src/Basal/IFox.Basal.Shared/General/ArrayEx.cs b/src/Basal/IFox.Basal.Shared/General/ArrayEx.cs deleted file mode 100644 index 36bf8e7..0000000 --- a/src/Basal/IFox.Basal.Shared/General/ArrayEx.cs +++ /dev/null @@ -1,58 +0,0 @@ -namespace IFoxCAD.Basal; - -/* - * 由于linq的函数大部分带有状态机,而cad是一个单机程序, - * 使用状态机会变得缓慢,因此我们设计的时候着重于时间优化, - * 本工具类在着重于数组遍历时候替代linq - */ -/// -/// 数组扩展类 -/// -public static class ArrayEx -{ - /// - /// 合并数组 - /// - /// - /// - public static T[] Combine2(this T[] a, T[] b) - { - var c = new T[a.Length + b.Length]; - Array.Copy(a, 0, c, 0, a.Length); - Array.Copy(b, 0, c, a.Length, b.Length); - return c; - } - - /// - /// 一维数组按规则消除
- /// 本例适用于数值类型比较,特定规则比较
- /// 如果是哈希比较,建议更改为: - /// set = new(); - /// foreach (var item in listInOut) - /// set.Add(item); - /// ]]> - ///
- /// - /// 传入有重复成员的数组,原数组修改 - /// - /// 传出参数1:数组开头
- /// 传出参数2:数组结尾
- /// 返回值比较结尾为就移除
- /// - [DebuggerStepThrough] - public static void Deduplication(List lst, Func func) - { - // 头和尾比较,满足条件移除尾巴 - for (var i = 0; i < lst.Count; i++) - { - var first = lst[i]; - for (var j = lst.Count - 1; j > i/*符号是 >= 而且是i*/; j--) - { - var last = lst[j]; - if (func(first, last)) - lst.RemoveAt(j); - } - } - } -} \ No newline at end of file diff --git a/src/Basal/IFox.Basal.Shared/General/DebugHelper.cs b/src/Basal/IFox.Basal.Shared/General/DebugHelper.cs deleted file mode 100644 index b956094..0000000 --- a/src/Basal/IFox.Basal.Shared/General/DebugHelper.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace IFoxCAD.Basal; -/// -/// 调试工具 -/// -public static class DebugEx -{ - /// - /// cad命令切换: Debugx - /// - /// 打印信息 - /// 打印时间 - [DebuggerHidden] - public static void Printl(object message, bool time = true) - { - var flag = Environment.GetEnvironmentVariable("debugx", EnvironmentVariableTarget.User); - if (flag is null or "0") - return; - - if (time) - //message = $"{DateTime.Now.ToLongDateString() + DateTime.Now.TimeOfDay}\n" + - message = $"{DateTime.Now.TimeOfDay} ThreadId:{Environment.CurrentManagedThreadId}\n" + - $"\t\t{message}"; - - //System.Diagnostics.Debug.Indent(); -#if DEBUG - Debug.WriteLine(message); -#else - System.Diagnostics.Trace.WriteLine(message); -#endif - //System.Diagnostics.Debug.Unindent(); - } -} \ No newline at end of file diff --git a/src/Basal/IFox.Basal.Shared/General/EnumEx.cs b/src/Basal/IFox.Basal.Shared/General/EnumEx.cs deleted file mode 100644 index 158c5bd..0000000 --- a/src/Basal/IFox.Basal.Shared/General/EnumEx.cs +++ /dev/null @@ -1,111 +0,0 @@ -namespace IFoxCAD.Basal; - -/// -/// 枚举扩展 -/// -public static class EnumEx -{ - /// - /// 清理缓存 - /// - public static void CleanCache() - { - Cache.Clear(); - } - - // (类型完整名,描述组合) - private static readonly Dictionary> Cache = []; - - /// - /// 打印枚举的特性注释内容 - /// - /// 枚举 - /// - /// 注释内容 - public static HashSet? GetAttribute(this Enum e, bool noDescrToString = true) - where T : DescriptionAttribute - { - var eType = e.GetType(); - var eFullName = eType.FullName + "." + e; - - if (Cache.TryGetValue(eFullName, out var attribute1)) - return attribute1; - - var fieldInfo = eType.GetField(Enum.GetName(eType, e)); - if (fieldInfo == null) - return null!; - - // 注释存放的容器 - HashSet nodes = new(); - if (Attribute.GetCustomAttribute(fieldInfo, typeof(T)) is T attribute) - { - nodes.Add(attribute.Description); - Cache.Add(eFullName, nodes); - return nodes; - } - - // 通常到这里的就是 ALL = A | B | C - // 遍历所有的枚举,组合每个注释 - List enumHas = []; - enumHas.AddRange(Enum.GetValues(eType).Cast().Where(em => - (e.GetHashCode() & em.GetHashCode()) == em.GetHashCode() && e.GetHashCode() != em.GetHashCode())); - - // 遍历这个枚举类型,获取枚举按位包含的成员 - - - // 采取的行为是:注释的行为是特殊的,就按照注释的,否则,遍历子元素提取注释 - // 大的在前面才能判断是否按位包含后面的,后面的就是要移除的 - enumHas = [.. enumHas.OrderByDescending(a => a.GetHashCode())]; - ArrayEx.Deduplication(enumHas, (a, b) => (a.GetHashCode() & b.GetHashCode()) == b.GetHashCode()); - - // 逆序仅仅为排序后处理,不一定和书写顺序一样,尤其是递归可能存在重复的元素 - for (var i = enumHas.Count - 1; i >= 0; i--) - { - var atts = GetAttribute(enumHas[i], noDescrToString);// 递归 - if (atts == null) - continue; - foreach (var item in atts) - nodes.Add(item); - } - - if (nodes.Count == 0 && noDescrToString) - nodes.Add(e.ToString()); - - Cache.Add(eFullName, nodes); - return nodes; - } - - /// - /// 打印枚举的特性注释内容 - /// - public static string? PrintNote(this Enum e, bool noDescToString = true) - { - var hash = GetAttribute(e, noDescToString); - return hash == null ? null : string.Join("|", [.. hash]); - } - - /// - /// 获取枚举的描述内容 - /// - /// 不按位运算的情况下,直接获取比较快捷 - /// - /// - public static string GetDesc(this Enum e) - { - return GetDesc(e.GetType(), e.ToString()); - } - - /// - /// 获取字段的描述内容 - /// - /// - /// - /// - public static string GetDesc(this Type type, string field) - { - var memberInfo = type.GetMember(field); - var attributes = memberInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false); - // 如果没有定义描述,就把当前枚举值的对应名称返回 - return attributes.Length != 1 ? field : ((DescriptionAttribute)attributes.Single()).Description; - } -} \ No newline at end of file diff --git a/src/Basal/IFox.Basal.Shared/General/IsExternalInit.cs b/src/Basal/IFox.Basal.Shared/General/IsExternalInit.cs deleted file mode 100644 index 935714d..0000000 --- a/src/Basal/IFox.Basal.Shared/General/IsExternalInit.cs +++ /dev/null @@ -1,19 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -namespace System.Runtime.CompilerServices -{ - /// - /// Reserved to be used by the compiler for tracking metadata. - /// This class should not be used by developers in source code. - /// - [EditorBrowsable(EditorBrowsableState.Never)] -#if NET30_OR_GREATER - public -#else - internal -#endif - static class IsExternalInit - { - } -} \ No newline at end of file diff --git a/src/Basal/IFox.Basal.Shared/General/LinkedHashMap.cs b/src/Basal/IFox.Basal.Shared/General/LinkedHashMap.cs deleted file mode 100644 index 2cbfd43..0000000 --- a/src/Basal/IFox.Basal.Shared/General/LinkedHashMap.cs +++ /dev/null @@ -1,157 +0,0 @@ -namespace IFoxCAD.Basal; - - -/// -/// A least-recently-used cache stored like a dictionary. -/// -/// -/// The type of the key to the cached item -/// -/// -/// The type of the cached item. -/// -/// -/// Derived from https://stackoverflow.com/a/3719378/240845 -/// https://stackoverflow.com/users/240845/mheyman -/// -/// -/// Initializes a new instance of the -/// class. -/// -/// -/// Maximum number of elements to cache. -/// -/// -/// When elements cycle out of the cache, disposes them. May be null. -/// -public class LinkedHashMap(int capacity, Action? dispose = null) -{ - private readonly Dictionary> _cacheMap = []; - - private readonly LinkedList _lruList = []; - - /// - /// Gets the capacity of the cache. - /// - public int Capacity { get; } = capacity; - - /// Gets the value associated with the specified key. - /// - /// The key of the value to get. - /// - /// - /// When this method returns, contains the value associated with the specified - /// key, if the key is found; otherwise, the default value for the type of the - /// parameter. This parameter is passed - /// uninitialized. - /// - /// - /// true if the - /// contains an element with the specified key; otherwise, false. - /// - public bool TryGetValue(TKey key, out TValue? value) - { - lock (_cacheMap) - { - if (_cacheMap.TryGetValue(key, out var node)) - { - value = node.Value.Value; - _lruList.Remove(node); - _lruList.AddLast(node); - return true; - } - - value = default; - return false; - } - } - - /// - /// Looks for a value for the matching . If not found, - /// calls to retrieve the value and add it to - /// the cache. - /// - /// - /// The key of the value to look up. - /// - /// - /// Generates a value if one isn't found. - /// - /// - /// The requested value. - /// - public TValue Get(TKey key, Func valueGenerator) - { - lock (_cacheMap) - { - TValue value; - if (_cacheMap.TryGetValue(key, out var node)) - { - value = node.Value.Value; - _lruList.Remove(node); - _lruList.AddLast(node); - } - else - { - value = valueGenerator(); - if (_cacheMap.Count >= Capacity) - { - RemoveFirst(); - } - - MapItem cacheItem = new(key, value); - node = new LinkedListNode(cacheItem); - _lruList.AddLast(node); - _cacheMap.Add(key, node); - } - - return value; - } - } - - /// - /// Adds the specified key and value to the dictionary. - /// - /// - /// The key of the element to add. - /// - /// - /// The value of the element to add. The value can be null for reference types. - /// - public void Add(TKey key, TValue value) - { - lock (_cacheMap) - { - if (_cacheMap.Count >= Capacity) - { - RemoveFirst(); - } - - MapItem cacheItem = new(key, value); - LinkedListNode node = new(cacheItem); - _lruList.AddLast(node); - _cacheMap.Add(key, node); - } - } - - private void RemoveFirst() - { - // Remove from LRUPriority - var node = _lruList.First; - _lruList.RemoveFirst(); - - // Remove from cache - _cacheMap.Remove(node.Value.Key); - - // dispose - dispose?.Invoke(node.Value.Value); - } - - private class MapItem(TKey k, TValue v) - { - public TKey Key { get; } = k; - - public TValue Value { get; } = v; - } -} - diff --git a/src/Basal/IFox.Basal.Shared/General/LinkedHashSet.cs b/src/Basal/IFox.Basal.Shared/General/LinkedHashSet.cs deleted file mode 100644 index a4ad211..0000000 --- a/src/Basal/IFox.Basal.Shared/General/LinkedHashSet.cs +++ /dev/null @@ -1,210 +0,0 @@ -namespace IFoxCAD.Basal; -#pragma warning disable CS1591 // 缺少对公共可见类型或成员的 XML 注释 -public sealed class LinkedHashSet : ICollection where T : IComparable -{ - private readonly IDictionary> _mDictionary = new Dictionary>(); - private readonly LoopList _mLinkedList = []; - - public LoopListNode? First => _mLinkedList.First; - - public LoopListNode? Last => _mLinkedList.Last; - - public LoopListNode? MinNode { get; private set; } - - public bool Add(T item) - { - if (_mDictionary.ContainsKey(item)) - return false; - var node = _mLinkedList.AddLast(item); - _mDictionary.Add(item, node); - - if (MinNode is null) - { - MinNode = node; - } - else - { - if (item.CompareTo(MinNode.Value) < 0) - { - MinNode = node; - } - } - - - - return true; - } - - void ICollection.Add(T item) - { - Add(item); - } - - public LoopListNode AddFirst(T value) - { - if (_mDictionary.TryGetValue(value, out var first)) - { - return first; - } - var node = _mLinkedList.AddFirst(value); - _mDictionary.Add(value, node); - if (MinNode is null) - { - MinNode = node; - } - else - { - if (value.CompareTo(MinNode.Value) < 0) - { - MinNode = node; - } - } - return node; - } - - public void AddRange(IEnumerable collection) - { - foreach (var item in collection) - { - Add(item); - } - } - - - public void Clear() - { - _mLinkedList.Clear(); - _mDictionary.Clear(); - } - - public bool Remove(T item) - { - var found = _mDictionary.TryGetValue(item, out var node); - if (!found) return false; - _mDictionary.Remove(item); - _mLinkedList.Remove(node!); - return true; - } - - public int Count => _mDictionary.Count; - - public void For(LoopListNode from, Action action) - { - var first = from; - var last = from; - - for (var i = 0; i < Count; i++) - { - action.Invoke(i, first!.Value, last!.Value); - first = first.Next; - last = last.Previous; - } - } - - public List ToList() - { - return [.. _mLinkedList]; - } - - [DebuggerStepThrough] - public IEnumerator GetEnumerator() - { - return _mLinkedList.GetEnumerator(); - } - - [DebuggerStepThrough] - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - - - public bool Contains(T item) - { - return _mDictionary.ContainsKey(item); - } - - public void CopyTo(T[] array, int arrayIndex) - { - // m_LinkedList.CopyTo(array, arrayIndex); - - } - - public bool SetFirst(LoopListNode node) - { - return _mLinkedList.SetFirst(node); - } - - public LinkedHashSet Clone() - { - var newSet = new LinkedHashSet(); - foreach (var item in this) - { - newSet.Add(item); - } - return newSet; - } - - public bool IsReadOnly => _mDictionary.IsReadOnly; - - public override string ToString() - { - return _mLinkedList.ToString(); - } - - public void UnionWith(IEnumerable other) - { - throw GetNotSupportedDueToSimplification(); - } - - public void IntersectWith(IEnumerable other) - { - throw GetNotSupportedDueToSimplification(); - } - - public void ExceptWith(IEnumerable other) - { - throw GetNotSupportedDueToSimplification(); - } - - public bool IsSubsetOf(IEnumerable other) - { - throw GetNotSupportedDueToSimplification(); - } - - public void SymmetricExceptWith(IEnumerable other) - { - throw GetNotSupportedDueToSimplification(); - } - - public bool IsSupersetOf(IEnumerable other) - { - throw GetNotSupportedDueToSimplification(); - } - - public bool IsProperSupersetOf(IEnumerable other) - { - throw GetNotSupportedDueToSimplification(); - } - - public bool IsProperSubsetOf(IEnumerable other) - { - throw GetNotSupportedDueToSimplification(); - } - - public bool Overlaps(IEnumerable other) - { - throw GetNotSupportedDueToSimplification(); - } - - public bool SetEquals(IEnumerable other) - { - throw GetNotSupportedDueToSimplification(); - } - - private static Exception GetNotSupportedDueToSimplification() - { - return new NotSupportedException("This method is not supported due to simplification of example code."); - } -} -#pragma warning restore CS1591 // 缺少对公共可见类型或成员的 XML 注释 \ No newline at end of file diff --git a/src/Basal/IFox.Basal.Shared/General/LinqEx.cs b/src/Basal/IFox.Basal.Shared/General/LinqEx.cs deleted file mode 100644 index 746bacf..0000000 --- a/src/Basal/IFox.Basal.Shared/General/LinqEx.cs +++ /dev/null @@ -1,327 +0,0 @@ -namespace IFoxCAD.Basal; - -/// -/// linq 扩展类 -/// -public static class LinqEx -{ - #region FindByMax - - /// - /// 按转换函数找出序列中最大键值的对应值 - /// - /// - /// - /// 序列 - /// 转换函数 - /// 最大键值的对应值 - public static TValue FindByMax(this IEnumerable source, Func func) - where TKey : IComparable - { - using var itr = source.GetEnumerator(); - if (!itr.MoveNext()) - throw new ArgumentNullException(nameof(source), "对象为 null"); - - var value = itr.Current; - var key = func(value); - - while (itr.MoveNext()) - { - var tKey = func(itr.Current); - if (tKey.CompareTo(key) <= 0) continue; - key = tKey; - value = itr.Current; - } - return value; - } - - /// - /// 按转换函数找出序列中最大键值的对应值 - /// - /// - /// - /// 序列 - /// 对应的最大键值 - /// 转换函数 - /// 最大键值的对应值 - public static TValue FindByMax(this IEnumerable source, out TKey maxResult, Func func) - where TKey : IComparable - { - using var itr = source.GetEnumerator(); - if (!itr.MoveNext()) - throw new ArgumentNullException(nameof(source), "对象为 null"); - - var value = itr.Current; - var key = func(value); - - while (itr.MoveNext()) - { - var tKey = func(itr.Current); - if (tKey.CompareTo(key) <= 0) continue; - key = tKey; - value = itr.Current; - } - maxResult = key; - return value; - } - - /// - /// 按比较器找出序列中最大键值的对应值 - /// - /// - /// 序列 - /// 比较器 - /// 最大键值的对应值 - public static TValue FindByMax(this IEnumerable source, Comparison comparison) - { - using var itr = source.GetEnumerator(); - if (!itr.MoveNext()) - throw new ArgumentNullException(nameof(source), "对象为 null"); - - var value = itr.Current; - - while (itr.MoveNext()) - { - if (comparison(itr.Current, value) > 0) - value = itr.Current; - } - return value; - } - - #endregion FindByMax - - #region FindByMin - - /// - /// 按转换函数找出序列中最小键值的对应值 - /// - /// - /// - /// 序列 - /// 对应的最小键值 - /// 转换函数 - /// 最小键值的对应值 - public static TValue FindByMin(this IEnumerable source, out TKey minKey, Func func) - where TKey : IComparable - { - using var itr = source.GetEnumerator(); - if (!itr.MoveNext()) - throw new ArgumentNullException(nameof(source), "对象为 null"); - - var value = itr.Current; - var key = func(value); - - while (itr.MoveNext()) - { - var tKey = func(itr.Current); - if (tKey.CompareTo(key) >= 0) continue; - key = tKey; - value = itr.Current; - } - minKey = key; - return value; - } - - /// - /// 按转换函数找出序列中最小键值的对应值 - /// - /// - /// - /// 序列 - /// 转换函数 - /// 最小键值的对应值 - public static TValue FindByMin(this IEnumerable source, Func func) - where TKey : IComparable - { - using var itr = source.GetEnumerator(); - if (!itr.MoveNext()) - throw new ArgumentNullException(nameof(source), "对象为 null"); - - var value = itr.Current; - var key = func(value); - - while (itr.MoveNext()) - { - var tKey = func(itr.Current); - if (tKey.CompareTo(key) >= 0) continue; - key = tKey; - value = itr.Current; - } - return value; - } - - /// - /// 按比较器找出序列中最小键值的对应值 - /// - /// - /// 序列 - /// 比较器 - /// 最小键值的对应值 - public static TValue FindByMin(this IEnumerable source, Comparison comparison) - { - using var itr = source.GetEnumerator(); - if (!itr.MoveNext()) - throw new ArgumentNullException(nameof(source), "对象为 null"); - - var value = itr.Current; - - while (itr.MoveNext()) - { - if (comparison(itr.Current, value) < 0) - value = itr.Current; - } - return value; - } - - #endregion FindByMin - - #region FindByExt - - /// - /// 按转换函数找出序列中最(小/大)键值的对应值 - /// - /// - /// - /// 序列 - /// 转换函数 - /// 最(小/大)键值的对应值 - public static TValue[] FindByExt(this IEnumerable source, Func func) - where TKey : IComparable - { - using var itr = source.GetEnumerator(); - if (!itr.MoveNext()) - throw new ArgumentNullException(nameof(source), "对象为 null"); - - var values = new TValue[2]; - values[0] = values[1] = itr.Current; - - var keys = new TKey[2]; - keys[0] = keys[1] = func(itr.Current); - - while (itr.MoveNext()) - { - var tKey = func(itr.Current); - if (tKey.CompareTo(keys[0]) < 0) - { - keys[0] = tKey; - values[0] = itr.Current; - } - else if (tKey.CompareTo(keys[1]) > 0) - { - keys[1] = tKey; - values[1] = itr.Current; - } - } - return values; - } - - /// - /// 按比较器找出序列中最(小/大)键值的对应值 - /// - /// - /// 序列 - /// 比较器 - /// 最(小/大)键值的对应值 - public static TValue[] FindByExt(this IEnumerable source, Comparison comparison) - { - using var itr = source.GetEnumerator(); - if (!itr.MoveNext()) - throw new ArgumentNullException(nameof(source), "对象为 null"); - - var values = new TValue[2]; - values[0] = values[1] = itr.Current; - - while (itr.MoveNext()) - { - if (comparison(itr.Current, values[0]) < 0) - values[0] = itr.Current; - else if (comparison(itr.Current, values[1]) > 0) - values[1] = itr.Current; - } - return values; - } - - /// - /// 按转换函数找出序列中最(小/大)键值的对应键值 - /// - /// - /// - /// 序列 - /// 转换函数 - /// 最(小/大)键值 - public static TKey[] FindExt(this IEnumerable source, Func func) - where TKey : IComparable - { - using var itr = source.GetEnumerator(); - if (!itr.MoveNext()) - throw new ArgumentNullException(nameof(source), "对象为 null"); - - var keys = new TKey[2]; - keys[0] = keys[1] = func(itr.Current); - - while (itr.MoveNext()) - { - var tKey = func(itr.Current); - if (tKey.CompareTo(keys[0]) < 0) - keys[0] = tKey; - else if (tKey.CompareTo(keys[1]) > 0) - keys[1] = tKey; - } - return keys; - } - - #endregion FindByExt - - #region Order - - /// - /// 自定义的比较泛型类 - /// - /// 泛型 - private class SpecComparer : IComparer - { - private readonly Comparison _comp; - - internal SpecComparer(Comparison comp) - { - _comp = comp; - } - - #region IComparer 成员 - public int Compare(T x, T y) - { - return _comp(x, y); - } - #endregion IComparer 成员 - } - - /// - /// 使用指定的比较器将序列按升序排序 - /// - /// 输入泛型 - /// 输出泛型 - /// 序列 - /// 用于从元素中提取键的函数 - /// 比较器 - /// 排序的序列 - public static IOrderedEnumerable OrderBy(this IEnumerable source, Func keySelector, Comparison comparison) - { - return source.OrderBy(keySelector, new SpecComparer(comparison)); - } - - /// - /// 使用指定的比较器将其后的序列按升序排序 - /// - /// 输入泛型 - /// 输出泛型 - /// 序列 - /// 用于从元素中提取键的函数 - /// 比较器 - /// 排序的序列 - public static IOrderedEnumerable ThenBy(this IOrderedEnumerable source, Func keySelector, Comparison comparison) - { - return source.ThenBy(keySelector, new SpecComparer(comparison)); - } - - #endregion Order -} diff --git a/src/Basal/IFox.Basal.Shared/General/LoopList.cs b/src/Basal/IFox.Basal.Shared/General/LoopList.cs deleted file mode 100644 index da1e258..0000000 --- a/src/Basal/IFox.Basal.Shared/General/LoopList.cs +++ /dev/null @@ -1,745 +0,0 @@ -namespace IFoxCAD.Basal; - -#line hidden // 调试的时候跳过它 - -/// -/// 环链表节点 -/// -/// -public class LoopListNode -{ - #region 成员 - /// - /// 取值 - /// - public T Value; - - /// - /// 上一个节点 - /// - public LoopListNode? Previous { internal set; get; } - - /// - /// 下一个节点 - /// - public LoopListNode? Next { internal set; get; } - - /// - /// 环链表序列 - /// - public LoopList? List { internal set; get; } - #endregion - - #region 构造 - /// - /// 环链表节点构造函数 - /// - /// 节点值 - /// 环链表 - public LoopListNode(T value, LoopList ts) - { - Value = value; - List = ts; - } - - /// - /// 获取当前节点的临近节点 - /// - /// 搜索方向标志,为向前搜索,为向后搜索 - /// - public LoopListNode? GetNext(bool forward) - { - return forward ? Next : Previous; - } - #endregion - - #region 方法 - /// - /// 无效化成员 - /// - internal void Invalidate() - { - List = null; - Next = null; - Previous = null; - } - #endregion -} - -/// -/// 环链表 -/// -/// -public class LoopList : IEnumerable, IFormattable -{ - #region 成员 - - /// - /// 节点数 - /// - public int Count { get; private set; } - - /// - /// 首节点 - /// - public LoopListNode? First { get; private set; } - - /// - /// 尾节点 - /// - public LoopListNode? Last => First?.Previous; - - - - - #endregion - - #region 构造 - - /// - /// 默认构造函数 - /// - public LoopList() { } - - /// - /// 环链表构造函数 - /// - /// 节点迭代器 - [DebuggerStepThrough] - public LoopList(IEnumerable values) - { - using var ge = values.GetEnumerator(); - while (ge.MoveNext()) - Add(ge.Current); - } - - #endregion - - #region 方法 - - /// - /// 设置首节点 - /// - /// 节点 - /// - public bool SetFirst(LoopListNode node) - { - if (!Contains(node)) - return false; - - First = node; - return true; - } - - /// - /// 交换两个节点的值 - /// - /// 第一个节点 - /// 第二个节点 - public void Swap(LoopListNode node1, LoopListNode node2) - { - (node2.Value, node1.Value) = (node1.Value, node2.Value); - } - - /// - /// 链内翻转 - /// - public void Reverse() - { - var first = First; - if (first is null) - return; - var last = Last; - for (int i = 0; i < Count / 2; i++) - { - Swap(first!, last!); - first = first!.Next; - last = last!.Previous; - } - } - - /// - /// 清理 - /// - public void Clear() - { - // 移除头部,表示链表再也无法遍历得到 - First = null; - Count = 0; - } - - /// - /// 从头遍历_非迭代器(此处和通用ForEach冲突,所以内部用) - /// - /// - void ForEach(Func, bool> action) - { - var node = First; - if (node is null) - return; - for (int i = 0; i < Count; i++) - { - if (action(node!)) - break; - node = node!.Next; - } - } - - /// - /// 从头遍历_非迭代器(扔出计数) - /// - /// - public void For(Func, bool> action) - { - var node = First; - if (node is null) - return; - for (int i = 0; i < Count; i++) - { - if (action(i, node!)) - break; - node = node!.Next; - } - } - - #region Contains - - /// - /// 是否包含节点 - /// - /// - /// - public bool Contains(LoopListNode node) - { - return node.List == this; - } - - /// - /// 是否包含值 - /// - /// - /// - public bool Contains(T value) - { - var result = false; - ForEach(node => { - if (!node.Value!.Equals(value)) return false; - result = true; - return true; - }); - return result; - } - - /// - /// 查找第一个出现的节点 - /// - /// - /// - public LoopListNode? Find(T value) - { - // LoopListNode result = null; - // ForEach(node => - // { - // if (node.Value.Equals(t2)) - // { - // result = node; - // return true; - // } - // return false; - // }); - // return result; - - LoopListNode? node = First; - var c = EqualityComparer.Default; - if (node is not null) - { - if (value is not null) - { - do - { - if (c.Equals(node!.Value, value)) - return node; - node = node.Next; - } while (node != First); - } - else - { - do - { - if (node!.Value is null) - return node; - node = node.Next; - } while (node != First); - } - } - return null; - } - - /// - /// 查找所有出现的节点 - /// - /// - /// - public IEnumerable>? Finds(T value) - { - var node = First; - if (node is null) - return null; - - List> result = new(); - var c = EqualityComparer.Default; - if (value is not null) - { - do - { - if (c.Equals(node!.Value, value)) - result.Add(node); - node = node.Next; - } while (node != First); - } - else - { - do - { - if (node!.Value is null) - result.Add(node); - node = node.Next; - } while (node != First); - } - return result; - } - - /// - /// 获取节点 - /// - /// - /// - public LoopListNode? GetNode(Func func) - { - LoopListNode? result = null; - ForEach(node => { - if (func(node.Value)) - { - result = node; - return true; - } - return false; - }); - return result; - } - - #endregion - - #region Add - - /// - /// 在首节点之前插入节点,并设置新节点为首节点 - /// - /// - /// - public LoopListNode AddFirst(T value) - { - var node = new LoopListNode(value, this); - - if (Count == 0) - { - First = node; - First.Previous = First.Next = node; - } - else - { - LoopListNode last = Last!; - First!.Previous = last.Next = node; - node.Next = First; - node.Previous = last; - First = node; - } - Count++; - return First; - } - - /// - /// 在尾节点之后插入节点,并设置新节点为尾节点 - /// - /// - /// - public LoopListNode Add(T value) - { - var node = new LoopListNode(value, this); - - if (Count == 0) - { - First = node; - First.Previous = First.Next = node; - } - else - { - var last = First!.Previous!; - First.Previous = last.Next = node; - node.Next = First; - node.Previous = last; - } - Count++; - return Last!; - } - - /// - /// 在尾节点之后插入节点,并设置新节点为尾节点_此函数仅为与LinkedList同名方法 - /// - /// - /// - [DebuggerStepThrough] - public LoopListNode AddLast(T value) - { - return Add(value); - } - - /// - /// 容器内容全部加入到末尾 - /// - /// - [DebuggerStepThrough] - public void AddRange(IEnumerable list) - { - using var ge = list.GetEnumerator(); - while (ge.MoveNext()) - Add(ge.Current); - } - - /// - /// 前面增加节点 - /// - /// - /// - /// - public LoopListNode AddBefore(LoopListNode node, T value) - { - if (node == First) - return AddFirst(value); - - var tNode = new LoopListNode(value, this); - node.Previous!.Next = tNode; - tNode.Previous = node.Previous; - node.Previous = tNode; - tNode.Next = node; - Count++; - return tNode; - } - - /// - /// 后面增加节点 - /// - /// - /// - /// - public LoopListNode AddAfter(LoopListNode node, T value) - { - var tNode = new LoopListNode(value, this); - node.Next!.Previous = tNode; - tNode.Next = node.Next; - node.Next = tNode; - tNode.Previous = node; - Count++; - return tNode; - } - - #endregion - - #region Remove - - /// - /// 删除首节点 - /// - /// - public bool RemoveFirst() - { - switch (Count) - { - case 0: - return false; - - case 1: - First = null; - break; - - default: - LoopListNode last = Last!; - First = First!.Next; - First!.Previous = last; - last.Next = First; - break; - } - Count--; - return true; - } - - /// - /// 删除尾节点 - /// - /// - public bool RemoveLast() - { - switch (Count) - { - case 0: - return false; - - case 1: - First = null; - break; - - default: - LoopListNode last = Last!.Previous!; - last.Next = First; - First!.Previous = last; - break; - } - Count--; - return true; - } - - /// - /// 删除此参数节点(唯一) - /// - /// 指定节点 - /// - public bool Remove(LoopListNode node) - { - if (!Contains(node)) - return false; - InternalRemove(node); - return true; - } - - /// - /// 删除含有此参数节点(所有) - /// - /// 将移除所有含有此值 - /// - public bool Remove(T value) - { - var lst = Finds(value); - if (lst is null) - return false; - - using var ge = lst.GetEnumerator(); - while (ge.MoveNext()) - if (ge.Current != null) - InternalRemove(ge.Current); - return true; - } - - /// - /// 删除节点_内部调用 - /// - /// 此值肯定存在当前链表 - /// - void InternalRemove(LoopListNode node) - { - if (Count == 1 || node == First) - { - RemoveFirst();// 此处会减数字 - } - else - { - node.Next!.Previous = node.Previous; - node.Previous!.Next = node.Next; - Count--; - } - node.Invalidate(); - } - - #endregion - - #region LinkTo - - /// - /// 链接两节点,并去除这两个节点间的所有节点 - /// - /// - /// - public void LinkTo(LoopListNode from, LoopListNode to) - { - if (from != to && Contains(from) && Contains(to)) - { - LoopListNode node = from.Next!; - bool isFirstChanged = false; - int number = 0; - - while (node != to) - { - if (node == First) - isFirstChanged = true; - - node = node.Next!; - number++; - } - - from.Next = to; - to.Previous = from; - - if (number > 0 && isFirstChanged) - First = to; - - Count -= number; - } - } - - /// - /// 链接两节点,并去除这两个节点间的所有节点 - /// - /// - /// - /// - public void LinkTo(LoopListNode from, LoopListNode to, int number) - { - if (from != to && Contains(from) && Contains(to)) - { - from.Next = to; - to.Previous = from; - First = to; - Count -= number; - } - } - - /// - /// 链接两节点,并去除这两个节点间的所有节点 - /// - /// - /// - /// - /// - public void LinkTo(LoopListNode from, LoopListNode to, int number, bool isFirstChanged) - { - if (from != to && Contains(from) && Contains(to)) - { - from.Next = to; - to.Previous = from; - if (isFirstChanged) - First = to; - Count -= number; - } - } - - #endregion - - #endregion - - #region IEnumerable - - /// - /// 获取节点的查询器 - /// - /// - /// - [DebuggerStepThrough] - public IEnumerable> GetNodes(LoopListNode from) - { - var node = from; - for (int i = 0; i < Count; i++) - { - yield return node!; - node = node!.Next; - } - } - - /// - /// 获取节点的查询器 - /// - /// - [DebuggerStepThrough] - public IEnumerable> GetNodes() - { - LoopListNode node = First!; - for (int i = 0; i < Count; i++) - { - yield return node!; - node = node.Next!; - } - } - - /// - /// 获取节点值的查询器 - /// - /// - [DebuggerStepThrough] - public IEnumerator GetEnumerator() - { - LoopListNode node = First!; - for (int i = 0; i < Count; i++) - { - yield return node!.Value; - node = node.Next!; - } - } - - [DebuggerStepThrough] - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - - #region IEnumerable 成员 - - [DebuggerStepThrough] - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - - #endregion IEnumerable 成员 - - #endregion - - #region IFormattable - /// - /// 转换为字符串_格式化实现 - /// - /// - /// - /// - string IFormattable.ToString(string? format, IFormatProvider? formatProvider) - { - return ToString(format, formatProvider); - } - - /// - /// 转换为字符串_无参调用 - /// - /// - public override string ToString() - { - return ToString(null); - } - - /// - /// 转换为字符串_有参调用 - /// - /// - public string ToString(string? format, IFormatProvider? formatProvider = null) - { - var s = new StringBuilder(); - s.Append($"Count = {Count};"); - if (format is not null) return s.ToString(); - s.Append("{ "); - foreach (var value in this) - s.Append($"{value} "); - s.Append(" }"); - return s.ToString(); - } - #endregion - - #region ICloneable - /* 山人说无法分辨ICloneable接口是深浅克隆, - * 因此不要在泛型模板实现克隆函数, - * 让用户自己来 new(xx)实现浅克隆,所以也不提供Clone()了 - * - * 因此约定了:CopyTo(T,index)是深克隆;MemberwiseClone()是浅克隆; - * public object Clone() - * { - * var lst = new LoopList>(); - * ForEach(node => { - * lst.Add(node); - * return false; - * }); - * return lst; - * } - */ - #endregion -} - -#line default \ No newline at end of file diff --git a/src/Basal/IFox.Basal.Shared/General/LoopState.cs b/src/Basal/IFox.Basal.Shared/General/LoopState.cs deleted file mode 100644 index c758c48..0000000 --- a/src/Basal/IFox.Basal.Shared/General/LoopState.cs +++ /dev/null @@ -1,70 +0,0 @@ -#pragma warning disable CS1591 // 缺少对公共可见类型或成员的 XML 注释 -namespace IFoxCAD.Basal; - -#line hidden // 调试的时候跳过它 -/// -/// 控制循环结束 -/// -public class LoopState -{ - private const int PlsNone = 0; - private const int PlsExceptional = 1; - private const int PlsBroken = 2; - private const int PlsStopped = 4; - private const int PlsCanceled = 8; - - private volatile int _flag = PlsNone; - - public bool IsRun => _flag == PlsNone; - public bool IsExceptional => (_flag & PlsExceptional) == PlsExceptional; - public bool IsBreak => (_flag & PlsBroken) == PlsBroken; - public bool IsStop => (_flag & PlsStopped) == PlsStopped; - public bool IsCancel => (_flag & PlsCanceled) == PlsCanceled; - - public void Exceptional() - { - if ((_flag & PlsExceptional) != PlsExceptional) - _flag |= PlsExceptional; - } - public void Break() => _flag = PlsBroken; - public void Stop() => _flag = PlsStopped; - public void Cancel() => _flag = PlsCanceled; - public void Reset() => _flag = PlsNone; -} -#line default - -/// -/// 控制程序流程 -/// -public class ProState -{ - private const int PlsNone = 0; // 初始化(构造就立马运行,将导致构造函数中也被检测,这是浪费性能及挖坑给自己的) - private const int PlsRun = 1; // 运行 - private const int PlsBroken = 2; - private const int PlsStopped = 4; - private const int PlsCanceled = 8; - private const int PlsExceptional = 16; // 异常 用于附加状态 - - private volatile int _flag = PlsNone; - - public bool IsNone => _flag == PlsNone; - public bool IsRun => (_flag & PlsRun) == PlsRun; - public bool IsBreak => (_flag & PlsBroken) == PlsBroken; - public bool IsStop => (_flag & PlsStopped) == PlsStopped; - public bool IsCancel => (_flag & PlsCanceled) == PlsCanceled; - public bool IsExceptional => (_flag & PlsExceptional) == PlsExceptional; - - public void Exceptional() - { - if ((_flag & PlsExceptional) != PlsExceptional) - _flag |= PlsExceptional; - } - public void Break() => _flag = PlsBroken; - public void Stop() => _flag = PlsStopped; - public void Cancel() => _flag = PlsCanceled; - public void Start() => _flag = PlsRun; - public void None() => _flag = PlsNone; -} -#line default - -#pragma warning restore CS1591 // 缺少对公共可见类型或成员的 XML 注释 \ No newline at end of file diff --git a/src/Basal/IFox.Basal.Shared/General/MathEx.cs b/src/Basal/IFox.Basal.Shared/General/MathEx.cs deleted file mode 100644 index d33b404..0000000 --- a/src/Basal/IFox.Basal.Shared/General/MathEx.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace IFoxCAD.Basal; - -/// -/// 数学函数扩展类 -/// -public static class MathEx -{ - /// - /// 转换弧度到角度 - /// - /// 弧度值 - /// 角度(10进制小数) - public static double ConvertRadToDeg(double rad) => rad / Math.PI * 180; - - /// - /// 转换角度(10进制小数)到弧度 - /// - /// 角度 - /// 弧度 - public static double ConvertDegToRad(double deg) => deg / 180 * Math.PI; -} - diff --git a/src/Basal/IFox.Basal.Shared/General/RandomEx.cs b/src/Basal/IFox.Basal.Shared/General/RandomEx.cs deleted file mode 100644 index 119bd2b..0000000 --- a/src/Basal/IFox.Basal.Shared/General/RandomEx.cs +++ /dev/null @@ -1,196 +0,0 @@ -/* -*┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━模块信息━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ -*┃ 作 者:YxrWendao -*┃ 创建时间:2022/8/30 22:49:30 -*┃ 模块描述:随机数生成器 -*┃ 使用范围:通用 -*┃ 说 明:本模块中除GetRandom与NextColor方法是IFoxCAD原有的以外,其他方法均通过网络收集整理而来。 -*┃ 代码版本:1.0 -*┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ -*/ - -namespace IFoxCAD.Basal; - -/// -/// 随机值扩展类 -/// -public static class RandomEx -{ - /// - /// 生成一个指定范围的浮点数值
- /// 相关链接 - ///
- /// 一个随机值产生器 - /// 范围最小浮点数值 - /// 范围最大浮点数值 - /// - public static double NextDouble(Random ran, double minValue, double maxValue) - { - return ran.NextDouble() * (maxValue - minValue) + minValue; - } - /// - /// 生成一个指定范围的浮点数值 - /// - /// 范围最小浮点数值 - /// 范围最大浮点数值 - /// - public static double NextDouble(double minValue, double maxValue) - { - return NextDouble(GetRandom(), minValue, maxValue); - } - /// - /// 生成一个布尔随机数 - /// - /// - public static bool NextBool() - { - return NextBool(GetRandom()); - } - /// - /// 生成一个布尔随机数
- ///
- /// - public static bool NextBool(Random ran) - { - bool[] arr = { true, false }; - return arr[ran.Next(2)]; - } - /// - /// 生成一个不连续或指定值的随机值 - /// - /// 一个字符串数组 - /// - public static string NextString(string[] arr) - { - return NextString(GetRandom(), arr); - } - /// - /// 生成一个不连续或指定值的随机值 - /// - /// 一个随机值产生器 - /// 一个字符串数组 - /// - public static string NextString(Random ran, string[] arr) - { - var n = ran.Next(arr.Length - 1); - return arr[n]; - } - /// - /// 生成一个不连续或指定值的随机值 - /// - /// 一个双精度值数组 - /// - public static double NextDouble(double[] arr) - { - return NextDouble(GetRandom(), arr); - } - /// - /// 生成不连续或指定值的随机值 - /// - /// 一个随机值产生器 - /// 一个双精度值数组 - /// - public static double NextDouble(Random ran, double[] arr) - { - int n = ran.Next(arr.Length - 1); - return arr[n]; - } - /// - /// 生成指定范围内的整数 - /// - /// 范围最大整数值 - /// - public static int NextInt(int max) - { - return NextInt(GetRandom(), max); - } - /// - /// 生成指定范围内的整数 - /// - /// 一个随机值产生器 - /// 范围最大整数值 - /// - public static int NextInt(Random ran, int max) - { - return ran.Next(max); - } - /// - /// 生成指定范围内的整数 - /// - /// 范围的最小整数 - /// 范围的最大整数 - /// 返回一个介于之间的整数 - public static int NextInt(int min, int max) - { - return NextInt(GetRandom(), min, max); - } - /// - /// 生成指定范围内的整数 - /// - /// 一个随机值产生器 - /// 范围的最小整数 - /// 范围的最大整数 - /// 返回一个介于之间的整数 - public static int NextInt(Random ran, int min, int max) - { - return ran.Next(min, max); - } - - /// - /// 生成一个随机颜色 - /// - /// 返回 - public static System.Drawing.Color NextColor() - { - return NextColor(GetRandom()); - } - /// - /// 生成一个随机颜色 - /// - /// - public static System.Drawing.Color NextColor(Random ran) - { - var R = ran.Next(255); - var G = ran.Next(255); - var B = ran.Next(255); - B = (R + G > 400) ? R + G - 400 : B;// 0 : 380 - R - G; - B = (B > 255) ? 255 : B; - return System.Drawing.Color.FromArgb(R, G, B); - } - - - /* - * 知识准备: - * | 高位64位 | 低位32位 | - * Convert.ToString(int.MaxValue, 2)输出二进制 "1111111111111111111111111111111" 31个;最高位是符号位,所以少1位 - * Convert.ToString(long.MaxValue,2)输出二进制,刚好长一倍 "11111111111111111111111111111111 1111111111111111111111111111111" 63个;最高位是符号位,所以少1位 - * Convert.ToString(0xffffffffL, 2)int.MaxValue再按位多1 "1 1111111111111111111111111111111" 32个;前面的0不会打印出来 - * - * Convert.ToString(long.MaxValue>>32, 2)相当于平移高位的到低位范围,也就是上面少打印的二进制 - * 验证右移是不是高位保留,答案是 - * var a = Convert.ToInt64("101111111111111111111111111111111111111111111111111111111111111", 2); - * Convert.ToString(a >> 32,2); - * - * 解释代码: - * 0x01: - * (int)(long.MaxValue & 0xffffffffL) | (int)(long.MaxValue >> 32); - * Convert.ToString(long.MaxValue & 0xffffffffL, 2)// 去掉高位:"11111111111111111111111111111111" 32个,再强转int - * 按位与&是保证符号位肯定是1,其他尽可能为0,高位被去掉只是MaxValue&0的原因,强转才是去掉高位..."尽可能"一词带来第一次随机性 - * 0x02: - * Convert.ToString((long.MaxValue >> 32), 2) // 去掉低位: "1111111111111111111111111111111" 31个,再强转int - * 按位或|是尽可能为1..."尽可能"一词带来第二次随机性 - * - */ - - /// - /// 带有随机种子的随机数
- /// 为什么这样写随机种子呢 - ///
- /// - public static Random GetRandom() - { - var tick = DateTime.Now.Ticks; - var tickSeeds = (int)(tick & 0xffffffffL) | (int)(tick >> 32); - return new Random(tickSeeds); - } -} \ No newline at end of file diff --git a/src/Basal/IFox.Basal.Shared/General/Timer.cs b/src/Basal/IFox.Basal.Shared/General/Timer.cs deleted file mode 100644 index 78b1abb..0000000 --- a/src/Basal/IFox.Basal.Shared/General/Timer.cs +++ /dev/null @@ -1,148 +0,0 @@ -namespace IFoxCAD.Basal; - -/* -// 测试例子,同时验证两个计时器 -var stopwatch = new Stopwatch(); -Timer.RunTime(() => { - stopwatch.Start(); - for (int i = 0; i < 10000000; i++) - i++; - stopwatch.Stop(); -}, Timer.TimeEnum.Millisecond, "运行:"); -Console.WriteLine("运行毫秒:" + stopwatch.ElapsedMilliseconds); - */ - -/// -/// 时间定时类 -/// -public class Timer -{ - /// - /// 时间单位枚举 - /// - public enum TimeEnum - { - /// - /// 秒 - /// - Second, - /// - /// 毫秒 - /// - Millisecond, - /// - /// 微秒 - /// - Microsecond, - /// - /// 纳秒 - /// - Nanosecond, - } - - [DllImport("Kernel32.dll")] - private static extern bool QueryPerformanceCounter(out long lpPerformanceCount); - - /// - /// 这个函数会检索性能计数器的频率. - /// 性能计数器的频率在系统启动时是固定的,并且在所有处理器上都是一致的 - /// 因此,只需在应用初始化时查询频率,即可缓存结果 - /// 在运行 Windows XP 或更高版本的系统上,该函数将始终成功,因此永远不会返回零 - /// - /// - /// - [DllImport("Kernel32.dll")] - private static extern bool QueryPerformanceFrequency(out long lpFrequency); - - private long _startTime, _stopTime; - private readonly long _freq; - /// - /// 构造函数 - /// - /// - public Timer() - { - _startTime = 0; - _stopTime = 0; - - if (!QueryPerformanceFrequency(out _freq)) - throw new Win32Exception("不支持高性能计数器"); - } - - /// - /// 开始计时器 - /// - public void Start() - { - Thread.Sleep(0); - QueryPerformanceCounter(out _startTime); - } - - /// - /// 停止计时器 - /// - public void Stop() - { - QueryPerformanceCounter(out _stopTime); - Second = (double)(_stopTime - _startTime) / _freq; - } - - // 返回计时器经过时间 - /// - /// 秒 - /// - public double Second { get; private set; } - - /// - /// 毫秒 - /// - public double Millisecond => Second * 1000.0; - /// - /// 微秒 - /// - public double Microsecond => Second * 1000000.0; - /// - /// 纳秒 - /// - public double Nanosecond => Second * 1000000000.0; - /// - /// 计算执行委托的时间 - /// - /// 要执行的委托 - /// 时间单位 - /// 执行委托的时间 - public static double RunTime(Action action, - TimeEnum timeEnum = TimeEnum.Millisecond) - { - var nanoSecond = new Timer(); - nanoSecond.Start(); - action(); - nanoSecond.Stop(); - - var time = timeEnum switch - { - TimeEnum.Second => nanoSecond.Second, - TimeEnum.Millisecond => nanoSecond.Millisecond, - TimeEnum.Microsecond => nanoSecond.Microsecond, - TimeEnum.Nanosecond => nanoSecond.Nanosecond, - _ => 0.0 - }; - //string timeNameZn = ""; - //switch (timeEnum) - //{ - // case TimeEnum.Second: - // timeNameZn = " 秒"; - // break; - // case TimeEnum.Millisecond: - // timeNameZn = " 毫秒"; - // break; - // case TimeEnum.Microsecond: - // timeNameZn = " 微秒"; - // break; - // case TimeEnum.Nanosecond: - // timeNameZn = " 纳秒"; - // break; - //} - return time; - } -} \ No newline at end of file diff --git a/src/Basal/IFox.Basal.Shared/IFox.Basal.Shared.projitems b/src/Basal/IFox.Basal.Shared/IFox.Basal.Shared.projitems deleted file mode 100644 index 3025783..0000000 --- a/src/Basal/IFox.Basal.Shared/IFox.Basal.Shared.projitems +++ /dev/null @@ -1,38 +0,0 @@ - - - - $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - true - c823514a-2bc2-45c2-aced-18924a7b80bf - - - IFox.Basal.Shared - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Basal/IFox.Basal.Shared/IFox.Basal.Shared.shproj b/src/Basal/IFox.Basal.Shared/IFox.Basal.Shared.shproj deleted file mode 100644 index e04b5b6..0000000 --- a/src/Basal/IFox.Basal.Shared/IFox.Basal.Shared.shproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - c823514a-2bc2-45c2-aced-18924a7b80bf - 14.0 - - - - - - - - diff --git a/src/Basal/IFox.Basal.Shared/Nullable/ArgumentNullEx.cs b/src/Basal/IFox.Basal.Shared/Nullable/ArgumentNullEx.cs deleted file mode 100644 index 2a9fe39..0000000 --- a/src/Basal/IFox.Basal.Shared/Nullable/ArgumentNullEx.cs +++ /dev/null @@ -1,39 +0,0 @@ -namespace IFoxCAD.Basal -{ - /// - /// 参数null检查类 - /// - public static class ArgumentNullEx - { - /// - /// 检查参数是否为 null - /// - /// 参数 - /// 参数名字 - public static void ThrowIfNull([NotNull] object? argument, - [CallerArgumentExpression(nameof(argument))] string? paramName = null) - { - if (argument is null) - { - Throw(paramName); - } - } - - [DoesNotReturn] - private static void Throw(string? paramName) => throw new ArgumentNullException(paramName); - - - - /// - /// 检查参数是否为 null - /// - /// 参数 - /// 参数为null时的提示信息 - /// - [Obsolete("请使用 ArgumentNullEx.ThrowIfNull(value);")] - public static void NotNull([NotNull] this object? value, [CallerArgumentExpression(nameof(value))] string valueExpression = "") - { - _ = value ?? throw new ArgumentNullException(nameof(value), valueExpression); - } - } -} \ No newline at end of file diff --git a/src/Basal/IFox.Basal.Shared/Nullable/CallerArgumentExpressionAttribute.cs b/src/Basal/IFox.Basal.Shared/Nullable/CallerArgumentExpressionAttribute.cs deleted file mode 100644 index aceee41..0000000 --- a/src/Basal/IFox.Basal.Shared/Nullable/CallerArgumentExpressionAttribute.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace System.Runtime.CompilerServices -{ - /// - /// 指示参数将为另一个参数传递的表达式捕获为字符串。 - /// - [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] - internal sealed class CallerArgumentExpressionAttribute : Attribute - { - /// - /// 初始化 CallerArgumentExpressionAttribute 类的新实例。 - /// - /// - public CallerArgumentExpressionAttribute(string parameterName) - { - ParameterName = parameterName; - } - /// - /// 获取其表达式应捕获为字符串的参数的名称。 - /// - public string ParameterName { get; } - } -} \ No newline at end of file diff --git a/src/Basal/IFox.Basal.Shared/Nullable/NullableAttributes.cs b/src/Basal/IFox.Basal.Shared/Nullable/NullableAttributes.cs deleted file mode 100644 index 361f88f..0000000 --- a/src/Basal/IFox.Basal.Shared/Nullable/NullableAttributes.cs +++ /dev/null @@ -1,196 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -namespace System.Diagnostics.CodeAnalysis -{ -#if !NETSTANDARD2_1 - /// Specifies that null is allowed as an input even if the corresponding type disallows it. - [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)] -#if SYSTEM_PRIVATE_CORELIB - public -#else - internal -#endif - sealed class AllowNullAttribute : Attribute { } - - /// Specifies that null is disallowed as an input even if the corresponding type allows it. - [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)] -#if SYSTEM_PRIVATE_CORELIB - public -#else - internal -#endif - sealed class DisallowNullAttribute : Attribute { } - - /// Specifies that an output may be null even if the corresponding type disallows it. - [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)] -#if SYSTEM_PRIVATE_CORELIB - public -#else - internal -#endif - sealed class MaybeNullAttribute : Attribute { } - - /// Specifies that an output will not be null even if the corresponding type allows it. Specifies that an input argument was not null when the call returns. - [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)] -#if SYSTEM_PRIVATE_CORELIB - public -#else - internal -#endif - sealed class NotNullAttribute : Attribute { } - - /// Specifies that when a method returns , the parameter may be null even if the corresponding type disallows it. - [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] -#if SYSTEM_PRIVATE_CORELIB - public -#else - internal -#endif - sealed class MaybeNullWhenAttribute : Attribute - { - /// Initializes the attribute with the specified return value condition. - /// - /// The return value condition. If the method returns this value, the associated parameter may be null. - /// - public MaybeNullWhenAttribute(bool returnValue) => ReturnValue = returnValue; - - /// Gets the return value condition. - public bool ReturnValue { get; } - } - - /// Specifies that when a method returns , the parameter will not be null even if the corresponding type allows it. - [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] -#if SYSTEM_PRIVATE_CORELIB - public -#else - internal -#endif - sealed class NotNullWhenAttribute : Attribute - { - /// Initializes the attribute with the specified return value condition. - /// - /// The return value condition. If the method returns this value, the associated parameter will not be null. - /// - public NotNullWhenAttribute(bool returnValue) => ReturnValue = returnValue; - - /// Gets the return value condition. - public bool ReturnValue { get; } - } - - /// Specifies that the output will be non-null if the named parameter is non-null. - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, AllowMultiple = true, Inherited = false)] -#if SYSTEM_PRIVATE_CORELIB - public -#else - internal -#endif - sealed class NotNullIfNotNullAttribute : Attribute - { - /// Initializes the attribute with the associated parameter name. - /// - /// The associated parameter name. The output will be non-null if the argument to the parameter specified is non-null. - /// - public NotNullIfNotNullAttribute(string parameterName) => ParameterName = parameterName; - - /// Gets the associated parameter name. - public string ParameterName { get; } - } - - /// Applied to a method that will never return under any circumstance. - [AttributeUsage(AttributeTargets.Method, Inherited = false)] -#if SYSTEM_PRIVATE_CORELIB - public -#else - internal -#endif - sealed class DoesNotReturnAttribute : Attribute { } - - /// Specifies that the method will not return if the associated Boolean parameter is passed the specified value. - [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] -#if SYSTEM_PRIVATE_CORELIB - public -#else - internal -#endif - sealed class DoesNotReturnIfAttribute : Attribute - { - /// Initializes the attribute with the specified parameter value. - /// - /// The condition parameter value. Code after the method will be considered unreachable by diagnostics if the argument to - /// the associated parameter matches this value. - /// - public DoesNotReturnIfAttribute(bool parameterValue) => ParameterValue = parameterValue; - - /// Gets the condition parameter value. - public bool ParameterValue { get; } - } -#endif - - /// Specifies that the method or property will ensure that the listed field and property members have not-null values. - [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] -#if SYSTEM_PRIVATE_CORELIB - public -#else - internal -#endif - sealed class MemberNotNullAttribute : Attribute - { - /// Initializes the attribute with a field or property member. - /// - /// The field or property member that is promised to be not-null. - /// - public MemberNotNullAttribute(string member) => Members = new[] { member }; - - /// Initializes the attribute with the list of field and property members. - /// - /// The list of field and property members that are promised to be not-null. - /// - public MemberNotNullAttribute(params string[] members) => Members = members; - - /// Gets field or property member names. - public string[] Members { get; } - } - - /// Specifies that the method or property will ensure that the listed field and property members have not-null values when returning with the specified return value condition. - [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] -#if SYSTEM_PRIVATE_CORELIB - public -#else - internal -#endif - sealed class MemberNotNullWhenAttribute : Attribute - { - /// Initializes the attribute with the specified return value condition and a field or property member. - /// - /// The return value condition. If the method returns this value, the associated parameter will not be null. - /// - /// - /// The field or property member that is promised to be not-null. - /// - public MemberNotNullWhenAttribute(bool returnValue, string member) - { - ReturnValue = returnValue; - Members = new[] { member }; - } - - /// Initializes the attribute with the specified return value condition and list of field and property members. - /// - /// The return value condition. If the method returns this value, the associated parameter will not be null. - /// - /// - /// The list of field and property members that are promised to be not-null. - /// - public MemberNotNullWhenAttribute(bool returnValue, params string[] members) - { - ReturnValue = returnValue; - Members = members; - } - - /// Gets the return value condition. - public bool ReturnValue { get; } - - /// Gets field or property member names. - public string[] Members { get; } - } -} diff --git a/src/Basal/IFox.Basal.Shared/WindowsAPI/Enums.cs b/src/Basal/IFox.Basal.Shared/WindowsAPI/Enums.cs deleted file mode 100644 index 059f92c..0000000 --- a/src/Basal/IFox.Basal.Shared/WindowsAPI/Enums.cs +++ /dev/null @@ -1,1073 +0,0 @@ -#pragma warning disable CS1591 // 缺少对公共可见类型或成员的 XML 注释 -#if true -namespace IFoxCAD.Basal; - -// https://blog.csdn.net/qq_43812868/article/details/108587936 -[Flags] -public enum TH32CS : uint -{ - /// - /// 原因在于如果不采用改参数的话,有可能快照会占用整个堆的空间 - /// - TH32CS_SNAPNOHEAPS = 0x40000000, - /// - /// 声明快照句柄是可继承的 - /// - TH32CS_INHERIT = 0x80000000, - /// - /// 在快照中包含在th32ProcessID中指定的进程的所有的堆 - /// - TH32CS_SNAPHEAPLIST = 0x00000001, - /// - /// 在快照中包含系统中所有的进程 - /// - TH32CS_SNAPPROCESS = 0x00000002, - /// - /// 在快照中包含系统中所有的线程 - /// - TH32CS_SNAPTHREAD = 0x00000004, - /// - /// 在快照中包含在th32ProcessID中指定的进程的所有的模块 - /// - TH32CS_SNAPMODULE = 0x00000008, - /// - /// 在快照中包含系统中所有的进程和线程 - /// - TH32CS_SNAPALL = TH32CS_SNAPHEAPLIST | TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD | TH32CS_SNAPMODULE, -} - -/// -/// 设置的钩子类型 -/// -[Flags] -public enum HookType : int -{ - /// - /// WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks使我们可以监视菜单,滚动 - /// 条,消息框,对话框消息并且发现用户使用ALT+TAB or ALT+ESC 组合键切换窗口。 - /// WH_MSGFILTER Hook只能监视传递到菜单,滚动条,消息框的消息,以及传递到通 - /// 过安装了Hook子过程的应用程序建立的对话框的消息。WH_SYSMSGFILTER Hook - /// 监视所有应用程序消息。 - /// - /// WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks使我们可以在模式循环期间 - /// 过滤消息,这等价于在主消息循环中过滤消息。 - /// - /// 通过调用CallMsgFilter function可以直接的调用WH_MSGFILTER Hook。通过使用这 - /// 个函数,应用程序能够在模式循环期间使用相同的代码去过滤消息,如同在主消息循 - /// 环里一样 - /// - WH_MSGFILTER = -1, - /// - /// WH_JOURNALRECORD Hook用来监视和记录输入事件。典型的,可以使用这 - /// 个Hook记录连续的鼠标和键盘事件,然后通过使用WH_JOURNALPLAYBACK Hook - /// 来回放。WH_JOURNALRECORD Hook是全局Hook,它不能象线程特定Hook一样 - /// 使用。WH_JOURNALRECORD是system-wide local hooks,它们不会被注射到任何行 - /// 程地址空间 - /// - WH_JOURNALRECORD = 0, - /// - /// WH_JOURNALPLAYBACK Hook使应用程序可以插入消息到系统消息队列。可 - /// 以使用这个Hook回放通过使用WH_JOURNALRECORD Hook记录下来的连续的鼠 - /// 标和键盘事件。只要WH_JOURNALPLAYBACK Hook已经安装,正常的鼠标和键盘 - /// 事件就是无效的。WH_JOURNALPLAYBACK Hook是全局Hook,它不能象线程特定 - /// Hook一样使用。WH_JOURNALPLAYBACK Hook返回超时值,这个值告诉系统在处 - /// 理来自回放Hook当前消息之前需要等待多长时间(毫秒)。这就使Hook可以控制实 - /// 时事件的回放。WH_JOURNALPLAYBACK是system-wide local hooks,它们不会被 - /// 注射到任何行程地址空间 - /// - WH_JOURNALPLAYBACK = 1, - /// - /// 在应用程序中,WH_KEYBOARD Hook用来监视WM_KEYDOWN and - /// WM_KEYUP消息,这些消息通过GetMessage or PeekMessage function返回。可以使 - /// 用这个Hook来监视输入到消息队列中的键盘消息 - /// - WH_KEYBOARD = 2, - /// - /// 应用程序使用WH_GETMESSAGE Hook来监视从GetMessage or PeekMessage函 - /// 数返回的消息。你可以使用WH_GETMESSAGE Hook去监视鼠标和键盘输入,以及 - /// 其它发送到消息队列中的消息 - /// - WH_GETMESSAGE = 3, - /// - /// 监视发送到窗口过程的消息,系统在消息发送到接收窗口过程之前调用 - /// - WH_CALLWNDPROC = 4, - /// - /// 在以下事件之前,系统都会调用WH_CBT Hook子过程,这些事件包括: - /// 1. 激活,建立,销毁,最小化,最大化,移动,改变尺寸等窗口事件; - /// 2. 完成系统指令; - /// 3. 来自系统消息队列中的移动鼠标,键盘事件; - /// 4. 设置输入焦点事件; - /// 5. 同步系统消息队列事件。 - /// Hook子过程的返回值确定系统是否允许或者防止这些操作中的一个 - /// - WH_CBT = 5, - /// - /// WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks使我们可以监视菜单,滚动 - /// 条,消息框,对话框消息并且发现用户使用ALT+TAB or ALT+ESC 组合键切换窗口。 - /// WH_MSGFILTER Hook只能监视传递到菜单,滚动条,消息框的消息,以及传递到通 - /// 过安装了Hook子过程的应用程序建立的对话框的消息。WH_SYSMSGFILTER Hook - /// 监视所有应用程序消息。 - /// - /// WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks使我们可以在模式循环期间 - /// 过滤消息,这等价于在主消息循环中过滤消息。 - /// - /// 通过调用CallMsgFilter function可以直接的调用WH_MSGFILTER Hook。通过使用这 - /// 个函数,应用程序能够在模式循环期间使用相同的代码去过滤消息,如同在主消息循 - /// 环里一样 - /// - WH_SYSMSGFILTER = 6, - /// - /// WH_MOUSE Hook监视从GetMessage 或者 PeekMessage 函数返回的鼠标消息。 - /// 使用这个Hook监视输入到消息队列中的鼠标消息 - /// - WH_MOUSE = 7, - /// - /// 当调用GetMessage 或 PeekMessage 来从消息队列种查询非鼠标、键盘消息时 - /// - WH_HARDWARE = 8, - /// - /// 在系统调用系统中与其它Hook关联的Hook子过程之前,系统会调用 - /// WH_DEBUG Hook子过程。你可以使用这个Hook来决定是否允许系统调用与其它 - /// Hook关联的Hook子过程 - /// - WH_DEBUG = 9, - /// - /// 外壳应用程序可以使用WH_SHELL Hook去接收重要的通知。当外壳应用程序是 - /// 激活的并且当顶层窗口建立或者销毁时,系统调用WH_SHELL Hook子过程。 - /// WH_SHELL 共有5钟情况: - /// 1. 只要有个top-level、unowned 窗口被产生、起作用、或是被摧毁; - /// 2. 当Taskbar需要重画某个按钮; - /// 3. 当系统需要显示关于Taskbar的一个程序的最小化形式; - /// 4. 当目前的键盘布局状态改变; - /// 5. 当使用者按Ctrl+Esc去执行Task Manager(或相同级别的程序)。 - /// - /// 按照惯例,外壳应用程序都不接收WH_SHELL消息。所以,在应用程序能够接 - /// 收WH_SHELL消息之前,应用程序必须调用SystemParametersInfo function注册它自 - /// 己 - /// - WH_SHELL = 10, - /// - /// 当应用程序的前台线程处于空闲状态时,可以使用WH_FOREGROUNDIDLE - /// Hook执行低优先级的任务。当应用程序的前台线程大概要变成空闲状态时,系统就 - /// 会调用WH_FOREGROUNDIDLE Hook子过程 - /// - WH_FOREGROUNDIDLE = 11, - /// - /// 监视发送到窗口过程的消息,系统在消息发送到接收窗口过程之后调用 - /// - WH_CALLWNDPROCRET = 12, - /// - /// 监视键盘消息 - /// - WH_KEYBOARD_LL = 13, - /// - /// 监视鼠标消息 - /// - WH_MOUSE_LL = 14 -} - -/// -/// 消息类型 -/// 作为SendMessage和PostMessage的参数 -/// -[Flags] -public enum WM : uint -{ - /// - /// 创建一个窗口 - /// - WM_CREATE = 0x01, - /// - /// 当一个窗口被破坏时发送 - /// - WM_DESTROY = 0x02, - /// - /// 移动一个窗口 - /// - WM_MOVE = 0x03, - /// - /// 改变一个窗口的大小 - /// - WM_SIZE = 0x05, - /// - /// 一个窗口被激活或失去激活状态 - /// - WM_ACTIVATE = 0x06, - /// - /// 一个窗口获得焦点 - /// - WM_SETFOCUS = 0x07, - /// - /// 一个窗口失去焦点 - /// - WM_KILLFOCUS = 0x08, - /// - /// 一个窗口改变成Enable状态 - /// - WM_ENABLE = 0x0A, - /// - /// 设置窗口是否能重画 - /// - WM_SETREDRAW = 0x0B, - /// - /// 应用程序发送此消息来设置一个窗口的文本 - /// - WM_SETTEXT = 0x0C, - /// - /// 应用程序发送此消息来复制对应窗口的文本到缓冲区 - /// - WM_GETTEXT = 0x0D, - /// - /// 得到与一个窗口有关的文本的长度(不包含空字符) - /// - WM_GETTEXTLENGTH = 0x0E, - /// - /// 要求一个窗口重画自己 - /// - WM_PAINT = 0x0F, - /// - /// 当一个窗口或应用程序要关闭时发送一个信号 - /// - WM_CLOSE = 0x10, - /// - /// 当用户选择结束对话框或程序自己调用ExitWindows函数 - /// - WM_QUERYENDSESSION = 0x11, - /// - /// 用来结束程序运行 - /// - WM_QUIT = 0x12, - /// - /// 当用户窗口恢复以前的大小位置时,把此消息发送给某个图标 - /// - WM_QUERYOPEN = 0x13, - /// - /// 当窗口背景必须被擦除时(例在窗口改变大小时) - /// - WM_ERASEBKGND = 0x14, - /// - /// 当系统颜色改变时,发送此消息给所有顶级窗口 - /// - WM_SYSCOLORCHANGE = 0x15, - /// - /// 当系统进程发出WM_QUERYENDSESSION消息后,此消息发送给应用程序,通知它对话是否结束 - /// - WM_ENDSESSION = 0x16, - /// - /// 当隐藏或显示窗口是发送此消息给这个窗口 - /// - WM_SHOWWINDOW = 0x18, - /// - /// 发此消息给应用程序哪个窗口是激活的,哪个是非激活的 - /// - WM_ACTIVATEAPP = 0x1C, - /// - /// 当系统的字体资源库变化时发送此消息给所有顶级窗口 - /// - WM_FONTCHANGE = 0x1D, - /// - /// 当系统的时间变化时发送此消息给所有顶级窗口 - /// - WM_TIMECHANGE = 0x1E, - /// - /// 发送此消息来取消某种正在进行的摸态(操作) - /// - WM_CANCELMODE = 0x1F, - /// - /// 如果鼠标引起光标在某个窗口中移动且鼠标输入没有被捕获时,就发消息给某个窗口 - /// - WM_SETCURSOR = 0x20, - /// - /// 当光标在某个非激活的窗口中而用户正按着鼠标的某个键发送此消息给当前窗口 - /// - WM_MOUSEACTIVATE = 0x21, - /// - /// 发送此消息给MDI子窗口当用户点击此窗口的标题栏或当窗口被激活,移动,改变大小 - /// - WM_CHILDACTIVATE = 0x22, - /// - /// 此消息由基于计算机的训练程序发送,通过WH_JOURNALPALYBACK的hook程序分离出用户输入消息 - /// - WM_QUEUESYNC = 0x23, - /// - /// 此消息发送给窗口当它将要改变大小或位置 - /// - WM_GETMINMAXINFO = 0x24, - /// - /// 发送给最小化窗口当它图标将要被重画 - /// - WM_PAINTICON = 0x26, - /// - /// 此消息发送给某个最小化窗口,仅当它在画图标前它的背景必须被重画 - /// - WM_ICONERASEBKGND = 0x27, - /// - /// 发送此消息给一个对话框程序去更改焦点位置 - /// - WM_NEXTDLGCTL = 0x28, - /// - /// 每当打印管理列队增加或减少一条作业时发出此消息 - /// - WM_SPOOLERSTATUS = 0x2A, - /// - /// 当button,combobox,listbox,menu的可视外观改变时发送 - /// - WM_DRAWITEM = 0x2B, - /// - /// 当button, combo box, list box, list view control, or menu item 被创建时 - /// - WM_MEASUREITEM = 0x2C, - /// - /// 此消息有一个LBS_WANTKEYBOARDINPUT风格的发出给它的所有者来响应WM_KEYDOWN消息 - /// - WM_VKEYTOITEM = 0x2E, - /// - /// 此消息由一个LBS_WANTKEYBOARDINPUT风格的列表框发送给他的所有者来响应WM_CHAR消息 - /// - WM_CHARTOITEM = 0x2F, - /// - /// 当绘制文本时程序发送此消息得到控件要用的颜色 - /// - WM_SETFONT = 0x30, - /// - /// 应用程序发送此消息得到当前控件绘制文本的字体 - /// - WM_GETFONT = 0x31, - /// - /// 应用程序发送此消息让一个窗口与一个热键相关连 - /// - WM_SETHOTKEY = 0x32, - /// - /// 应用程序发送此消息来判断热键与某个窗口是否有关联 - /// - WM_GETHOTKEY = 0x33, - /// - /// 此消息发送给最小化窗口,当此窗口将要被拖放而它的类中没有定义图标,应用程序能返回一个图标或光标的句柄,当用户拖放图标时系统显示这个图标或光标 - /// - WM_QUERYDRAGICON = 0x37, - /// - /// 发送此消息来判定combobox或listbox新增加的项的相对位置 - /// - WM_COMPAREITEM = 0x39, - /// - /// 显示内存已经很少了 - /// - WM_COMPACTING = 0x41, - /// - /// 窗口大小和位置将要被改变时,来调用Setwindowpos函数或其它窗口管理函数 - /// - WM_WINDOWPOSCHANGING = 0x46, - /// - /// 窗口大小和位置已经被改变后,来调用Setwindowpos函数或其它窗口管理函数 - /// - WM_WINDOWPOSCHANGED = 0x47, - /// - /// 当系统将要进入暂停状态时发送此消息 - /// - WM_POWER = 0x48, - /// - /// 当一个应用程序传递数据给另一个应用程序时发送此消息 - /// - WM_COPYDATA = 0x4A, - /// - /// 当某个用户取消程序日志激活状态,提交此消息给程序 - /// - WM_CANCELJOURNA = 0x4B, - /// - /// 当某个控件的某个事件已经发生或这个控件需要得到一些信息时,发送此消息给它的父窗口 - /// - WM_NOTIFY = 0x4E, - /// - /// 当用户选择某种输入语言,或输入语言的热键改变 - /// - WM_INPUTLANGCHANGEREQUEST = 0x50, - /// - /// 当平台现场已经被改变后发送此消息给受影响的最顶级窗口 - /// - WM_INPUTLANGCHANGE = 0x51, - /// - /// 当程序已经初始化windows帮助例程时发送此消息给应用程序 - /// - WM_TCARD = 0x52, - /// - /// 此消息显示用户按下了F1,如果某个菜单是激活的,就发送此消息个此窗口关联的菜单,否则就发送给有焦点的窗口,如果当前都没有焦点,就把此消息发送给当前激活的窗口 - /// - WM_HELP = 0x53, - /// - /// 当用户已经登入或退出后发送此消息给所有的窗口,当用户登入或退出时系统更新用户的具体设置信息,在用户更新设置时系统马上发送此消息 - /// - WM_USERCHANGED = 0x54, - /// - /// 公用控件,自定义控件和他们的父窗口通过此消息来判断控件是使用ANSI还是UNICODE结构 - /// - WM_NOTIFYFORMAT = 0x55, - /// - /// 当用户某个窗口中点击了一下右键就发送此消息给这个窗口 - /// - WM_CONTEXTMENU = 0x7B, - /// - /// 当调用SETWINDOWLONG函数将要改变一个或多个窗口的风格时发送此消息给那个窗口 - /// - WM_STYLECHANGING = 0x7C, - /// - /// 当调用SETWINDOWLONG函数一个或多个窗口的风格后发送此消息给那个窗口 - /// - WM_STYLECHANGED = 0x7D, - /// - /// 当显示器的分辨率改变后发送此消息给所有的窗口 - /// - WM_DISPLAYCHANGE = 0x7E, - /// - /// 此消息发送给某个窗口来返回与某个窗口有关连的大图标或小图标的句柄 - /// - WM_GETICON = 0x7F, - /// - /// 程序发送此消息让一个新的大图标或小图标与某个窗口关联 - /// - WM_SETICON = 0x80, - /// - /// 当某个窗口第一次被创建时,此消息在WM_CREATE消息发送前发送 - /// - WM_NCCREATE = 0x81, - /// - /// 此消息通知某个窗口,非客户区正在销毁 - /// - WM_NCDESTROY = 0x82, - /// - /// 当某个窗口的客户区域必须被核算时发送此消息 - /// - WM_NCCALCSIZE = 0x83, - /// - /// 移动鼠标/按住/释放鼠标时 - /// - WM_NCHITTEST = 0x84, - /// - /// 程序发送此消息给某个窗口当它(窗口)的框架必须被绘制时 - /// - WM_NCPAINT = 0x85, - /// - /// 此消息发送给某个窗口仅当它的非客户区需要被改变来显示是激活还是非激活状态 - /// - WM_NCACTIVATE = 0x86, - /// - /// 发送此消息给某个与对话框程序关联的控件,widdows控制方位键和TAB键使输入进入此控件通过应 - /// - WM_GETDLGCODE = 0x87, - /// - /// 当光标在一个窗口的非客户区内移动时发送此消息给这个窗口 非客户区为:窗体的标题栏及窗的边框体 - /// - WM_NCMOUSEMOVE = 0xA0, - /// - /// 当光标在一个窗口的非客户区同时按下鼠标左键时提交此消息 - /// - WM_NCLBUTTONDOWN = 0xA1, - /// - /// 当用户释放鼠标左键同时光标某个窗口在非客户区时发送此消息 - /// - WM_NCLBUTTONUP = 0xA2, - /// - /// 当用户双击鼠标左键同时光标某个窗口在非客户区时发送此消息 - /// - WM_NCLBUTTONDBLCLK = 0xA3, - /// - /// 当用户按下鼠标右键同时光标又在窗口的非客户区时发送此消息 - /// - WM_NCRBUTTONDOWN = 0xA4, - /// - /// 当用户释放鼠标右键同时光标又在窗口的非客户区时发送此消息 - /// - WM_NCRBUTTONUP = 0xA5, - /// - /// 当用户双击鼠标右键同时光标某个窗口在非客户区时发送此消息 - /// - WM_NCRBUTTONDBLCLK = 0xA6, - /// - /// 当用户按下鼠标中键同时光标又在窗口的非客户区时发送此消息 - /// - WM_NCMBUTTONDOWN = 0xA7, - /// - /// 当用户释放鼠标中键同时光标又在窗口的非客户区时发送此消息 - /// - WM_NCMBUTTONUP = 0xA8, - /// - /// 当用户双击鼠标中键同时光标又在窗口的非客户区时发送此消息 - /// - WM_NCMBUTTONDBLCLK = 0xA9, - - // 所有的键盘消息只有中间的八种,也就是 WM_KEYDOWN 到 WM_SYSDEADCHAR - /// - /// 按下一个键 == WM_KEYDOWN - /// - WM_KEYFIRST = 0x0100, - /// - /// 按下一个键 - /// - WM_KEYDOWN = 0x0100, - /// - /// 释放一个键 - /// - WM_KEYUP = 0x0101, - /// - /// 按下某键,并已发出WM_KEYDOWN, WM_KEYUP消息 - /// - WM_CHAR = 0x102, - /// - /// 当用translatemessage函数翻译WM_KEYUP消息时发送此消息给拥有焦点的窗口 - /// - WM_DEADCHAR = 0x103, - /// - /// 当用户按住ALT键同时按下其它键时提交此消息给拥有焦点的窗口 - /// - WM_SYSKEYDOWN = 0x104, - /// - /// 当用户释放一个键同时ALT 键还按着时提交此消息给拥有焦点的窗口 - /// - WM_SYSKEYUP = 0x105, - /// - /// 当WM_SYSKEYDOWN消息被TRANSLATEMESSAGE函数翻译后提交此消息给拥有焦点的窗口 - /// - WM_SYSCHAR = 0x106, - /// - /// 当WM_SYSKEYDOWN消息被TRANSLATEMESSAGE函数翻译后发送此消息给拥有焦点的窗口 - /// - WM_SYSDEADCHAR = 0x107, - /// - /// 在一个对话框程序被显示前发送此消息给它,通常用此消息初始化控件和执行其它任务 - /// - WM_INITDIALOG = 0x110, - /// - /// 当用户选择一条菜单命令项或当某个控件发送一条消息给它的父窗口 - /// - WM_COMMAND = 0x111, - - /// - /// 当用户选择窗口菜单的一条命令或最大化最小化时窗口前会收到此消息 - /// - WM_SYSCOMMAND = 0x112, - /// - /// 发生了定时器事件 - /// - WM_TIMER = 0x113, - /// - /// 当一个窗口标准水平滚动条产生一个滚动事件时发送此消息给那个窗口,也发送给拥有它的控件 - /// - WM_HSCROLL = 0x114, - /// - /// 当一个窗口标准垂直滚动条产生一个滚动事件时发送此消息给那个窗口也,发送给拥有它的控件 - /// - WM_VSCROLL = 0x115, - /// - /// 当一个菜单将要被激活时发送此消息,它发生在用户菜单条中的某项或按下某个菜单键,它允许程序在显示前更改菜单 - /// - WM_INITMENU = 0x116, - /// - /// 当一个下拉菜单或子菜单将要被激活时发送此消息,它允许程序在它显示前更改菜单,而不要改变全部 - /// - WM_INITMENUPOPUP = 0x117, - /// - /// 当用户选择一条菜单项时发送此消息给菜单的所有者(一般是窗口) - /// - WM_MENUSELECT = 0x11F, - /// - /// 当菜单已被激活用户按下了某个键(不同于加速键),发送此消息给菜单的所有者 - /// - WM_MENUCHAR = 0x120, - /// - /// 当一个模态对话框或菜单进入空载状态时发送此消息给它的所有者,一个模态对话框或菜单进入空载状态就是在处理完一条或几条先前的消息后没有消息它的列队中等待 - /// - WM_ENTERIDLE = 0x121, - /// - /// 在windows绘制消息框前发送此消息给消息框的所有者窗口,通过响应这条消息,所有者窗口可以通过使用给定的相关显示设备的句柄来设置消息框的文本和背景颜色 - /// - WM_CTLCOLORMSGBOX = 0x132, - /// - /// 当一个编辑型控件将要被绘制时发送此消息给它的父窗口通过响应这条消息,所有者窗口可以通过使用给定的相关显示设备的句柄来设置编辑框的文本和背景颜色 - /// - WM_CTLCOLOREDIT = 0x133, - - /// - /// 当一个列表框控件将要被绘制前发送此消息给它的父窗口通过响应这条消息,所有者窗口可以通过使用给定的相关显示设备的句柄来设置列表框的文本和背景颜色 - /// - WM_CTLCOLORLISTBOX = 0x134, - /// - /// 当一个按钮控件将要被绘制时发送此消息给它的父窗口通过响应这条消息,所有者窗口可以通过使用给定的相关显示设备的句柄来设置按纽的文本和背景颜色 - /// - WM_CTLCOLORBTN = 0x135, - /// - /// 当一个对话框控件将要被绘制前发送此消息给它的父窗口通过响应这条消息,所有者窗口可以通过使用给定的相关显示设备的句柄来设置对话框的文本背景颜色 - /// - WM_CTLCOLORDLG = 0x136, - /// - /// 当一个滚动条控件将要被绘制时发送此消息给它的父窗口通过响应这条消息,所有者窗口可以通过使用给定的相关显示设备的句柄来设置滚动条的背景颜色 - /// - WM_CTLCOLORSCROLLBAR = 0x137, - /// - /// 当一个静态控件将要被绘制时发送此消息给它的父窗口通过响应这条消息,所有者窗口可以通过使用给定的相关显示设备的句柄来设置静态控件的文本和背景颜色 - /// - WM_CTLCOLORSTATIC = 0x138, - - /// - /// 当鼠标轮子转动时发送此消息个当前有焦点的控件 - /// - WM_MOUSEWHEEL = 0x20A, - /// - /// 双击鼠标中键 - /// - WM_MBUTTONDBLCLK = 0x209, - /// - /// 释放鼠标中键 - /// - WM_MBUTTONUP = 0x208, - /// - /// 移动鼠标时发生,同WM_MOUSEFIRST - /// - WM_MOUSEMOVE = 0x200, - /// - /// 按下鼠标左键 - /// - WM_LBUTTONDOWN = 0x201, - /// - /// 释放鼠标左键 - /// - WM_LBUTTONUP = 0x202, - /// - /// 双击鼠标左键 - /// - WM_LBUTTONDBLCLK = 0x203, - /// - /// 按下鼠标右键 - /// - WM_RBUTTONDOWN = 0x204, - /// - /// 释放鼠标右键 - /// - WM_RBUTTONUP = 0x205, - /// - /// 双击鼠标右键 - /// - WM_RBUTTONDBLCLK = 0x206, - /// - /// 按下鼠标中键 - /// - WM_MBUTTONDOWN = 0x207, - - WM_USER = 0x0400, - - /// - /// 执行复制成功 - /// - WM_CLIPBOARDUPDATE = 0x031D, -} - -// https://blog.csdn.net/biyusr/article/details/108376195 -public enum MOUSEEVENTF : int -{ - /// - /// 移动鼠标 - /// - MOVE = 0x0001, - /// - /// 模拟鼠标左键按下 - /// - LEFTDOWN = 0x0002, - /// - /// 模拟鼠标左键抬起 - /// - LEFTUP = 0x0004, - /// - /// 模拟鼠标右键按下 - /// - RIGHTDOWN = 0x0008, - /// - /// 模拟鼠标右键抬起 - /// - RIGHTUP = 0x0010, - /// - /// 模拟鼠标中键按下 - /// - MIDDLEDOWN = 0x0020, - /// - /// 模拟鼠标中键抬起 - /// - MIDDLEUP = 0x0040, - /// - /// 标示是否采用绝对坐标 - /// - ABSOLUTE = 0x8000, - /// - /// 模拟鼠标滚轮滚动操作,必须配合dwData参数 - /// - WHEEL = 0x0800, -} - -// C#使用SendMessage发送组合键 -// https://www.cnblogs.com/johnsonton/articles/2331430.html -// Windows 使用的256个虚拟键码 -[Flags]// 打印的时候可以有名称输出,而不是值输出 -public enum VK : int -{ - VK_LBUTTON = 0x1, - VK_RBUTTON = 0x2, - VK_CANCEL = 0x3, - VK_MBUTTON = 0x4, - VK_BACK = 0x8, - VK_TAB = 0x9, - VK_CLEAR = 0xC, - VK_RETURN = 0xD, - VK_SHIFT = 0x10, - VK_CONTROL = 0x11, - VK_MENU = 0x12,// VK_ALT - VK_ALT = 0x12, - VK_PAUSE = 0x13, - VK_CAPITAL = 0x14, - VK_ESCAPE = 0x1B, - VK_SPACE = 0x20, - VK_PRIOR = 0x21, - VK_NEXT = 0x22, - VK_END = 0x23, - VK_HOME = 0x24, - VK_LEFT = 0x25, - VK_UP = 0x26, - VK_RIGHT = 0x27, - VK_DOWN = 0x28, - VK_Select = 0x29, - VK_PRINT = 0x2A, - VK_EXECUTE = 0x2B, - VK_SNAPSHOT = 0x2C, - VK_Insert = 0x2D, - VK_Delete = 0x2E, - VK_HELP = 0x2F, - VK_0 = 0x30, - VK_1 = 0x31, - VK_2 = 0x32, - VK_3 = 0x33, - VK_4 = 0x34, - VK_5 = 0x35, - VK_6 = 0x36, - VK_7 = 0x37, - VK_8 = 0x38, - VK_9 = 0x39, - VK_A = 0x41, - VK_B = 0x42, - VK_C = 0x43, - VK_D = 0x44, - VK_E = 0x45, - VK_F = 0x46, - VK_G = 0x47, - VK_H = 0x48, - VK_I = 0x49, - VK_J = 0x4A, - VK_K = 0x4B, - VK_L = 0x4C, - VK_M = 0x4D, - VK_N = 0x4E, - VK_O = 0x4F, - VK_P = 0x50, - VK_Q = 0x51, - VK_R = 0x52, - VK_S = 0x53, - VK_T = 0x54, - VK_U = 0x55, - VK_V = 0x56, - VK_W = 0x57, - VK_X = 0x58, - VK_Y = 0x59, - VK_Z = 0x5A, - VK_STARTKEY = 0x5B, - VK_CONTEXTKEY = 0x5D, - VK_NUMPAD0 = 0x60, - VK_NUMPAD1 = 0x61, - VK_NUMPAD2 = 0x62, - VK_NUMPAD3 = 0x63, - VK_NUMPAD4 = 0x64, - VK_NUMPAD5 = 0x65, - VK_NUMPAD6 = 0x66, - VK_NUMPAD7 = 0x67, - VK_NUMPAD8 = 0x68, - VK_NUMPAD9 = 0x69, - VK_MULTIPLY = 0x6A, - VK_ADD = 0x6B, - VK_SEPARATOR = 0x6C, - VK_SUBTRACT = 0x6D, - VK_DECIMAL = 0x6E, - VK_DIVIDE = 0x6F, - VK_F1 = 0x70, - VK_F2 = 0x71, - VK_F3 = 0x72, - VK_F4 = 0x73, - VK_F5 = 0x74, - VK_F6 = 0x75, - VK_F7 = 0x76, - VK_F8 = 0x77, - VK_F9 = 0x78, - VK_F10 = 0x79, - VK_F11 = 0x7A, - VK_F12 = 0x7B, - VK_F13 = 0x7C, - VK_F14 = 0x7D, - VK_F15 = 0x7E, - VK_F16 = 0x7F, - VK_F17 = 0x80, - VK_F18 = 0x81, - VK_F19 = 0x82, - VK_F20 = 0x83, - VK_F21 = 0x84, - VK_F22 = 0x85, - VK_F23 = 0x86, - VK_F24 = 0x87, - VK_NUMLOCK = 0x90, - VK_OEM_SCROLL = 0x91, - VK_OEM_1 = 0xBA, - VK_OEM_PLUS = 0xBB, - VK_OEM_COMMA = 0xBC, - VK_OEM_MINUS = 0xBD, - VK_OEM_PERIOD = 0xBE, - VK_OEM_2 = 0xBF, - VK_OEM_3 = 0xC0, - VK_OEM_4 = 0xDB, - VK_OEM_5 = 0xDC, - VK_OEM_6 = 0xDD, - VK_OEM_7 = 0xDE, - VK_OEM_8 = 0xDF, - VK_ICO_F17 = 0xE0, - VK_ICO_F18 = 0xE1, - VK_OEM102 = 0xE2, - VK_ICO_HELP = 0xE3, - VK_ICO_00 = 0xE4, - VK_ICO_CLEAR = 0xE6, - VK_OEM_RESET = 0xE9, - VK_OEM_JUMP = 0xEA, - VK_OEM_PA1 = 0xEB, - VK_OEM_PA2 = 0xEC, - VK_OEM_PA3 = 0xED, - VK_OEM_WSCTRL = 0xEE, - VK_OEM_CUSEL = 0xEF, - VK_OEM_ATTN = 0xF0, - VK_OEM_FINNISH = 0xF1, - VK_OEM_COPY = 0xF2, - VK_OEM_AUTO = 0xF3, - VK_OEM_ENLW = 0xF4, - VK_OEM_BACKTAB = 0xF5, - VK_ATTN = 0xF6, - VK_CRSEL = 0xF7, - VK_EXSEL = 0xF8, - VK_EREOF = 0xF9, - VK_PLAY = 0xFA, - VK_ZOOM = 0xFB, - VK_NONAME = 0xFC, - VK_PA1 = 0xFD, - VK_OEM_CLEAR = 0xFE, -} - -[Flags] -public enum SC : uint -{ - // 窗体关闭消息 - SC_CLOSE = 0xf060, - // 窗体最小化消息 - SC_MINIMIZE = 0xf020, - // 窗体最大化消息 - SC_MAXIMIZE = 0xf030, - // 窗体正常态消息 SC_RESTORE = 0xf120, - SC_NOMAL = 0xf120, -} - -[Flags] -public enum NCmdShow : uint -{ - /// - /// 隐藏窗口并激活其他窗口。nCmdShow - /// - SW_HIDE = 0, - /// - /// 正常态的窗口(非最大化和非最小化) - /// 激活并显示一个窗口。如果窗口被最小化或最大化,系统将其恢复到原来的尺寸和大小。应用程序在第一次显示窗口的时候应该指定此标志 - /// - SW_SHOWNORMAL = 1, - /// - /// 激活窗口并将其最小化 - /// - SW_SHOWMINIMIZED = 2, - /// - /// 激活窗口并将其最大化 - /// - SW_SHOWMAXIMIZED = 3, - /// - /// 最大化指定的窗口 - /// - SW_MAXIMIZE = 3, - /// - /// 以窗口最近一次的大小和状态显示窗口。激活窗口仍然维持激活状态 - /// - SW_SHOWNOACTIVATE = 4, - /// - /// 在窗口原来的位置以原来的尺寸激活和显示窗口 - /// - SW_SHOW = 5, - /// - /// 最小化指定的窗口并且激活在Z序中的下一个顶层窗口 - /// - SW_MINIMIZE = 6, - /// - /// 窗口最小化,激活窗口仍然维持激活状态 - /// - SW_SHOWMINNOACTIVE = 7, - /// - /// 以窗口原来的状态显示窗口。激活窗口仍然维持激活状态 - /// - SW_SHOWNA = 8, - /// - /// 激活并显示窗口。如果窗口最小化或最大化,则系统将窗口恢复到原来的尺寸和位置。在恢复最小化窗口时,应用程序应该指定这个标志 - /// - SW_RESTORE = 9, - /// - /// 依据在STARTUPINFO结构中指定的SW_FLAG标志设定显示状态,STARTUPINFO 结构是由启动应用程序的程序传递给CreateProcess函数的 - /// - SW_SHOWDEFAULT = 10, - /// - /// 在WindowNT5.0中最小化窗口,即使拥有窗口的线程被挂起也会最小化。在从其他线程最小化窗口时才使用这个参数 - /// - SW_FORCEMINIMIZE = 11, -} - -public enum WS : uint -{ - // 窗口风格 - WS_CAPTION = 0xC00000, // 带标题栏的窗口 - WS_MAXIMIZEBOX = 0x10000, // 带最大化按钮的窗口 - WS_MINIMIZEBOX = 0x20000, // 带最小化按钮的窗口 - WS_SYSMENU = 0x80000, // 带系统菜单的窗口 - WS_CLIPSIBLINGS = 0x4000000, // 不重绘层叠子窗口 - WS_CLIPCHILDREN = 0x2000000, // 绘图时排子窗口区域 - WS_OVERLAPPED = 0x0, // 具有标题栏和边框的层叠窗口 - WS_THICKFRAME = 0x40000, // 具有可调边框 - - // 具有标题栏、窗口菜单、可调边框和最大化、最小化按钮的窗口 - WS_OVERLAPPEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX, - - WS_GROUP = 0x20000, // 指定一组控制的第一个控制 - WS_POPUP = 0x80000000, // 弹出式窗口 - WS_BORDER = 0x800000, // 单边框窗口 - WS_POPUPWINDOW = WS_POPUP | WS_BORDER | WS_SYSMENU, // 具有单边框、标题栏菜单的弹出式窗口 - WS_MINIMIZE = 0x20000000, // 窗口最小化 - WS_VISIBLE = 0x10000000, // 窗口可见 - WS_DISABLED = 0x8000000, // 窗口被禁用 - WS_MAXIMIZE = 0x1000000, // 窗口最大化 - WS_DLGFRAME = 0x400000, // 对话框边框风格 - WS_VSCROLL = 0x200000, // 具有垂直滚动条 - WS_HSCROLL = 0x100000, // 具有水平滚动条 - WS_TABSTOP = 0x10000, // 具有TAB键控制 - WS_CHILD = 0x40000000, // 设置窗口属性为child 多文档界面的子窗体 - WS_CHILDWINDOW = WS_CHILD, // 具有子窗口 - - // 扩展风格 - WS_EX_WINDOWEDGE = 0x100, // 窗口具有凸起的3D边框 - WS_EX_CLIENTEDGE = 0x200, // 窗口具有阴影边界 - WS_EX_TOOLWINDOW = 0x80, // 小标题工具窗口 - WS_EX_TOPMOST = 0x8, // 窗口总在顶层 const int WS_EX_TOPMOST = 0x00000008; - WS_EX_OVERLAPPEDWINDOW = WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE, // WS_EX-CLIENTEDGE和WS_EX_WINDOWEDGE的组合 - WS_EX_PALETTEWINDOW = WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST, // WS_EX_WINDOWEDGE和WS_EX_TOOLWINDOW和WS_EX_TOPMOST的组合 - WS_EX_DLGMODALFRAME = 0x1, // 带双边的窗口 - WS_EX_NOPARENTNOTIFY = 0x4, // 窗口在创建和销毁时不向父窗口发送WM_PARENTNOTIFY消息 - WS_EX_TRANSPARENT = 0x20, // 窗口透眀 - WS_EX_MDICHILD = 0x40, // MDI子窗口 - WS_EX_CONTEXTHELP = 0x400, // 标题栏包含问号联机帮助按钮 - WS_EX_RIGHT = 0x1000, // 窗口具有右对齐属性 - WS_EX_RTLREADING = 0x2000, // 窗口文本自右向左显示 - WS_EX_LEFTSCROLLBAR = 0x4000, // 标题栏在客户区的左边 - WS_EX_CONTROLPARENT = 0x10000, // 允许用户使用Tab键在窗口的子窗口间搜索 - WS_EX_STATICEDGE = 0x20000, // 为不接受用户输入的项创建一个三维边界风格 - WS_EX_APPWINDOW = 0x40000, // 在任务栏上显示顶层窗口的标题按钮 - WS_EX_LAYERED = 0x80000, // 窗口具有透眀属性(Win2000)以上 - WS_EX_NOINHERITLAYOUT = 0x100000, // 窗口布局不传递给子窗口(Win2000)以上 - WS_EX_LAYOUTRTL = 0x400000, // 水平起点在右边的窗口 - WS_EX_NOACTIVATE = 0x8000000, // 窗口不会变成前台窗口(Win2000)以上 - WS_EX_LEFT = 0x0, // 窗口具有左对齐属性 - WS_EX_LTRREADING = 0x0, // 窗口文本自左向右显示 - WS_EX_RIGHTSCROLLBAR = 0x0, // 垂直滚动条在窗口的右边界 - WS_EX_ACCEPTFILES = 0x10, // 接受文件拖曳 - WS_EX_COMPOSITED = 0x2000000, // 窗体所有子窗口使用双缓冲从低到高绘制(XP) -} - -public enum GWL : int -{ - /// - /// 获取、设置窗口过程的地址 - /// - GWL_WNDPROC = -4, - /// - /// 获取应用程序的实例句柄 - /// - GWL_HINSTANCE = -6, - /// - /// 获取父窗口句柄 - /// - GWL_HWNDPARENT = -8, - /// - /// 获取窗口标识 - /// - GWL_ID = -12, - /// - /// 获取、设置窗口样式 - /// - GWL_STYLE = -16, - /// - /// 获取、设置窗口扩展样式 - /// - GWL_EXSTYLE = -20, - /// - /// 获取、设置与窗口关联的自定义数据 - /// - GWL_USERDATA = -21, -} - -public enum GetWindowCmd : uint -{ - /// - /// 返回的句柄标识了在Z序最高端的相同类型的窗口。 - /// 如果指定窗口是最高端窗口,则该句柄标识了在Z序最高端的最高端窗口; - /// 如果指定窗口是顶层窗口,则该句柄标识了在z序最高端的顶层窗口: - /// 如果指定窗口是子窗口,则句柄标识了在Z序最高端的同属窗口。 - /// - GW_HWNDFIRST = 0, - /// - /// 返回的句柄标识了在z序最低端的相同类型的窗口。 - /// 如果指定窗口是最高端窗口,则该柄标识了在z序最低端的最高端窗口: - /// 如果指定窗口是顶层窗口,则该句柄标识了在z序最低端的顶层窗口; - /// 如果指定窗口是子窗口,则句柄标识了在Z序最低端的同属窗口。 - /// - GW_HWNDLAST = 1, - /// - /// 返回的句柄标识了在Z序中指定窗口下的相同类型的窗口。 - /// 如果指定窗口是最高端窗口,则该句柄标识了在指定窗口下的最高端窗口: - /// 如果指定窗口是顶层窗口,则该句柄标识了在指定窗口下的顶层窗口; - /// 如果指定窗口是子窗口,则句柄标识了在指定窗口下的同属窗口。 - /// - GW_HWNDNEXT = 2, - /// - /// 返回的句柄标识了在Z序中指定窗口上的相同类型的窗口。 - /// 如果指定窗口是最高端窗口,则该句柄标识了在指定窗口上的最高端窗口; - /// 如果指定窗口是顶层窗口,则该句柄标识了在指定窗口上的顶层窗口; - /// 如果指定窗口是子窗口,则句柄标识了在指定窗口上的同属窗口。 - /// - GW_HWNDPREV = 3, - /// - /// 返回的句柄标识了指定窗口的所有者窗口(如果存在)。 - /// GW_OWNER与GW_CHILD不是相对的参数,没有父窗口的含义,如果想得到父窗口请使用GetParent()。 - /// 例如:例如有时对话框的控件的GW_OWNER,是不存在的。 - /// - GW_OWNER = 4, - /// - /// 如果指定窗口是父窗口,则获得的是在Tab序顶端的子窗口的句柄,否则为NULL。 - /// 函数仅检查指定父窗口的子窗口,不检查继承窗口。 - /// - GW_CHILD = 5, - /// - /// (WindowsNT 5.0)返回的句柄标识了属于指定窗口的处于使能状态弹出式窗口(检索使用第一个由GW_HWNDNEXT 查找到的满足前述条件的窗口); - /// 如果无使能窗口,则获得的句柄与指定窗口相同。 - /// - GW_ENABLEDPOPUP = 6 -} -#endif -#pragma warning restore CS1591 // 缺少对公共可见类型或成员的 XML 注释 diff --git a/src/Basal/IFox.Basal.Shared/WindowsAPI/MouseHook.cs b/src/Basal/IFox.Basal.Shared/WindowsAPI/MouseHook.cs deleted file mode 100644 index 46f1725..0000000 --- a/src/Basal/IFox.Basal.Shared/WindowsAPI/MouseHook.cs +++ /dev/null @@ -1,316 +0,0 @@ -using System.Drawing; -using System.Windows.Forms; -using MouseEventArgs = System.Windows.Forms.MouseEventArgs; -using MouseEventHandler = System.Windows.Forms.MouseEventHandler; -#pragma warning disable CS1591 // 缺少对公共可见类型或成员的 XML 注释 - -namespace IFoxCAD.Basal; - -public class MouseHook -{ - /// - /// 鼠标按下事件 - /// - public event MouseEventHandler? MouseDown; - /// - /// 松开鼠标事件 - /// - public event MouseEventHandler? MouseUp; - /// - /// 鼠标移动事件 - /// - public event MouseEventHandler? MouseMove; - /// - /// 鼠标滚轮事件 - /// - public event MouseEventHandler? MouseWheel; - /// - /// 鼠标单击事件 - /// - public event EventHandler? Click; - /// - /// 鼠标双击事件 - /// - public event EventHandler? DoubleClick; - - - private bool _isHookBreak; - /// - /// 否决本次输入:设置不向下回调 - /// - public void Vote() - { - _isHookBreak = true; - } - - /// 不要试图省略此变量,否则将会导致GC变量池满后释放
- /// 提示:激活 CallbackOnCollectedDelegate 托管调试助手(MDA) - internal static WindowsAPI.CallBack? HookProc; - internal static IntPtr _NextHookProc;//挂载成功的标记 - public readonly Process Process; - - - [DllImport("user32.dll", EntryPoint = "GetDoubleClickTime")] - public extern static int GetDoubleClickTime(); - - private static readonly Stopwatch _watch = new(); - - /// - /// 安装鼠标钩子 - /// - /// 低级钩子超时时间 - public MouseHook(int setLowLevel = 25000) - { - _NextHookProc = IntPtr.Zero; - Process = Process.GetCurrentProcess(); - WindowsAPI.CheckLowLevelHooksTimeout(setLowLevel); - _watch.Start(); - } - - private void UnHook() - { - if (_NextHookProc != IntPtr.Zero) - { - WindowsAPI.UnhookWindowsHookEx(_NextHookProc); - _NextHookProc = IntPtr.Zero; - } - } - - /// - /// 设置钩子 - /// - /// false进程钩子,true全局钩子 - public void SetHook(bool processHook = false) - { - UnHook(); - if (_NextHookProc != IntPtr.Zero) - return; - - if (processHook) - { - HookProc = (nCode, wParam, lParam) => { - if (nCode >= 0 && HookTask(nCode, wParam, lParam)) - return (IntPtr)1; - return WindowsAPI.CallNextHookEx(_NextHookProc, nCode, wParam, lParam); - }; - _NextHookProc = WindowsAPI.SetWindowsHookEx(HookType.WH_MOUSE, HookProc, - IntPtr.Zero, WindowsAPI.GetCurrentThreadId()); - } - else - { - var moduleHandle = WindowsAPI.GetModuleHandle(Process.MainModule.ModuleName); - HookProc = (nCode, wParam, lParam) => { - if (nCode >= 0 && HookTask(nCode, wParam, lParam)) - return (IntPtr)1; - return WindowsAPI.CallNextHookEx(_NextHookProc, nCode, wParam, lParam); - }; - _NextHookProc = WindowsAPI.SetWindowsHookEx(HookType.WH_MOUSE_LL, HookProc, - moduleHandle, 0); - } - } - - - private MouseButtons _button; - private int _clickCount = 0; - private bool _down = false; - private bool _up = false; - private bool _ck = false; - private bool _wheel = false; - private bool _move = false; - - /// - /// 钩子的消息处理 - /// - /// - /// - /// - /// false不终止回调,true终止回调 - private bool HookTask(int nCode, int wParam, IntPtr lParam) - { - if (MouseDown is null - && MouseUp is null - && MouseMove is null - && MouseWheel is null - && Click is null - && DoubleClick is null) - return false; - - _button = MouseButtons.None; - _clickCount = 0; - _down = false; - _up = false; - _ck = false; - _wheel = false; - _move = false; - - switch ((WM)wParam) - { - case WM.WM_LBUTTONDOWN: - _button = MouseButtons.Left; - _clickCount = 1; - _down = true; - _ck = true; - break; - case WM.WM_LBUTTONUP: - _button = MouseButtons.Left; - _clickCount = 1; - _up = true; - break; - case WM.WM_LBUTTONDBLCLK: - _button = MouseButtons.Left; - _clickCount = 2; - _ck = true; - break; - case WM.WM_RBUTTONDOWN: - _button = MouseButtons.Right; - _clickCount = 1; - _down = true; - _ck = true; - break; - case WM.WM_RBUTTONUP: - _button = MouseButtons.Right; - _clickCount = 1; - _up = true; - break; - case WM.WM_RBUTTONDBLCLK: - _button = MouseButtons.Right; - _clickCount = 2; - _ck = true; - break; - case WM.WM_MBUTTONDOWN: - _button = MouseButtons.Middle; - _clickCount = 1; - _ck = true; - break; - case WM.WM_MBUTTONUP: - _button = MouseButtons.Middle; - _clickCount = 1; - _up = true; - break; - case WM.WM_MBUTTONDBLCLK: - _button = MouseButtons.Middle; - _clickCount = 2; - _ck = true; - break; - case WM.WM_MOUSEWHEEL: - _wheel = true; - // 滚轮 - break; - case WM.WM_MOUSEMOVE: - _move = true; - // 移动 - // 假设想要限制鼠标在屏幕中的移动区域能够在此处设置 - // 后期须要考虑实际的x y的容差 - // if (!Screen.PrimaryScreen.Bounds.Contains(e.X, e.Y)) - // // return 1; - // if (button == MouseButtons.Left) - // { - // GetCursorPos(out POINT pt); - // // 防止频繁获取导致出错 - // if (pt0ld.Leng(pt) > 20) - // pt0ld = pt; - // } - break; - } - - // 从回调函数中得到鼠标的信息 - var mouseMsg = MouseHookStruct.Create(lParam); - MouseEventArgs e = new(_button, _clickCount, mouseMsg.Point.X, mouseMsg.Point.Y, 0); - if (_down) - MouseDown?.Invoke(this, e); - if (_up) - MouseUp?.Invoke(this, e); - if (_ck) - Click?.Invoke(this, e); - if (_clickCount == 2) - { - // 如果不用时间控制,那么双击会执行两次 - if (_watch.Elapsed.TotalMilliseconds > GetDoubleClickTime()) - { - DoubleClick?.Invoke(this, e); - _watch.Reset(); - _watch.Start(); - } - } - if (_move) - { - MouseMove?.Invoke(this, e); - } - if (_wheel) - { - MouseWheel?.Invoke(this, e); - } - - // 屏蔽此输入 - if (_isHookBreak) - return true; - - return false; - } - - - /// - /// Hook鼠标数据结构 - /// - [StructLayout(LayoutKind.Sequential)] - public struct MouseHookStruct - { - /// - /// 鼠标在屏幕上的x,y坐标 - /// - public Point Point; - /// - /// 点击窗体的句柄 - /// - public IntPtr hWnd; - /// - /// 消息 - /// - public int wHitTestCode; - /// - /// 扩展信息,可以使用GetMessageExtraInfo的返回值 - /// - public int dwExtraInfo; - - public static MouseHookStruct Create(IntPtr lParam) - { - return (MouseHookStruct)Marshal.PtrToStructure(lParam, typeof(MouseHookStruct)); - } - - public void ToPtr(IntPtr lParam) - { - Marshal.StructureToPtr(this, lParam, true); - } - } - - - #region IDisposable接口相关函数 - public bool IsDisposed { get; private set; } = false; - - /// - /// 手动调用释放 - /// - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - /// - /// 析构函数调用释放 - /// - ~MouseHook() - { - Dispose(false); - } - - protected virtual void Dispose(bool disposing) - { - // 不重复释放,并设置已经释放 - if (IsDisposed) return; - IsDisposed = true; - UnHook(); - } - #endregion -} -#pragma warning restore CS1591 // 缺少对公共可见类型或成员的 XML 注释 \ No newline at end of file diff --git a/src/Basal/IFox.Basal.Shared/WindowsAPI/WindowsAPI.cs b/src/Basal/IFox.Basal.Shared/WindowsAPI/WindowsAPI.cs deleted file mode 100644 index 986a7f9..0000000 --- a/src/Basal/IFox.Basal.Shared/WindowsAPI/WindowsAPI.cs +++ /dev/null @@ -1,660 +0,0 @@ -#pragma warning disable CS1591 // 缺少对公共可见类型或成员的 XML 注释 -#define Marshal - -namespace IFoxCAD.Basal; -public partial class WindowsAPI -{ - #region kernel32 - // https://blog.csdn.net/haelang/article/details/45147121 - [DllImport("kernel32.dll")] - public extern static uint GetLastError(); - - [DllImport("kernel32.dll")] - public static extern long GetHandleInformation(long hObject, ref long lpdwFlags); - - [DllImport("kernel32.dll")] - public static extern IntPtr GetModuleHandle(string ModuleName); - - [DllImport("kernel32.dll")] - public static extern int GetCurrentThreadId(); - - /// - /// 获取要引入的函数,将符号名或标识号转换为DLL内部地址 - /// - /// exe/dll句柄 - /// 接口名 - /// - [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true)] - public static extern IntPtr GetProcAddress(IntPtr hModule, string procName); - - /// - /// 锁定内存 - /// - /// - /// - [DllImport("kernel32.dll", SetLastError = true)] - static extern IntPtr GlobalLock(IntPtr hMem); - /// - /// 解锁内存 - /// - /// - /// - [DllImport("kernel32.dll", SetLastError = true)] - static extern bool GlobalUnlock(IntPtr hMem); -#if !Marshal - /* - const int GMEM_MOVEABLE = 0x0002; - IntPtr newPtr = WindowsAPI.GlobalAlloc(GMEM_MOVEABLE, Marshal.SizeOf(structObj)); - */ - /// - /// 从堆中分配内存 - /// 被代替: Marshal.AllocHGlobal - /// - /// 分配方式 - /// 分配的字节数 - /// - [DllImport("kernel32.dll", SetLastError = true)] - public static extern IntPtr GlobalAlloc(uint uFlags, int dwBytes); - /// - /// 释放堆内存 - /// 被代替: Marshal.FreeHGlobal - /// - /// 产生的句柄 - /// - [DllImport("kernel32.dll", SetLastError = true)] - public static extern IntPtr GlobalFree(IntPtr hMem); -#endif - /// - /// 获取内存块大小 - /// - /// - /// - [DllImport("kernel32.dll", SetLastError = true)] - public static extern uint GlobalSize(IntPtr hMem); - - /// - /// 锁定和释放内存 - /// - /// 锁定数据对象指针 - /// 返回锁定的内存片段指针,锁定期间执行任务 - /// 是否锁定成功 - /// - public static bool GlobalLockTask(IntPtr data, Action task) - { - //if (task == null) - // throw new ArgumentNullException(nameof(task)); - ArgumentNullEx.ThrowIfNull(task); - if (data == IntPtr.Zero) - return false; - - try - { - var ptr = GlobalLock(data); - // 有几率导致无效锁定: - // 重复复制同一个图元时,第二次是 IntPtr.Zero, - // 第三次就又可以复制了 - if (ptr == IntPtr.Zero) - return false; - task.Invoke(ptr); - } - finally { GlobalUnlock(data); } - return true; - } - - /// - /// byte数组转结构体 - /// - /// byte数组 - /// 返回的结构大小 - /// 返回的结构体 - [Obsolete("效率太低", true)] - public static T? BytesToStruct(byte[] bytes, out int typeSize) - { - var structType = typeof(T); - typeSize = Marshal.SizeOf(structType); - if (typeSize > bytes.Length) - return default; - - // 安全写法效率太低了 - // 分配结构体大小的内存空间 - IntPtr structPtr = Marshal.AllocHGlobal(typeSize); - - // 将byte数组拷到分配好的内存空间 - Marshal.Copy(bytes, 0, structPtr, typeSize); - // 将内存空间转换为目标结构体; - // 转类型的时候会拷贝一次,看它们地址验证 &result != &structPtr - var result = (T)Marshal.PtrToStructure(structPtr, structType); - - // 释放内存空间 - Marshal.FreeHGlobal(structPtr); - return result; - } - - /// - /// byte数组转结构体 - /// - /// byte数组 - /// 返回的结构体 - [MethodImpl] - public static T? BytesToStruct(byte[] bytes) - { - T? result = default; - unsafe - { - // 安全指针方法 - // var pB = Marshal.UnsafeAddrOfPinnedArrayElement(bytes, 0); - // 不安全指针方法 - fixed (byte* pB = &bytes[0]) - { - result = (T?)Marshal.PtrToStructure(new IntPtr(pB), typeof(T)); - } - } - return result; - } - - /// - /// 结构体转byte数组 - /// unmanaged - /// - /// 要转换的结构体 - [MethodImpl] - public static byte[] StructToBytes(T structObj) where T : unmanaged/*非托管的T从来不为空*/ - { - // 得到结构体的大小 - var typeSize = Marshal.SizeOf(structObj); - // 从内存空间拷到byte数组 - var bytes = new byte[typeSize]; - unsafe - { - Marshal.Copy(new IntPtr(&structObj), bytes, 0, typeSize); - } -#if true20221030 - // 安全写法效率太低了 - StructToPtr(structObj, structPtr => { - Marshal.Copy(structPtr, bytes, 0, typeSize); - }); -#endif - return bytes; - } - -#if true20221030 - /// - /// 结构体转指针 - /// - /// 要转换的结构体 - /// 输出指针 - /// 释放申请的内存 - /// 是否锁定内存 - /// - public static void StructToPtr(T structObj, - Action? task = null, - bool freeHGlobal = true, - bool lockPrt = true) - { - IntPtr newPtr = Marshal.AllocHGlobal(Marshal.SizeOf(structObj)); - if (newPtr == IntPtr.Zero) - throw new ArgumentException(nameof(newPtr)); - - try - { - // 剪贴板写入的时候不允许锁定内存,否则在频繁触发剪贴板将导致卡死程序 - if (lockPrt) - { - GlobalLockTask(newPtr, ptr => { - // 将结构体拷到分配好的内存空间 - Marshal.StructureToPtr(structObj, newPtr, true); - task?.Invoke(newPtr); - }); - } - else - { - // 将结构体拷到分配好的内存空间 - Marshal.StructureToPtr(structObj, newPtr, true); - task?.Invoke(newPtr); - } - } - catch (Exception e) - { - Debugger.Break(); - Debugx.Printl(e.Message); - } - finally - { - if (freeHGlobal && newPtr != IntPtr.Zero) - Marshal.FreeHGlobal(newPtr); - } - } -#endif - #endregion -} - -public partial class WindowsAPI -{ - #region imm32 - /// - /// 获取输入法的虚拟键码 - /// - /// - /// - [DllImport("imm32.dll")] - public static extern IntPtr ImmGetVirtualKey(IntPtr hWnd); - /// - /// 获取输入法状态 - /// - /// 输入法标识符 - /// 输入模式 - /// 指向函数在其中检索句子模式值的变量的指针 - /// - [DllImport("imm32.dll")] - public static extern bool ImmGetConversionStatus(IntPtr himc, out int lpdw, out int lpdw2); - - /// - /// 获取指定窗口的输入法状态 - /// - /// 窗口句柄 - /// - [DllImport("imm32.dll")] - public static extern IntPtr ImmGetContext(IntPtr hwnd); - /// - /// 设置输入法的当前状态 - /// - /// 窗口句柄 - /// - /// - [DllImport("imm32.dll")] - public static extern bool ImmSetOpenStatus(IntPtr hwnd, bool fOpen); - /// - /// 输入法打开状态 - /// - /// - /// 非0打开,0关闭;(true中文,false英文) - [DllImport("imm32.dll")] - public static extern bool ImmGetOpenStatus(IntPtr hwnd); - #endregion -} - -public partial class WindowsAPI -{ - #region user32 - - /// - /// 获取窗口客户区的大小,客户区为窗口中除标题栏,菜单栏之外的地方 - /// - /// - /// - /// - [DllImport("user32.dll", CharSet = CharSet.Auto, EntryPoint = "GetClientRect")] - public static extern bool GetClientRect(IntPtr hwnd, out IntRect lpRect); - - /// - /// 查找主线程
- /// 代替
- /// 托管线程和他们不一样: - ///
- /// 主窗口 - /// 进程ID - /// 线程ID - [DllImport("user32.dll", SetLastError = true)] - public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId); - - /// - /// 设置焦点 - /// - /// - /// - [DllImport("user32.dll")] - public static extern IntPtr SetFocus(IntPtr hWnd); - - /// - /// 获取当前窗口 - /// - /// 当前窗口标识符 - [DllImport("user32.dll")] - public static extern IntPtr GetForegroundWindow(); - /// - /// 将一个消息的组成部分合成一个消息并放入对应线程消息队列的方法 - /// - /// 控件句柄 - /// 消息是什么。键盘按键、鼠标点击还是其他 - /// - /// - /// - [DllImport("user32.dll")] - public static extern bool PostMessage(IntPtr hhwnd, int msg, IntPtr wparam, IntPtr lparam); - /// - /// 发送击键 - /// - /// - /// - /// - /// - [DllImport("user32.dll", EntryPoint = "keybd_event")] - public static extern void KeybdEvent(byte bVk, byte bScan, int dwFlags, int dwExtraInfo); - /// - /// 获取窗口文字的长度 - /// - /// 窗口标识符 - /// 文字长度 - [DllImport("user32.dll")] - public static extern int GetWindowTextLength(IntPtr hWnd); - /// - /// 获取窗口的标题 - /// - /// 窗口标识符 - /// 窗口文字 - /// 文字长度 - /// - [DllImport("User32.dll", CharSet = CharSet.Auto)] - public static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int nMaxCount); - - // [DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)] - // internal static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount); - - - /// - /// 获取某个线程的输入法布局 - /// - /// 线程ID - /// 布局码 - [DllImport("user32.dll")] - public static extern int GetKeyboardLayout(int threadid); - - - /// - /// 获取按键的当前状态 - /// - /// 按键虚拟代码 - /// 表示没按下>0;按下<0 - [DllImport("user32.dll")] - public static extern short GetKeyState(int nVirtKey); - /// - /// 检索指定窗口所属的类的名称。 - /// - /// 窗口标识符 - /// - /// - /// - [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] - public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount); - - [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] - public static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd); - - [DllImport("user32.DLL", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall, SetLastError = true)] - public static extern IntPtr GetTopWindow(IntPtr hWnd); - - - /// - /// 获取线程对应的窗体信息 - /// - /// 线程 - /// - /// - [DllImport("user32.dll")] - [return: MarshalAs(UnmanagedType.Bool)] - static extern bool GetGUIThreadInfo(uint idThread, ref GuiThreadInfo lpgui); - - /// - /// 获取线程对应的窗体信息 - /// - [StructLayout(LayoutKind.Sequential)] - public struct GuiThreadInfo - { - public int cbSize; - public int flags; - public IntPtr hwndActive; - public IntPtr hwndFocus; - public IntPtr hwndCapture; - public IntPtr hwndMenuOwner; - public IntPtr hwndMoveSize; - public IntPtr hwndCaret; - public System.Drawing.Rectangle rcCaret; - - public static GuiThreadInfo Create(uint windowThreadProcessId) - { - if (windowThreadProcessId == 0) - throw new ArgumentNullException(nameof(windowThreadProcessId)); - - GuiThreadInfo gti = new(); - gti.cbSize = Marshal.SizeOf(gti); - GetGUIThreadInfo(windowThreadProcessId, ref gti); - return gti; - } - } - - [DllImport("user32.dll", SetLastError = true)] - public static extern IntPtr GetFocus(); - - [DllImport("user32.dll")] - public static extern IntPtr SendMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam); - - [DllImport("user32.dll", SetLastError = true)] - public static extern IntPtr GetParent(IntPtr hWnd); - - [DllImport("user32.dll")] - public static extern int ToAscii(int uVirtKey, int uScancode, byte[] lpdKeyState, byte[] lpwTransKey, int fuState); - - [DllImport("user32.dll", SetLastError = true)] - public static extern IntPtr GetActiveWindow(); - - [DllImport("user32.dll", SetLastError = true)] - public static extern long GetWindowThreadProcessId(IntPtr hwnd, ref int lpdwProcessId); - - [DllImport("user32.dll", SetLastError = true)] - public static extern bool IsIconic(int hWnd); - - [DllImport("user32.dll")] - public static extern bool IsWindowEnabled(IntPtr hWnd); - #endregion - - #region 键盘钩子 - public delegate IntPtr CallBack(int nCode, int wParam, IntPtr lParam); - [DllImport("user32.dll")] - public static extern IntPtr SetWindowsHookEx(HookType idHook, CallBack lpfn, IntPtr hmod, int dwThreadId); - [DllImport("user32.dll")] - public static extern IntPtr UnhookWindowsHookEx(IntPtr hHook); - [DllImport("user32.dll")] - public static extern IntPtr CallNextHookEx(IntPtr hHook, int ncode, int wParam, IntPtr lParam); - /// - /// Hook键盘数据结构 - /// - [ComVisible(true)] - [Serializable] - //[DebuggerDisplay("{DebuggerDisplay,nq}")] - //[DebuggerTypeProxy(typeof(KeyboardHookStruct))] - [StructLayout(LayoutKind.Sequential)] - public struct KeyboardHookStruct - { - public int VkCode; // 键码,该代码必须有一个价值的范围1至254 - public int ScanCode; // 指定的硬件扫描码的关键 - public int Flags; // 键标志 - public int Time; // 指定的时间戳记的这个讯息 - public int DwExtraInfo; // 指定额外信息相关的信息 - - public static KeyboardHookStruct Create(IntPtr lParam) - { - return (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct)); - } - public void ToPtr(IntPtr lParam) - { - Marshal.StructureToPtr(this, lParam, true); - } - } - /// - /// 注册表增加低级钩子超时处理,防止系统不允许, - /// 否则:偶发性出现 键盘钩子不能用了,而且退出时产生 1404 错误 - /// https://www.cnblogs.com/songr/p/5131655.html - /// - public static void CheckLowLevelHooksTimeout(int setLowLevel = 25000) - { - const string llh = "LowLevelHooksTimeout"; - using var registryKey = Registry.CurrentUser.OpenSubKey("Control Panel\\Desktop", true); - if ((int)registryKey.GetValue(llh, 0) < setLowLevel) - registryKey.SetValue(llh, setLowLevel, RegistryValueKind.DWord); - } - #endregion -} - -public partial class WindowsAPI -{ - [DllImport("user32.dll")] - public static extern bool GetWindowRect(IntPtr hwnd, ref IntRect lpRect); - - [ComVisible(true)] - [Serializable] - [StructLayout(LayoutKind.Sequential)] - [DebuggerDisplay("{DebuggerDisplay,nq}")] - [DebuggerTypeProxy(typeof(IntRect))] - public struct IntRect - { - [DebuggerBrowsable(DebuggerBrowsableState.Never)] - private string DebuggerDisplay => $"(Left:{_Left},Top:{_Top},Right:{_Right},Bottom:{_Bottom})"; - - int _Left; - int _Top; - int _Right; - int _Bottom; - public int Left => _Left; - public int Top => _Top; - public int Right => _Right; - public int Bottom => _Bottom; - public int Width => checked(Right - Left); - public int Height => checked(Bottom - Top); - - public IntRect(int left, int top, int right, int bottom) - { - _Left = left; - _Top = top; - _Right = right; - _Bottom = bottom; - } - - static readonly IntRect _Zero = new(0, 0, 0, 0); - public static IntRect Zero => _Zero; - - public override string ToString() => $"({_Left},{_Top},{_Right},{_Bottom})"; - - #region 重载运算符_比较 - public bool Equals(IntRect other) - { - return - _Left == other._Left && - _Top == other._Top && - _Right == other._Right && - _Bottom == other._Bottom; - } - public static bool operator !=(IntRect a, IntRect b) - { - return !(a == b); - } - public static bool operator ==(IntRect a, IntRect b) - { - return a.Equals(b); - } - public override bool Equals(object obj) - { - return obj is IntRect d && Equals(d); - } - public override int GetHashCode() - { - return ((_Left, _Top).GetHashCode(), _Right).GetHashCode() ^ _Bottom.GetHashCode(); - } - - public IntRect Clone() - { - return (IntRect)MemberwiseClone(); - } - #endregion - } - - [ComVisible(true)] - [Serializable] - [DebuggerDisplay("{DebuggerDisplay,nq}")] - [DebuggerTypeProxy(typeof(IntSize))] - [StructLayout(LayoutKind.Sequential)] - public struct IntSize - { - [DebuggerBrowsable(DebuggerBrowsableState.Never)] - private string DebuggerDisplay => $"(Hight:{Hight},Width:{Width})"; - public int Hight; - public int Width; - - public IntSize(int cx, int cy) - { - Hight = cx; - Width = cy; - } - public override string ToString() => $"({Hight},{Width})"; - } - - [ComVisible(true)] - [Serializable] - [DebuggerDisplay("{DebuggerDisplay,nq}")] - [DebuggerTypeProxy(typeof(Point3D))] - [StructLayout(LayoutKind.Sequential)] - public struct Point3D : IEquatable - { - [DebuggerBrowsable(DebuggerBrowsableState.Never)] - private string DebuggerDisplay => $"(X:{X},Y:{Y},Z:{Z})"; - - /* 由于此类是用来优化,从而实现字段修改,因此直接暴露字段减少栈帧 */ - public double X; - public double Y; - public double Z; - - public Point3D(double x, double y, double z) - { - X = x; - Y = y; - Z = z; - } - //public static implicit operator Point3D(Point3d pt) - //{ - // return new Point3D(pt.X, pt.Y, pt.Z); - //} - //public static implicit operator Point3d(Point3D pt) - //{ - // return new Point3d(pt.X, pt.Y, pt.Z); - //} - public override string ToString() => $"({X},{Y},{Z})"; - - public static Point3D Create(IntPtr lParam) - { - return (Point3D)Marshal.PtrToStructure(lParam, typeof(Point3D)); - } - - public void ToPtr(IntPtr lParam) - { - Marshal.StructureToPtr(this, lParam, true); - } - - - #region 重载运算符_比较 - public bool Equals(Point3D other) - { - return - X == other.X && - Y == other.Y && - Z == other.Z; - } - public static bool operator !=(Point3D a, Point3D b) - { - return !(a == b); - } - public static bool operator ==(Point3D a, Point3D b) - { - return a.Equals(b); - } - public override bool Equals(object obj) - { - return obj is Point3D d && Equals(d); - } - public override int GetHashCode() - { - return (X, Y).GetHashCode() ^ Z.GetHashCode(); - } - #endregion - } -} - -#pragma warning restore CS1591 // 缺少对公共可见类型或成员的 XML 注释 \ No newline at end of file diff --git a/src/Basal/IFox.Basal.Source/IFox.Basal.Source.csproj b/src/Basal/IFox.Basal.Source/IFox.Basal.Source.csproj deleted file mode 100644 index 4a5496d..0000000 --- a/src/Basal/IFox.Basal.Source/IFox.Basal.Source.csproj +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - netstandard1.0 - true - $(AssemblyName) - $(Version) - true - - - - CS8021 - true - false - contentFiles - true - false - false - true - - - - - true - $(ContentTargetFolders)\cs\any\$(PackageId)\ - false - - - true - - - - true - $(ContentTargetFolders)\any\any\$(PackageId)\ - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Basal/IFox.Basal/GlobalUsings.cs b/src/Basal/IFox.Basal/GlobalUsings.cs deleted file mode 100644 index adaece7..0000000 --- a/src/Basal/IFox.Basal/GlobalUsings.cs +++ /dev/null @@ -1,16 +0,0 @@ -// 系统引用 -global using System; -global using System.Collections; -global using System.Collections.Generic; -global using System.Linq; -global using System.Text; -global using System.ComponentModel; -global using System.Runtime.InteropServices; -global using System.Diagnostics; -global using Microsoft.Win32; -global using System.Runtime.CompilerServices; -global using System.Threading; -global using System.Linq.Expressions; -global using System.Collections.ObjectModel; -global using Microsoft.CSharp.RuntimeBinder; -global using System.Diagnostics.CodeAnalysis; diff --git a/src/Basal/IFox.Basal/IFox.Basal.csproj b/src/Basal/IFox.Basal/IFox.Basal.csproj deleted file mode 100644 index 062524c..0000000 --- a/src/Basal/IFox.Basal/IFox.Basal.csproj +++ /dev/null @@ -1,22 +0,0 @@ - - - - NET48 - true - true - MSB3270 - false - - - - - - - 4.7.0 - - - - - - - diff --git a/src/CAD/Directory.Build.props b/src/CAD/Directory.Build.props deleted file mode 100644 index aff56da..0000000 --- a/src/CAD/Directory.Build.props +++ /dev/null @@ -1,34 +0,0 @@ - - - - 0.7.2 - 发布0.7.2 - - - - preview - enable - true - ..\..\..\bin\$(Configuration)\ - true - true - True - True - - - - - InspireFunction - xsfhlzh;vicwjb;liuqihong;DYH - InspireFunction - 基于.NET的二次开发基本类库. - MIT - true - https://gitee.com/inspirefunction/ifoxcad - https://gitee.com/inspirefunction/ifoxcad.git - git - IFox;CAD;AutoCad;C#;NET;GStarCAD;ZWCAD - - - - \ No newline at end of file diff --git a/src/CAD/IFox.CAD.ACAD/GlobalUsings.cs b/src/CAD/IFox.CAD.ACAD/GlobalUsings.cs deleted file mode 100644 index 09348ab..0000000 --- a/src/CAD/IFox.CAD.ACAD/GlobalUsings.cs +++ /dev/null @@ -1,41 +0,0 @@ -// 系统引用 -global using System; -global using System.Collections; -global using System.Collections.Generic; -global using System.IO; -global using System.Linq; -global using System.Text; -global using System.Reflection; -global using System.Text.RegularExpressions; -global using Microsoft.Win32; -global using System.ComponentModel; -global using System.Runtime.InteropServices; - -global using Exception = System.Exception; - -global using Registry = Microsoft.Win32.Registry; -global using RegistryKey = Microsoft.Win32.RegistryKey; - -// cad 引用 -global using Autodesk.AutoCAD.ApplicationServices; -global using Autodesk.AutoCAD.EditorInput; -global using Autodesk.AutoCAD.Colors; -global using Autodesk.AutoCAD.DatabaseServices; -global using Autodesk.AutoCAD.Geometry; -global using Autodesk.AutoCAD.Runtime; -global using Acap = Autodesk.AutoCAD.ApplicationServices.Application; -global using Acaop = Autodesk.AutoCAD.ApplicationServices.Core.Application; -global using AcException = Autodesk.AutoCAD.Runtime.Exception; - -global using Autodesk.AutoCAD.DatabaseServices.Filters; - -// jig命名空间会引起Viewport/Polyline等等重义,最好逐个引入 using Autodesk.AutoCAD.GraphicsInterface -global using Autodesk.AutoCAD.GraphicsInterface; -global using WorldDraw = Autodesk.AutoCAD.GraphicsInterface.WorldDraw; -global using Manager = Autodesk.AutoCAD.GraphicsSystem.Manager; -global using Group = Autodesk.AutoCAD.DatabaseServices.Group; -global using Viewport = Autodesk.AutoCAD.DatabaseServices.Viewport; -global using Polyline = Autodesk.AutoCAD.DatabaseServices.Polyline; - -// ifoxcad.basal 引用 -global using IFoxCAD.Basal; diff --git a/src/CAD/IFox.CAD.ACAD/IFox.CAD.ACAD.csproj b/src/CAD/IFox.CAD.ACAD/IFox.CAD.ACAD.csproj deleted file mode 100644 index 46b3b52..0000000 --- a/src/CAD/IFox.CAD.ACAD/IFox.CAD.ACAD.csproj +++ /dev/null @@ -1,41 +0,0 @@ - - - - NET48 - true - true - MSB3270 - false - - - - DEBUG - - - $(Configuration);acad - - - - - - - - - True - - - - - - - - - - - - - - - - - diff --git a/src/CAD/IFox.CAD.GCAD/GlobalUsings.cs b/src/CAD/IFox.CAD.GCAD/GlobalUsings.cs deleted file mode 100644 index a0398c2..0000000 --- a/src/CAD/IFox.CAD.GCAD/GlobalUsings.cs +++ /dev/null @@ -1,41 +0,0 @@ -// 系统引用 -global using System; -global using System.Collections; -global using System.Collections.Generic; -global using System.IO; -global using System.Linq; -global using System.Text; -global using System.Reflection; -global using System.Text.RegularExpressions; -global using Microsoft.Win32; -global using System.ComponentModel; -global using System.Runtime.InteropServices; - -global using Exception = System.Exception; -global using Registry = Microsoft.Win32.Registry; -global using RegistryKey = Microsoft.Win32.RegistryKey; - -// cad 引用 -global using Gssoft.Gscad.ApplicationServices; -global using Gssoft.Gscad.EditorInput; -global using Gssoft.Gscad.Colors; -global using Gssoft.Gscad.DatabaseServices; -global using Gssoft.Gscad.Geometry; -global using Gssoft.Gscad.Runtime; -global using Acap = Gssoft.Gscad.ApplicationServices.Application; -global using Acaop = Gssoft.Gscad.ApplicationServices.Core.Application; -global using AcException = Gssoft.Gscad.Runtime.Exception; -global using Gssoft.Gscad.DatabaseServices.Filters; - -// jig命名空间会引起Viewport/Polyline等等重义,最好逐个引入 using Autodesk.AutoCAD.GraphicsInterface -global using Gssoft.Gscad.GraphicsInterface; -global using WorldDraw = Gssoft.Gscad.GraphicsInterface.WorldDraw; -global using Manager = Gssoft.Gscad.GraphicsSystem.Manager; -global using Group = Gssoft.Gscad.DatabaseServices.Group; -global using Viewport = Gssoft.Gscad.DatabaseServices.Viewport; -global using Polyline = Gssoft.Gscad.DatabaseServices.Polyline; - -// ifoxcad.basal 引用 -global using IFoxCAD.Basal; - - diff --git a/src/CAD/IFox.CAD.GCAD/IFox.CAD.GCAD.csproj b/src/CAD/IFox.CAD.GCAD/IFox.CAD.GCAD.csproj deleted file mode 100644 index b73c017..0000000 --- a/src/CAD/IFox.CAD.GCAD/IFox.CAD.GCAD.csproj +++ /dev/null @@ -1,42 +0,0 @@ - - - - NET48 - - true - true - false - MSB3270 - - - - DEBUG - - - $(Configuration);gcad - - - - - True - - - - - - runtime - - - - - - - - - - - - - - - diff --git a/src/CAD/IFox.CAD.Shared/Algorithms/Graph/Graph.cs b/src/CAD/IFox.CAD.Shared/Algorithms/Graph/Graph.cs deleted file mode 100644 index 7b0097a..0000000 --- a/src/CAD/IFox.CAD.Shared/Algorithms/Graph/Graph.cs +++ /dev/null @@ -1,692 +0,0 @@ -namespace IFoxCAD.Cad; - -/// -/// 无权无向图实现 -/// IEnumerable 枚举所有顶点; -/// -public sealed class Graph : IGraph, IEnumerable -{ - #region 字段及属性 - /// - /// 存储所有节点的字典,key为顶点的类型,value为邻接表,类型是hashset,不可重复添加点 - /// - /// - private readonly Dictionary> _vertices = []; - /// - /// 邻接边表,key为顶点的类型,value为邻接边表,类型是hashset,不可重复添加边 - /// - private readonly Dictionary> _edges = []; - /// - /// 为加快索引,引入hash检索 - /// - private readonly Dictionary _vertexStr = []; - /// - /// 节点数量 - /// - public int VerticesCount => _vertices.Count; - - /// - /// Returns a reference vertex. - /// Time complexity: O(1). - /// - private IGraphVertex? ReferenceVertex - { - get - { - using var enumerator = _vertexStr.GetEnumerator(); - return enumerator.MoveNext() ? enumerator.Current.Value : null; - } - } - IGraphVertex? IGraph.ReferenceVertex => ReferenceVertex; - /// - /// 目前点增加点的顺序号,这个点号不随删点而减少的 - /// - private int _insertCount; - #endregion - - #region 构造函数 - /// - /// - /// - public Graph() - { - _insertCount = 0; // 每次新建对象就将顶点顺序号归零 - } - #endregion - - #region 顶点及边_增 - /// - /// 向该图添加一个新顶点,但是无边; - /// - /// 点 - /// 创建的顶点 - public IGraphVertex AddVertex(Point3d pt) - { - var str = pt.GetHashString(); - if (_vertexStr.TryGetValue(str, out var addVertex)) - return addVertex; - - var vertex = new GraphVertex(pt, _insertCount++); - _vertices.Add(vertex, []); - _edges.Add(vertex, []); - - _vertexStr[str] = vertex; - - return vertex; - } - - /// - /// 向该图添加一个边; - /// - /// - public void AddEdge(Curve3d curve) - { - //if (curve == null) - // throw new ArgumentNullException(nameof(curve)); - - ArgumentNullEx.ThrowIfNull(curve); - var start = AddVertex(curve.StartPoint); - var end = AddVertex(curve.EndPoint); - - // 添加起点的邻接表和邻接边 - _vertices[start].Add(end); - _edges[start].Add(new GraphEdge(end, curve)); - - // 为了保证点顺序,每个点的邻接边必须按起点-终点,所以添加曲线终点时,将添加一个方向的曲线 - var curTmp = (Curve3d)curve.Clone(); - curTmp = curTmp.GetReverseParameterCurve(); - - // 添加终点的邻接表和邻接边 - _vertices[end].Add(start); - _edges[end].Add(new GraphEdge(start, curTmp)); - } - #endregion - - #region 顶点及边_删 - /// - /// 从此图中删除现有顶点; - /// - /// 点 - public void RemoveVertex(Point3d pt) - { - var str = pt.GetHashString(); - if (_vertexStr.ContainsKey(str)) - { - var vertex = _vertexStr[str]; - - // 删除邻接表里的vertex点,先删除后面的遍历可以少一轮 - _vertices.Remove(vertex!); - - // 删除其他顶点的邻接表里的vertex点 - foreach (var item in _vertices.Values) - item.Remove(vertex!); - - // 删除邻接边表里的vertex点,先删除后面的遍历可以少一轮 - _edges.Remove(vertex!); - - // 删除其他顶点的邻接边表的指向vertex的边 - foreach (var item in _edges.Values) - { - item.RemoveWhere(x => vertex.Equals(x.TargetVertex)); - // foreach (var edge in item) - // { - // if (vertex.Equals(edge.TargetVertex)) - // item.Remove(edge); - // } - } - _vertexStr.Remove(str); - } - } - - /// - /// 从此图中删除一条边; - /// - /// 曲线 - public void RemoveEdge(Curve3d curve) - { - //if (curve == null) - // throw new ArgumentNullException(nameof(curve)); - ArgumentNullEx.ThrowIfNull(curve); - - RemoveVertex(curve.StartPoint); - RemoveVertex(curve.EndPoint); - } - #endregion - - #region 顶点和边_查 - /// - /// 我们在给定的来源和目的地之间是否有边? - /// - /// 起点 - /// 终点 - /// 有边返回 ,反之返回 - public bool HasEdge(IGraphVertex source, IGraphVertex dest) - { - if (!_vertices.ContainsKey(source) || !_vertices.ContainsKey(dest)) - throw new ArgumentException("源或目标不在此图中;"); - - return _edges[source].Any(item => Equals(item.TargetVertex, dest)); - } - - /// - /// 获取边 - /// - /// 起点 - /// 终点 - /// - /// 传入的点不在图中时抛出参数异常 - public IEdge? GetEdge(IGraphVertex source, IGraphVertex dest) - { - if (!_vertices.ContainsKey(source) || !_vertices.ContainsKey(dest)) - throw new ArgumentException("源或目标不在此图中;"); - - return _edges[source].FirstOrDefault(item => item.TargetVertex.Equals(dest)); - } - - /// - /// 是否存在顶点,此函数目前未发现有啥用 - /// - /// 顶点 - /// 存在顶点返回 ,反之返回 - public bool ContainsVertex(IGraphVertex value) - { - return _vertices.ContainsKey(value); - } - #endregion - - #region 获取邻接表和曲线 - /// - /// 获取顶点的邻接表 - /// - /// 顶点 - /// 邻接表 - public HashSet GetAdjacencyList(IGraphVertex vertex) - { - return _vertices[vertex]; - } - - /// - /// 获取顶点的邻接边表 - /// - /// 顶点 - /// 邻接边表 - public HashSet GetAdjacencyEdge(IGraphVertex vertex) - { - return _edges[vertex]; - } - - /// - /// 根据顶点表获取曲线集合 - /// - /// 顶点表 - /// 曲线表 - public List GetCurves(List graphVertices) - { - List curves = []; - for (int i = 0; i < graphVertices.Count - 1; i++) - { - var cur = graphVertices[i]; - var next = graphVertices[i + 1]; - var edge = GetEdge(cur, next); - if (edge is not null) - curves.Add(edge.TargetEdge); - } - var lastEdge = GetEdge(graphVertices[^1], graphVertices[0]); - if (lastEdge is not null) - curves.Add(lastEdge.TargetEdge); - - return curves; - } - #endregion - - #region 克隆及接口实现 - /// - /// 克隆此图;目测是深克隆 - /// - [System.Diagnostics.DebuggerStepThrough] - public Graph Clone() - { - var newGraph = new Graph(); - - foreach (var item in _edges.Values.SelectMany(vertex => vertex)) - newGraph.AddEdge(item.TargetEdge); - - return newGraph; - } - - IGraph IGraph.Clone() - { - return Clone(); - } - - /// - /// 节点迭代器 - /// - /// - [System.Diagnostics.DebuggerStepThrough] - public IEnumerator GetEnumerator() - { - return VerticesEnumberable.GetEnumerator(); - } - - [System.Diagnostics.DebuggerStepThrough] - IEnumerator IEnumerable.GetEnumerator() - { - return (IEnumerator)GetEnumerator(); - } - /// - /// 节点迭代器 - /// - public IEnumerable VerticesEnumberable => - _vertices.Select(x => x.Key); - #endregion - - #region 方法 - /// - /// 输出点的邻接表的可读字符串 - /// - /// - public string ToReadable() - { - var i = 1; - var output = string.Empty; - foreach (var node in _vertices) - { - var adjacents = string.Empty; - - output = string.Format("{1}\r\n{0}-{2}: [", i, output, node.Key.Data.ToString()); - - adjacents = node.Value.Aggregate(adjacents, - (current, adjacentNode) => $"{current}{adjacentNode.Data},"); - - if (adjacents.Length > 0) - adjacents = adjacents.TrimEnd([',', ' ']); - - output = $"{output}{adjacents}]"; - i++; - } - return output; - } - #endregion -} - - -/// -/// 邻接表图实现的顶点; -/// IEnumerable 枚举所有邻接点; -/// -/// -/// 邻接表图实现的顶点 -/// -/// 点 -/// 所在节点索引 -public sealed class GraphVertex(Point3d value, int index) : IGraphVertex, IEquatable, IComparable -{ - #region 属性 - /// - /// 数据 - /// - public Point3d Data => value; - /// - /// 索引 - /// - public int Index => index; - - #endregion - - #region 重载运算符_比较 - /// - /// 是否相等 - /// - /// - /// - public bool Equals(IGraphVertex other) - { - return Index == other.Index; - } - /// - /// 是否相等 - /// - /// - /// - public override bool Equals(object? obj) - { - if (obj is null) - return false; - return obj is IGraphVertex vertex && Equals(vertex); - } - /// - /// 计算hashcode - /// - /// - public override int GetHashCode() - { - return Index; - } - /// - /// 比较大小 - /// - /// - /// - public int CompareTo(IGraphVertex other) - { - if (Equals(other)) - return 0; - - if (Index < other.Index) - return -1; - else - return 1; - } - - int IComparable.CompareTo(IGraphVertex other) - { - return CompareTo(other); - } - /// - /// 比较大小 - /// - /// - /// - /// - public int CompareTo(object? obj) - { - if (obj is null) - return 1; - - try - { - var other = (GraphVertex)obj; - return CompareTo(other); - } - catch (Exception) - { - throw new ArgumentException("Object is not a IGraphVertex"); - } - } - /// - /// 相等 - /// - /// - /// - /// - public static bool operator ==(GraphVertex person1, GraphVertex? person2) - { - return person2 is null ? Equals(person1, person2) : person1.Equals(person2); - } - /// - /// 不相等 - /// - /// - /// - /// - public static bool operator !=(GraphVertex person1, GraphVertex? person2) - { - if (person2 is null) - return !Equals(person1, person2); - - return !person1.Equals(person2); - } - #endregion -} - - -/// -/// 无向图中边的定义 -/// -/// -/// 无向图中边的定义 -/// -/// 下一点 -/// 下一点之间的曲线 -public sealed class GraphEdge(IGraphVertex target, Curve3d edge) : IEdge, IEquatable -{ - #region 属性 - /// - /// 顶点 - /// - public IGraphVertex TargetVertex { get; } = target; - /// - /// 边 - /// - public Curve3d TargetEdge { get; } = edge; - - #endregion - - #region 重载运算符_比较 - /// - /// 是否相等 - /// - /// - /// - public bool Equals(GraphEdge other) - { - return Equals(TargetVertex, other.TargetVertex) && - TargetEdge == other.TargetEdge; - } - /// - /// 是否相等 - /// - /// - /// - public override bool Equals(object? obj) - { - if (obj is null) - return false; - return obj is GraphEdge personObj && Equals(personObj); - } - /// - /// 获取hashcode - /// - /// - public override int GetHashCode() - { - return (TargetVertex.GetHashCode(), TargetEdge.GetHashCode()).GetHashCode(); - } - /// - /// 相等 - /// - /// - /// - /// - public static bool operator ==(GraphEdge person1, GraphEdge? person2) - { - return person2 is null ? Equals(person1, person2) : person1.Equals(person2); - } - /// - /// 不相等 - /// - /// - /// - /// - public static bool operator !=(GraphEdge person1, GraphEdge? person2) - { - if (person2 is null) - return !Equals(person1, person2); - - return !person1.Equals(person2); - } - #endregion -} - - -/// -/// 深度优先搜索; -/// -public sealed class DepthFirst -{ - #region 公共方法 - /// - /// 存储所有的边 - /// -#if true - public List> Curve3ds { get; } = new(); -#else - public List> Curve3ds { get; } = new(); -#endif - private HashSet Curved { get; } = new(); - - - /// - /// 找出所有的路径 - /// - /// 图 - public void FindAll(IGraph graph) - { - var total = new HashSet(); - // var graphtmp = graph.Clone(); - foreach (var item in graph.VerticesEnumberable) - { - Dfs(graph, [item], total); - total.Add(item); - } - } - #endregion - - #region 内部方法 - /// - /// 递归 DFS; - /// - /// 图 - /// 已经遍历的路径 - /// -#if true - private void Dfs(IGraph graph, LinkedHashSet visited, HashSet totalVisited) - { - var adjlist = graph.GetAdjacencyList(/*startNode*/ visited.First!.Value); // O(1) - foreach (var nextNode in adjlist) // O(n) - { - if (totalVisited.Contains(nextNode)) - { - continue; - } - // 如果下一个点未遍历过 - if (!visited.Contains(nextNode)) // O(1) - { - // 将下一点加入路径集合,并进行下一次递归 - var sub = new LinkedHashSet { nextNode }; - sub.AddRange(visited); // O(n) - Dfs(graph, sub, totalVisited); - } - // 如果下一点遍历过,并且路径大于2,说明已经找到起点 - else if (visited.Count > 2 && nextNode.Equals(visited.Last!.Value)) - { - // 将重复的路径进行过滤,并把新的路径存入结果 - var curstr = GetHashString(visited); // O(n) - if (IsNew(curstr)) // O(1) - { - Curve3ds.Add(visited); - Curved.Add(curstr.Item1); - } - } - } - } - - - - -#else - - void Dfs(IGraph graph, List visited) - { - var startNode = visited[0]; - IGraphVertex nextNode; - List sub; - - var adjlist = graph.GetAdjacencyList(startNode).ToList(); // O(n) - for (int i = 0; i < adjlist.Count; i++) // O(n) - { - nextNode = adjlist[i]; - - // 如果下一个点未遍历过 - if (!visited.Contains(nextNode)) // O(n) - { - // 将下一点加入路径集合,并进行下一次递归 - sub = new List { nextNode }; - sub.AddRange(visited); // O(n) - Dfs(graph, sub); - } - - // 如果下一点遍历过,并且路径大于2,说明已经找到起点 - else if (visited.Count > 2 && nextNode.Equals(visited[^1])) - { - // 将重复的路径进行过滤,并把新的路径存入结果 - var cur = RotateToSmallest(visited); // O(n) - var inv = Invert(cur,cur[0]); // O(n) - - var curstr = Gethashstring(cur,inv); - // Env.Print(curstr); - if (Isnew(curstr)) - { - Curve3ds.Add(cur); - Curved.Add(curstr.Item1); - } - } - } - } -#endif - - - - - - - - - /// - /// 将列表旋转到最小的值为列表起点 - /// - /// - /// - private static List RotateToSmallest(List lst) - { - var index = lst.IndexOf(lst.Min()); - return lst.Skip(index).Concat(lst.Take(index)).ToList(); - } - - /// - /// 将列表反向,并旋转到起点为最小值 - /// - /// - /// - /// - private static List Invert(List lst, IGraphVertex vertex) - { - var tmp = lst.ToList(); - tmp.Reverse(); - var index = tmp.IndexOf(vertex); - return tmp.Skip(index).Concat(lst.Take(index)).ToList(); - } - - private static (string, string) GetHashString(IReadOnlyList pathone, IReadOnlyList pathtwo) - { - var one = new string[pathone.Count]; - var two = new string[pathtwo.Count]; - for (var i = 0; i < pathone.Count; i++) - { - one[i] = pathone[i].Index.ToString(); - two[i] = pathtwo[i].Index.ToString(); - } - return (string.Join("-", one), string.Join("-", two)); - } - - private static (string, string) GetHashString(LinkedHashSet path) - { - var one = new string[path.Count]; - var two = new string[path.Count]; - path.For(path.MinNode!, (i, ver1, ver2) => { - one[i] = ver1.Index.ToString(); - two[i] = ver2.Index.ToString(); - }); - return (string.Join("-", one), string.Join("-", two)); - } - - - private bool IsNew((string, string) path) - { - return !Curved.Contains(path.Item1) && !Curved.Contains(path.Item2); - } - - - #endregion -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/Algorithms/Graph/IGraph.cs b/src/CAD/IFox.CAD.Shared/Algorithms/Graph/IGraph.cs deleted file mode 100644 index b0726c8..0000000 --- a/src/CAD/IFox.CAD.Shared/Algorithms/Graph/IGraph.cs +++ /dev/null @@ -1,107 +0,0 @@ -namespace IFoxCAD.Cad; - -/// -/// 无向图 -/// -public interface IGraph -{ - /// - /// 顶点的数量 - /// - /// - int VerticesCount { get; } - - /// - /// 是否存在顶点 - /// - /// 顶点键 - /// - bool ContainsVertex(IGraphVertex key); - - /// - /// 顶点的迭代器 - /// - /// - IEnumerable VerticesEnumberable { get; } - - /// - /// 是否有边 - /// - /// 源顶点 - /// 目的顶点 - /// - bool HasEdge(IGraphVertex source, IGraphVertex destination); - /// - /// 图克隆函数 - /// - /// - IGraph Clone(); - /// - /// 获取边 - /// - /// - /// - /// - IEdge? GetEdge(IGraphVertex source, IGraphVertex dest); - /// - /// 邻接表 - /// - /// - /// - HashSet GetAdjacencyList(IGraphVertex vertex); - /// - /// 邻接边表 - /// - /// - /// - HashSet GetAdjacencyEdge(IGraphVertex vertex); - /// - /// 当前的节点 - /// - IGraphVertex? ReferenceVertex { get; } - /// - /// 删除节点 - /// - /// 节点的坐标 - void RemoveVertex(Point3d pt); - /// - /// 删除边 - /// - /// 曲线 - void RemoveEdge(Curve3d curve); - -} - -/// -/// 无向图顶点 -/// -public interface IGraphVertex : IComparable -{ - /// - /// 顶点的键 - /// - /// - int Index { get; } - - /// - /// 顶点的数据 - /// - Point3d Data { get; } -} -/// -/// 无向图边 -/// -public interface IEdge -{ - /// - /// 边 - /// - Curve3d TargetEdge { get; } - /// - /// 目标顶点 - /// - IGraphVertex TargetVertex { get; } -} - - - diff --git a/src/CAD/IFox.CAD.Shared/Algorithms/QuadTree/QuadEntity.cs b/src/CAD/IFox.CAD.Shared/Algorithms/QuadTree/QuadEntity.cs deleted file mode 100644 index c5f7f11..0000000 --- a/src/CAD/IFox.CAD.Shared/Algorithms/QuadTree/QuadEntity.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace IFoxCAD.Cad; - -/* - * 这个类存在的意义是为了不暴露Rect类字段 - * 同时利用了Rect类字段的快速 - * 提供到外面去再继承 - */ - -/// -/// 四叉树图元 -/// -public class QuadEntity : Rect -{ - /// - /// 四叉树图元 - /// - /// 包围盒 - public QuadEntity(Rect box) - { - _X = box._X; - _Y = box._Y; - _Top = box._Top; - _Right = box._Right; - } -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/Algorithms/QuadTree/QuadTree.cs b/src/CAD/IFox.CAD.Shared/Algorithms/QuadTree/QuadTree.cs deleted file mode 100644 index 2872540..0000000 --- a/src/CAD/IFox.CAD.Shared/Algorithms/QuadTree/QuadTree.cs +++ /dev/null @@ -1,260 +0,0 @@ -/* - * 四叉树维基百科 http://en.wikipedia.org/wiki/Quadtree - * 四叉树是一种分区空间的算法,更快找出内部或外部给定区域. - * 通过一个正交矩形边界进行中心点分裂四个正交矩形, - * 插入时候会一直分裂四个正交矩形, - * 当分裂四个节点都无法单独拥有 图元包围盒 就停止分裂,并且你属于这四个节点的父亲. - * (不包含就是面积少了,就这么一句话看代码看半天), - * 还可以通过限制树的深度实现加速. - * - * 第一版: https://www.codeproject.com/script/Articles/ViewDownloads.aspx?aid=30535 - * - * 第二版: 找邻居 - * https://blog.csdn.net/dive_shallow/article/details/112438050 - * https://geidav.wordpress.com/2017/12/02/advanced-octrees-4-finding-neighbor-nodes/ - * - * 1.根节点:控制根节点从而控制所有节点 - * 2.子节点:包含自身根节点,插入矩形的时候进行递归分裂自身,和实现查找. - * 3.接口:约束都要有正交矩形,否则无法调用"包含"方法 - * 4.选择模式:模仿cad的窗选和框选 - */ -namespace IFoxCAD.Cad; - -/// -/// 根节点控制器 -/// -/// 类型接口约束必须有正交矩形 -public class QuadTree where TEntity : QuadEntity -{ - #region 成员 - /// - /// 根节点 - /// - QuadTreeNode _rootNode; - - /// - /// 四叉树节点的数目 - /// - public int Count { get => _rootNode.CountSubTree; } - - /// - /// 点容器(红黑树) - /// - SortedSet _points; - #endregion - - #region 构造 - /// - /// 四叉树根节点控制器 - /// - /// 四叉树矩形范围 - public QuadTree(Rect rect) - { - _rootNode = new QuadTreeNode(rect, null, 0);// 初始化根节点 - _points = new(); - } - #endregion - - #region 方法 - /// - /// 通过根节点插入数据项 - /// - /// - public void Insert(TEntity ent) - { - /* - * 图元点 是不分裂空间的,加入一个红黑树内部. - */ - if (ent.IsPoint) - { - _points.Add(ent); - return; - } - - while (!_rootNode.Contains(ent)) - { - /* - * 四叉树插入时候,如果超出根边界,就需要扩展 - * 扩展时候有一个要求,当前边界要作为扩展边界的一个象限,也就是反向分裂 - * - * 创建新根,计算原根在新根的位置, - * 替换指针:获取新分裂的节点的父节点,判断它哪个儿子是它, - * 替换之后可能仍然不包含图元边界,再循环计算. - */ - var sq_Left = _rootNode._X; - var sq_Botton = _rootNode._Y; - var sq_Right = _rootNode._Right; - var sq_Top = _rootNode._Top; - if (ent._Y >= _rootNode._Y)// 上↑增殖 - { - if (ent._X >= _rootNode._X) - { - // 右上↗增殖 - sq_Right += _rootNode.Width; - sq_Top += _rootNode.Height; - } - else - { - // 左上↖增殖 - sq_Left -= _rootNode.Width; - sq_Top += _rootNode.Height; - } - } - else// 在下↓ - { - if (ent._X >= _rootNode._X) - { - // 右下↘增殖 - sq_Right += _rootNode.Width; - sq_Botton -= _rootNode.Height; - } - else - { - // 左下↙增殖 - sq_Left -= _rootNode.Width; - sq_Botton -= _rootNode.Height; - } - } - // 扩大2次方 - var rectSquare = new Rect(sq_Left, sq_Botton, sq_Right, sq_Top); - - // 四叉树的旧根要作为四分之一插入 - // 新根中计算原根 - // 把 旧根节点 连接到 新根节点 上面,然后新根成为根 - var newRoot = new QuadTreeNode(rectSquare, null, 0); - var insert = newRoot.Insert(_rootNode); - if (insert is null) - throw new("四叉树:新根尺寸不对"); - if (!insert.Equals(_rootNode)) - throw new("四叉树:新旧节点大小不一致,无法连接"); - - var insPar = insert.Parent; - _rootNode.Parent = insPar; - if (insPar is null) - return; - - if (_rootNode.Equals(insPar.RightTopTree)) - insPar.RightTopTree = _rootNode; - else if (_rootNode.Equals(insPar.RightBottomTree)) - insPar.RightBottomTree = _rootNode; - else if (_rootNode.Equals(insPar.LeftBottomTree)) - insPar.LeftBottomTree = _rootNode; - else if (_rootNode.Equals(insPar.LeftTopTree)) - insPar.LeftTopTree = _rootNode; - else - throw new("四叉树:新节点不对,无法连接"); - - // 其后的子节点层数全部增加层数, - // 要加多少层取决于当前根边界属于新根边界的所在层 - var depth = insert.Depth; - if (depth == 0) - throw new("四叉树:插入节点是0,造成错误"); - _rootNode.ForEach(node => { - node.Depth += depth; - return false; - }); - - // 交换根控制 - _rootNode = newRoot; - } - - _rootNode.Insert(ent); - } - - - /// - /// 查询四叉树,返回给定区域的数据项 - /// - /// 矩形选区查询 - /// 查询模式 - /// 查询结果列表 - public List Query(Rect rect, QuadTreeSelectMode selectMode = QuadTreeSelectMode.IntersectsWith) - { - QuadTreeEvn.SelectMode = selectMode; - - List results = []; - // 选择图元 - _rootNode.Query(rect, results); - // 选择点 - using var ptge = _points.GetEnumerator(); - switch (selectMode) - { - case QuadTreeSelectMode.IntersectsWith: - case QuadTreeSelectMode.Contains: - /* 由于红黑树的方法 _points.GetViewBetween() - * 过滤只能过滤X区间,Y区间还是要过滤, - * 那么我就只能用这样的方法加速了 - * - * 而更好的方式是不用红黑树,去加入一个点云数据来进行,可谓是编程无极限.... - */ - while (ptge.MoveNext()) - { - var ptEnt = ptge.Current; - if (ptEnt != null && rect._X <= ptEnt._X && ptEnt._X <= rect._Right) - { - if (rect._Y <= ptEnt._Y && ptEnt._Y <= rect.Top) - results.Add(ptEnt); - } - else if (ptEnt != null && ptEnt._X > rect._Right) - break;// 超过后面范围就break,因为红黑树已经排序 - } - break; - default: - throw new("四叉树:" + nameof(selectMode)); - } - return results; - } - - /// - /// 删除子节点 - /// - /// 根据范围删除 - public void Remove(Rect rect) - { - _rootNode.Remove(rect); - } - - /// - /// 删除子节点 - /// - /// 根据图元删除 - public void Remove(TEntity ent) - { - _rootNode.Remove(ent); - } - - /// - /// 找到附近节点图元 - /// - [Obsolete("找附近节点的并不是最近的图元")] - public TEntity? FindNeibor(Rect rect, QuadTreeFindMode findMode) - { - return _rootNode.FindNeibor(rect, findMode); - } - - /// - /// 找到附近图元 - /// - /// - /// - public TEntity? FindNearEntity(Rect rect) - { - return _rootNode.FindNearEntity(rect); - } - - /// - /// 执行四叉树中特定的行为 - /// - /// - public void ForEach(QTAction action) - { - _rootNode.ForEach(action); - } - - /// - /// 委托:四叉树节点上执行一个操作 - /// - /// - public delegate bool QTAction(QuadTreeNode obj); - #endregion -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/Algorithms/QuadTree/QuadTreeEvn.cs b/src/CAD/IFox.CAD.Shared/Algorithms/QuadTree/QuadTreeEvn.cs deleted file mode 100644 index f077a02..0000000 --- a/src/CAD/IFox.CAD.Shared/Algorithms/QuadTree/QuadTreeEvn.cs +++ /dev/null @@ -1,28 +0,0 @@ -#pragma warning disable CA2211 // 非常量字段应当不可见 -namespace IFoxCAD.Cad; -/// -/// 四叉树环境变量 -/// -public class QuadTreeEvn -{ - /// - /// 最小的节点有一个面积(一定要大于0) - /// - public static double MinArea = 1e-6; - - /// - /// 选择模式 - /// - public static QuadTreeSelectMode SelectMode; - - /// - /// 最大深度 - /// - public static int QuadTreeMaximumDepth = 2046; - - /// - /// 节点内容超过就分裂 - /// - public static int QuadTreeContentsCountSplit = 20; -} -#pragma warning restore CA2211 // 非常量字段应当不可见 \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/Algorithms/QuadTree/QuadTreeNode.cs b/src/CAD/IFox.CAD.Shared/Algorithms/QuadTree/QuadTreeNode.cs deleted file mode 100644 index 315117f..0000000 --- a/src/CAD/IFox.CAD.Shared/Algorithms/QuadTree/QuadTreeNode.cs +++ /dev/null @@ -1,818 +0,0 @@ -namespace IFoxCAD.Cad; - -/// -/// 子节点 -/// -/// -public class QuadTreeNode - : Rect - where TEntity : QuadEntity -{ - #region 成员 - /// - /// 子节点:第一象限:右上↗ - /// - public QuadTreeNode? RightTopTree; - /// - /// 子节点:第二象限:左上↖ - /// - public QuadTreeNode? LeftTopTree; - /// - /// 子节点:第三象限:左下↙ - /// - public QuadTreeNode? LeftBottomTree; - /// - /// 子节点:第四象限:右下↘ - /// - public QuadTreeNode? RightBottomTree; - /// - /// 所有子节点 - /// - QuadTreeNode[] Nodes - { - get - { - return new QuadTreeNode[] - { - RightTopTree!, - LeftTopTree!, - LeftBottomTree!, - RightBottomTree!, - }; - } - } - /// - /// 所有子节点是空的 - /// - bool NodesIsEmpty => RightTopTree is null && LeftTopTree is null && LeftBottomTree is null && RightBottomTree is null; - - /// - /// 父节点 - /// - public QuadTreeNode? Parent; - /// - /// 节点的在四叉树的深度 - /// - public int Depth; - - // 注意,内容没有限制:这不是 impement 四叉树的标准方法 - /// (节点图元是交叉线压着的,并不是矩形范围内全部,因为这是四叉树的特性决定) - /// - /// 本节点:内容 - /// - public List Contents; - - /// - /// 本节点和旗下所有子节点:内容群 - /// - public void ContentsSubTree(List results) - { - if (Contents is null) - return; - results.AddRange(Contents); - var nodes = Nodes; - for (int i = 0; i < nodes.Length; i++) - nodes[i]?.ContentsSubTree(results); - } - - /// - /// 本节点和旗下所有子节点:内容群数量 - /// - public int CountSubTree - { - get - { - if (Contents is null) - return 0; - int count = Contents.Count; - - var nodes = Nodes; - for (int i = 0; i < nodes.Length; i++) - { - var node = nodes[i]; - if (node is null) - continue; - count += node.CountSubTree; - } - return count; - } - } - #endregion - - #region 构造 - /// - /// 四叉树节点 - /// - /// 当前节点边界 - /// 父节点 - /// 节点深度 - public QuadTreeNode(Rect box, QuadTreeNode? parent, int depth) - { - _X = box._X; - _Y = box._Y; - _Right = box._Right; - _Top = box._Top; - - Parent = parent; - Depth = depth; - Contents = new(); - } - #endregion - - #region 增 - /// - /// 将原有节点插入用 - /// - /// - internal QuadTreeNode? Insert(Rect rect) - { - if (!Contains(rect)) - return null; - - // 四叉树分裂,将当前节点分为四个子节点 - if (NodesIsEmpty) - CreateChildren(); - - // 当前节点边界 包含 图元包围盒 就插入 - // 退出递归:4个节点都不完全包含 - // 4个节点的上层 - var nodes = Nodes; - for (int i = 0; i < nodes.Length; i++) - { - var node = nodes[i]; - if (node is null) - continue; - - if (node.Equals(rect)) - { - rect = node; - return node.Insert(rect); - } - } - return this; - } - - /// - /// 将数据项递归插入四叉树 - /// - /// - public QuadTreeNode? Insert(TEntity ent) - { - if (!Contains(ent)) - { - // Debugx.Printl("不在四叉树边界范围"); - // Trace.WriteLine("不在四叉树边界范围"); - return null; - } - - // if (ent.IsPoint) - // { - // // 找到最后一层包含它的节点,然后加入它 - // // 因此是跳过分裂矩形的,以免造成无限递归 - // var minNode = GetMinNode(ent); - // minNode.Contents.Add(ent); - // return minNode; - // } - -#if true2 - // 方案二: - // 内容数超过才分裂,防止树深度过高,但是多选过滤时候慢一点 - if (Contents.Count > QuadTreeEvn.QuadTreeContentsCountSplit) - { - // 分裂出四个子节点 - if (_nodesIsEmpty) - { - CreateChildren(); - // 分裂之后将当前层的内容扔到四个子节点, - // 如果被压着,那么就不会扔到下面 - for (int i = Contents.Count - 1; i >= 0; i--) - { - var minNode = GetMinNode(Contents[i].Box); - minNode.Contents.Add(Contents[i]); - Contents.RemoveAt(i); - } - } - else - { - // 没有分裂的话,就递归 - // 退出递归:4个节点都不完全包含,内容就是他们的父亲 - var nodes = _Nodes; - for (int i = 0; i < nodes.Length; i++) - { - var node = nodes[i]; - if (node is null) - continue; - - // 这里需要中断.(匿名方法ForEach无法中断,会造成父节点加入内容) - if (node.Contains(ent)) - return node.Insert(ent); - } - } - } -#else - // 方案一:分裂到最细节点 - - // 分裂出四个子节点 - if (NodesIsEmpty) - CreateChildren(); - - // 4个子节点开始递归 - // 退出递归:4个节点都不完全包含,内容就是他们的父亲 - var nodes = Nodes; - for (int i = 0; i < nodes.Length; i++) - { - var node = nodes[i]; - if (node is null) - continue; - // 这里需要中断.(匿名方法ForEach无法中断,会造成父节点加入内容) - if (node.Contains(ent)) - return node.Insert(ent); - } -#endif - - // 为什么要用容器? - // 相同包围盒或者四叉树分割线压着多个. - this.Contents.Add(ent); - return this; - } - - /// - /// 创建子节点 - /// - void CreateChildren() - { - // 最小面积控制节点深度,但是这样可能导致树分成高,引起爆栈 - if (Depth > QuadTreeEvn.QuadTreeMaximumDepth) - return; - var recs = RectSplit(this); - var de = Depth + 1; - RightTopTree = new QuadTreeNode(recs[0], this, de); - LeftTopTree = new QuadTreeNode(recs[1], this, de); - LeftBottomTree = new QuadTreeNode(recs[2], this, de); - RightBottomTree = new QuadTreeNode(recs[3], this, de); - } - - /// - /// 矩形分裂为四个 - /// - /// - /// - static Rect[] RectSplit(Rect box) - { - var halfWidth = box.Width / 2.0; - var halfHeight = box.Height / 2.0; - - var upperRight = new Rect(box._X + halfWidth, box._Y + halfHeight, box._Right, box._Top); - var upperLeft = new Rect(box._X, box._Y + halfHeight, box._Right - halfWidth, box._Top); - var lowerleft = new Rect(box._X, box._Y, box._Right - halfWidth, box._Top - halfHeight);// 基础 - var lowerRight = new Rect(box._X + halfWidth, box._Y, box._Right, box._Top - halfHeight); - - // 依照象限顺序输出 - return new Rect[] { upperRight, upperLeft, lowerleft, lowerRight }; - } - #endregion - - #region 删 - /// - /// 删除图元 - /// - /// 根据图元删除 - public bool Remove(TEntity easeEnt) - { - // 通过图元id删除无疑是非常低效的, - // 1.相当于在所有的容器查找它,但是移除只会移除一次, - // 因此必须要求图元只会加入一次,才能中断检索剩余分支. - // 2.这个代价还是太高,因此我们还是要默认条件,图元载入一次之后,不再改动. - // 3.不再改动也不太合理,因为cad图元还是可以修改的 - - // 1.处理内容 - if (Contents.Remove(easeEnt)) - { - if (CountSubTree == 0) - this.Clear(this); - return true; - } - - // 2.递归子节点移除 - var nodes = Nodes; - for (int i = 0; i < nodes.Length; i++) - { - var node = nodes[i]; - if (node is null) - continue; - if (node.Remove(easeEnt)) // 递归进入子节点删除内容 - return true; // 删除成功就中断其他节点的搜索 - } - return false; - } - - /// - /// 递归进入最下层节点,然后开始清理 - /// - /// - void Clear(QuadTreeNode node) - { - var nodes = Nodes; - for (int i = 0; i < nodes.Length; i++) - nodes[i]?.Clear(nodes[i]); - - node.Contents.Clear(); - // node.Contents = null;// 重复加入时候会出错 - node.RightTopTree = null; - node.LeftTopTree = null; - node.LeftBottomTree = null; - node.RightBottomTree = null; - node.Parent = null; - // node.Box = zoreRect; - } - - /// - /// 删除子节点内容 - /// - /// 根据范围删除 - public void Remove(Rect queryArea) - { - // 本节点内容移除 - if (Contents is not null && Contents.Count > 0)// 从最上层的根节点开始进入 - { - for (int i = Contents.Count - 1; i >= 0; i--) - { - var ent = Contents[i]; - // 移除之后,如果容器是0,那么这里不能直接 Contents=null, - // 因为此节点下面可能还有节点, - // 需要判断了其后数量0才可以清理. - // 否则其后还有内容,那么此节点就是仍然可以用的. - if (queryArea.Contains(ent)) - Contents.Remove(ent); - } - } - - // 同插入一样 - // 跳到指定节点再搜索这个节点下面的图元 - var nodes = Nodes; - for (int i = 0; i < nodes.Length; i++) - { - var node = nodes[i]; - if (node is null) - continue; - if (node.NodesIsEmpty) - continue; - - // 此节点边界 完全包含 查询区域,则转到该节点,并跳过其余节点(打断此循环) - if (node.Contains(queryArea)) - { - node.Remove(queryArea); - break; - } - // 查询区域 完全包含 此节点边界,提取此节点全部内容 - // 跳过分析碰撞,并继续循环搜索其他节点 - if (queryArea.Contains(node)) - { - node.Clear(node); - continue; - } - // 查询区域 与 此节点四边形边线碰撞 查询该四边形中,并继续循环搜索其他节点 - // 1,角点碰撞 2,边界碰撞 - if (node.IntersectsWith(queryArea)) - node.Remove(queryArea); - } - - // 本节点内容移除之后,旗下还有内容的话, - // 会跳过此处,再进入子节点进行递归,直到最后一个节点 - if (CountSubTree == 0) - Clear(this); - } - #endregion - - #region 查 - /// - /// 查询范围内的实体 - /// - /// 查询矩形 - /// 查询结果 - public void Query(Rect queryArea, List results) - { - GetCurrentContents(queryArea, results); - - // 遍历子节点 - var nodes = Nodes; - for (int i = 0; i < nodes.Length; i++) - { - var node = nodes[i]; - if (node is null) - continue; - // 子节点的4个子节点都是空的, - // 那么表示元素会在子节点这一层啊... - if (node.NodesIsEmpty) - continue; - - // 此节点边界 完全包含 查询区域,则转到该节点,并跳过其余节点(打断此循环) - if (node.Contains(queryArea)) - { - node.Query(queryArea, results); - break; - } - // 查询区域 完全包含 此节点边界,提取此节点全部内容 - // 跳过分析碰撞,并继续循环搜索其他节点 - if (queryArea.Contains(node)) - { - node.ContentsSubTree(results); - continue; - } - // 查询区域 与 此节点四边形边线碰撞 查询该四边形中,并继续循环搜索其他节点 - // 1,角点碰撞 2,边界碰撞 - if (node.IntersectsWith(queryArea)) - node.Query(queryArea, results); - } - } - - /// - /// 获取本节点内容 - /// - /// - /// - void GetCurrentContents(Rect queryArea, List results) - { - // 遍历当前节点内容,加入方式取决于碰撞模式 - if (QuadTreeEvn.SelectMode == QuadTreeSelectMode.IntersectsWith) - { - for (int i = 0; i < Contents.Count; i++) - { - var ent = Contents[i]; - if (queryArea.IntersectsWith(ent)) - results.Add(ent); - } - } - else - { - for (int i = 0; i < Contents.Count; i++) - { - var ent = Contents[i]; - if (queryArea.Contains(ent)) - results.Add(ent); - } - } - } - - /// - /// 找临近图元 - /// - /// 查找矩形 - /// - public TEntity? FindNearEntity(Rect queryArea) - { - TEntity? resultEntity = default; - // 1.找到 查找矩形 所在的节点,利用此节点的矩形. - var queryNode = GetMinNode(queryArea); - var queryAreaCenter = queryArea.CenterPoint; - - // 2.从根开始搜索 - // 如果搜索父亲的父亲的...内容群,它不是距离最近的,只是节点(亲属关系)最近 - // 储存找过的<图元,距离> - var entDic = new Dictionary(); - - var old = QuadTreeEvn.SelectMode; - QuadTreeEvn.SelectMode = QuadTreeSelectMode.IntersectsWith; - while (true) - { - // 循环找父节点大小 - var hw = queryNode.Width / 2.0; - var hh = queryNode.Height / 2.0; - // 3.利用选区中心扩展一个节点边界大小的矩形.从而选择图元 - // 再判断图元的与目标的距离,找到最小距离,即为最近 - var minPt = new Point2d(queryAreaCenter.X - hw, queryAreaCenter.Y - hh); - var maxPt = new Point2d(queryAreaCenter.X + hw, queryAreaCenter.Y + hh); - List ents = []; - Query(new Rect(minPt, maxPt), ents); - for (int i = 0; i < ents.Count; i++) - { - var ent = ents[i]; - if (entDic.ContainsKey(ent)) - continue; - var dis = ent.CenterPoint.GetDistanceTo(queryAreaCenter); - if (dis > 1e-6)// 剔除本身 - entDic.Add(ent, dis); - } - if (entDic.Count > 0) - { - resultEntity = entDic.OrderBy(a => a.Value).First().Key; - break; - } - if (queryNode.Parent is null)// 最顶层就退出 - break; - queryNode = queryNode.Parent;// 利用父节点矩形进行变大选区 - } - QuadTreeEvn.SelectMode = old; - return resultEntity; - } - - /// - /// 找临近节点的图元 - /// - /// 查找矩形 - /// 查找什么方向 - /// - [Obsolete("找附近节点的并不是最近的图元")] - public TEntity? FindNeibor(Rect queryArea, QuadTreeFindMode findMode) - { - TEntity? resultEntity = default; - // 1.找到 查找矩形 所在的节点,利用此节点的矩形. - // 2.利用节点矩形是分裂的特点,边和边必然贴合. - // 3.找到方向 findMode 拥有的节点,然后查找节点的内容 - var queryNode = GetMinNode(queryArea); - - bool whileFlag = true; - // 同一个节点可能包含邻居,因为四叉树的加入是图元压线, - // 那么就在这里搜就得了,用中心点决定空间位置 - // 但是本空间的图元可能都比它矮,无法满足条件 - if (queryNode.CountSubTree > 1) - { - resultEntity = GetNearestNeighbor(queryNode, findMode, queryArea); - if (resultEntity is null || resultEntity.CenterPoint == queryArea.CenterPoint) - whileFlag = true; - else - whileFlag = false; - } - - while (whileFlag) - { - // 同一个父节点是临近的,优先获取 兄弟节点 的内容. - // 循环了第二次是北方兄弟的节点, - // 但是这不是一个找到临近图元的方法, - // 因为临近的可能是父亲的父亲的父亲...另一个函数 FindNearEntity 写 - // 本方案也仅仅作为找北方节点 - var parent = queryNode.Parent; - if (parent is not null) - { - switch (findMode) - { - case QuadTreeFindMode.Top: - { - // 下格才获取上格,否则导致做了无用功,上格就直接获取邻居了 - if (parent.LeftBottomTree == queryNode || parent.RightBottomTree == queryNode) - resultEntity = GetNearestNeighbor(parent, findMode, queryArea); - } - break; - case QuadTreeFindMode.Bottom: - { - if (parent.LeftTopTree == queryNode || parent.RightTopTree == queryNode) - resultEntity = GetNearestNeighbor(parent, findMode, queryArea); - } - break; - case QuadTreeFindMode.Left: - { - if (parent.RightTopTree == queryNode || parent.RightBottomTree == queryNode) - resultEntity = GetNearestNeighbor(parent, findMode, queryArea); - } - break; - case QuadTreeFindMode.Right: - { - if (parent.LeftTopTree == queryNode || parent.LeftBottomTree == queryNode) - resultEntity = GetNearestNeighbor(parent, findMode, queryArea); - } - break; - } - } - if (resultEntity is not null) - break; - - // 通过 所在节点 找 邻居节点, - // 拿到 邻居节点 下面的所有内容(图元) - // 内容可能是空的,再从邻居那往北找...如果找到了四叉树最外层,仍然没有内容,退出循环 - var neiborNode = FindNeiborNode(queryNode, findMode); - if (neiborNode is null) - continue; - if (neiborNode.CountSubTree > 0) - { - resultEntity = GetNearestNeighbor(neiborNode, findMode, queryArea); - break; - } - if (neiborNode.Parent is null)// 如果找到了四叉树最外层,仍然没有内容,退出循环 - break; - queryNode = neiborNode; - } - - return resultEntity; - } - - /// - /// 查找节点的(本内容和子内容)与(查找面积)矩形中点对比,找到最近一个内容 - /// - /// 查找面积 - /// 查找方向 - /// 查找节点 - /// - static TEntity? GetNearestNeighbor(QuadTreeNode queryNode, - QuadTreeFindMode findMode, - Rect queryArea) - { - TEntity? results = default; - - List lst = []; - var qcent = queryArea.CenterPoint; - - switch (findMode) - { - case QuadTreeFindMode.Top: - { - // 取出Y比queryArea的还大的一个,是最近的那个 - var qy = qcent.Y; - queryNode.ContentsSubTree(lst); - lst.ForEach(ent => { - if (ent.CenterPoint.Y > qy) - lst.Add(ent); - }); - lst = lst.OrderBy(ent => ent.CenterPoint.Y).ToList(); - } - break; - case QuadTreeFindMode.Bottom: - { - var qy = qcent.Y; - queryNode.ContentsSubTree(lst); - lst.ForEach(ent => { - if (ent.CenterPoint.Y < qy) - lst.Add(ent); - }); - lst = lst.OrderByDescending(ent => ent.CenterPoint.Y).ToList(); - } - break; - case QuadTreeFindMode.Left: - { - var qx = qcent.Y; - queryNode.ContentsSubTree(lst); - lst.ForEach(ent => { - if (ent.CenterPoint.X > qx) - lst.Add(ent); - }); - lst = lst.OrderBy(ent => ent.CenterPoint.X).ToList(); - } - break; - case QuadTreeFindMode.Right: - { - var qx = qcent.Y; - queryNode.ContentsSubTree(lst); - lst.ForEach(ent => { - if (ent.CenterPoint.X < qx) - lst.Add(ent); - }); - lst = lst.OrderByDescending(ent => ent.CenterPoint.X).ToList(); - } - break; - } - - if (lst.Count > 0) - return lst[0];// 可能就是本体重叠 - return results; - } - - /// - /// 找包含它的最小分支 - /// - /// 查询的矩形 - /// 节点 - QuadTreeNode GetMinNode(Rect queryArea) - { - var nodes = Nodes; - for (int i = 0; i < nodes.Length; i++) - { - var node = nodes[i]; - if (node is null) - continue; - - // 边界包含查询面积,那么再递归查询, - // 直到最后四个都不包含,那么上一个就是图元所在节点 - if (node.Contains(queryArea)) - return node.GetMinNode(queryArea);// 中断后面的范围,才可以返回正确的 - } - return this; - } - - /// - /// 四叉树找邻居节点(相同或更大) - /// - /// 源节点 - /// 方向 - /// - QuadTreeNode? FindNeiborNode(QuadTreeNode tar, QuadTreeFindMode findMode) - { - var parent = tar.Parent; - if (parent is null) - return null; - switch (findMode) - { - case QuadTreeFindMode.Top: - { - // 判断当前节点在父节点的位置,如果是在 下格 就取对应的 上格 - if (tar == parent.LeftBottomTree) - return parent.LeftTopTree; - if (tar == parent.RightBottomTree) - return parent.RightTopTree; - // 否则就是上格 - // 找父节点的北方邻居..也就是在爷节点上面找 - // 递归,此时必然是 下格,就必然返回 上格,然后退出递归 - var parentNeibor = FindNeiborNode(parent, QuadTreeFindMode.Top); - // 父节点的北方邻居 无 子节点 - if (parentNeibor is null || parentNeibor.RightTopTree is null) - return parentNeibor;// 返回父节点的北方邻居,比较大 - // 父节点的北方邻居 有 子节点,剩下条件就只有这两 - - // 如果直接返回,那么是(相同或更大), - // 而找邻近图元需要的是这个(相同或更大)下面的图元,在外面对这个格子内图元用坐标分析就好了 - if (tar == parent.LeftTopTree) - return parentNeibor.LeftBottomTree; - return parentNeibor.RightBottomTree; - } - case QuadTreeFindMode.Bottom: - { - if (tar == parent.LeftTopTree) - return parent.LeftBottomTree; - if (tar == parent.RightTopTree) - return parent.RightBottomTree; - var parentNeibor = FindNeiborNode(parent, QuadTreeFindMode.Bottom); - if (parentNeibor is null || parentNeibor.RightTopTree is null) - return parentNeibor; - if (tar == parent.LeftBottomTree) - return parentNeibor.LeftTopTree; - return parentNeibor.RightTopTree; - } - case QuadTreeFindMode.Right: - { - if (tar == parent.LeftTopTree) - return parent.RightTopTree; - if (tar == parent.LeftBottomTree) - return parent.RightBottomTree; - var parentNeibor = FindNeiborNode(parent, QuadTreeFindMode.Right); - if (tar == parent.RightTopTree) - return parentNeibor?.LeftTopTree; - return parentNeibor?.LeftBottomTree; - } - case QuadTreeFindMode.Left: - { - if (tar == parent.RightTopTree) - return parent.LeftTopTree; - if (tar == parent.RightBottomTree) - return parent.LeftBottomTree; - var parentNeibor = FindNeiborNode(parent, QuadTreeFindMode.Left); - if (tar == parent.LeftTopTree) - return parentNeibor?.RightTopTree; - return parentNeibor?.RightBottomTree; - } - } - return null; - } - #endregion - - #region 改 - /* - /// - /// 所有的点归类到最小包围它的空间 - /// - public void PointsToMinNode() - { - ForEach(node => - { - for (int i = 0; i < node.Contents.Count; i++) - { - var ent = node.Contents[i]; - if (ent.IsPoint) - { - // 如果最小包含!=当前,就是没有放在最适合的位置 - var queryNode = GetMinNode(ent); - if (queryNode != node) - { - node.Remove(ent); - queryNode.Contents.Add(ent); - } - } - } - return false; - }); - } - */ - #endregion - - #region 方法 - /// - /// 递归全部节点(提供给根用的,所以是全部) - /// - /// QTAction - public bool ForEach(QuadTree.QTAction action) - { - // 执行本节点 - if (action(this)) - return true; - - // 递归执行本节点的子节点 - var nodes = Nodes; - for (int i = 0; i < nodes.Length; i++) - { - var node = nodes[i]; - if (node is null) - continue; - if (node.ForEach(action)) - break; - } - return false; - } - #endregion -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/Algorithms/QuadTree/QuadTreeSelectMode.cs b/src/CAD/IFox.CAD.Shared/Algorithms/QuadTree/QuadTreeSelectMode.cs deleted file mode 100644 index 624d313..0000000 --- a/src/CAD/IFox.CAD.Shared/Algorithms/QuadTree/QuadTreeSelectMode.cs +++ /dev/null @@ -1,39 +0,0 @@ -namespace IFoxCAD.Cad; - -/// -/// 四叉树选择模式 -/// -public enum QuadTreeSelectMode -{ - /// - /// 碰撞到就选中 - /// - IntersectsWith, - /// - /// 全包含才选中 - /// - Contains, -} - -/// -/// 四叉树查找方向 -/// -public enum QuadTreeFindMode -{ - /// - /// 上 - /// - Top = 1, - /// - /// 下 - /// - Bottom = 2, - /// - /// 左 - /// - Left = 4, - /// - /// 右 - /// - Right = 8, -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/Algorithms/QuadTree/Rect.cs b/src/CAD/IFox.CAD.Shared/Algorithms/QuadTree/Rect.cs deleted file mode 100644 index 583c07d..0000000 --- a/src/CAD/IFox.CAD.Shared/Algorithms/QuadTree/Rect.cs +++ /dev/null @@ -1,742 +0,0 @@ -using System.Diagnostics; -using System.Runtime.CompilerServices; - -namespace IFoxCAD.Cad; - -/// -/// Linq Distinct 消重比较两点在容差范围内就去除 -/// -public class TolerancePoint2d : IEqualityComparer -{ - readonly double _tolerance; - /// - /// 构造函数 - /// - /// 容差 - public TolerancePoint2d(double tolerance = 1e-6) - { - _tolerance = tolerance; - } - /// - /// 比较 - /// - /// - /// - /// - public bool Equals(Point2d a, Point2d b)// Point3d是struct不会为null - { - /*默认规则是==是0容差,Eq是有容差*/ - // 方形限定 - // 在 0~1e-6 范围实现 圆形限定 则计算部分在浮点数6位后,没有啥意义 - // 在 0~1e-6 范围实现 从时间和CPU消耗来说,圆形限定 都没有 方形限定 的好 - if (_tolerance <= 1e-6) - return Math.Abs(a.X - b.X) <= _tolerance && Math.Abs(a.Y - b.Y) <= _tolerance; - - // 圆形限定 - // DistanceTo 分别对XYZ进行了一次乘法,也是总数3次乘法,然后求了一次平方根 - // (X86.CPU.FSQRT指令用的牛顿迭代法/软件层面可以使用快速平方根....我还以为CPU会采取快速平方根这样的取表操作) - return a.IsEqualTo(b, new Tolerance(_tolerance, _tolerance)); - } - /// - /// 哈希 - /// - /// - /// - public int GetHashCode(Point2d obj) - { - // 结构体直接返回 obj.GetHashCode(); Point3d ToleranceDistinct3d - // 因为结构体是用可值叠加来判断?或者因为结构体兼备了一些享元模式的状态? - // 而类是构造的指针,所以取哈希值要改成x+y+z..s给Equals判断用,+是会溢出,所以用^ - return (int)obj.X ^ (int)obj.Y;// ^ (int)obj.Z; - } -} - -/// -/// 矩形范围类 -/// -[Serializable] -[StructLayout(LayoutKind.Sequential)] -[DebuggerDisplay("{DebuggerDisplay,nq}")] -[DebuggerTypeProxy(typeof(Rect))] -public class Rect : IEquatable, IComparable -{ - [DebuggerBrowsable(DebuggerBrowsableState.Never)] - private string DebuggerDisplay => ToString("f4"); - -#pragma warning disable CA2211 // 非常量字段应当不可见 - /// - /// 矩形容差 - /// - public static TolerancePoint2d RectTolerance = new(1e-6); - /// - /// cad容差 - /// - public static Tolerance CadTolerance = new(1e-6, 1e-6); -#pragma warning restore CA2211 // 非常量字段应当不可见 - - #region 字段 - // 这里的成员不要用{get}封装成属性,否则会导致跳转了一次函数, - // 10w图元将会从187毫秒变成400毫秒 - // 不用 protected 否则子类传入Rect对象进来无法用 - internal double _X; - internal double _Y; - internal double _Right; - internal double _Top; - #endregion - - #region 成员 - /// - /// X - /// - public double X => _X; - /// - /// Y - /// - public double Y => _Y; - /// - /// 左 - /// - public double Left => _X; - /// - /// 下 - /// - public double Bottom => _Y; - /// - /// 右 - /// - public double Right => _Right; - /// - /// 上 - /// - public double Top => _Top; - /// - /// 宽 - /// - public double Width => _Right - _X; - /// - /// 高 - /// - public double Height => _Top - _Y; - /// - /// 面积 - /// - public double Area - { - get - { - var ar = (_Right - _X) * (_Top - _Y); - return ar < 1e-10 ? 0 : ar; - } - } - /// - /// 左下Min - /// - public Point2d MinPoint => LeftLower; - /// - /// 右上Max - /// - public Point2d MaxPoint => RightUpper; - /// - /// 中间 - /// - public Point2d CenterPoint => Midst; - - /// - /// 左下Min - /// - public Point2d LeftLower => new(_X, _Y); - - /// - /// 左中 - /// - public Point2d LeftMidst => new(_X, Midst.Y); - - /// - /// 左上 - /// - public Point2d LeftUpper => new(_X, _Top); - - /// - /// 右上Max - /// - public Point2d RightUpper => new(_Right, _Top); - - /// - /// 右中 - /// - public Point2d RightMidst => new(_Right, Midst.Y); - - /// - /// 右下 - /// - public Point2d RightBottom => new(_Right, _Y); - - /// - /// 中间 - /// - public Point2d Midst => new(((_Right - _X) * 0.5) + _X, ((_Top - _Y) * 0.5) + _Y); - - /// - /// 中上 - /// - public Point2d MidstUpper => new(Midst.X, _Top); - - /// - /// 中下 - /// - public Point2d MidstBottom => new(Midst.X, _Y); - - /// - /// 是一个点 - /// 水平或垂直直线包围盒是面积是0,所以面积是0不一定是点 - /// - public bool IsPoint => Math.Abs(_X - _Right) < 1e-10 && Math.Abs(_Y - _Top) < 1e-10; - #endregion - - #region 构造 - /// - /// - /// - public Rect() - { - } - - /// - /// 矩形类 - /// - /// 左 - /// 下 - /// 右 - /// 上 - public Rect(double left, double bottom, double right, double top) - { - _X = left; - _Y = bottom; - _Right = right; - _Top = top; - } - - /// - /// 构造矩形类 - /// - /// - /// - /// 是否检查大小 - public Rect(Point2d p1, Point2d p3, bool check = false) - { - if (check) - { - _X = Math.Min(p1.X, p3.X); - _Y = Math.Min(p1.Y, p3.Y); - _Right = Math.Max(p1.X, p3.X); - _Top = Math.Max(p1.Y, p3.Y); - } - else - { - _X = p1.X; - _Y = p1.Y; - _Right = p3.X; - _Top = p3.Y; - } - } - #endregion - - #region 重载运算符_比较 - /// - /// - /// - /// - /// - public override bool Equals(object? obj) - { - return this.Equals(obj as Rect); - } - /// - /// - /// - /// - /// - public bool Equals(Rect? b) - { - return this.Equals(b, 1e-6);/*默认规则是==是0容差,Eq是有容差*/ - } - /// - /// - /// - /// - /// - /// - public static bool operator !=(Rect? a, Rect? b) - { - return !(a == b); - } - /// - /// - /// - /// - /// - /// - public static bool operator ==(Rect? a, Rect? b) - { - // 此处地方不允许使用==null,因为此处是定义 - if (b is null) - return a is null; - else if (a is null) - return false; - if (ReferenceEquals(a, b))// 同一对象 - return true; - - return a.Equals(b, 0); - } - - /// - /// 比较核心 - /// - public bool Equals(Rect? b, double tolerance = 1e-6) - { - if (b is null) - return false; - if (ReferenceEquals(this, b)) // 同一对象 - return true; - - return Math.Abs(_X - b._X) < tolerance && - Math.Abs(_Right - b._Right) < tolerance && - Math.Abs(_Top - b._Top) < tolerance && - Math.Abs(_Y - b._Y) < tolerance; - } - /// - /// - /// - /// - public override int GetHashCode() - { - return (((int)_X ^ (int)_Y).GetHashCode() ^ (int)_Right).GetHashCode() ^ (int)_Top; - } - #endregion - - #region 包含 - /// - /// - /// - /// - /// - public bool Contains(Point2d Point2d) - { - return Contains(Point2d.X, Point2d.Y); - } - /// - /// - /// - /// - /// - /// - public bool Contains(double x, double y) - { - return _X <= x && x <= _Right && - _Y <= y && y <= _Top; - } - - /// - /// 四个点都在内部就是包含 - /// - /// - /// - public bool Contains(Rect rect) - { - return _X <= rect._X && rect._Right <= _Right && - _Y <= rect._Y && rect._Top <= _Top; - } - - /// - /// 一个点在内部就是碰撞 - /// - /// - /// true内部 - [MethodImpl] - public bool IntersectsWith(Rect rect) - { - return rect._X <= _Right && _X <= rect._Right && - rect._Top >= _Y && rect._Y <= _Top; - } - #endregion - - #region 方法 - /// - /// 获取共点 - /// - /// - public Point2d[] GetCommonPoint(Rect other) - { - return ToPoints().Intersect(other.ToPoints(), RectTolerance).ToArray(); - } - /// - /// 转换为point2d数组 - /// - /// - public Point2d[] ToPoints() - { - Point2d a = MinPoint;// min - Point2d b = new(_Right, _Y); - Point2d c = MaxPoint;// max - Point2d d = new(_X, _Top); - return [a, b, c, d]; - } - /// - /// 转换为point2d元组 - /// - /// - public (Point2d boxMin, Point2d boxRigthDown, Point2d boxMax, Point2d boxLeftUp) ToPoints4() - { - Point2d a = MinPoint;// min - Point2d b = new(_Right, _Y); - Point2d c = MaxPoint;// max - Point2d d = new(_X, _Top); - return (a, b, c, d); - } - - /// - /// 四周膨胀 - /// - /// - public Rect Expand(double d) - { - return new Rect(_X - d, _Y - d, _Right + d, _Top + d); - } - - /// - /// 是否矩形(带角度) - /// - /// - /// - /// - public static bool IsRectAngle(List? ptList, double tolerance = 1e-8) - { - //if (ptList == null) - // throw new ArgumentNullException(nameof(ptList)); - - ArgumentNullEx.ThrowIfNull(ptList); - var pts = ptList.ToList(); - /* - * 消重,不这里设置,否则这不是一个正确的单元测试 - * // var ptList = pts.Distinct().ToList(); - * var ptList = pts.DistinctExBy((a, b) => a.DistanceTo(b) < 1e-6).ToList(); - */ - if (ptList.Count == 5) - { - // 首尾点相同移除最后 - if (pts[0].IsEqualTo(pts[^1], CadTolerance)) - pts.RemoveAt(pts.Count - 1); - } - if (pts.Count != 4) - return false; - - // 最快的方案 - // 点乘求值法:(为了处理 正梯形/平行四边形 需要三次) - // 这里的容差要在1e-8内,因为点乘的三次浮点数乘法会令精度变低 - var dot = DotProductValue(pts[0], pts[1], pts[3]); - if (Math.Abs(dot) < tolerance) - { - dot = DotProductValue(pts[1], pts[2], pts[0]); - if (Math.Abs(dot) < tolerance) - { - dot = DotProductValue(pts[2], pts[3], pts[1]); - return Math.Abs(dot) < tolerance; - } - } - return false; - } - - /// - /// 点积,求值 - /// 1.是两个向量的长度与它们夹角余弦的积 - /// 2.求四个点是否矩形使用 - /// - /// 原点 - /// 点 - /// 点 - /// 0方向相同,夹角0~90度;=0相互垂直;<0方向相反,夹角90~180度]]> - static double DotProductValue(Point2d o, Point2d a, Point2d b) - { - var oa = o.GetVectorTo(a); - var ob = o.GetVectorTo(b); - return (oa.X * ob.X) + (oa.Y * ob.Y); - } - - /// - /// 是否轴向矩形(无角度) - /// - public static bool IsRect(List? ptList, double tolerance = 1e-10) - { - //if (ptList == null) - // throw new ArgumentNullException(nameof(ptList)); - ArgumentNullEx.ThrowIfNull(ptList); - var pts = ptList.ToList(); - if (ptList.Count == 5) - { - // 首尾点相同移除最后 - if (pts[0].IsEqualTo(pts[^1], CadTolerance)) - pts.RemoveAt(pts.Count - 1); - } - if (pts.Count != 4) - return false; - - return Math.Abs(pts[0].X - pts[3].X) < tolerance && - Math.Abs(pts[0].Y - pts[1].Y) < tolerance && - Math.Abs(pts[1].X - pts[2].X) < tolerance && - Math.Abs(pts[2].Y - pts[3].Y) < tolerance; - } - - /// - /// 获取点集的包围盒的最小点和最大点(无角度) - /// - /// - public static (Point2d boxMin, Point2d boxMax) GetMinMax(IEnumerable pts) - { - var xMin = double.MaxValue; - var xMax = double.MinValue; - var yMin = double.MaxValue; - var yMax = double.MinValue; - // var zMin = double.MaxValue; - // var zMax = double.MinValue; - - pts.ForEach(p => { - xMin = Math.Min(p.X, xMin); - xMax = Math.Max(p.X, xMax); - yMin = Math.Min(p.Y, yMin); - yMax = Math.Max(p.Y, yMax); - // zMin = Math.Min(p.Z, zMin); - // zMax = Math.Max(p.Z, zMax); - }); - return (new Point2d(xMin, yMin), new Point2d(xMax, yMax)); - } - - /// - /// 矩形点序逆时针排列,将min点[0],max点是[3](带角度) - /// - /// - /// - public static bool RectAnglePointOrder(List? pts) - { - //if (pts == null) - // throw new ArgumentNullException(nameof(pts)); - ArgumentNullEx.ThrowIfNull(pts); - if (!Rect.IsRectAngle(pts)) - return false; - - // 获取min和max点(非包围盒) - pts = pts.OrderBy(a => a.X).ThenBy(a => a.Y).ToList(); - var minPt = pts.First(); - var maxPt = pts.Last(); - var link = new LoopList(); - link.AddRange(pts); - - pts.Clear(); - // 排序这四个点,左下/右下/右上/左上 - var node = link.Find(minPt); - for (int i = 0; i < 4; i++) - { - pts.Add(node!.Value); - node = node.Next; - } - // 保证是逆时针 - var isAcw = CrossAclockwise(pts[0], pts[1], pts[2]); - if (!isAcw) - (pts[3], pts[1]) = (pts[1], pts[3]); - return true; - } - - /// - /// 叉积,二维叉乘计算 - /// - /// 传参是向量,表示原点是0,0 - /// 传参是向量,表示原点是0,0 - /// 其模为a与b构成的平行四边形面积 - static double Cross(Vector2d a, Vector2d b) - { - return a.X * b.Y - a.Y * b.X; - } - - /// - /// 叉积,二维叉乘计算 - /// - /// 原点 - /// oa向量 - /// ob向量,此为判断点 - /// 返回值有正负,表示绕原点四象限的位置变换,也就是有向面积 - static double Cross(Point2d o, Point2d a, Point2d b) - { - return Cross(o.GetVectorTo(a), o.GetVectorTo(b)); - } - - /// - /// 叉积,逆时针方向为真 - /// - /// 直线点1 - /// 直线点2 - /// 判断点 - /// b点在oa的逆时针时为 - static bool CrossAclockwise(Point2d o, Point2d a, Point2d b) - { - return Cross(o, a, b) > -1e-6;// 浮点数容差考虑 - } - -#if !WinForm - /// - /// 创建矩形范围多段线 - /// - /// 多段线对象 - public Entity ToPolyLine() - { - List bv = []; - var pts = ToPoints(); - Polyline pl = new(); - pl.SetDatabaseDefaults(); - pts.ForEach((vertex, state, index) => { - pl.AddVertexAt(index, vertex, 0, 0, 0); - }); - return pl; - } -#endif - - /// - /// 列扫碰撞检测(碰撞算法) - /// 比四叉树还快哦~ - /// - /// - /// 继承Rect的集合 - /// 先处理集合每一个成员;返回true就跳过后续委托 - /// 碰撞,返回两个碰撞的成员;返回true就跳过后续委托 - /// 后处理集合每一个成员 - public static void XCollision(List box, - Func firstProcessing, - Func collisionProcessing, - Action lastProcessing) where T : Rect - { - // 先排序X:不需要Y排序,因为Y的上下浮动不共X .ThenBy(a => a.Box.Y) - // 因为先排序就可以有序遍历x区间,超过就break,达到更快 - box = box.OrderBy(a => a._X).ToList(); - - // 遍历所有图元 - for (int i = 0; i < box.Count; i++) - { - var oneRect = box[i]; - if (firstProcessing(oneRect)) - continue; - - bool actionlast = true; - - // 搜索范围要在 one 的头尾中间的部分 - for (int j = i + 1; j < box.Count; j++) - { - var twoRect = box[j]; - // x碰撞:矩形2的Left 在 矩形1[Left-Right]闭区间;穿过的话,也必然有自己的Left因此不需要处理 - if (oneRect._X <= twoRect._X && twoRect._X <= oneRect._Right) - { - // y碰撞,那就是真的碰撞了 - if ((oneRect._Top >= twoRect._Top && twoRect._Top >= oneRect._Y) /*包容上边*/ - || (oneRect._Top >= twoRect._Y && twoRect._Y >= oneRect._Y) /*包容下边*/ - || (twoRect._Top >= oneRect._Top && oneRect._Y >= twoRect._Y)) /*穿过*/ - { - if (collisionProcessing(oneRect, twoRect)) - actionlast = false; - } - // 这里想中断y高过它的无意义比较, - // 但是必须排序Y,而排序Y必须同X,而这里不是同X(而是同X区间),所以不能中断 - // 而做到X区间排序,就必须创造一个集合,再排序这个集合, - // 会导致每个图元都拥有一次X区间集合,开销更巨大(因此放弃). - } - else - break;// 因为已经排序了,后续的必然超过 x碰撞区间 - } - - if (actionlast) - lastProcessing(oneRect); - } - } - - #endregion - - #region 转换类型 -#if !WinForm - // 隐式转换(相当于是重载赋值运算符) - // public static implicit operator Rect(System.Windows.Rect rect) - // { - // return new Rect(rect.Left, rect.Bottom, rect.Right, rect.Top); - // } - /// - /// - /// - /// - public static implicit operator Rect(System.Drawing.RectangleF rect) - { - return new Rect(rect.Left, rect.Bottom, rect.Right, rect.Top); - } - /// - /// - /// - /// - public static implicit operator Rect(System.Drawing.Rectangle rect) - { - return new Rect(rect.Left, rect.Bottom, rect.Right, rect.Top); - } -#endif - - #region ToString - /// - /// - /// - /// - public sealed override string ToString() - { - return ToString(null, null); - } - /// - /// - /// - /// - /// - public string ToString(IFormatProvider? provider) - { - return ToString(null, provider); - } - /// - /// - /// - /// - /// - /// - public string ToString(string? format = null, IFormatProvider? formatProvider = null) - { - return $"({_X.ToString(format, formatProvider)},{_Y.ToString(format, formatProvider)})," + - $"({_Right.ToString(format, formatProvider)},{_Top.ToString(format, formatProvider)})"; - - // return $"X={_X.ToString(format, formatProvider)}," + - // $"Y={_Y.ToString(format, formatProvider)}," + - // $"Right={_Right.ToString(format, formatProvider)}," + - // $"Top={_Top.ToString(format, formatProvider)}"; - } - - /*为了红黑树,加入这个*/ - /// - /// - /// - /// - /// - public int CompareTo(Rect rect) - { - if (rect == null) - return -1; - if (_X < rect._X) - return -1; - else if (_X > rect._X) - return 1; - else if (_Y < rect._Y)/*x是一样的*/ - return -1; - else if (_Y > rect._Y) - return 1; - return 0;/*全部一样*/ - } - #endregion - - #endregion -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/AutoReg/AcadEMR.cs b/src/CAD/IFox.CAD.Shared/AutoReg/AcadEMR.cs deleted file mode 100644 index 6cde870..0000000 --- a/src/CAD/IFox.CAD.Shared/AutoReg/AcadEMR.cs +++ /dev/null @@ -1,150 +0,0 @@ -#if true -namespace IFoxCAD.Cad; - -// 作者: [VB.net]福萝卜 莱昂纳多·胖子 -// Email:oneeshine@163.com -// QQ: 461884072 -// 测试 2006-2019+ - -/// -/// 去教育版 -/// -/// -internal class AcadEMR -{ - /// - /// 释放库 - /// - /// 句柄 - /// - [DllImport("kernel32.dll", CharSet = CharSet.Auto)] - static extern IntPtr FreeLibrary(IntPtr loadLibraryIntPtr); - - /// - /// 获取一个应用程序或dll的模块句柄,要求已经载入 - /// - /// - /// - [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] - static extern IntPtr GetModuleHandle(string name); - - /// - /// 获取要引入的函数,将符号名或标识号转换为DLL内部地址 - /// - /// exe/dll句柄 - /// 接口名 - /// - [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true)] - static extern IntPtr GetProcAddress(IntPtr hModule, string procName); - - /// - /// 虚拟保护 - /// - /// - /// - /// - /// - /// - [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] - static extern bool VirtualProtect(IntPtr lpAddress, IntPtr dwSize, uint flNewProtect, ref uint lpflOldProtect); - - - /// - /// 移除教育版 - /// - /// 打印出错信息 - public static void Remove(bool echoes = false) - { - var dllName = Env.GetAcapVersionDll(); - IntPtr moduleHandle = GetModuleHandle(dllName); - if (moduleHandle == IntPtr.Zero) - { - if (echoes) - Env.Printl(typeof(AcadEMR).FullName + "." + nameof(Remove) + "找不到模块:" + dllName); - return; - } - - string funcname = System.Text.Encoding.Unicode.GetString(new byte[] { 63 }); - if (IntPtr.Size == 4) - funcname += "isEMR@AcDbDatabase@@QBE_NXZ"; - else - funcname += "isEMR@AcDbDatabase@@QEBA_NXZ"; - - IntPtr funcAdress = GetProcAddress(moduleHandle, funcname); - if (funcAdress == IntPtr.Zero) - { - if (echoes) - Env.Printl("无法找指定函数:" + funcname); - return; - } - - IntPtr ptr; - if (IntPtr.Size == 4) - ptr = new IntPtr(funcAdress.ToInt32() + 3); - else - ptr = new IntPtr(funcAdress.ToInt64() + 4); - - if (!CheckFunc(ref ptr, 51, 2))// 08 通过此处 - if (echoes) - Env.Printl("无法验证函数体:0x33"); - IntPtr destPtr = ptr; - - if (!CheckFunc(ref ptr, 57, 6))// 08 无法通过此处,所以只是打印提示 - if (echoes) - Env.Printl("无法验证函数体:0x39"); - if (!CheckFunc(ref ptr, 15, 2))// 08 无法通过此处,所以只是打印提示 - if (echoes) - Env.Printl("无法验证函数体:0x0F"); - - uint flag = default; - uint tccc = default; - - IntPtr ip100 = new(100); - if (!VirtualProtect(destPtr, ip100, 64, ref flag))// 修改内存权限 - { - if (echoes) - Env.Printl("内存模式修改失败!"); - return; - } - - Marshal.WriteByte(destPtr, 137); - VirtualProtect(destPtr, ip100, flag, ref tccc);// 恢复内存权限 - } - - /// - /// 验证函数体 - /// - /// - /// - /// - /// - static bool CheckFunc(ref IntPtr adress, byte val, int len) - { - if (adress.ToInt64() > 0) - { - if (Marshal.ReadByte(adress) == 233) - { - if (IntPtr.Size == 4) - { - var pass = Marshal.ReadInt32(new IntPtr(adress.ToInt32() + 1)); - adress = new IntPtr(adress.ToInt32() + pass + 5); - } - else - { - var pass = Marshal.ReadInt64(new IntPtr(adress.ToInt64() + 1)); - adress = new IntPtr(adress.ToInt64() + pass + 5); - } - } - if (adress.ToInt64() > 0 && Marshal.ReadByte(adress) == val) - { - if (IntPtr.Size == 4) - adress = new IntPtr(adress.ToInt32() + len); - else - adress = new IntPtr(adress.ToInt64() + len); - return true; - } - } - return false; - } -} -#endif \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/AutoReg/AssemInfo.cs b/src/CAD/IFox.CAD.Shared/AutoReg/AssemInfo.cs deleted file mode 100644 index f200e4d..0000000 --- a/src/CAD/IFox.CAD.Shared/AutoReg/AssemInfo.cs +++ /dev/null @@ -1,88 +0,0 @@ -namespace IFoxCAD.Cad; - -/// -/// 程序集信息 -/// -[Serializable] -public struct AssemInfo -{ - /// - /// 注册名 - /// - public string Name; - - /// - /// 程序集全名 - /// - public string Fullname; - - /// - /// 程序集路径 - /// - public string Loader; - - /// - /// 加载方式 - /// - public AssemLoadType LoadType; - - /// - /// 程序集说明 - /// - public string Description; -} - - -/// -/// 程序集加载类型 -/// -public enum AssemLoadType -{ - /// - /// 启动 - /// - Startting = 2, - - /// - /// 随命令 - /// - ByCommand = 12, - - /// - /// 无效 - /// - Disabled = 20 -} - - -/// -/// 注册中心配置信息 -/// -[Flags] -public enum AutoRegConfig -{ - /// - /// 不进行任何操作 - /// - Undefined = 0, - /// - /// 注册表 - /// - Regedit = 1, - /// - /// 反射特性 - /// - ReflectionAttribute = 2, - /// - /// 反射接口 - /// - ReflectionInterface = 4, - /// - /// 移除教育版 - /// - RemoveEMR = 8, - /// - /// 全部 - /// - All = Regedit | ReflectionAttribute | ReflectionInterface | RemoveEMR, -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/AutoReg/AutoLoad.cs b/src/CAD/IFox.CAD.Shared/AutoReg/AutoLoad.cs deleted file mode 100644 index 7c84a04..0000000 --- a/src/CAD/IFox.CAD.Shared/AutoReg/AutoLoad.cs +++ /dev/null @@ -1,62 +0,0 @@ -namespace IFoxCAD.Cad; - -/// -/// 自动加载和初始化抽象类 -/// -public abstract class AutoLoad : IExtensionApplication -{ - private readonly AssemInfo _info; - - /// - /// 程序集的路径 - /// - public static FileInfo Location => new(Assembly.GetCallingAssembly().Location); - - /// - /// 程序集的目录 - /// - public static DirectoryInfo? CurrentDirectory => Location.Directory; - - /// - /// 获取程序集的目录 - /// - /// 程序集 - /// 路径对象 - public static DirectoryInfo? GetDirectory(Assembly assem) - { - ArgumentNullEx.ThrowIfNull(assem); - return new FileInfo(assem.Location).Directory; - } - - /// - /// 初始化程序集信息 - /// - public AutoLoad() - { - var assem = Assembly.GetCallingAssembly(); - _info.Loader = assem.Location; - _info.Fullname = assem.FullName; - _info.Name = assem.GetName().Name; - _info.LoadType = AssemLoadType.Startting; - - if (!AutoReg.SearchForReg(_info)) - { - AutoReg.RegApp(_info); - } - - } - -#region IExtensionApplication 成员 - - /// - /// 初始化函数 - /// - public abstract void Initialize(); - - /// - /// 结束函数 - /// - public abstract void Terminate(); - -#endregion IExtensionApplication 成员 -} diff --git a/src/CAD/IFox.CAD.Shared/AutoReg/AutoReg.cs b/src/CAD/IFox.CAD.Shared/AutoReg/AutoReg.cs deleted file mode 100644 index 0588d12..0000000 --- a/src/CAD/IFox.CAD.Shared/AutoReg/AutoReg.cs +++ /dev/null @@ -1,66 +0,0 @@ -namespace IFoxCAD.Cad; - -/// -/// 自动加载辅助类 -/// -public static class AutoReg -{ - /// - /// 获取自动加载注册表位置节点 - /// - /// 注册表节点 - public static RegistryKey? GetAcAppKey() - { - var key = HostApplicationServices.Current.UserRegistryProductRootKey; - var ackey = Registry.CurrentUser.OpenSubKey(key, true); - return ackey?.CreateSubKey("Applications"); - } - /// - /// 是否已经自动加载 - /// - /// 程序集信息 - /// 已经设置返回true,反之返回false - public static bool SearchForReg(AssemInfo info) - { - // 在使用netloadx的时候,此处注册表是失效的,具体原因要进行netloadx测试 - var appkey = GetAcAppKey(); - if (appkey?.SubKeyCount == 0) - return false; - - var regApps = appkey?.GetSubKeyNames(); - if (regApps == null || !regApps.Contains(info.Name)) return false; - // 20220409 bug:文件名相同,路径不同,需要判断路径 - var subkey = appkey?.OpenSubKey(info.Name); - return string.Equals(subkey?.GetValue("LOADER")?.ToString(), info.Loader, StringComparison.CurrentCultureIgnoreCase); - } - - /// - /// 在注册表写入自动加载的程序集信息 - /// - /// 程序集信息 - public static void RegApp(AssemInfo info) - { - var appkey = GetAcAppKey(); - var rk = appkey?.CreateSubKey(info.Name); - rk?.SetValue("DESCRIPTION", info.Fullname, RegistryValueKind.String); - rk?.SetValue("LOADCTRLS", info.LoadType, RegistryValueKind.DWord); - rk?.SetValue("LOADER", info.Loader, RegistryValueKind.String); - rk?.SetValue("MANAGED", 1, RegistryValueKind.DWord); - appkey?.Close(); - } - - /// - /// 卸载注册表信息 - /// - public static bool UnRegApp(AssemInfo info) - { - var appkey = GetAcAppKey(); - if (appkey is { SubKeyCount: 0 }) - return false; - - var regApps = appkey?.GetSubKeyNames(); - if (regApps != null && !regApps.Contains(info.Name)) return false; - appkey?.DeleteSubKey(info.Name, false); - return true; - } -} diff --git a/src/CAD/IFox.CAD.Shared/AutoReg/AutoRegAssem.cs b/src/CAD/IFox.CAD.Shared/AutoReg/AutoRegAssem.cs deleted file mode 100644 index 32bf875..0000000 --- a/src/CAD/IFox.CAD.Shared/AutoReg/AutoRegAssem.cs +++ /dev/null @@ -1,102 +0,0 @@ -namespace IFoxCAD.Cad; - - -/// -/// 注册中心 -/// -/// 初始化程序集信息写入注册表并反射特性和接口
-/// 启动cad后的执行顺序为:
-/// 1:程序集配置中心构造函数
-/// 2:特性..(多个)
-/// 3:接口..(多个)
-///
-///
-public abstract class AutoRegAssem : IExtensionApplication -{ - #region 字段 - - private readonly AutoReflection? _autoRef; - #endregion - - #region 静态方法 - /// - /// 程序集的路径 - /// - public static FileInfo Location => new(Assembly.GetCallingAssembly().Location); - /// - /// 程序集的目录 - /// - public static DirectoryInfo? CurrDirectory => Location.Directory; - /// - /// 获取程序集的目录 - /// - /// 程序集 - /// 路径对象 - public static DirectoryInfo? GetDirectory(Assembly? assem) - { - ArgumentNullEx.ThrowIfNull(assem); - return new FileInfo(assem.Location).Directory; - } - #endregion - - #region 构造函数 - /// - /// 注册中心 - /// - /// 配置项目 - public AutoRegAssem(AutoRegConfig autoRegConfig) - { - var assem = Assembly.GetCallingAssembly(); - var info = new AssemInfo - { - Loader = assem.Location, - Fullname = assem.FullName, - Name = assem.GetName().Name, - LoadType = AssemLoadType.Startting - }; - - if ((autoRegConfig & AutoRegConfig.Regedit) == AutoRegConfig.Regedit) - { - if (!AutoReg.SearchForReg(info)) - AutoReg.RegApp(info); - } - - if ((autoRegConfig & AutoRegConfig.RemoveEMR) == AutoRegConfig.RemoveEMR) - AcadEMR.Remove(); - - // 实例化了 AutoClass 之后会自动执行 IFoxAutoGo 接口下面的类, - // 以及自动执行特性 [IFoxInitialize] - // 类库用户不在此处进行其他代码,而是实现特性 - if ((autoRegConfig & AutoRegConfig.ReflectionInterface) != AutoRegConfig.ReflectionInterface && - (autoRegConfig & AutoRegConfig.ReflectionAttribute) != AutoRegConfig.ReflectionAttribute) return; - _autoRef = new AutoReflection(info.Name, autoRegConfig); - _autoRef.Initialize(); - } - #endregion - - #region RegApp - - - - // 这里的是不会自动执行的 - /// - /// - /// - public void Initialize() - { - } - /// - /// - /// - public void Terminate() - { - } - /// - /// - /// - ~AutoRegAssem() - { - _autoRef?.Terminate(); - } - #endregion RegApp -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/AutoReg/IAutoGo.cs b/src/CAD/IFox.CAD.Shared/AutoReg/IAutoGo.cs deleted file mode 100644 index e9bb446..0000000 --- a/src/CAD/IFox.CAD.Shared/AutoReg/IAutoGo.cs +++ /dev/null @@ -1,404 +0,0 @@ -namespace IFoxCAD.Cad; - - -using System.Diagnostics; - -/// -/// 加载时优先级 -/// -[Flags] -public enum Sequence : byte -{ - /// - /// 最先 - /// - First, - /// - /// 最后 - /// - Last, -} - -/// -/// 加载时自动执行接口 -/// -public interface IFoxAutoGo -{ - /// - /// 控制加载顺序 - /// - /// - Sequence SequenceId(); - - /// - /// 关闭cad的时候会自动执行 - /// - void Terminate(); - - /// - /// 打开cad的时候会自动执行 - /// - void Initialize(); -} - -/// -/// 加载时自动执行特性 -/// -/// -/// 用于初始化和结束回收 -/// -/// 优先级 -/// 用于初始化;用于结束回收 -[AttributeUsage(AttributeTargets.Method)] -public class IFoxInitialize(Sequence sequence = Sequence.Last, bool isInitialize = true) : Attribute -{ - /// - /// 优先级 - /// - internal Sequence SequenceId = sequence; - /// - /// 用于初始化;用于结束回收 - /// - internal bool IsInitialize = isInitialize; -} - -// 为了解决IExtensionApplication在一个dll内无法多次实现接口的关系 -// 所以在这里反射加载所有的 IAutoGo ,以达到能分开写"启动运行"函数的目的 -/// -/// 执行此方法 -/// -/// -/// -/// 已经创建的对象 -internal class RunClass(MethodInfo method, Sequence sequence, object? instance = null) -{ - public Sequence Sequence { get; } = sequence; - - /// - /// 运行方法 - /// - public void Run() - { - method.Invoke(ref instance); - } -} - -/// -/// 此类作为加载后cad自动运行接口的一部分,用于反射特性和接口 -/// -/// 启动cad后的执行顺序为:
-/// 1:特性..(多个)
-/// 2:接口..(多个) -///
-///
-/// -/// 反射执行 -/// -/// 1.特性:
-/// 2.接口: -///
-///
-/// 约束在此dll进行加速 -/// -public class AutoReflection(string dllName, AutoRegConfig configInfo) -{ - private static List _InitializeList = []; // 储存方法用于初始化 - private static List _TerminateList = []; // 储存方法用于结束释放 - - readonly string _dllName = dllName; - readonly AutoRegConfig _autoRegConfig = configInfo; - - /// - /// 启动cad的时候会自动执行 - /// - public void Initialize() - { - try - { - // 收集特性,包括启动时和关闭时 - if ((_autoRegConfig & AutoRegConfig.ReflectionAttribute) == AutoRegConfig.ReflectionAttribute) - GetAttributeFunctions(_InitializeList, _TerminateList); - - if ((_autoRegConfig & AutoRegConfig.ReflectionInterface) == AutoRegConfig.ReflectionInterface) - { - GetInterfaceFunctions(_InitializeList, nameof(Initialize), _TerminateList, nameof(Terminate)); - } - - if (_InitializeList.Count <= 0) return; - // 按照 SequenceId 排序_升序 - _InitializeList = _InitializeList.OrderBy(runClass => runClass.Sequence).ToList(); - RunFunctions(_InitializeList); - } - catch - { - Debugger.Break(); - } - } - - /// - /// 关闭cad的时候会自动执行 - /// - public void Terminate() - { - try - { - //if ((_autoRegConfig & AutoRegConfig.ReflectionInterface) == AutoRegConfig.ReflectionInterface) - // GetInterfaceFunctions(_TerminateList, nameof(Terminate)); - - if (_TerminateList.Count <= 0) return; - // 按照 SequenceId 排序_降序 - _TerminateList = [.. _TerminateList.OrderByDescending(runClass => runClass.Sequence)]; - RunFunctions(_TerminateList); - } - catch (Exception e) - { - Env.Printl(e.Message); - Debugger.Break(); - } - } - - /// - /// 遍历程序域下所有类型 - /// - /// 输出每个成员执行 - /// 过滤此dll,不含后缀 - public static void AppDomainGetTypes(Action action, string? dllNameWithoutExtension = null) - { -#if DEBUG - var error = 0; -#endif - try - { - var assemblies = AppDomain.CurrentDomain.GetAssemblies(); - - // cad2021出现如下报错 - // System.NotSupportedException:动态程序集中不支持已调用的成员 - // assemblies = assemblies.Where(p => !p.IsDynamic).ToArray();// 这个要容器类型转换 - assemblies = Array.FindAll(assemblies, p => !p.IsDynamic); - - // 主程序域 - for (var ii = 0; ii < assemblies.Length; ii++) - { - var assembly = assemblies[ii]; - - // 获取类型集合,反射时候还依赖其他的dll就会这个错误 - // 此通讯库要跳过,否则会报错. - var location = Path.GetFileNameWithoutExtension(assembly.Location); - if (dllNameWithoutExtension != null && location != dllNameWithoutExtension) - continue; - if (location == "AcInfoCenterConn")// 通讯库 - continue; - - Type[]? types = null; - try - { - types = assembly.GetTypes(); - } - catch (ReflectionTypeLoadException) { continue; } - - if (types is null) - continue; - - for (var jj = 0; jj < types.Length; jj++) - { - var type = types[jj]; - if (type is not null) - { -#if DEBUG - ++error; -#endif - action.Invoke(type); - } - } - } - } -#if DEBUG - catch (Exception e) - { - DebugEx.Printl($"出错:{nameof(AppDomainGetTypes)};计数{error};错误信息:{e.Message}"); - Debugger.Break(); -#else - catch - { -#endif - } -} - - /// - /// 收集接口下的函数 - /// - /// - /// - /// - /// - void GetInterfaceFunctions(List initializes, string initializeName, - List terminates, string terminateName) - { - AppDomainGetTypes(type => { - // 接口的静态类屏蔽,继承接口无法使用静态类,因此跳过 - if (type.IsAbstract) - return; - - var ints = type.GetInterfaces(); - for (int sss = 0; sss < ints.Length; sss++) - { - if (ints[sss].Name != nameof(IFoxAutoGo)) - continue; - - Sequence? sequence = null; - MethodInfo? initialize = null; - MethodInfo? terminate = null; - object? instance = null; - - var mets = type.GetMethods(); - for (int jj = 0; jj < mets.Length; jj++) - { - var method = mets[jj]; - - // 接口的静态方法屏蔽,继承的方法也不可能是静态的,因此跳过 - if (method.IsAbstract) - continue; - - if (method.Name == nameof(IFoxAutoGo.SequenceId)) - { - // 避免触发两次构造函数,所以这里需要ref构造的对象出来 - var obj = method.Invoke(ref instance); - if (obj is not null) - sequence = (Sequence)obj; - continue; - } - if (method.Name == initializeName) - { - initialize = method; - continue; - } - if (method.Name == terminateName) - { - terminate = method; - continue; - } - if (sequence is not null && initialize is not null && terminate is not null) - break; - } - - // 避免在terminate释放的时候去再次构造,所以需要一次性收集 - // 若是释放的时候去再次构造: - // 0x01 initialize构造的字段拥有的资源就处于系统释放了,这是不合理的 - // 0x02 同时也发生了,为了释放而去构造这个操作 - var seq = sequence is null ? Sequence.Last : sequence.Value; - if (initialize is not null) - initializes.Add(new(initialize, seq, instance)); - if (terminate is not null) - terminates.Add(new(terminate, seq, instance)); - break; - } - }, _dllName); - } - - /// - /// 收集特性下的函数 - /// - void GetAttributeFunctions(List initializes, - List terminates) - { - AppDomainGetTypes(type => { - if (!type.IsClass) - return; - - // 特性的静态类不屏蔽 - //if (type.IsAbstract) - // return; - - var mets = type.GetMethods(); - for (int ii = 0; ii < mets.Length; ii++) - { - var method = mets[ii]; - - // 特性的静态方法不屏蔽 - //if (method.IsAbstract) - // continue; - - var attr = method.GetCustomAttributes(true); - for (int jj = 0; jj < attr.Length; jj++) - { - if (attr[jj] is IFoxInitialize jjAtt) - { - var runc = new RunClass(method, jjAtt.SequenceId); - if (jjAtt.IsInitialize) - initializes.Add(runc); - else - terminates.Add(runc); - break; - } - } - } - }, _dllName); - } - - /// - /// 执行收集到的函数 - /// - static void RunFunctions(List runClassList) - { - for (int i = 0; i < runClassList.Count; i++) - runClassList[i].Run(); - runClassList.Clear(); - } - -#if Debug - /// - /// 检查当前程序域重复出现命令, - /// 当出现重复时候将引起断点 - /// - public static void DebugCheckCmdRecurrence() - { - HashSet keys = new(); - - // 本dll中存在冲突命令,此时cad自动接口可以运行,但是加载命令之后会报错,因此利用断点告诉程序员 - AutoReflection.AppDomainGetTypes(type => { - var mets = type.GetMethods(); - for (int ii = 0; ii < mets.Length; ii++) - { - var method = mets[ii]; - var attr = method.GetCustomAttributes(true); - for (int jj = 0; jj < attr.Length; jj++) - if (attr[jj] is CommandMethodAttribute att) - { - if (keys.Contains(att.GlobalName)) - Debugger.Break(); - keys.Add(att.GlobalName); - } - } - }, Assembly.GetCallingAssembly().GetName().Name); - - // 其他dll中存在冲突命令,此时会覆盖命令,友好的提示程序员 - keys.Clear(); - HashSet msgMod = new(); - AutoReflection.AppDomainGetTypes(type => { - var mets = type.GetMethods(); - for (int ii = 0; ii < mets.Length; ii++) - { - var method = mets[ii]; - var attr = method.GetCustomAttributes(true); - for (int jj = 0; jj < attr.Length; jj++) - if (attr[jj] is CommandMethodAttribute att) - { - if (keys.Contains(att.GlobalName)) - msgMod.Add(att.GlobalName); - keys.Add(att.GlobalName); - } - } - }); - var sb = new StringBuilder(); - foreach (string key in msgMod) - sb.AppendLine(key); - if (sb.Length != 0) - { - Env.Printl("当前cad环境加载的多个DLL中存在重复命令将被覆盖:"); - Env.Printl("{"); - Env.Printl(sb.ToString()); - Env.Printl("}"); - } - } -#endif -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/AutoReg/MethodInfoHelper.cs b/src/CAD/IFox.CAD.Shared/AutoReg/MethodInfoHelper.cs deleted file mode 100644 index 7aa9579..0000000 --- a/src/CAD/IFox.CAD.Shared/AutoReg/MethodInfoHelper.cs +++ /dev/null @@ -1,64 +0,0 @@ - - -namespace IFoxCAD.Cad; - -internal static class MethodInfoHelper -{ -#if cache - private static readonly Dictionary methodDic = new(); -#endif - - /// - /// 执行函数 - /// - /// 函数 - /// 已经外部创建的对象,为空则此处创建 - public static object? Invoke(this MethodInfo methodInfo, ref object? instance) - { - ArgumentNullEx.ThrowIfNull(methodInfo); - object? result = null; - if (methodInfo.IsStatic) - { - // 新函数指针进入此处 - // 参数数量一定要匹配,为null则参数个数不同导致报错, - // 参数为stirng[],则可以传入object[]代替,其他参数是否还可以实现默认构造? - var args = new List(); - var paramInfos = methodInfo.GetParameters(); - for (var i = 0; i < paramInfos.Length; i++) - args.Add(null!); - result = methodInfo.Invoke(null, args.ToArray());// 静态调用 - } - else - { -#if cache - // 原命令的函数指针进入此处 - // object instance; - if (methodDic.ContainsKey(methodInfo)) - instance = methodDic[methodInfo]; -#endif - if (instance == null) - { - var reftype = methodInfo.ReflectedType; - if (reftype == null) - return null; - - var fullName = reftype.FullName; // 命名空间+类 - if (fullName == null) - return null; - - var type = reftype.Assembly.GetType(fullName); - if (type == null) - return null; - - instance = Activator.CreateInstance(type);// 构造类 -#if cache - if (!type.IsAbstract)// 无法创建抽象类成员 - methodDic.Add(methodInfo, instance); -#endif - } - if (instance != null) - result = methodInfo.Invoke(instance, null); // 非静态,调用实例化方法 - } - return result; - } -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/CadVersion/AcadVersion.cs b/src/CAD/IFox.CAD.Shared/CadVersion/AcadVersion.cs deleted file mode 100644 index bfaa57d..0000000 --- a/src/CAD/IFox.CAD.Shared/CadVersion/AcadVersion.cs +++ /dev/null @@ -1,57 +0,0 @@ -namespace IFoxCAD.Cad; - -/// -/// cad版本号类 -/// -public static class AcadVersion -{ - private static readonly string _pattern = @"Autodesk\\AutoCAD\\R(\d+)\.(\d+)\\.*?"; - - /// - /// 所有安装的cad的版本号 - /// - public static List Versions - { - get - { - string[] copys = Registry.LocalMachine - .OpenSubKey(@"SOFTWARE\Autodesk\Hardcopy")! - .GetValueNames(); - - List _versions = []; - _versions.AddRange(from t in copys - where Regex.IsMatch(t, _pattern) - let gs = Regex.Match(t, _pattern).Groups - select new CadVersion - { - ProductRootKey = t, - ProductName = Registry.LocalMachine.OpenSubKey("SOFTWARE")!.OpenSubKey(t) - ?.GetValue("ProductName") - .ToString(), - Major = int.Parse(gs[1].Value), - Minor = int.Parse(gs[2].Value), - }); - return _versions; - } - } - - /// 已打开的cad的版本号 - /// 已打开cad的application对象 - /// cad版本号对象 - public static CadVersion? FromApp(object app) - { - ArgumentNullEx.ThrowIfNull(app); - - var acver = app.GetType() - .InvokeMember( - "Version", - BindingFlags.GetProperty, - null, - app, []).ToString(); - - var gs = Regex.Match(acver, @"(\d+)\.(\d+).*?").Groups; - var major = int.Parse(gs[1].Value); - var minor = int.Parse(gs[2].Value); - return Versions.FirstOrDefault(t => t.Major == major && t.Minor == minor); - } -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/CadVersion/CadVersion.cs b/src/CAD/IFox.CAD.Shared/CadVersion/CadVersion.cs deleted file mode 100644 index 98d05a9..0000000 --- a/src/CAD/IFox.CAD.Shared/CadVersion/CadVersion.cs +++ /dev/null @@ -1,41 +0,0 @@ -namespace IFoxCAD.Cad; - -/// -/// CAD版本 -/// -public record CadVersion -{ - /// - /// 主版本 - /// - public int Major; - - /// - /// 次版本 - /// - public int Minor; - - /// - /// 版本号 - /// - public double ProgId => double.Parse($"{Major}.{Minor}"); - - /// - /// 注册表名称 - /// - public string? ProductName; - - /// - /// 注册表位置 - /// - public string? ProductRootKey; - - /// - /// 转换为字符串 - /// - /// 表示版本号的字符串 - public override string ToString() - { - return $"名称:{ProductName}\n版本号:{ProgId}\n注册表位置:{ProductRootKey}"; - } -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/Copyclip/BitmapTool.cs b/src/CAD/IFox.CAD.Shared/Copyclip/BitmapTool.cs deleted file mode 100644 index e16ad87..0000000 --- a/src/CAD/IFox.CAD.Shared/Copyclip/BitmapTool.cs +++ /dev/null @@ -1,165 +0,0 @@ -namespace IFoxCAD.Cad; - -using System; -/// -/// bitmap工具类 -/// -public class BitmapTool -{ - // https://blog.csdn.net/shellching/article/details/18405185 - /// Windows不允许程序员直接访问硬件, - /// 它对屏幕的操作是通过环境设备,也就是DC来完成的 - /// 屏幕上的每一个窗口都对应一个DC,可以把DC想象成一个视频缓冲区, - /// 对这这个缓冲区的操作,会表现在这个缓冲区对应的屏幕窗口上. - /// 在窗口的DC之外,可以建立自己的DC,就是说它不对应窗口, - /// 这个方法就是 CreateCompatibleDC,这个DC就是一个内存缓冲区, - /// 通过这个DC你可以把和它兼容的窗口DC保存到这个DC中, - /// 就是说你可以通过它在不同的DC之间拷贝数据. - /// 例如:你先在这个DC中建立好数据,然后在拷贝到窗口的DC就是完成了这个窗口的刷新 - - /// - /// 检索指定窗口的工作区的显示设备上下文(DC)的句柄
- /// 显示设备上下文可以在随后的图形显示界面(GDI)函数中使用,
- /// 以在窗口的工作区中绘制
- ///
- /// - /// - [DllImport("user32.dll", SetLastError = true)] - public static extern IntPtr GetDC(IntPtr hWnd); - /// - /// - /// - /// - /// - /// - [DllImport("user32.dll")] - public static extern bool ReleaseDC(IntPtr hWnd, IntPtr hDC); - - /// - /// 创建DC - /// - /// - /// - [DllImport("gdi32.dll", EntryPoint = "CreateCompatibleDC", SetLastError = true)] - public static extern IntPtr CreateCompatibleDC([In] IntPtr hdc); - - /// - /// Creates a bitmap compatible with the device that is associated with the specified device context. - /// - /// A handle to a device context. - /// The bitmap width, in pixels. - /// The bitmap height, in pixels. - /// If the function succeeds, the return value is a handle to the compatible bitmap (DDB). If the function fails, the return value is . - [DllImport("gdi32.dll", EntryPoint = "CreateCompatibleBitmap")] - public static extern IntPtr CreateCompatibleBitmap([In] IntPtr hdc, int nWidth, int nHeight); - - /// Selects an object into the specified device context (DC). The new object replaces the previous object of the same type. - /// A handle to the DC. - /// A handle to the object to be selected. - /// - /// If the selected object is not a region and the function succeeds, the return value is a handle to the object being replaced. If the selected object is a region and the function succeeds, the return value is one of the following values. - /// SIMPLEREGION - Region consists of a single rectangle. - /// COMPLEXREGION - Region consists of more than one rectangle. - /// NULLREGION - Region is empty. - /// If an error occurs and the selected object is not a region, the return value is NULL. Otherwise, it is HGDI_ERROR. - /// - /// - /// This function returns the previously selected object of the specified type. An application should always replace a new object with the original, default object after it has finished drawing with the new object. - /// An application cannot select a single bitmap into more than one DC at a time. - /// ICM: If the object being selected is a brush or a pen, color management is performed. - /// - [DllImport("gdi32.dll", EntryPoint = "SelectObject")] - public static extern IntPtr SelectObject([In] IntPtr hdc, [In] IntPtr hgdiobj); - - /// Deletes a logical pen, brush, font, bitmap, region, or palette, freeing all system resources associated with the object. After the object is deleted, the specified handle is no longer valid. - /// A handle to a logical pen, brush, font, bitmap, region, or palette. - /// - /// If the function succeeds, the return value is nonzero. - /// If the specified handle is not valid or is currently selected into a DC, the return value is zero. - /// - /// - /// Do not delete a drawing object (pen or brush) while it is still selected into a DC. - /// When a pattern brush is deleted, the bitmap associated with the brush is not deleted. The bitmap must be deleted independently. - /// - [DllImport("gdi32.dll", EntryPoint = "DeleteObject")] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool DeleteObject([In] IntPtr hObject); - - /// - /// 指定的源设备环境区域中的像素进行位块转换,以传送到目标设备环境 - /// - /// Handle to the destination device context. - /// The leftmost x-coordinate of the destination rectangle (in pixels). - /// The topmost y-coordinate of the destination rectangle (in pixels). - /// The width of the source and destination rectangles (in pixels). - /// The height of the source and the destination rectangles (in pixels). - /// Handle to the source device context. - /// The leftmost x-coordinate of the source rectangle (in pixels). - /// The topmost y-coordinate of the source rectangle (in pixels). - /// A raster-operation code. - /// - /// true if the operation succeedes, false otherwise. To get extended error information, call . - /// - [DllImport("gdi32.dll", EntryPoint = "BitBlt", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool BitBlt([In] IntPtr hdc, int nXDest, int nYDest, int nWidth, int nHeight, [In] IntPtr hdcSrc, int nXSrc, int nYSrc, TernaryRasterOperations dwRop); - /// - /// A raster-operation code enum - /// - public enum TernaryRasterOperations : uint - { - -#pragma warning disable CS1591 // 缺少对公共可见类型或成员的 XML 注释 - SRCCOPY = 0x00CC0020, - SRCPAINT = 0x00EE0086, - SRCAND = 0x008800C6, - SRCINVERT = 0x00660046, - SRCERASE = 0x00440328, - NOTSRCCOPY = 0x00330008, - NOTSRCERASE = 0x001100A6, - MERGECOPY = 0x00C000CA, - MERGEPAINT = 0x00BB0226, - PATCOPY = 0x00F00021, - PATPAINT = 0x00FB0A09, - PATINVERT = 0x005A0049, - DSTINVERT = 0x00550009, - BLACKNESS = 0x00000042, - WHITENESS = 0x00FF0062, - CAPTUREBLT = 0x40000000 //only if WinVer >= 5.0.0 (see wingdi.h) -#pragma warning restore CS1591 // 缺少对公共可见类型或成员的 XML 注释 - } - - /// - /// 截图成为BMP - /// - /// 截图的窗口 - /// 扔出BMP执行任务 - /// - public static void CaptureWndImage(IntPtr hWnd, Action action) - { - //if (action == null) - // throw new ArgumentNullException(nameof(action)); - ArgumentNullEx.ThrowIfNull(action); - var hDC = GetDC(hWnd); - var hMemDC = CreateCompatibleDC(hDC); - if (hMemDC == IntPtr.Zero) - return; - - WindowsAPI.GetClientRect(hWnd, out WindowsAPI.IntRect rcClient); - int width = rcClient.Right - rcClient.Left; - int height = rcClient.Bottom - rcClient.Top; - - var hBitmap = CreateCompatibleBitmap(hDC, width, height); - if (hBitmap != IntPtr.Zero) - { - SelectObject(hMemDC, hBitmap); - if (BitBlt(hMemDC, 0, 0, width, height, - hDC, 0, 0, TernaryRasterOperations.SRCCOPY)) - { - action.Invoke(hBitmap); - } - DeleteObject(hBitmap); - } - DeleteObject(hMemDC); - } -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/Copyclip/EmfTool.cs b/src/CAD/IFox.CAD.Shared/Copyclip/EmfTool.cs deleted file mode 100644 index 98cdd50..0000000 --- a/src/CAD/IFox.CAD.Shared/Copyclip/EmfTool.cs +++ /dev/null @@ -1,927 +0,0 @@ -#pragma warning disable CS1591 // 缺少对公共可见类型或成员的 XML 注释 -namespace IFoxCAD.Cad; - -using System; -using System.Diagnostics; -using System.Drawing; -using System.Drawing.Imaging; -using System.Text; -using static IFoxCAD.Basal.WindowsAPI; -using Point = System.Drawing.Point; -using Size = System.Drawing.Size; - -// DWORD == uint -// WORD == ushort -// LONG == int - -/* - * Console.WriteLine(Marshal.SizeOf(typeof(PlaceableMetaHeader))); - * Console.WriteLine(Marshal.SizeOf(typeof(WindowsMetaHeader))); - * Console.WriteLine(Marshal.SizeOf(typeof(StandardMetaRecord))); - */ - - -// https://learn.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-metafilepict -// http://www.cppblog.com/zwp/archive/2012/02/25/60225.html -[Serializable] -[StructLayout(LayoutKind.Sequential, Pack = 2)] - -public struct MetaFilePict - - -{ - public MappingModes mm; - public int xExt; - public int yExt; - public IntPtr hMF; //内存图元文件的句柄 -} - -public enum MappingModes : int -{ - MM_TEXT = 1, - MM_LOMETRIC = 2, - MM_HIMETRIC = 3, - MM_LOENGLISH = 4,//逻辑坐标的单位为0.01英寸 - MM_HIENGLISH = 5, - MM_TWIPS = 6, - MM_ISOTROPIC = 7, - MM_ANISOTROPIC = 8, - - //Minimum and Maximum Mapping Mode values - MM_MIN = MM_TEXT, - MM_MAX = MM_ANISOTROPIC, - MM_MAX_FIXEDSCALE = MM_TWIPS, -} - - -//WMF 文件格式: -//https://blog.51cto.com/chenyanxi/803247 -//文件缩放信息:22字节 -[Serializable] -[StructLayout(LayoutKind.Sequential, Pack = 2)] -public struct PlaceableMetaHeader -{ - public uint Key; /* 固定大小以相反顺序出现 9AC6CDD7h */ - public ushort Handle; /* Metafile HANDLE number (always 0) */ - - public short Left; /* Left coordinate in metafile units */ - public short Top; /* Top coordinate in metafile units */ - public short Right; /* Right coordinate in metafile units */ - public short Bottom; /* Bottom coordinate in metafile units */ - - public ushort Inch; /* Number of metafile units per inch */ - public uint Reserved; /* Reserved (always 0) */ - public ushort Checksum; /* Checksum value for previous 10 WORDs */ - - // 微软的wmf文件分为两种一种是标准的图元文件, - // 一种是活动式图元文件,活动式图元文件 与 标准的图元文件 的主要区别是, - // 活动式图元文件包含了图像的原始大小和缩放信息. - /// - /// 是活动式图元文件 - /// - public bool IsActivity => Key == 0x9AC6CDD7; - - /// - /// wmf转为emf
- ///
- /// 文件路径 - /// - /// 错误: ;
- /// 成功: 返回一个增强型图元 emf文件句柄 (位于内存中) - ///
- /// - public static IntPtr Wmf2Emf(string wmfFile) - { - using FileStream file = new(wmfFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); // FileShare才能进c盘 - if (file.Length == 0) - throw new IOException("文件字节0长:" + file); - if (file.Length < 5) - throw new IOException("无法校验文件签名:" + file); - - var fileByte = new byte[file.Length]; - file.Read(fileByte, 0, fileByte.Length); - file.Close(); - - var sWMF = BytesToStruct(fileByte); - // 转为emf的地址 - IntPtr hEMF = IntPtr.Zero; - - // 控制输出的时候跟cad一样带有一个矩形框边界,而不是所有图元的包围盒作为边界 - var mpType = new MetaFilePict - { - mm = MappingModes.MM_ANISOTROPIC, - xExt = sWMF.Right - sWMF.Left, - yExt = sWMF.Bottom - sWMF.Top, - hMF = IntPtr.Zero - }; - - // byte[] 指针偏移 - int iOffset = 0; - if (sWMF.IsActivity) - iOffset = Marshal.SizeOf(typeof(PlaceableMetaHeader)); - - unsafe - { - // 安全指针方法 - //IntPtr fileIntPtr = Marshal.UnsafeAddrOfPinnedArrayElement(fileByte, iOffset); - // 不安全指针方法 - fixed (byte* fileIntPtr = &fileByte[iOffset]) - hEMF = EmfTool.SetWinMetaFileBits( - (uint)fileByte.Length, new IntPtr(fileIntPtr), IntPtr.Zero, new IntPtr(&mpType)); - } - return hEMF; - } -} - -public class Emf -{ - public IntPtr EmfHandle; - - /// - /// 转换wmf到emf - /// - /// - public void Wmf2Emf(string wmfFile) - { - EmfHandle = PlaceableMetaHeader.Wmf2Emf(wmfFile);//emf文件句柄 - } - - /// - /// 获取emf结构 - /// - /// - public EnhMetaHeader CreateEnhMetaHeader() - { - if (EmfHandle == IntPtr.Zero) - throw new ArgumentException(nameof(EmfHandle) + "== IntPtr.Zero"); - return EnhMetaHeader.Create(EmfHandle); - } -} - -//紧接文件缩放信息的是 WMFHEAD, 18字节 -[Serializable] -[StructLayout(LayoutKind.Sequential, Pack = 2)] -public struct WindowsMetaHeader -{ - public ushort FileType; /* Type of metafile (0=memory, 1=disk) */ - public ushort HeaderSize; /* Size of header in WORDS (always 9) */ - public ushort Version; /* Version of Microsoft Windows used */ - public uint FileSize; /* Total size of the metafile in WORDs */ - public ushort NumOfObjects; /* Number of objects in the file */ - public uint MaxRecordSize; /* The size of largest record in WORDs */ - public ushort NumOfParams;    /* Not Used (always 0) */ -} - -//紧接 WMFHEAD 的是 WMFRECORD, 14字节 -[Serializable] -[StructLayout(LayoutKind.Sequential, Pack = 2)] -public struct StandardMetaRecord -{ - public uint Size; /* Total size of the record in WORDs */ - public ushort Function; /* Function number (defined in WINDOWS.H) */ - public ushort[] Parameters;  /* Parameter values passed to function */ -} - -// 文件结构:头记录(ENHMETAHEADER),各记录(ENHMETARECORD),文件结尾(EMR_EOF) -// https://www.cnblogs.com/5iedu/p/4706327.html -[Serializable] -[StructLayout(LayoutKind.Sequential, Pack = 2)] -public struct EnhMetaHeader -{ - [Description("记录类型")] - public uint iType; - [Description("结构大小")] - public int nSize; //注意这个大小是含描述字符串的长度,即等于sizeof(ENHMETAHEADER)+nDescription*2 - [Description("外接矩形(单位是像素)")] - public IntRect rclBounds; - [Description("图片矩形(单位是 0.1 毫米)")] - public IntRect rclFrame; - [Description("文件签名")] - public uint dSignature; - [Description("文件版本")] - public uint nVersion; - [Description("文件尺寸")] - public uint nBytes; - [Description("记录数")] - public uint nRecords; - [Description("句柄数")] - public ushort nHandles; - [Description("保留")] - public ushort sReserved; - [Description("说明文本的长度")] - public uint nDescription; - [Description("说明文本的偏移量")] - public uint offDescription; - [Description("调色板的元素数")] - public uint nPalEntries; - [Description("分辨率(像素)")] - public IntSize szlDevice; - [Description("分辨率(毫米)")] - public IntSize szlMillimeters; - [Description("像素格式的尺寸")] - public uint cbPixelFormat; - [Description("像素格式的起始偏移位置")] - public uint offPixelFormat; - [Description("在不含OpenGL记录时,该值为FALSE")] - public uint bOpenGL; - [Description("参考设备的尺寸(微米)")] - public IntSize szlMicrometers; - - public override string ToString() - { - //var tp = GetType(); - //var sb = new StringBuilder(); - //sb.AppendLine(EnumEx.GetDesc(tp, nameof(iType)) + ":" + iType); - - // 输出json - // NET472 System.Text.Json - var serializer = new System.Web.Script.Serialization.JavaScriptSerializer(); - string jsonString = serializer.Serialize(this); - return jsonString; - } - - /// - /// 通过wmf创建 - /// - /// - /// - public static EnhMetaHeader Create(string wmf) - { - var emf = PlaceableMetaHeader.Wmf2Emf(wmf); - if (emf == IntPtr.Zero) - throw new ArgumentException(nameof(emf)); - return Create(emf); - } - - /// - /// 通过emf指针创建 - /// - /// 参数1的结构体首地址
- /// 也就是的返回值 - /// - /// - public static EnhMetaHeader Create(IntPtr emf) - { - var len = EmfTool.GetEnhMetaFileHeader(emf, 0, IntPtr.Zero); - if (len == 0) - throw new ArgumentException(nameof(len)); - - IntPtr header = Marshal.AllocHGlobal((int)len); - EmfTool.GetEnhMetaFileHeader(emf, len, header);//这里是切割获取内部的bytes,存放在header - - var result = (EnhMetaHeader)Marshal.PtrToStructure(header, typeof(EnhMetaHeader)); - - Marshal.FreeHGlobal(header); - return result; - } -} - - - -public static class EmfTool -{ - /// - /// 保存 - /// - /// GetEnhMetaFileBits 参数1的结构体首地址 - /// 保存路径 - /// - public static void Save(IntPtr clipTypeData, string file) - { - // 保存emf文件 - // https://blog.csdn.net/tigertianx/article/details/7098490 - var len = EmfTool.GetEnhMetaFileBits(clipTypeData, 0, null!); - if (len != 0) - { - var bytes = new byte[len]; - _ = EmfTool.GetEnhMetaFileBits(clipTypeData, len, bytes); - - using MemoryStream ms1 = new(bytes); - using var bm = Image.FromStream(ms1);//此方法emf保存成任何版本都会变成png - bm.Save(file); - } - } - - /// - /// 返回对一个增强型图元文件的说明 - /// - /// 目标增强型图元文件的句柄 - /// lpszDescription缓冲区的长度 - /// 指定一个预先初始化好的字串缓冲区,准备随同图元文件说明载入; - /// 参考 CreateEnhMetaFile 函数,了解增强型图元文件说明字串的具体格式 - /// - [DllImport("gdi32.dll")] - static extern uint GetEnhMetaFileDescription(IntPtr hemf, uint cchBuffer, [MarshalAs(UnmanagedType.LPStr)] StringBuilder lpDescription); - - /// - /// 获取emf描述 - /// - /// 文件句柄 - /// 描述的内容 - [System.Diagnostics.DebuggerStepThrough] - [System.CodeDom.Compiler.GeneratedCode("InteropSignatureToolkit", "0.9 Beta1")]//初始化时指定生成代码的工具的名称和版本 - public static string? GetEnhMetaFileDescriptionEx(IntPtr clipTypeData) - { - var len = GetEnhMetaFileDescription(clipTypeData, 0, null!); - if (len != 0) - { - StringBuilder desc = new((int)len); - GetEnhMetaFileDescription(clipTypeData, (uint)desc.Capacity, desc); - return desc.ToString(); - } - return null; - } - - public enum DeviceCap : int - { - /// - /// Device driver version - /// - DRIVERVERSION = 0, - /// - /// Device classification - /// - TECHNOLOGY = 2, - /// - /// Horizontal size in millimeters - /// - HORZSIZE = 4, - /// - /// Vertical size in millimeters - /// - VERTSIZE = 6, - /// - /// Horizontal width in pixels - /// - HORZRES = 8, - /// - /// Vertical height in pixels - /// - VERTRES = 10, - /// - /// Number of bits per pixel - /// - BITSPIXEL = 12, - /// - /// Number of planes - /// - PLANES = 14, - /// - /// Number of brushes the device has - /// - NUMBRUSHES = 16, - /// - /// Number of pens the device has - /// - NUMPENS = 18, - /// - /// Number of markers the device has - /// - NUMMARKERS = 20, - /// - /// Number of fonts the device has - /// - NUMFONTS = 22, - /// - /// Number of colors the device supports - /// - NUMCOLORS = 24, - /// - /// Size required for device descriptor - /// - PDEVICESIZE = 26, - /// - /// Curve capabilities - /// - CURVECAPS = 28, - /// - /// Line capabilities - /// - LINECAPS = 30, - /// - /// Polygonal capabilities - /// - POLYGONALCAPS = 32, - /// - /// Text capabilities - /// - TEXTCAPS = 34, - /// - /// Clipping capabilities - /// - CLIPCAPS = 36, - /// - /// Bitblt capabilities - /// - RASTERCAPS = 38, - /// - /// Length of the X leg - /// - ASPECTX = 40, - /// - /// Length of the Y leg - /// - ASPECTY = 42, - /// - /// Length of the hypotenuse - /// - ASPECTXY = 44, - /// - /// Shading and Blending caps - /// - SHADEBLENDCAPS = 45, - - /// - /// Logical pixels inch in X - /// - LOGPIXELSX = 88, - /// - /// Logical pixels inch in Y - /// - LOGPIXELSY = 90, - - /// - /// Number of entries in physical palette - /// - SIZEPALETTE = 104, - /// - /// Number of reserved entries in palette - /// - NUMRESERVED = 106, - /// - /// Actual color resolution - /// - COLORRES = 108, - - // Printing related DeviceCaps. These replace the appropriate Escapes - /// - /// Physical Width in device units - /// - PHYSICALWIDTH = 110, - /// - /// Physical Height in device units - /// - PHYSICALHEIGHT = 111, - /// - /// Physical Printable Area x margin - /// - PHYSICALOFFSETX = 112, - /// - /// Physical Printable Area y margin - /// - PHYSICALOFFSETY = 113, - /// - /// Scaling factor x - /// - SCALINGFACTORX = 114, - /// - /// Scaling factor y - /// - SCALINGFACTORY = 115, - - /// - /// Current vertical refresh rate of the display device (for displays only) in Hz - /// - VREFRESH = 116, - /// - /// Vertical height of entire desktop in pixels - /// - DESKTOPVERTRES = 117, - /// - /// Horizontal width of entire desktop in pixels - /// - DESKTOPHORZRES = 118, - /// - /// Preferred blt alignment - /// - BLTALIGNMENT = 119 - } - - [DllImport("gdi32.dll")] - static extern int GetDeviceCaps(IntPtr hDC, DeviceCap nIndex); - - [DllImport("gdi32.dll")] - static extern int SetMapMode(IntPtr hDC, MappingModes fnMapMode); - - [DllImport("gdi32.dll")] - static extern bool SetViewportOrgEx(IntPtr hDC, int x, int y, Point[] prevPoint); - - [DllImport("gdi32.dll")] - static extern bool SetWindowOrgEx(IntPtr hDC, int x, int y, Point[] prevPoint); - - [DllImport("gdi32.dll")] - static extern bool SetViewportExtEx(IntPtr hDC, int nExtentX, int nExtentY, Size[] prevSize); - - [DllImport("gdi32.dll")] - static extern bool SetWindowExtEx(IntPtr hDC, int nExtentX, int nExtentY, Size[] prevSize); - - [DllImport("Gdi32.dll")] - public static extern int CreatePen(int nPenStyle, int nWidth, int nColor); - - [DllImport("Gdi32.dll")] - public static extern int GetStockObject(int nStockBrush); - - [DllImport("Gdi32.dll")] - public static extern int SelectObject(IntPtr hDC, int hGdiObject); - - [DllImport("Gdi32.dll")] - public static extern int DeleteObject(int hBitmap); - - [DllImport("Gdi32.dll")] - public static extern int MoveToEx(IntPtr hDC, int x, int y, int nPreviousPoint); - - [DllImport("Gdi32.dll")] - public static extern int LineTo(IntPtr hDC, int x, int y); - - [DllImport("Gdi32.dll")] - public static extern int Rectangle(IntPtr hDC, int nLeft, int nTop, int nRight, int nBottom); - - [DllImport("Gdi32.dll")] - public static extern bool DPtoLP(IntPtr hdc, [In, Out] Point[] lpPoints, int nCount); - - - /// - /// 设置emf描述 - /// - /// emf文件句柄 - /// 设置描述 - /// 新的emf指针 - /// - public static void SetEnhMetaFileDescriptionEx(ref IntPtr hMetaFile, string desc) - { - //if (hMetaFile == IntPtr.Zero) - // throw new ArgumentNullException(nameof(hMetaFile)); - ArgumentNullEx.ThrowIfNull(hMetaFile); - var emh = EnhMetaHeader.Create(hMetaFile);//emf结构 GetEnhMetaFileHeader - // 创建画布句柄 - IntRect intRect = emh.rclFrame; //new(0, 0, 0, 0); - var hMetaDC = EmfTool.CreateEnhMetaFile(IntPtr.Zero, null!, ref intRect, desc); - if (hMetaDC == IntPtr.Zero) - return; - //SetMapMode(hMetaDC, MappingModes.MM_ANISOTROPIC); // 默认的就是这个模式 - //SetMapMode(hMetaDC, MappingModes.MM_HIMETRIC);//逻辑单位:0.01mm - - // 设置单位 - //var size = new IntSize(0, 0); - //EmfTool.SetWindowExtEx(hMetaDC, 0, 0, ref size); - //EmfTool.SetViewportExtEx(hMetaDC, 0, 0, ref size); - //EmfTool.GetEnhMetaFilePaletteEntries() 统一调色 - //SetViewportOrgEx(hMetaDC, 0, 0, null!);//将视口原点设在左下角 - - // 旧的克隆到新的 - /* - * 第18章 图元文件_18.2 增强型图元文件(emf)(2) - * https://blog.51cto.com/u_15082403/3724715 - * 方案2——利用图像的物理尺寸 - * 通过rclFrame字段(是设备单位:0.01mm)显示出来的刻度尺,这样不管在视频显示器 - * 打印机上,显示出来的刻度尺都较为真实 - */ - //目标设备信息 - int cxMms = GetDeviceCaps(hMetaDC, DeviceCap.HORZSIZE);//宽度(单位:mm) - int cyMms = GetDeviceCaps(hMetaDC, DeviceCap.VERTSIZE);//高度(单位:mm) - var cxArea = cxMms; - var cyArea = cyMms; -#if true2 - int cxPix = GetDeviceCaps(hMetaDC, DeviceCap.HORZRES);//宽度(单位:像素) - int cyPix = GetDeviceCaps(hMetaDC, DeviceCap.VERTRES);//高度(单位:像素) - int cxImage = emh.rclFrame.Right - emh.rclFrame.Left; //单位:0.01mm - int cyImage = emh.rclFrame.Bottom - emh.rclFrame.Top; - - // 设置之后图像就没有拉伸了,但是跑偏了 - //将图元文件大小(0.01mm为单位)转换为像素大小 - cxImage = cxImage * cxPix / cxMms / 100; - cyImage = cyImage * cyPix / cyMms / 100; - - //在指定的矩形区内,水平和垂直居中显示图元文件,同时保证了区域的大小为cxImage和cyImage - int left = (cxArea - cxImage) / 2; - int right = (cxArea + cxImage) / 2; - int top = (cyArea - cyImage) / 2; - int bottom = (cyArea + cyImage) / 2; -#else - cxArea = 0; - cyArea = 0; - SetMapMode(hMetaDC, MappingModes.MM_HIMETRIC);//逻辑单位:0.01mm - SetViewportOrgEx(hMetaDC, 0, cyArea, null!);//将视口原点设在左下角 - var pt = new Point(cxArea, 0); - - int cxImage = emh.rclFrame.Right - emh.rclFrame.Left; //单位:0.01mm - int cyImage = emh.rclFrame.Bottom - emh.rclFrame.Top; - - //在指定的矩形区内,水平和垂直居中显示图元文件,同时保证了区域的大小为cxImage和cyImage - int left = (pt.X - cxImage) / 2; - int right = (pt.X + cxImage) / 2; - int top = (pt.Y + cyImage) / 2; //注意,这里与前面例子不同 - int bottom = (pt.Y - cyImage) / 2; //注意,这里与前面例子不同 -#endif - var rect = new IntRect(left, top, right, bottom); - - // 图像拉伸了 - //bool pef = EmfTool.EnumEnhMetaFile(hMetaDC, hMetaFile, IntPtr.Zero, IntPtr.Zero, ref emhValue.rclFrame);// 这个失败 - bool pef = EmfTool.PlayEnhMetaFile(hMetaDC, hMetaFile, ref rect); - if (!pef) - { - DeleteObject(hMetaDC); - Debugger.Break(); - return; - } - // 删除旧的图元文件句柄,返回新的 - var del = EmfTool.DeleteEnhMetaFile(hMetaFile); - if (del) - hMetaFile = EmfTool.CloseEnhMetaFile(hMetaDC); - } - - [DllImport("gdi32.dll", EntryPoint = "GetEnhMetaFileHeader")] - public static extern uint GetEnhMetaFileHeader(IntPtr hemf, uint cbBuffer, IntPtr /*ENHMETAHEADER*/ lpemh); - - - /// - /// 将一个标准Windows图元文件转换成增强型图元文件 - /// - /// 数组的长度 - /// - /// 数组包含了标准图元文件数据.
- /// 常用 GetMetaFileBitsEx 或 GetWinMetaFileBits 函数获得 - /// - /// - /// 用于决定原始格式及图元文件分辨率的一个参考设备场景;
- /// 采用显示器分辨率为: - /// - /// - /// 定义一个图元文件附加参考信息的结构
- /// 为null时,会假定使用当前显示器的 MM_ANISOTROPIC 映射模式 - /// - /// - /// 错误: ;
- /// 成功: 返回一个增强型图元emf文件的指针(位于内存中) - ///
- [DllImport("gdi32.dll", EntryPoint = "SetWinMetaFileBits")] - public static extern IntPtr SetWinMetaFileBits(uint nSize, IntPtr lpMeta16Data, IntPtr hdcRef, IntPtr lpMFP); - /// - /// 获取矢量图的byte - /// - /// - /// - /// - /// - [DllImport("gdi32.dll")] - public static extern uint GetEnhMetaFileBits(IntPtr hemf, uint cbBuffer, byte[] lpbBuffer); - /// - /// byte转换矢量图 - /// - /// - /// - /// - [DllImport("gdi32.dll")] - public static extern IntPtr SetEnhMetaFileBits(uint cbBuffer, byte[] lpBuffer); - /// - /// 删除矢量图 - /// - /// - /// - [DllImport("gdi32.dll")] - public static extern bool DeleteEnhMetaFile(IntPtr hemf); - - /// - /// 创建emf
- /// https://www.cnblogs.com/5iedu/p/4706327.html - ///
- /// 参考设备环境,null以整个屏幕为参考 - /// 指定文件名时,创建磁盘文件(.EMF),为null时创建内存图元文件 - /// 用于描述图元文件的大小和位置(以0.01mm为单位),可用它精确定义图元文件的物理尺寸 - /// 对图元文件的一段说明.包括创建应用程序的名字、一个NULL字符、对图元文件的一段说明以及两个NULL字符. - /// 返回画布句柄DC(图元文件句柄得调用 CloseEnhMetaFile 函数) - [DllImport("gdi32.dll", SetLastError = true)] - public static extern IntPtr CreateEnhMetaFile(IntPtr hdcRef, string szFilename, ref IntRect lpRect, string lpDescription); - - [DllImport("gdi32.dll", SetLastError = true)] - public static extern bool DeleteObject(IntPtr hdcRef); - - /// - /// 在指定的设备场景中画一个增强型图元文件;
- /// 与标准图元文件不同,完成回放后,增强型图元文件会恢复设备场景以前的状态 - ///
- /// 画布句柄 - /// 欲描绘的emf的图元文件句柄 - /// 指定显示区域(逻辑单位)GDI会缩放图像以适应该矩形范围 - /// - [DllImport("gdi32.dll")] - public static extern bool PlayEnhMetaFile(IntPtr hdcRef, IntPtr hemf, ref IntRect lpRect); - - // https://blog.csdn.net/hongke457546235/article/details/17404715 - /// - /// 逻辑单位设置窗口单位 - /// {只能在 MM_ISOTROPIC 或 MM_ANISOTROPIC 模式下使用下面两个函数} - /// - /// 画布句柄 - /// 以逻辑单位表示的新窗口区域的高度 - /// 以逻辑单位表示的新窗口区域的宽度 - /// 保存函数调用前窗口区域尺寸的SIZE结构地址,NULL则表示忽略调用前的尺寸 - [DllImport("gdi32.dll")] - public static extern bool SetWindowExtEx(IntPtr hdcRef, int nHeight, int nWidth, ref IntSize lpSize); - - /// - /// 视口区域的定义 - /// {只能在 MM_ISOTROPIC 或 MM_ANISOTROPIC 模式下使用下面两个函数} - /// - /// - /// - /// - /// - [DllImport("gdi32.dll")] - public static extern bool SetViewportExtEx(IntPtr hdcRef, int nHeight, int nWidth, ref IntSize lpSize); - - /// - /// 旧emf绘制新的hdcEMF中(即回放) - /// - /// 画布句柄 - /// 图元文件句柄 - /// 回调函数 - /// 传给回调函数的额外参数 - /// 在指定的矩形区内显示图元文件 - /// - [DllImport("gdi32.dll", SetLastError = true)] - public static extern bool EnumEnhMetaFile(IntPtr hdcRef, IntPtr hmf, IntPtr proc, IntPtr procParam, ref IntRect lpRect); - - /// - /// 返回图元文件句柄 - /// - /// 画布句柄 - [DllImport("gdi32.dll", SetLastError = true)] - public static extern IntPtr CloseEnhMetaFile(IntPtr hdcRef); - - // https://zhidao.baidu.com/question/646739770512964165/answer/1616737219.html?qq-pf-to=pcqq.c2c - //16位的函数 - [DllImport("gdi32.dll")] - public static extern IntPtr GetMetaFile(string path); - //32位的函数 - [DllImport("gdi32.dll")] - public static extern IntPtr GetEnhMetaFile(string path); - - - - /// - /// EMF保存到文件或者路径 - /// - /// EMF要复制的增强型图元文件的句柄 - /// 指向目标文件名称的指针,为NULL则将源图元文件复制到内存中 - /// - [DllImport("gdi32.dll")] - public static extern IntPtr CopyEnhMetaFile(IntPtr hemfSrc, string? lpszFile); - - /// - /// 矢量图保存 - /// - /// - /// - public static void SaveMetaFile(this Metafile file, string emfName) - { - //MetafileHeader metafileHeader = file.GetMetafileHeader(); //这句话可要可不要 - IntPtr h = file.GetHenhmetafile(); - CopyEnhMetaFile(h, emfName); - DeleteEnhMetaFile(h); - } - - /// - /// 矢量图 转换 byte[] - /// - /// - /// - public static byte[]? ToByteArray(this Image image) - { - return ToByteArray((Metafile)image); - } - - // https://www.pinvoke.net/default.aspx/gdi32.getenhmetafile - /// - /// 矢量图 转换 byte[] - /// - /// - /// - public static byte[]? ToByteArray(this Metafile mf) - { - byte[]? arr = null; - IntPtr handle = mf.GetHenhmetafile(); - if (handle != IntPtr.Zero) - { - var size = GetEnhMetaFileBits(handle, 0, null!); - if (size != 0) - { - arr = new byte[size]; - _ = GetEnhMetaFileBits(handle, size, arr); - } - DeleteEnhMetaFile(handle); - } - return arr; - } - - /// - /// byte[] 转换 矢量图 - /// - /// - /// 返回值true删除句柄 - /// - public static void ToMetafile(byte[] data, Func task) - { - //if (task == null) - // throw new ArgumentNullException(nameof(task)); - ArgumentNullEx.ThrowIfNull(task); - IntPtr hemf = SetEnhMetaFileBits((uint)data.Length, data); - using var mf = new Metafile(hemf, true); - if (task.Invoke(mf)) // 对图像进行操作,就不能进行删除句柄 - DeleteEnhMetaFile(hemf); - } - - -#if false - /// - /// c#获取wmf方式 - /// - /// - /// - public static IntPtr GetMetafile(string wmfFile) - { - using FileStream file = new(wmfFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); // FileShare才能进c盘 - var hEMF2 = IntPtr.Zero; - - using Metafile mf = new(file); - var hEMF = mf.GetHenhmetafile(); - if (hEMF != IntPtr.Zero) - hEMF2 = CopyEnhMetaFile(hEMF, null);// 这句: 句柄无效..cad的wmf文件不识别 - //EmfTool.DeleteEnhMetaFile(hEMF);//托管类应该是封装好的 - return hEMF2; - } - - - /* - * // 这是c#写入wmf流程 - * // c#画的wmf格式是可以的...用这样方式生成的就是可以写剪贴板 - * WindowsAPI.GetClientRect(doc.Window.Handle, out IntRect rcClient); - * int width = rcClient.Right - rcClient.Left; - * int height = rcClient.Bottom - rcClient.Top; - * EmfTool.Export(wmf, width, height);//cad的命令wmfin:不能导入c#自绘的 - * - * //c#方法,但是它读取不了cad的wmf - * wmfMeta = EmfTool.GetMetafile(wmf); - */ - - /// - /// 导出为 Emf 或 Wmf 文件 - /// 相关链接 - /// - /// 文件路径 - /// 窗口宽度 - /// 窗口高度 - /// 是否成功 - public static bool Export(string filePath, int width, int height) - { - try - { - using Bitmap bmp = new(width, height); - using Graphics gs = Graphics.FromImage(bmp); - using Metafile mf = new(filePath, gs.GetHdc()); - using Graphics g = Graphics.FromImage(mf); - Draw(g); - g.Save(); - return true; - } - catch { return false; } - } - - - /// - /// 绘制图形 - /// - /// 用于绘图的Graphics对象 - static void Draw(Graphics g) - { - HatchBrush hb = new(HatchStyle.LightUpwardDiagonal, Color.Black, Color.White); - - g.FillEllipse(Brushes.Gray, 10f, 10f, 200, 200); - g.DrawEllipse(new Pen(Color.Black, 1f), 10f, 10f, 200, 200); - - g.FillEllipse(hb, 30f, 95f, 30, 30); - g.DrawEllipse(new Pen(Color.Black, 1f), 30f, 95f, 30, 30); - - g.FillEllipse(hb, 160f, 95f, 30, 30); - g.DrawEllipse(new Pen(Color.Black, 1f), 160f, 95f, 30, 30); - - g.FillEllipse(hb, 95f, 30f, 30, 30); - g.DrawEllipse(new Pen(Color.Black, 1f), 95f, 30f, 30, 30); - - g.FillEllipse(hb, 95f, 160f, 30, 30); - g.DrawEllipse(new Pen(Color.Black, 1f), 95f, 160f, 30, 30); - - g.FillEllipse(Brushes.Blue, 60f, 60f, 100, 100); - g.DrawEllipse(new Pen(Color.Black, 1f), 60f, 60f, 100, 100); - - g.FillEllipse(Brushes.BlanchedAlmond, 95f, 95f, 30, 30); - g.DrawEllipse(new Pen(Color.Black, 1f), 95f, 95f, 30, 30); - - g.DrawRectangle(new Pen(Brushes.Blue, 0.1f), 6, 6, 208, 208); - - g.DrawLine(new Pen(Color.Black, 0.1f), 110f, 110f, 220f, 25f); - g.DrawString("剖面图", new Font("宋体", 9f), Brushes.Green, 220f, 20f); - } -#endif -} -#pragma warning restore CS1591 // 缺少对公共可见类型或成员的 XML 注释 \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/Copyclip/TagClipboardInfo.cs b/src/CAD/IFox.CAD.Shared/Copyclip/TagClipboardInfo.cs deleted file mode 100644 index 91cdcd9..0000000 --- a/src/CAD/IFox.CAD.Shared/Copyclip/TagClipboardInfo.cs +++ /dev/null @@ -1,662 +0,0 @@ -#pragma warning disable CS1591 // 缺少对公共可见类型或成员的 XML 注释 -namespace IFoxCAD.Cad; - -using System; -using System.Diagnostics; -using System.Text; -using static IFoxCAD.Basal.WindowsAPI; - -public class ClipboardEnv -{ - // 0x01 将r17写死,代表每个cad版本都去找它,实现不隔离cad版本 - public static string CadVer = "AutoCAD.r17"; - // 0x02 当前版本在r17找不到的时候找,避免按需加载插件的时候无法获取剪贴板 - public static string CadCurrentVer = $"AutoCAD.r{Acap.Version.Major}"; -} - -/// -/// ARX剪贴板结构 -/// -[Serializable] -[StructLayout(LayoutKind.Sequential, Pack = 8, CharSet = CharSet.Unicode/*此参数将导致260*2*/)] -public struct TagClipboardInfo : IEquatable -{ - #region 字段,对应arx结构的,不要改动,本结构也不允许再加字段 - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] - public string szTempFile; // 临时文件夹的dwg文件 - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] - public string szSourceFile; // 文件名从中做出选择..是不是指定块表记录? - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)] - public string szSignature; - public int nFlags; // kbDragGeometry: 从AutoCAD拖动几何图形 - public Point3D dptInsert; // 插入点的原始世界坐标' - public IntRect rectGDI; // GDI coord 选择集的边界矩形 - public IntPtr mpView; // 用于验证这个对象是在这个视图中创建的 (HWND*) - public int dwThreadId; // AutoCAD thread 创建数据对象 - public int nLen; // 下一段的长度的数据,如果有的话,从chData - public int nType; // 类型的数据,如果有(eExpandedClipDataTypes) - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1)] - public string chData; // 数据的开始,如果有 - #endregion - - #region 属性,可以改动 - public string File => szTempFile; - public Point3d Point => new Point3d(dptInsert.X, dptInsert.Y, dptInsert.Z); - -#pragma warning disable CA2211 // 非常量字段应当不可见 - public static IntPtr AcadDwgview - = IntPtr.Zero; - //= AcedGetAcadDwgview(); // c#需要收集这个函数,我先不写,免得中间版本挂了 - - public static int MainWindowThreadId = - (int)WindowsAPI.GetWindowThreadProcessId(Acap.MainWindow.Handle, out uint processId); -#pragma warning restore CA2211 // 非常量字段应当不可见 - #endregion - - #region 构造 - /// - /// cad剪贴板 - /// - /// 临时dwg的保存路径 - /// 粘贴点 - public TagClipboardInfo(string tmpFile, Point3d insert) - { - szTempFile = tmpFile; - szSourceFile = string.Empty; - szSignature = "R15"; //恒定是这个 - nFlags = 0; - dptInsert = new Point3D(insert.X, insert.Y, insert.Z); - rectGDI = IntRect.Zero; - nLen = 0; - nType = 0; - chData = string.Empty; - - // mpView threadid 可能是用来删除的,用于剪贴板回调清理资源时候判断信息 - mpView = AcadDwgview; - dwThreadId = MainWindowThreadId; - } - #endregion - - #region 方法 - public override string ToString() - { - var sb = new StringBuilder(); - sb.AppendLine($"szTempFile:{szTempFile}"); - sb.AppendLine($"szSourceFile:{szSourceFile}"); - sb.AppendLine($"szSignature:{szSignature}"); - sb.AppendLine($"nFlags:{nFlags}"); - sb.AppendLine($"dptInsert:{dptInsert}"); - sb.AppendLine($"rectGDI:{rectGDI}"); - sb.AppendLine($"mpView:{mpView}"); - sb.AppendLine($"dwThreadId:{dwThreadId}"); - sb.AppendLine($"nLen:{nLen}"); - sb.AppendLine($"nType:{nType}"); - sb.AppendLine($"chData:{chData}"); - return sb.ToString(); - } - #endregion - - #region 测试大小 - void GetSize() - { - var v_1 = Marshal.OffsetOf(typeof(TagClipboardInfo), nameof(TagClipboardInfo.szTempFile)).ToInt32(); - var v_2 = Marshal.OffsetOf(typeof(TagClipboardInfo), nameof(TagClipboardInfo.szSourceFile)).ToInt32(); - var v_3 = Marshal.OffsetOf(typeof(TagClipboardInfo), nameof(TagClipboardInfo.szSignature)).ToInt32(); - var v_4 = Marshal.OffsetOf(typeof(TagClipboardInfo), nameof(TagClipboardInfo.nFlags)).ToInt32(); - var v_5 = Marshal.OffsetOf(typeof(TagClipboardInfo), nameof(TagClipboardInfo.dptInsert)).ToInt32(); - var v_6 = Marshal.OffsetOf(typeof(TagClipboardInfo), nameof(TagClipboardInfo.rectGDI)).ToInt32(); - var v_7 = Marshal.OffsetOf(typeof(TagClipboardInfo), nameof(TagClipboardInfo.mpView)).ToInt32(); - var v_8 = Marshal.OffsetOf(typeof(TagClipboardInfo), nameof(TagClipboardInfo.dwThreadId)).ToInt32(); - var v_9 = Marshal.OffsetOf(typeof(TagClipboardInfo), nameof(TagClipboardInfo.nLen)).ToInt32(); - var v_10 = Marshal.OffsetOf(typeof(TagClipboardInfo), nameof(TagClipboardInfo.nType)).ToInt32(); - var v_11 = Marshal.OffsetOf(typeof(TagClipboardInfo), nameof(TagClipboardInfo.chData)).ToInt32(); - var v_12 = Marshal.SizeOf(typeof(TagClipboardInfo)); //1120 - - var v_a = Marshal.SizeOf(typeof(Point3D));//24 - var v_b = Marshal.SizeOf(typeof(IntRect));//16 - } - #endregion - - #region 视口指针 - /* - [CommandMethod(nameof(Test_AcedGetAcadDwgview))] - public void testAcedGetAcadDwgview() - { - var dm = Acap.DocumentManager; - var doc = dm.MdiActiveDocument; - var ed = doc.Editor; - - var a = AcedGetAcadDwgview().ToString(); //自动执行的时候就存在了 - var b = ed.CurrentViewportObjectId.ToString(); - Debugx.Printl("a == b:" + a == b);//不对 - - var tab = ed.GetCurrentView(); - var c = tab.ObjectId.ToString(); - Debugx.Printl("a == c:" + a == c);//不对 - } - */ - - /// - /// 获取视口指针 - /// - - [DllImport("acad.exe", EntryPoint = "?acedGetAcadDwgView@@YAPEAVCView@@XZ")]//acad21 - static extern IntPtr AcedGetAcadDwgview(); - #endregion - - #region 重载运算符_比较 - public bool Equals(TagClipboardInfo other) - { - return - szTempFile == other.szTempFile && - szSourceFile == other.szSourceFile && - szSignature == other.szSignature && - nFlags == other.nFlags && - dptInsert == other.dptInsert && - rectGDI == other.rectGDI && - mpView == other.mpView && - dwThreadId == other.dwThreadId && - nLen == other.nLen && - nType == other.nType && - chData == other.chData; - } - public static bool operator !=(TagClipboardInfo a, TagClipboardInfo b) - { - return !(a == b); - } - public static bool operator ==(TagClipboardInfo a, TagClipboardInfo b) - { - return a.Equals(b); - } - public override bool Equals(object obj) - { - return obj is TagClipboardInfo info && Equals(info); - } - public override int GetHashCode() - { - return - szTempFile.GetHashCode() ^ - szSourceFile.GetHashCode() ^ - szSignature.GetHashCode() ^ - nFlags ^ - dptInsert.GetHashCode() ^ - rectGDI.GetHashCode() ^ - mpView.GetHashCode() ^ - dwThreadId ^ - nLen ^ - nType ^ - chData.GetHashCode(); - } - - public IntPtr CloneToPtr() - { - var lParam = Marshal.AllocHGlobal(Marshal.SizeOf(this)); - if (lParam != IntPtr.Zero) - Marshal.StructureToPtr(this, lParam, true); - return lParam; - } - #endregion -} - - -/* - * OLE 剪贴板说明 https://blog.csdn.net/chinabinlang/article/details/9815495 - * 写入时候注意: - * 0x01 c#自带的是com剪贴板 - * 最好不要使用,它不能在已经打开的剪贴板中使用, - * 也无法写入多个cf对象,也就是复制bitmap的时候会覆盖cad图元 - * Clipboard.SetImage(bitmap); - * 0x02 - * 剪贴板写入各种类型 https://blog.csdn.net/glt3953/article/details/8808262 - * - */ - -public partial class ClipTool -{ - /// - /// 侦听剪贴板 - /// - /// - /// - [DllImport("user32.dll", SetLastError = true)] - public static extern bool AddClipboardFormatListener(IntPtr hWnd); - /// - /// 移除侦听剪贴板 - /// - /// - /// - [DllImport("user32.dll", SetLastError = true)] - public static extern bool RemoveClipboardFormatListener(IntPtr hWnd); - /// - /// 将CWnd加入一个窗口链 - /// 每当剪贴板的内容发生变化时,就会通知这些窗口 - /// - /// 句柄 - /// 返回剪贴板观察器链中下一个窗口的句柄 - [DllImport("User32.dll")] - public static extern int SetClipboardViewer(IntPtr hWndNewViewer); - /// - /// 从剪贴板链中移出的窗口句柄 - /// - /// 从剪贴板链中移出的窗口句柄 - /// hWndRemove的下一个在剪贴板链中的窗口句柄 - /// 如果成功,非零;否则为0。 - [DllImport("User32.dll", CharSet = CharSet.Auto)] - public static extern bool ChangeClipboardChain(IntPtr hWndRemove, IntPtr hWndNewNext); - - - /// - /// 开启剪贴板
- /// 如果另一个窗口已经打开剪贴板,函数会失败.每次成功调用后都应有调用. - ///
- /// - /// - [DllImport("user32.dll", SetLastError = true)] - static extern bool OpenClipboard(IntPtr hWndNewOwner); - /// - /// 关闭剪贴板 - /// - /// - [DllImport("user32.dll", SetLastError = true)] - public static extern bool CloseClipboard(); - /// - /// 根据数据格式获取剪贴板 - /// - /// 数据格式名称 - /// - [DllImport("user32.dll", SetLastError = true)] - public static extern uint RegisterClipboardFormat(string lpszFormat); - /// - /// 获取剪贴板 - /// - /// 通常为但是cad有自己的位码 - /// - [DllImport("user32.dll", SetLastError = true)] - public static extern IntPtr GetClipboardData(uint uFormat); - /// - /// 设置剪贴板 - /// - /// 通常为但是cad有自己的位码 - /// 指定具有指定格式的数据的句柄,
- /// 该参数为空则为延迟提交:
- /// 有其他程序对剪切板中的数据进行请求时,该程序才会将指定格式的数据写入到剪切板中. - /// - /// - [DllImport("user32.dll", SetLastError = true)] - public static extern IntPtr SetClipboardData(uint uFormat, IntPtr hMem); - /// - /// 清空剪切板并释放剪切板内数据的句柄 - /// - /// - [DllImport("user32.dll", SetLastError = true)] - public static extern bool EmptyClipboard(); - /// - /// 枚举剪贴板内数据类型 - /// - /// - /// - [DllImport("user32.dll", SetLastError = true)] - public static extern uint EnumClipboardFormats(uint format); - - - /// - /// 打开剪贴板
- /// 写入之前必须清空,
- /// 否则将导致发送 WM_DESTROYCLIPBOARD 消息到上一次剪贴板拥有者释放资源
- /// 所以写入的时候必须一次性写入多个cf
- ///
- /// 接收返回的栈空间指针用于释放 - /// true写入,false读取 - /// - /// - [System.Diagnostics.DebuggerStepThrough] - public static bool OpenClipboardTask(bool isWrite, Action action) - { - //if (action == null) - // throw new ArgumentNullException(nameof(action)); - ArgumentNullEx.ThrowIfNull(action); - bool openFlag = false; - try - { - openFlag = OpenClipboard(IntPtr.Zero); - if (!openFlag) - return false; - if (isWrite) - EmptyClipboard(); - action.Invoke(); - } - catch (Exception e) - { - Debugger.Break(); - DebugEx.Printl(e.Message); - } - finally - { - if (openFlag) - CloseClipboard(); - } - return openFlag; - } - - /// - /// 获取剪贴板 - /// - /// 剪贴板的索引名 - /// 返回的结构 - public static bool GetClipboard(string clipKey, out T? tag) - { - bool locked = false; - T? result = default; - - ClipTool.OpenClipboardTask(false, () => { - // 读取剪贴板的指定数据 - var clipKeyFormat = RegisterClipboardFormat(clipKey);//ClipboardEnv.CadVer - var clipTypeData = GetClipboardData(clipKeyFormat); - - // 剪贴板的数据拷贝进去结构体中,会依照数据长度进行拷贝 - locked =IFoxCAD.Basal.WindowsAPI.GlobalLockTask(clipTypeData, ptr => { - // 非托管内存块->托管对象 - result = (T)Marshal.PtrToStructure(ptr, typeof(T)); - }); - }); - - tag = result; - return locked; - } -} - -#if true2 -// 无法备份emf内容 -// https://blog.csdn.net/vencon_s/article/details/46345083 -public static class ClipEx -{ - /// - /// 剪贴板数据保存目标数据列表 - /// - static readonly List _bytes = new(); - /// - /// 剪贴板数据类型列表 - /// - static readonly List _formats = new(); - - /// - /// 遍历剪贴板保存内容 - /// - /// true成功,false失败 - public static bool SaveClip() - { - bool result = ClipTool.OpenClipboardTask(false, free => { - _bytes.Clear(); - _formats.Clear(); - - uint cf = 0; - while (true) - { - cf = ClipTool.EnumClipboardFormats(cf);// 枚举剪贴板所有数据类型 - if (cf == 0) - break; - - _formats.Add(cf); - IntPtr clipTypeData = ClipTool.GetClipboardData(cf); - var locked = WindowsAPI.GlobalLockTask(clipTypeData, prt => { - uint size = WindowsAPI.GlobalSize(clipTypeData); - if (size > 0) - { - var buffer = new byte[size]; - Marshal.Copy(prt, buffer, 0, buffer.Length);// 将剪贴板数据保存到自定义字节数组 - _bytes.Add(buffer); - } - }); - } - }); - if (result) - result = _formats.Count > 0; - return result; - } - - /// - /// 恢复保存的数据 - /// - /// true成功,false失败 - public static bool RestoreClip() - { - if (_formats.Count <= 0) - return false; - - bool result = ClipTool.OpenClipboardTask(true, free => { - for (int i = 0; i < _formats.Count; i++) - { - int size = _bytes[i].Length; - IntPtr structPtr = Marshal.AllocHGlobal(size); - if (size > 0) - { - Marshal.Copy(_bytes[i], 0, structPtr, size); - ClipTool.SetClipboardData(_formats[i], structPtr); - } - } - }); - - if (result) - result = _formats.Count > 0; - return result; - } -} -#endif - - - -/// -/// 剪贴板的CF,也就是它的key -/// -public enum ClipboardFormat : uint -{ - /// - /// Text format. Each line ends with a carriage return/linefeed (CR-LF) combination. A null character signals - /// the end of the data. Use this format for ANSI text. - /// - CF_TEXT = 1, - - /// - /// A handle to a bitmap (HBITMAP). - /// - CF_BITMAP = 2, - - /// - /// Handle to a metafile picture format as defined by the METAFILEPICT structure. When passing a - /// CF_METAFILEPICT handle by means of DDE, the application responsible for deleting hMem should - /// also free the metafile referred to by the CF_METAFILEPICT handle. - /// - CF_METAFILEPICT = 3, - - /// - /// Microsoft Symbolic Link (SYLK) format. - /// - CF_SYLK = 4, - - /// - /// Software Arts' Data Interchange Format. - /// - CF_DIF = 5, - - /// - /// Tagged-image file format. - /// - CF_TIFF = 6, - - /// - /// Text format containing characters in the OEM character set. Each line ends with a carriage return/linefeed - /// (CR-LF) combination. A null character signals the end of the data. - /// - CF_OEMTEXT = 7, - - /// - /// A memory object containing a BITMAPINFO structure followed by the bitmap bits. - /// - CF_DIB = 8, - - /// - /// Handle to a color palette. Whenever an application places data in the clipboard that depends on or assumes - /// a color palette, it should place the palette on the clipboard as well. If the clipboard contains data in - /// the (logical color palette) format, the application should use the - /// SelectPalette and RealizePalette functions to realize (compare) any other data in the - /// clipboard against that logical palette. When displaying clipboard data, the clipboard always uses as its - /// current palette any object on the clipboard that is in the CF_PALETTE format. - /// - CF_PALETTE = 9, - - /// - /// Data for the pen extensions to the Microsoft Windows for Pen Computing. - /// - CF_PENDATA = 10, - - /// - /// Represents audio data more complex than can be represented in a CF_WAVE standard wave format. - /// - CF_RIFF = 11, - - /// - /// Represents audio data in one of the standard wave formats, such as 11 kHz or 22 kHz PCM. - /// - CF_WAVE = 12, - - /// - /// Unicode text format. Each line ends with a carriage return/linefeed (CR-LF) combination. A null character - /// signals the end of the data. - /// - CF_UNICODETEXT = 13, - - /// - /// A handle to an enhanced metafile (HENHMETAFILE). - /// - CF_ENHMETAFILE = 14, - - /// - /// A handle to type HDROP that identifies a list of files. An application can retrieve information - /// about the files by passing the handle to the DragQueryFile function. - /// - CF_HDROP = 15, - - /// - /// The data is a handle to the locale identifier associated with text in the clipboard. When you close the - /// clipboard, if it contains CF_TEXT data but no CF_LOCALE data, the system automatically sets - /// the CF_LOCALE format to the current input language. You can use the CF_LOCALE format to - /// associate a different locale with the clipboard text. - /// An application that pastes text from the clipboard can retrieve this format to determine which character - /// set was used to generate the text. - /// Note that the clipboard does not support plain text in multiple character sets. To achieve this, use a - /// formatted text data type such as RTF instead. - /// The system uses the code page associated with CF_LOCALE to implicitly convert from - /// to . Therefore, the correct code page table is used for - /// the conversion. - /// - CF_LOCALE = 16, - - /// - /// A memory object containing a BITMAPV5HEADER structure followed by the bitmap color space - /// information and the bitmap bits. - /// - CF_DIBV5 = 17, - - -#pragma warning disable CS1574 // XML 注释中有无法解析的 cref 特性 - /// - /// Owner-display format. The clipboard owner must display and update the clipboard viewer window, and receive - /// the , , - /// , , and - /// messages. The hMem parameter must be null. - /// - CF_OWNERDISPLAY = 0x0080, -#pragma warning restore CS1574 // XML 注释中有无法解析的 cref 特性 - - /// - /// Text display format associated with a private format. The hMem parameter must be a handle to data - /// that can be displayed in text format in lieu of the privately formatted data. - /// - CF_DSPTEXT = 0x0081, - - /// - /// Bitmap display format associated with a private format. The hMem parameter must be a handle to - /// data that can be displayed in bitmap format in lieu of the privately formatted data. - /// - CF_DSPBITMAP = 0x0082, - - /// - /// Metafile-picture display format associated with a private format. The hMem parameter must be a - /// handle to data that can be displayed in metafile-picture format in lieu of the privately formatted data. - /// - CF_DSPMETAFILEPICT = 0x0083, - - /// - /// Enhanced metafile display format associated with a private format. The hMem parameter must be a - /// handle to data that can be displayed in enhanced metafile format in lieu of the privately formatted data. - /// - CF_DSPENHMETAFILE = 0x008E, - - /// - /// Start of a range of integer values for application-defined GDI object clipboard formats. The end of the - /// range is . Handles associated with clipboard formats in this range are not - /// automatically deleted using the GlobalFree function when the clipboard is emptied. Also, when using - /// values in this range, the hMem parameter is not a handle to a GDI object, but is a handle allocated - /// by the GlobalAlloc function with the GMEM_MOVEABLE flag. - /// - CF_GDIOBJFIRST = 0x0300, - - /// - /// See . - /// - CF_GDIOBJLAST = 0x03FF, -#pragma warning disable CS1574 // XML 注释中有无法解析的 cref 特性 - /// - /// Start of a range of integer values for private clipboard formats. The range ends with - /// . Handles associated with private clipboard formats are not freed - /// automatically, the clipboard owner must free such handles, typically in response to the - /// message. - /// - /// - CF_PRIVATEFIRST = 0x0200, -#pragma warning restore CS1574 // XML 注释中有无法解析的 cref 特性 - /// - /// See . - /// - CF_PRIVATELAST = 0x02FF, -} - -#if true2 -// arx剪贴板头文件的枚举 -enum eClipInfoFlags -{ - kbDragGeometry = 0x01, -}; - -enum eXrefType -{ - kXrefTypeAttach = 1, - kXrefTypeOverlay = 2 -}; - -enum eExpandedClipDataTypes -{ - kDcPlotStyles = 1, - kDcXrefs = 2, - kDcLayouts = 3, - kDcBlocks = 4, - kDcLayers = 5, - kDcDrawings = 6, - kDcLinetypes = 7, - kDcTextStyles = 8, - kDcDimStyles = 9, - kDcBlocksWithAttdef = 10, - //#ifdef ADCHATCH - kDcHatches = 11, - //#endif - kTpXrefs = 12, - kTpImages = 13, - kTpTable = 14, - kDcTableStyles = 15, - kDcMultileaderStyles = 16, - kDcVisualStyles = 17, - kDcSectionViewStyles = 18, - kDcDetailViewStyles = 19, -}; -#endif -#pragma warning restore CS1591 // 缺少对公共可见类型或成员的 XML 注释 \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/AttachmentPointHelper.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/AttachmentPointHelper.cs deleted file mode 100644 index 42c78cd..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/AttachmentPointHelper.cs +++ /dev/null @@ -1,56 +0,0 @@ -namespace IFoxCAD.Cad; - -/// -/// 文字对齐点帮助类 -/// -public static class AttachmentPointHelper -{ - static readonly Dictionary _alignment = new() - { - { "左上", AttachmentPoint.TopLeft }, - { "中上", AttachmentPoint.TopCenter },// 单行的对齐 - { "右上", AttachmentPoint.TopRight }, - - { "左中", AttachmentPoint.MiddleLeft }, - { "正中", AttachmentPoint.MiddleCenter },// 多行的正中 - { "右中", AttachmentPoint.MiddleRight }, - - { "左对齐", AttachmentPoint.BaseLeft },// ※优先(放在前面优先获取) - { "左", AttachmentPoint.BaseLeft }, - - { "中间", AttachmentPoint.BaseMid }, - - { "右对齐", AttachmentPoint.BaseRight },// ※优先(放在前面优先获取) - { "右", AttachmentPoint.BaseRight }, - - { "左下", AttachmentPoint.BottomLeft }, - { "中下", AttachmentPoint.BottomCenter }, - { "右下", AttachmentPoint.BottomRight }, - - { "对齐", AttachmentPoint.BaseAlign },// ※优先(放在前面优先获取) - { "调整", AttachmentPoint.BaseAlign }, - - { "居中", AttachmentPoint.BaseCenter },// 单行的中 - { "铺满", AttachmentPoint.BaseFit }, - }; - - /// - /// 输入文字获得对齐方式 - /// - /// - /// - public static AttachmentPoint Get(string key) - { - return _alignment[key]; - } - - /// - /// 输入对齐方式获得文字说明 - /// - /// - /// - public static string Get(AttachmentPoint value) - { - return _alignment.FirstOrDefault(q => q.Value == value).Key; - } -} diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/BulgeVertexWidth.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/BulgeVertexWidth.cs deleted file mode 100644 index 1929dd6..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/BulgeVertexWidth.cs +++ /dev/null @@ -1,92 +0,0 @@ -namespace IFoxCAD.Cad; - -/// -/// 多段线的顶点,凸度,头宽,尾宽 -/// -[Serializable] -public class BulgeVertexWidth -{ - /// - /// 顶点X - /// - public double X; - /// - /// 顶点Y - /// - public double Y; - /// - /// 凸度 - /// - public double Bulge; - /// - /// 头宽 - /// - public double StartWidth; - /// - /// 尾宽 - /// - public double EndWidth; - /// - /// 顶点 - /// - public Point2d Vertex => new(X, Y); - /// - /// 默认构造 - /// - public BulgeVertexWidth() { } - - /// - /// 多段线的顶点,凸度,头宽,尾宽 - /// - public BulgeVertexWidth(double vertex_X, double vertex_Y, - double bulge = 0, - double startWidth = 0, - double endWidth = 0) - { - X = vertex_X; - Y = vertex_Y; - Bulge = bulge; - StartWidth = startWidth; - EndWidth = endWidth; - } - - /// - /// 多段线的顶点,凸度,头宽,尾宽 - /// - public BulgeVertexWidth(Point2d vertex, - double bulge = 0, - double startWidth = 0, - double endWidth = 0) - : this(vertex.X, vertex.Y, bulge, startWidth, endWidth) - { } - - /// - /// 多段线的顶点,凸度,头宽,尾宽 - /// - public BulgeVertexWidth(BulgeVertex bv) - : this(bv.Vertex.X, bv.Vertex.Y, bv.Bulge) - { } - - /// - /// 多段线的顶点,凸度,头宽,尾宽 - /// - /// 多段线 - /// 子段编号 - public BulgeVertexWidth(Polyline pl, int index) - { - var pt = pl.GetPoint2dAt(index);// 这里可以3d - X = pt.X; - Y = pt.Y; - Bulge = pl.GetBulgeAt(index); - StartWidth = pl.GetStartWidthAt(index); - EndWidth = pl.GetEndWidthAt(index); - } - /// - /// 转换为 BulgeVertex - /// - /// - public BulgeVertex ToBulgeVertex() - { - return new BulgeVertex(Vertex, Bulge); - } -} diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/CheckFactory.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/CheckFactory.cs deleted file mode 100644 index 21454a1..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/CheckFactory.cs +++ /dev/null @@ -1,48 +0,0 @@ -#if Debug -namespace IFoxCAD.Cad; -/// -/// 命令检查类 -/// -public static class CheckFactory -{ - /* - * 平时command命令的globalName如果重复,加载时会报错 - * 但是并不会告诉你是哪里错了,通常需要花大量时间来查找 - * 将此函数添加在IExtensionApplication.Initialize()函数开头 - * 虽然还会报错,但是至少能知道哪个类下哪个方法导致的报错 - * 聊胜于无吧 - * 2023-05-16 by DYH - */ - - /// - /// 检查Command命令重复 - /// - public static void CheckDuplicateCommand(Assembly? assembly = null) - { - var dic = new Dictionary>(); - assembly ??= Assembly.GetCallingAssembly(); - var typeArray = assembly.GetTypes(); - foreach (var type in typeArray) - { - foreach (var method in type.GetMethods()) - { - foreach (Attribute add in method.GetCustomAttributes(typeof(CommandMethodAttribute), false)) - { - if (add is not CommandMethodAttribute cma) - continue; - if (!dic.ContainsKey(cma.GlobalName)) - { - dic.Add(cma.GlobalName, new()); - } - dic[cma.GlobalName].Add(type.Name + "." + method.Name); - } - } - } - var strings = dic.Where(o => o.Value.Count() > 1) - .Select(o => o.Key + "命令重复,在类" + string.Join("和", o.Value) + "中"); - string str = string.Join(Environment.NewLine, strings); - if (!string.IsNullOrEmpty(str)) - System.Windows.Forms. MessageBox.Show(str, @"错误:重复命令!"); - } -} -#endif \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/CollectionEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/CollectionEx.cs deleted file mode 100644 index 3dfe440..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/CollectionEx.cs +++ /dev/null @@ -1,307 +0,0 @@ - -namespace IFoxCAD.Cad; - -/// -/// 集合扩展类 -/// -public static class CollectionEx -{ - /// - /// 对象id迭代器转换为集合 - /// - /// 对象id的迭代器 - /// 对象id集合,记得释放 - [System.Diagnostics.DebuggerStepThrough] - public static ObjectIdCollection ToCollection(this IEnumerable ids) - { - return new ObjectIdCollection(ids.ToArray()); - } - - /// - /// 实体迭代器转换为集合 - /// - /// 对象类型 - /// 实体对象的迭代器 - /// 实体集合,记得释放 - [System.Diagnostics.DebuggerStepThrough] - public static DBObjectCollection ToCollection(this IEnumerable objs) where T : DBObject - { - DBObjectCollection objCol = new(); - foreach (T obj in objs) - objCol.Add(obj); - return objCol; - } - - /// - /// double 数值迭代器转换为 double 数值集合 - /// - /// double 数值迭代器 - /// 数值集合,它没有Dispose - [System.Diagnostics.DebuggerStepThrough] - public static DoubleCollection ToCollection(this IEnumerable doubles) - { - return new DoubleCollection(doubles.ToArray()); - } - - /// - /// 二维点迭代器转换为二维点集合 - /// - /// 二维点迭代器 - /// 二维点集合,!acad记得释放 - [System.Diagnostics.DebuggerStepThrough] - public static Point2dCollection ToCollection(this IEnumerable pts) - { - return new Point2dCollection(pts.ToArray()); - } - - /// - /// 三维点迭代器转换为三维点集合 - /// - /// 三维点迭代器 - /// 三维点集合,记得释放 - [System.Diagnostics.DebuggerStepThrough] - public static Point3dCollection ToCollection(this IEnumerable pts) - { - return new Point3dCollection(pts.ToArray()); - } - - /// - /// 对象id集合转换为对象id列表 - /// - /// 对象id集合 - /// 对象id列表 - [System.Diagnostics.DebuggerStepThrough] - public static List ToList(this ObjectIdCollection ids) - { - return ids.Cast().ToList(); - } - - - /// - /// 遍历集合,执行委托 - /// - /// 集合值的类型 - /// 集合 - /// 委托 - [System.Diagnostics.DebuggerStepThrough] //[DebuggerHidden] 两个特性差不多 - public static void ForEach(this IEnumerable source, Action action) - { - // 这里不要嵌套调用ForEach委托, - // 因为这样可以在调用函数上断点直接跑Action内,不会进入此处(除了cad之外); - // 而cad很奇怪,只能用预处理方式避免 - // 嵌套调用ForEach委托: - // source.ForEach((a, _, _) => { - // action.Invoke(a); - // }); - - foreach (var element in source) - action.Invoke(element); - } - - /// - /// 遍历集合,执行委托 - /// - /// 集合值的类型 - /// 集合 - /// 委托 - [System.Diagnostics.DebuggerStepThrough] //[DebuggerHidden] 两个特性差不多 - public static void ForEach(this IEnumerable source, Action action) - { - var i = 0; - foreach (var element in source) - { - action.Invoke(i, element); - i++; - } - } - - /// - /// 遍历集合,执行委托(允许循环中断) - /// - /// 集合值的类型 - /// 集合 - /// 委托 - [System.Diagnostics.DebuggerStepThrough] - public static void ForEach(this IEnumerable source, Action action) - { - // 这里不要嵌套调用ForEach委托, - // 因为这样可以在调用函数上断点直接跑Action内,不会进入此处(除了cad之外); - // 而cad很奇怪,只能用预处理方式避免 - // 嵌套调用ForEach委托: - // source.ForEach((a, b, _) => { - // action.Invoke(a, b); - // }); - - LoopState state = new();/*这种方式比Action改Func更友好*/ - foreach (var element in source) - { - action.Invoke(element, state); - if (!state.IsRun) - break; - } - } - - /// - /// 遍历集合,执行委托(允许循环中断,输出索引值) - /// - /// 集合值的类型 - /// 集合 - /// 委托 - [System.Diagnostics.DebuggerStepThrough] - public static void ForEach(this IEnumerable source, Action action) - { - int i = 0; - LoopState state = new();/*这种方式比Action改Func更友好*/ - foreach (var element in source) - { - action.Invoke(element, state, i); - if (!state.IsRun) - break; - i++; - } - } - - - #region 关键字集合 - /// - /// 关键字名字 - /// - public enum KeywordName - { - /// - /// 全局名字 - /// - GlobalName, - /// - /// 本地名字 - /// - LocalName, - /// - /// 显示名字 - /// - DisplayName, - } - - /// - /// 含有关键字 - /// - /// 关键字集合 - /// 关键字 - /// 关键字容器字段名 - /// true含有 - [System.Diagnostics.DebuggerStepThrough] - public static bool Contains(this KeywordCollection collection, string name, - KeywordName keywordName = KeywordName.GlobalName) - { - bool contains = false; - switch (keywordName) - { - case KeywordName.GlobalName: - for (int i = 0; i < collection.Count; i++) - { - - var item = collection[i]; - - if (item.GlobalName == name) - { - contains = true; - break; - } - } - break; - case KeywordName.LocalName: - for (int i = 0; i < collection.Count; i++) - { - - var item = collection[i]; - - if (item.LocalName == name) - { - contains = true; - break; - } - } - break; - case KeywordName.DisplayName: - for (int i = 0; i < collection.Count; i++) - { - - var item = collection[i]; - - if (item.DisplayName == name) - { - contains = true; - break; - } - } - break; - } - return contains; - } - - /// - /// 获取词典, - /// KeywordCollection是允许重复关键字的,没有哈希索引,在多次判断时候会遍历多次O(n),所以生成一个词典进行O(1) - /// - /// - /// - [System.Diagnostics.DebuggerStepThrough] - public static Dictionary GetDict(this KeywordCollection collection) - { - Dictionary map = new(); - for (int i = 0; i < collection.Count; i++) - { - - var item = collection[i]; - - map.Add(item.GlobalName, item.DisplayName); - } - return map; - } - #endregion - - - #region IdMapping - /// - /// 旧块名 - /// - /// - /// - [System.Diagnostics.DebuggerStepThrough] - public static List GetKeys(this IdMapping idmap) - { - List ids = new(); - foreach (IdPair item in idmap) - ids.Add(item.Key); - return ids; - } - - /// - /// 新块名 - /// - /// - /// - [System.Diagnostics.DebuggerStepThrough] - public static List GetValues(this IdMapping idmap) - { - List ids = new(); - foreach (IdPair item in idmap) - ids.Add(item.Value); - return ids; - } - - /// - /// 转换为词典 - /// - /// - /// - [System.Diagnostics.DebuggerStepThrough] - public static Dictionary ToDictionary(this IdMapping mapping) - { - var keyValuePairs = new Dictionary(); - foreach (IdPair item in mapping) - keyValuePairs.Add(item.Key, item.Value); - return keyValuePairs; - } - #endregion -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Curve2dEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Curve2dEx.cs deleted file mode 100644 index cd18835..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Curve2dEx.cs +++ /dev/null @@ -1,296 +0,0 @@ -namespace IFoxCAD.Cad; - -/// -/// 二维解析类曲线转换为二维实体曲线扩展类 -/// -public static class Curve2dEx -{ - internal static readonly Plane _planeCache = new(); - - #region Curve2d - - /// - /// 按矩阵转换Ge2d曲线为Db曲线 - /// - /// Ge2d曲线 - /// 曲线转换矩阵 - /// Db曲线 - public static Curve? ToCurve(this Curve2d curve, Matrix3d mat) - { - return curve switch - { - LineSegment2d li => ToCurve(li, mat), - NurbCurve2d nu => ToCurve(nu, mat), - EllipticalArc2d el => ToCurve(el, mat), - CircularArc2d ci => ToCurve(ci, mat), - PolylineCurve2d po => ToCurve(po, mat), - Line2d l2 => ToCurve(l2, mat), - CompositeCurve2d co => ToCurve(co, mat), - _ => null - }; - } - - #endregion Curve2d - - #region CircularArc2d - - /// - /// 判断点是否位于圆内及圆上 - /// - /// 二维解析类圆弧对象 - /// 二维点 - /// 位于圆内及圆上返回 ,反之返回 - public static bool IsIn(this CircularArc2d ca2d, Point2d pnt) - { - return ca2d.IsOn(pnt) || ca2d.IsInside(pnt); - } - - /// - /// 将二维解析类圆弧转换为实体圆或者圆弧,然后进行矩阵变换 - /// - /// 二维解析类圆弧对象 - /// 变换矩阵 - /// 实体圆或者圆弧 - public static Curve ToCurve(this CircularArc2d ca2d, Matrix3d mat) - { - Curve c = ToCurve(ca2d); - c.TransformBy(mat); - return c; - } - - /// - /// 将二维解析类圆弧转换为实体圆或者圆弧 - /// - /// 二维解析类圆弧对象 - /// 实体圆或者圆弧 - public static Curve ToCurve(this CircularArc2d ca2d) - { - if (ca2d.IsClosed()) - return ToCircle(ca2d); - else - return ToArc(ca2d); - } - - /// - /// 将二维解析类圆弧转换为实体圆 - /// - /// 二维解析类圆弧对象 - /// 实体圆 - public static Circle ToCircle(this CircularArc2d c2d) - { - return - new Circle( - new Point3d(_planeCache, c2d.Center), - Vector3d.ZAxis, - c2d.Radius); - } - - /// - /// 将二维解析类圆弧转换为实体圆弧 - /// - /// 二维解析类圆弧对象 - /// 圆弧 - public static Arc ToArc(this CircularArc2d a2d) - { - double startangle, endangle; - double refangle = a2d.ReferenceVector.Angle; - - if (a2d.IsClockWise) - { - startangle = -a2d.EndAngle + refangle; - endangle = -a2d.StartAngle + refangle; - } - else - { - startangle = a2d.StartAngle + refangle; - endangle = a2d.EndAngle + refangle; - } - - return - new Arc( - new Point3d(_planeCache, a2d.Center), - Vector3d.ZAxis, - a2d.Radius, - startangle, - endangle); - } - - #endregion CircularArc2d - - #region EllipticalArc2d - - // 椭圆弧 - /// - /// 将二维解析类椭圆弧转换为实体椭圆弧,然后进行矩阵变换 - /// - /// 二维解析类椭圆弧对象 - /// 变换矩阵 - /// 实体椭圆弧 - public static Ellipse ToCurve(this EllipticalArc2d ea2d, Matrix3d mat) - { - Ellipse e = ToCurve(ea2d); - e.TransformBy(mat); - return e; - } - - /// - /// 将二维解析类椭圆弧转换为实体椭圆弧 - /// - /// 二维解析类椭圆弧对象 - /// 实体椭圆弧 - public static Ellipse ToCurve(this EllipticalArc2d ea2d) - { - Ellipse ell = new( - new Point3d(_planeCache, ea2d.Center), - Vector3d.ZAxis, - new Vector3d(_planeCache, ea2d.MajorAxis) * ea2d.MajorRadius, - ea2d.MinorRadius / ea2d.MajorRadius, - 0, - Math.PI * 2); - if (!ea2d.IsClosed()) - { - if (ea2d.IsClockWise) - { - ell.StartAngle = -ell.GetAngleAtParameter(ea2d.EndAngle); - ell.EndAngle = -ell.GetAngleAtParameter(ea2d.StartAngle); - } - else - { - ell.StartAngle = ell.GetAngleAtParameter(ea2d.StartAngle); - ell.EndAngle = ell.GetAngleAtParameter(ea2d.EndAngle); - } - } - return ell; - } - - #endregion EllipticalArc2d - - #region Line2d - - /// - /// 将二维解析类直线转换为实体类构造线 - /// - /// 二维解析类直线 - /// 实体类构造线 - public static Xline ToCurve(this Line2d line2d) - { - return new Xline - { - BasePoint = new Point3d(_planeCache, line2d.PointOnLine), - SecondPoint = new Point3d(_planeCache, line2d.PointOnLine + line2d.Direction) - }; - } - - /// - /// 将二维解析类直线转换为实体类构造线,然后进行矩阵变换 - /// - /// 二维解析类直线 - /// 变换矩阵 - /// 实体类构造线 - public static Xline ToCurve(this Line2d line2d, Matrix3d mat) - { - Xline xl = ToCurve(line2d); - xl.TransformBy(mat); - return xl; - } - - /// - /// 将二维解析类构造线转换为二维解析类线段 - /// - /// 二维解析类构造线 - /// 起点参数 - /// 终点参数 - /// 二维解析类线段 - public static LineSegment2d ToLineSegment2d(this Line2d line2d, double fromParameter, double toParameter) - { - return - new LineSegment2d - ( - line2d.EvaluatePoint(fromParameter), - line2d.EvaluatePoint(toParameter) - ); - } - - #endregion Line2d - - #region LineSegment2d - - /// - /// 将二维解析类线段转换为实体类直线,并进行矩阵变换 - /// - /// 二维解析类线段 - /// 变换矩阵 - /// 实体类直线 - public static Line ToCurve(this LineSegment2d ls2d, Matrix3d mat) - { - Line l = ToCurve(ls2d); - l.TransformBy(mat); - return l; - } - - /// - /// 将二维解析类线段转换为实体类直线 - /// - /// 二维解析类线段 - /// 实体类直线 - public static Line ToCurve(this LineSegment2d ls2d) - { - return - new Line( - new Point3d(_planeCache, ls2d.StartPoint), - new Point3d(_planeCache, ls2d.EndPoint)); - } - - #endregion LineSegment2d - - #region NurbCurve2d - - /// - /// 将二维解析类BURB曲线转换为实体类样条曲线,并进行矩阵变换 - /// - /// 二维解析类BURB曲线 - /// 变换矩阵 - /// 实体类样条曲线 - public static Spline ToCurve(this NurbCurve2d nc2d, Matrix3d mat) - { - Spline spl = ToCurve(nc2d); - spl.TransformBy(mat); - return spl; - } - - /// - /// 将二维解析类BURB曲线转换为实体类样条曲线 - /// - /// 二维解析类BURB曲线 - /// 实体类样条曲线 - public static Spline ToCurve(this NurbCurve2d nc2d) - { - using Point3dCollection ctlpnts = new(); - for (int i = 0; i < nc2d.NumControlPoints; i++) - ctlpnts.Add(new Point3d(_planeCache, nc2d.GetControlPointAt(i))); - - DoubleCollection knots = new(); - for (int i = 0; i < nc2d.Knots.Count; i++) - knots.Add(nc2d.Knots[i]); - - DoubleCollection weights = new(); - for (int i = 0; i < nc2d.NumWeights; i++) - weights.Add(nc2d.GetWeightAt(i)); - - NurbCurve2dData ncdata = nc2d.DefinitionData; - - return - new Spline( - ncdata.Degree, - ncdata.Rational, - nc2d.IsClosed(), - ncdata.Periodic, - ctlpnts, - knots, - weights, - 0, - nc2d.Knots.Tolerance) { Type = SplineType.FitPoints }; - } - - #endregion NurbCurve2d -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Curve3dEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Curve3dEx.cs deleted file mode 100644 index f415ea3..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Curve3dEx.cs +++ /dev/null @@ -1,557 +0,0 @@ -using System.Runtime.CompilerServices; - -namespace IFoxCAD.Cad; - -/// -/// 三维解析类曲线转换为三维实体曲线扩展类 -/// -public static class Curve3dEx -{ - /// - /// 判断两个浮点数是否相等 - /// - /// 容差 - /// 第一个数 - /// 第二个数 - /// 两个数的差值的绝对值小于容差返回 ,反之返回 - [MethodImpl] - public static bool IsEqualPoint(this Tolerance tol, double d1, double d2) - { - return Math.Abs(d1 - d2) < tol.EqualPoint; - } - - #region Curve3d - - /// - /// 获取三维解析类曲线(自交曲线)的交点参数 - /// - /// 三维解析类曲线 - /// 是否排序 - /// 曲线参数的列表 - public static List GetParamsAtIntersectionPoints(this Curve3d c3d, bool sort = true) - { - CurveCurveIntersector3d cci = new(c3d, c3d, Vector3d.ZAxis); - List pars = []; - for (int i = 0; i < cci.NumberOfIntersectionPoints; i++) - pars.AddRange(cci.GetIntersectionParameters(i)); - if (sort) - pars.Sort(); - return pars; - } - - /// - /// 获取三维解析类子曲线 - /// - /// 三维解析类曲线 - /// 子段曲线起点参数 - /// 子段曲线终点参数 - /// 三维解析类曲线 - public static Curve3d GetSubCurve(this Curve3d curve, double from, double to) - { - Interval inter = curve.GetInterval(); - bool atStart = Tolerance.Global.IsEqualPoint(inter.LowerBound, from); - bool atEnd = Tolerance.Global.IsEqualPoint(inter.UpperBound, to); - if (atStart && atEnd) - return (Curve3d)curve.Clone(); - if (curve is NurbCurve3d) - { - if (from < to) - { - NurbCurve3d clone = (NurbCurve3d)curve.Clone(); - if (atStart || atEnd) - { - clone.HardTrimByParams(from, to); - return clone; - } - else - { - clone.HardTrimByParams(inter.LowerBound, to); - clone.HardTrimByParams(from, to); - return clone; - } - } - else - { - NurbCurve3d clone1 = (NurbCurve3d)curve.Clone(); - clone1.HardTrimByParams(from, inter.UpperBound); - NurbCurve3d clone2 = (NurbCurve3d)curve.Clone(); - clone2.HardTrimByParams(inter.LowerBound, to); - clone1.JoinWith(clone2); - return clone1; - } - } - else - { - Curve3d clone = (Curve3d)curve.Clone(); - clone.SetInterval(new Interval(from, to, Tolerance.Global.EqualPoint)); - return clone; - } - } - - /// - /// 将三维解析类曲线转换为三维实体类曲线 - /// - /// 三维解析类曲线 - /// 三维实体类曲线 - public static Curve? ToCurve(this Curve3d curve) - { - return curve switch - { - CompositeCurve3d co => ToCurve(co), - LineSegment3d li => ToCurve(li), - EllipticalArc3d el => ToCurve(el), - CircularArc3d ci => ToCurve(ci), - NurbCurve3d nu => ToCurve(nu), - PolylineCurve3d pl => ToCurve(pl), - Line3d l3 => ToCurve(l3), - _ => null - }; - } - - /// - /// 将三维解析类曲线转换为三维解析类Nurb曲线 - /// - /// 三维解析类曲线 - /// 三维解析类Nurb曲线 - public static NurbCurve3d? ToNurbCurve3d(this Curve3d curve) - { - return curve switch - { - LineSegment3d line => new NurbCurve3d(line), - EllipticalArc3d el => new NurbCurve3d(el), - CircularArc3d cir => new NurbCurve3d(ToEllipticalArc3d(cir)), - NurbCurve3d nur => nur, - PolylineCurve3d pl => new NurbCurve3d(3, pl, false), - _ => null - }; - } - - #endregion Curve3d - - #region CompositeCurve3d - - /// - /// 判断是否为圆和椭圆 - /// - /// 三维解析类曲线 - /// 完整圆及完整的椭圆返回 ,反之返回 - public static bool IsCircular(this Curve3d curve) - { - return curve switch - { - CircularArc3d or EllipticalArc3d => curve.IsClosed(), - _ => false - }; - } - - /// - /// 将三维复合曲线按曲线参数分割 - /// - /// 三维复合曲线 - /// 曲线参数列表 - /// 三维复合曲线列表 - public static List? GetSplitCurves(this CompositeCurve3d c3d, List pars) - { - // 曲线参数剔除重复的 - if (pars.Count > 0) - { - pars.Sort(); - for (int i = pars.Count - 1; i > 0; i--) - if (Tolerance.Global.IsEqualPoint(pars[i], pars[i - 1])) - pars.RemoveAt(i); - } - if (pars.Count == 0) - return null; - - // 这个是曲线参数类 - var inter = c3d.GetInterval(); - // 曲线们 - var c3ds = c3d.GetCurves(); - if (c3ds.Length == 1 && c3ds[0].IsClosed()) - { - // 闭合曲线不允许打断于一点 - if (pars.Count < 2) - return null; - - // 如果包含起点 - if (Tolerance.Global.IsEqualPoint(pars[0], inter.LowerBound)) - { - pars[0] = inter.LowerBound; - // 又包含终点,去除终点 - if (Tolerance.Global.IsEqualPoint(pars[^1], inter.UpperBound)) - { - pars.RemoveAt(pars.Count - 1); - if (pars.Count == 1) - return null; - } - } - else if (Tolerance.Global.IsEqualPoint(pars[^1], inter.UpperBound)) - { - pars[^1] = inter.UpperBound; - } - // 加入第一点以支持反向打断 - pars.Add(pars[0]); - } - else - { - // 非闭合曲线加入起点和终点 - if (Tolerance.Global.IsEqualPoint(pars[0], inter.LowerBound)) - pars[0] = inter.LowerBound; - else - pars.Insert(0, inter.LowerBound); - if (Tolerance.Global.IsEqualPoint(pars[^1], inter.UpperBound)) - pars[^1] = inter.UpperBound; - else - pars.Add(inter.UpperBound); - } - - List curves = new(); - List cc3ds = new(); - for (int i = 0; i < pars.Count - 1; i++) - { - cc3ds.Clear(); - // 复合曲线参数转换到包含曲线参数 - var cp1 = c3d.GlobalToLocalParameter(pars[i]); - var cp2 = c3d.GlobalToLocalParameter(pars[i + 1]); - if (cp1.SegmentIndex == cp2.SegmentIndex) - { - cc3ds.Add( - c3ds[cp1.SegmentIndex].GetSubCurve( - cp1.LocalParameter, - cp2.LocalParameter)); - } - else - { - inter = c3ds[cp1.SegmentIndex].GetInterval(); - cc3ds.Add( - c3ds[cp1.SegmentIndex].GetSubCurve( - cp1.LocalParameter, - inter.UpperBound)); - - for (int j = cp1.SegmentIndex + 1; j < cp2.SegmentIndex; j++) - cc3ds.Add((Curve3d)c3ds[j].Clone()); - - inter = c3ds[cp2.SegmentIndex].GetInterval(); - cc3ds.Add( - c3ds[cp2.SegmentIndex].GetSubCurve( - inter.LowerBound, - cp2.LocalParameter)); - } - curves.Add(new(cc3ds.ToArray())); - } - - // 封闭多段线 口口 并排形状,第二个口切割不成功,注释下面就成功了 - //if (c3d.IsClosed() && c3ds.Length > 1) - //{ - // var cus1 = curves[^1].GetCurves(); - // var cus2 = curves[0].GetCurves(); - // var cs = cus1.Combine2(cus2); - // curves[^1] = new(cs); - // curves.RemoveAt(0); - //} - return curves; - } - - /// - /// 将复合曲线转换为实体类曲线 - /// - /// 三维复合曲线 - /// 实体曲线 - public static Curve? ToCurve(this CompositeCurve3d curve) - { - Curve3d[] cs = curve.GetCurves(); - if (cs.Length == 0) - return null; - if (cs.Length == 1) - return ToCurve(cs[0]); - - bool hasNurb = false; - - for (int i = 0; i < cs.Length; i++) - { - var c = cs[i]; - if (c is NurbCurve3d || c is EllipticalArc3d) - { - hasNurb = true; - break; - } - } - if (hasNurb) - { - var nc3d = cs[0].ToNurbCurve3d(); - for (int i = 1; i < cs.Length; i++) - nc3d?.JoinWith(cs[i].ToNurbCurve3d()); - return nc3d?.ToCurve(); - } - - return ToPolyline(curve); - } - - /// - /// 将三维复合曲线转换为实体类多段线 - /// - /// 三维复合曲线 - /// 实体类多段线 - public static Polyline ToPolyline(this CompositeCurve3d cc3d) - { - Polyline pl = new(); - pl.SetDatabaseDefaults(); - pl.Elevation = cc3d.StartPoint[2]; - - Plane plane = pl.GetPlane(); - Point2d endver = Point2d.Origin; - int i = 0; - foreach (Curve3d c3d in cc3d.GetCurves()) - { - if (c3d is CircularArc3d ca3d) - { - double b = Math.Tan(0.25 * (ca3d.EndAngle - ca3d.StartAngle)) * ca3d.Normal[2]; - pl.AddVertexAt(i, c3d.StartPoint.Convert2d(plane), b, 0, 0); - endver = c3d.EndPoint.Convert2d(plane); - } - else - { - pl.AddVertexAt(i, c3d.StartPoint.Convert2d(plane), 0, 0, 0); - endver = c3d.EndPoint.Convert2d(plane); - } - i++; - } - pl.AddVertexAt(i, endver, 0, 0, 0); - return pl; - } - - #endregion CompositeCurve3d - - #region Line3d - - /// - /// 将解析类三维构造线转换为实体类构造线 - /// - /// 解析类三维构造线 - /// 实体类构造线 - public static Xline ToCurve(this Line3d line3d) - { - return - new Xline - { - BasePoint = line3d.PointOnLine, - SecondPoint = line3d.PointOnLine + line3d.Direction - }; - } - - /// - /// 将三维解析类构造线转换为三维解析类线段 - /// - /// 三维解析类构造线 - /// 起点参数 - /// 终点参数 - /// 三维解析类线段 - public static LineSegment3d ToLineSegment3d(this Line3d line3d, double fromParameter, double toParameter) - { - return - new LineSegment3d - ( - line3d.EvaluatePoint(fromParameter), - line3d.EvaluatePoint(toParameter) - ); - } - - #endregion Line3d - - #region LineSegment3d - - /// - /// 将三维解析类线段转换为实体类直线 - /// - /// 三维解析类线段 - /// 实体类直线 - public static Line ToCurve(this LineSegment3d lineSeg3d) - { - return new Line(lineSeg3d.StartPoint, lineSeg3d.EndPoint); - } - - #endregion LineSegment3d - - #region CircularArc3d - - /// - /// 将三维解析类圆/弧转换为实体圆/弧 - /// - /// 三维解析类圆/弧 - /// 实体圆/弧 - public static Curve ToCurve(this CircularArc3d ca3d) - { - if (ca3d.IsClosed()) - { - return ToCircle(ca3d); - } - else - { - return ToArc(ca3d); - } - } - - /// - /// 将三维解析类圆/弧转换为实体圆 - /// - /// 三维解析类圆/弧 - /// 实体圆 - public static Circle ToCircle(this CircularArc3d ca3d) => - new(ca3d.Center, ca3d.Normal, ca3d.Radius); - - /// - /// 将三维解析类圆/弧转换为实体圆弧 - /// - /// 三维解析类圆/弧 - /// 实体圆弧 - public static Arc ToArc(this CircularArc3d ca3d) - { - // 必须新建,而不能直接使用GetPlane()获取 - double angle = ca3d.ReferenceVector.AngleOnPlane(new Plane(ca3d.Center, ca3d.Normal)); - return new Arc(ca3d.Center, ca3d.Normal, ca3d.Radius, ca3d.StartAngle + angle, ca3d.EndAngle + angle); - } - - /// - /// 将三维解析类圆/弧转换为三维解析类椭圆弧 - /// - /// 三维解析类圆/弧 - /// 三维解析类椭圆弧 - public static EllipticalArc3d ToEllipticalArc3d(this CircularArc3d ca3d) - { - Vector3d zaxis = ca3d.Normal; - Vector3d xaxis = ca3d.ReferenceVector; - Vector3d yaxis = zaxis.CrossProduct(xaxis); - - return - new EllipticalArc3d( - ca3d.Center, - xaxis, - yaxis, - ca3d.Radius, - ca3d.Radius, - ca3d.StartAngle, - ca3d.EndAngle); - } - - /// - /// 将三维解析类圆/弧转换为三维解析类Nurb曲线 - /// - /// 三维解析类圆/弧 - /// 三维解析类Nurb曲线 - public static NurbCurve3d ToNurbCurve3d(this CircularArc3d ca3d) - { - EllipticalArc3d ea3d = ToEllipticalArc3d(ca3d); - NurbCurve3d nc3d = new(ea3d); - return nc3d; - } - - #endregion CircularArc3d - - #region EllipticalArc3d - - /// - /// 将三维解析类椭圆弧转换为实体类椭圆弧 - /// - /// 三维解析类椭圆弧 - /// 实体类椭圆弧 - public static Ellipse ToCurve(this EllipticalArc3d ea3d) - { - Ellipse ell = - new( - ea3d.Center, - ea3d.Normal, - ea3d.MajorAxis * ea3d.MajorRadius, - ea3d.MinorRadius / ea3d.MajorRadius, - 0, - Math.PI * 2); - // Ge椭圆角度就是Db椭圆的参数 - if (!ea3d.IsClosed()) - { - ell.StartAngle = ell.GetAngleAtParameter(ea3d.StartAngle); - ell.EndAngle = ell.GetAngleAtParameter(ea3d.EndAngle); - } - return ell; - } - - #endregion EllipticalArc3d - - #region NurbCurve3d - - /// - /// 将三维解析类Nurb曲线转换为实体类样条曲线 - /// - /// 三维解析类Nurb曲线 - /// 实体类样条曲线 - public static Spline ToCurve(this NurbCurve3d nc3d) - { - Spline spl; - if (nc3d.HasFitData) - { - NurbCurve3dFitData fdata = nc3d.FitData; - if (fdata.TangentsExist) - { - spl = new Spline( - fdata.FitPoints, - fdata.StartTangent, - fdata.EndTangent, - nc3d.Order, - fdata.FitTolerance.EqualPoint); - } - else - { - spl = new Spline( - fdata.FitPoints, - nc3d.Order, - fdata.FitTolerance.EqualPoint); - } - } - else - { - DoubleCollection knots = new(); - foreach (double knot in nc3d.Knots) - knots.Add(knot); - - NurbCurve3dData ncdata = nc3d.DefinitionData; - - spl = new Spline( - ncdata.Degree, - ncdata.Rational, - nc3d.IsClosed(), - ncdata.Periodic, - ncdata.ControlPoints, - knots, - ncdata.Weights, - Tolerance.Global.EqualPoint, - ncdata.Knots.Tolerance); - } - return spl; - } - - #endregion NurbCurve3d - - #region PolylineCurve3d - - /// - /// 将三维解析类多段线转换为实体类三维多段线 - /// - /// 三维解析类多段线 - /// 实体类三维多段线 - public static Polyline3d ToCurve(this PolylineCurve3d pl3d) - { - using Point3dCollection pnts = new(); - - for (int i = 0; i < pl3d.NumberOfControlPoints; i++) - pnts.Add(pl3d.ControlPointAt(i)); - - bool closed = false; - int n = pnts.Count - 1; - if (pnts[0] == pnts[n]) - { - pnts.RemoveAt(n); - closed = true; - } - return new Polyline3d(Poly3dType.SimplePoly, pnts, closed); - } - - #endregion PolylineCurve3d -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/CurveEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/CurveEx.cs deleted file mode 100644 index 295ed1a..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/CurveEx.cs +++ /dev/null @@ -1,989 +0,0 @@ - - -namespace IFoxCAD.Cad; - -/// -/// 实体类曲线扩展类 -/// -public static class CurveEx -{ - /// - /// 曲线长度 - /// - /// 曲线 - /// 长度 - public static double GetLength(this Curve curve) - { - return curve.GetDistanceAtParameter(curve.EndParam); - } - - /// - /// 获取分割曲线集合 - /// - /// 曲线 - /// 打断参数表 - /// 打断后曲线的集合 - public static IEnumerable GetSplitCurves(this Curve curve, IEnumerable pars) - { - //if (pars is null) - // throw new ArgumentNullException(nameof(pars)); - ArgumentNullEx.ThrowIfNull(pars); - return - curve - .GetSplitCurves(new DoubleCollection(pars.ToArray())) - .Cast(); - } - - /// - /// 获取分割曲线集合 - /// - /// 曲线 - /// 打断参数表 - /// 对参数表是否进行排序 - /// - /// 按参数值升序排序
- /// 不排序,默认值 - ///
- /// - /// 打断后曲线的集合 - public static IEnumerable GetSplitCurves(this Curve curve, IEnumerable pars, bool isOrder = false) - { - //if (pars is null) - // throw new ArgumentNullException(nameof(pars)); - ArgumentNullEx.ThrowIfNull(pars); - if (isOrder) - pars = pars.OrderBy(x => x); - - return - curve - .GetSplitCurves(new DoubleCollection(pars.ToArray())) - .Cast(); - } - - /// - /// 获取分割曲线集合 - /// - /// 曲线 - /// 打断点表 - /// 打断后曲线的集合 - public static IEnumerable GetSplitCurves(this Curve curve, IEnumerable points) - { - //if (points is null) - // throw new ArgumentNullException(nameof(points)); - ArgumentNullEx.ThrowIfNull(points); - using var pts = new Point3dCollection(points.ToArray()); - return curve.GetSplitCurves(pts).Cast(); - } - - /// - /// 获取分割曲线集合 - /// - /// 曲线 - /// 打断点表 - /// 对点表是否进行排序 - /// - /// 按参数值升序排序
- /// 不排序,默认值 - ///
- /// - /// 打断后曲线的集合 - public static IEnumerable GetSplitCurves(this Curve curve, IEnumerable points, bool isOrder = false) - { - //if (points is null) - // throw new ArgumentNullException(nameof(points)); - ArgumentNullEx.ThrowIfNull(points); - if (isOrder) - points = points.OrderBy(point => - { - var pt = curve.GetClosestPointTo(point, false); - return curve.GetParameterAtPoint(pt); - }); - - using Point3dCollection pts = new(points.ToArray()); - return curve.GetSplitCurves(pts).Cast(); - } - - /// - /// 获取曲线集所围成的封闭区域的曲线集,注意此函数不能处理平行边(两个点及两条线组成的闭合环) - /// - /// 曲线集合 - /// 所有的闭合环的曲线集合 - public static IEnumerable GetAllCycle(this IEnumerable curves) - { - ArgumentNullEx.ThrowIfNull(curves); - - // 新建图 - var graph = new Graph(); - foreach (var curve in curves) - { -#if !gcad - graph.AddEdge(curve.GetGeCurve()); -#else - graph.AddEdge(curve.ToCurve3d()!); -#endif - } - // 新建 dfs - var dfs = new DepthFirst(); - // 查询全部的 闭合环 - dfs.FindAll(graph); - // 遍历闭合环的列表,将每个闭合环转换为实体曲线 - List res = []; - foreach (var item in dfs.Curve3ds) - { - var curve = graph.GetCurves(item.ToList()).ToArray(); - var comcur = new CompositeCurve3d(curve).ToCurve(); - if (comcur is not null) - res.Add(comcur); - } - return res; - } - /// - /// 曲线打断 - /// - /// 曲线列表 - /// 打断后的曲线列表 - public static List BreakCurve(this List curves) - { - ArgumentNullEx.ThrowIfNull(curves); - - var tol = new Tolerance(0.01, 0.01); - - List geCurves = []; // 存储曲线转换后的复合曲线 - List> paramss = []; // 存储每个曲线的交点参数值 - - for (int i = 0; i < curves.Count; i++) - { - var cc3d = curves[i].ToCompositeCurve3d(); - if (cc3d is not null) - { - geCurves.Add(cc3d); - paramss.Add([]); - } - } - - // List oldCurves = []; - List newCurves = []; - var cci3d = new CurveCurveIntersector3d(); - - for (int i = 0; i < curves.Count; i++) - { - var gc1 = geCurves[i]; - var pars1 = paramss[i]; // 引用 - for (int j = i; j < curves.Count; j++) - { - var gc2 = geCurves[j]; - var pars2 = paramss[j]; // 引用 - - cci3d.Set(gc1, gc2, Vector3d.ZAxis, tol); - - for (int k = 0; k < cci3d.NumberOfIntersectionPoints; k++) - { - var pars = cci3d.GetIntersectionParameters(k); - pars1.Add(pars[0]); // 引用修改会同步到源对象 - pars2.Add(pars[1]); // 引用修改会同步到源对象 - } - } - - if (pars1.Count > 0) - { - var c3ds = gc1.GetSplitCurves(pars1); - if (c3ds is not null && c3ds.Count > 1) - { - foreach (var c3d in c3ds) - { - var c3dCur = c3d.ToCurve(); - if (c3dCur is not null) - { - c3dCur.SetPropertiesFrom(curves[i]); - newCurves.Add(c3dCur); - } - } - // oldCurves.Add(curves[i]); - } - } - } - - return newCurves; - } - - /// - /// 在z法向量平面打断曲线 - /// - /// 曲线列表 - /// 打断后的曲线列表 - /// 传入的曲线列表错误 - public static List BreakCurveOnZPlane(this List curves) - { - if (curves is null) - throw new ArgumentNullException(nameof(curves)); - var zPlane = new Plane(Point3d.Origin, Vector3d.ZAxis); - var curvesTemp = curves.Select(c => c.GetProjectedCurve(zPlane, Vector3d.ZAxis)).ToList(); - List geCurves = []; // 存储曲线转换后的复合曲线 - List> paramss = []; // 存储每个曲线的交点参数值 - - for (int i = 0; i < curvesTemp.Count; i++) - { - paramss.Add([]); - var cc3d = curvesTemp[i].ToCompositeCurve3d(); - if (cc3d is not null) - { - geCurves.Add(cc3d); - } - } - List newCurves = []; - var cci3d = new CurveCurveIntersector3d(); - - for (int i = 0; i < curvesTemp.Count; i++) - { - var gc1 = geCurves[i]; - var pars1 = paramss[i]; // 引用 - for (int j = i; j < curvesTemp.Count; j++) - { - var gc2 = geCurves[j]; - var pars2 = paramss[j]; // 引用 - - cci3d.Set(gc1, gc2, Vector3d.ZAxis); - - for (int k = 0; k < cci3d.NumberOfIntersectionPoints; k++) - { - var pars = cci3d.GetIntersectionParameters(k); - pars1.Add(pars[0]); // 引用修改会同步到源对象 - pars2.Add(pars[1]); // 引用修改会同步到源对象 - } - } - var curNow = curvesTemp[i]; - var length = curNow.GetLength(); - List np = pars1.Where(p => p >= 0 && p <= length) - .Select(curNow.GetParameterAtDistance) - .Where(p => !(Math.Abs(p - curNow.StartParam) < 1e-6 || Math.Abs(p - curNow.EndParam) < 1e-6)) - .ToList(); - if (np.Count > 0) - { - var splitCurs = curNow.GetSplitCurves(np, true); - if (splitCurs.Count() > 1) - { - newCurves.AddRange(splitCurs); - } - else - { - newCurves.Add(curNow.CloneEx()); - } - } - else - { - newCurves.Add(curNow.CloneEx()); - } - } - - return newCurves; - } -#if !gcad - /// - /// 打段曲线2维By四叉树 - /// - /// 目前对xline,ray的支持存在错误 - /// 需要更多的测试 - /// - /// - /// 曲线列表 - /// 容差 - /// 打断后的曲线列表 - public static List BreakCurve2dByQuadTree(this List sourceCurveList, double tol = 1e-6) - { - //var tolerance = new Tolerance(tol, tol); - var zPlane = new Plane(Point3d.Origin, Vector3d.ZAxis); - List curves = sourceCurveList.Select(c => c.GetOrthoProjectedCurve(zPlane)).ToList(); - List geCurves = []; - List xlines = []; - double minX = double.MaxValue; - double minY = double.MaxValue; - double maxX = double.MinValue; - double maxY = double.MinValue; - // 遍历每个曲线,计算出四叉树对象,加到四叉树曲线对象列表和四叉树容器中 - for (int i = 0; i < curves.Count; i++) - { - var curTemp = curves[i]; - if (curTemp is Ray || curTemp is Xline) - { - xlines.Add(curTemp); - } - else - { - var cc3d = curTemp.ToCompositeCurve3d(); - if (cc3d is not null) - { - var e3d = curTemp.GeometricExtents; - var rect = new Rect(e3d.MinPoint.Point2d(), e3d.MaxPoint.Point2d()); - var cit = new BreakCurveInfo(rect, curTemp, cc3d); - if (rect.Left < minX) minX = rect.Left; - if (rect.Right > maxX) maxX = rect.Right; - if (rect.Bottom < minY) minY = rect.Bottom; - if (rect.Top > maxY) maxY = rect.Top; - geCurves.Add(cit); - } - } - } - // 建四叉树容器 - var maxBox = new Rect(minX - 10, minY - 10, maxX + 10, maxY + 10); - xlines.ForEach(xl => - { - var cc3d = new CompositeCurve3d(new[] { xl.GetGeCurve() }); - var bci = new BreakCurveInfo(maxBox, xl, cc3d); - geCurves.Add(bci); - }); - List newCurves = []; - var quadTree = new QuadTree(maxBox); - foreach (var bci in geCurves) - { - quadTree.Insert(bci); - } - - var cci3d = new CurveCurveIntersector3d(); - - foreach (var gc1 in geCurves) - { - var parsList = new HashSet(); - var cts = quadTree.Query(new Rect(gc1.Left - tol, gc1.Bottom - tol, gc1.Right + tol, gc1.Top + tol)); - cts.Remove(gc1); - foreach (var gc2 in cts) - { - cci3d.Set(gc1.Cc3d, gc2.Cc3d, Vector3d.ZAxis, Tolerance.Global); - for (int k = 0; k < cci3d.NumberOfIntersectionPoints; k++) - { - var pars = cci3d.GetIntersectionParameters(k); - parsList.Add(pars[0]); - } - if (!gc2.Curve.Closed) - { - var cpt1 = gc1.Cc3d.GetClosestPointTo(gc2.Cc3d.StartPoint); - var cpt2 = gc1.Cc3d.GetClosestPointTo(gc2.Cc3d.EndPoint); - if (cpt1.Point.Distance2dTo(gc2.Cc3d.StartPoint) < tol && cpt1.Point.Distance2dTo(gc1.Cc3d.StartPoint) >= tol) - { - parsList.Add(cpt1.Parameter); - } - if (cpt2.Point.Distance2dTo(gc2.Cc3d.EndPoint) < tol && cpt2.Point.Distance2dTo(gc1.Cc3d.EndPoint) >= tol) - { - parsList.Add(cpt2.Parameter); - } - } - - } - if (gc1.Curve is Polyline || gc1.Curve is Spline) - { - cci3d.Set(gc1.Cc3d, gc1.Cc3d, Vector3d.ZAxis); - for (int k = 0; k < cci3d.NumberOfIntersectionPoints; k++) - { - var pars = cci3d.GetIntersectionParameters(k); - if (pars[0] == pars[1]) - continue; - parsList.Add(pars[0]); - parsList.Add(pars[1]); - } - } - var parsNew = parsList.OrderBy(d => d).ToList(); - - var cur = gc1.Curve; - if (parsNew.Count > 0) - { - var c3ds = Curve3dEx.GetSplitCurves(gc1.Cc3d, parsNew); - if (c3ds is not null && c3ds.Count > 1) - { - if (cur is Arc || (cur is Ellipse { Closed: false })) - { - foreach (var c3d in c3ds) - { - var c3dCur = Curve.CreateFromGeCurve(c3d); - - if (c3dCur is null || c3dCur.Closed || c3dCur is Circle || c3dCur.GetLength() < tol) - continue; - c3dCur.SetPropertiesFrom(cur); - newCurves.Add(c3dCur); - } - continue; - } - foreach (var c3d in c3ds) - { - var c3dCur = Curve.CreateFromGeCurve(c3d); - if (c3dCur is not null) - { - c3dCur.SetPropertiesFrom(cur); - newCurves.Add(c3dCur); - } - } - } - else - { - newCurves.Add(cur.CloneEx()); - } - } - else - { - newCurves.Add(cur.CloneEx()); - } - } - - return newCurves; - } - class BreakCurveInfo : QuadEntity - { - public Rect Rect { get; } - public Curve Curve { get; } - public CompositeCurve3d Cc3d { get; } - - public BreakCurveInfo(Rect rect, Curve curve, CompositeCurve3d cc3d) : base(rect) - { - Curve = curve; - Cc3d = cc3d; - Rect = rect; - } - } -#endif - /// - /// 获取非等比转换的曲线(旋转投影法) - /// - /// 转换前的曲线 - /// 基点 - /// x方向比例 - /// y方向比例 - /// 转换后的曲线 - public static Curve GetScaleCurve(this Curve cur, Point3d pt, double x, double y) - { - // 先做个z平面 - using var zplane = new Plane(pt, Vector3d.ZAxis); - // 克隆一个,防止修改到原来的 - using var cur2 = cur.CloneEx(); - - // 因为旋转投影后只能比原来小,所以遇到先放大 - while (Math.Abs(x) > 1 || Math.Abs(y) > 1) - { - cur2.TransformBy(Matrix3d.Scaling(2, pt)); - x /= 2; - y /= 2; - } - // 旋转投影 - var xA = Math.Acos(x); - cur2.TransformBy(Matrix3d.Rotation(xA, Vector3d.YAxis, pt)); - - using var cur3 = cur2.GetOrthoProjectedCurve(zplane); - - // 再次旋转投影 - var yA = Math.Acos(y); - cur3.TransformBy(Matrix3d.Rotation(yA, Vector3d.XAxis, pt)); - var cur4 = cur3.GetOrthoProjectedCurve(zplane); - - //设置属性 - cur4.SetPropertiesFrom(cur); - return cur4; - } - - - // 转换DBCurve为GeCurved - - #region Curve - - /// - /// 将曲线转换为ge曲线,此函数将在未来淘汰,二惊加油 - /// - /// 曲线 - /// ge曲线 - public static Curve3d? ToCurve3d(this Curve curve) - { - return curve switch - { - Line li => ToCurve3d(li), - Circle ci => ToCurve3d(ci), - Arc arc => ToCurve3d(arc), - Ellipse el => ToCurve3d(el), - Polyline pl => ToCurve3d(pl), - Polyline2d pl2 => ToCurve3d(pl2), - Polyline3d pl3 => ToCurve3d(pl3), - Spline sp => ToCurve3d(sp), - _ => null - }; - } - - /// - /// 将曲线转换为复合曲线 - /// - /// 曲线 - /// 复合曲线 - public static CompositeCurve3d? ToCompositeCurve3d(this Curve curve) - { - return curve switch - { - Line li => new CompositeCurve3d(new Curve3d[] { ToCurve3d(li) }), - Circle ci => new CompositeCurve3d(new Curve3d[] { ToCurve3d(ci) }), - Arc arc => new CompositeCurve3d(new Curve3d[] { ToCurve3d(arc) }), - Ellipse el => new CompositeCurve3d(new Curve3d[] { ToCurve3d(el) }), - Polyline pl => new CompositeCurve3d(new Curve3d[] { ToCurve3d(pl) }), - - Polyline2d pl2 => new CompositeCurve3d(new Curve3d[] { ToCurve3d(pl2)! }), - Polyline3d pl3 => new CompositeCurve3d(new Curve3d[] { ToCurve3d(pl3) }), - Spline sp => new CompositeCurve3d(new Curve3d[] { ToCurve3d(sp) }), - _ => null - }; - } - - /// - /// 将曲线转换为Nurb曲线 - /// - /// 曲线 - /// Nurb曲线 - public static NurbCurve3d? ToNurbCurve3d(this Curve curve) - { - return curve switch - { - Line li => ToNurbCurve3d(li), - Circle ci => ToNurbCurve3d(ci), - Arc arc => ToNurbCurve3d(arc), - Ellipse el => ToNurbCurve3d(el), - Polyline pl => ToNurbCurve3d(pl), - Polyline2d pl2 => ToNurbCurve3d(pl2), - Polyline3d pl3 => ToNurbCurve3d(pl3), - Spline sp => ToNurbCurve3d(sp), - _ => null - }; - } - - #region Line - - /// - /// 将直线转换为ge直线 - /// - /// 直线 - /// ge直线 - public static LineSegment3d ToCurve3d(this Line line) - { - return new LineSegment3d(line.StartPoint, line.EndPoint); - } - - /// - /// 将直线转换为Nurb曲线 - /// - /// 直线 - /// Nurb曲线 - public static NurbCurve3d ToNurbCurve3d(this Line line) - { - return new NurbCurve3d(ToCurve3d(line)); - } - - #endregion Line - - #region Circle - - /// - /// 将圆转换为ge圆弧曲线 - /// - /// 圆 - /// ge圆弧曲线 - public static CircularArc3d ToCurve3d(this Circle cir) - { - return - new CircularArc3d( - cir.Center, - cir.Normal, - cir.Radius); - } - - /// - /// 将圆转换为ge椭圆曲线 - /// - /// 圆 - /// ge椭圆曲线 - public static EllipticalArc3d ToEllipticalArc3d(this Circle cir) - { - return ToCurve3d(cir).ToEllipticalArc3d(); - } - - /// - /// 将圆转换为Nurb曲线 - /// - /// 圆 - /// Nurb曲线 - public static NurbCurve3d ToNurbCurve3d(this Circle cir) - { - return new NurbCurve3d(ToEllipticalArc3d(cir)); - } - - #endregion Circle - - #region Arc - - /// - /// 将圆弧转换为ge圆弧曲线 - /// - /// 圆弧 - /// ge圆弧曲线 - public static CircularArc3d ToCurve3d(this Arc arc) - { - Plane plane = new(arc.Center, arc.Normal); - - return - new CircularArc3d( - arc.Center, - arc.Normal, - plane.GetCoordinateSystem().Xaxis, - arc.Radius, - arc.StartAngle, - arc.EndAngle - ); - } - - /// - /// 将圆弧转换为ge椭圆曲线 - /// - /// 圆弧 - /// ge椭圆曲线 - public static EllipticalArc3d ToEllipticalArc3d(this Arc arc) - { - return ToCurve3d(arc).ToEllipticalArc3d(); - } - - /// - /// 将圆弧转换为三维Nurb曲线 - /// - /// 圆弧 - /// 三维Nurb曲线 - public static NurbCurve3d ToNurbCurve3d(this Arc arc) - { - return new NurbCurve3d(ToEllipticalArc3d(arc)); - } - - #endregion Arc - - #region Ellipse - - /// - /// 将椭圆转换为三维ge椭圆曲线 - /// - /// 椭圆 - /// 三维ge椭圆曲线 - public static EllipticalArc3d ToCurve3d(this Ellipse ell) - { - return - new EllipticalArc3d( - ell.Center, - ell.MajorAxis.GetNormal(), - ell.MinorAxis.GetNormal(), - ell.MajorRadius, - ell.MinorRadius, - ell.StartParam, - ell.EndParam); - } - - /// - /// 将椭圆转换为三维Nurb曲线 - /// - /// 椭圆 - /// 三维Nurb曲线 - public static NurbCurve3d ToNurbCurve3d(this Ellipse ell) - { - return new NurbCurve3d(ToCurve3d(ell)); - } - - #endregion Ellipse - - #region Spline - - /// - /// 将样条曲线转换为三维Nurb曲线 - /// - /// 样条曲线 - /// 三维Nurb曲线 - public static NurbCurve3d ToCurve3d(this Spline spl) - { - NurbCurve3d nc3d; - NurbsData ndata = spl.NurbsData; - KnotCollection knots = [.. ndata.GetKnots()]; - - if (ndata.Rational) - { - nc3d = - new NurbCurve3d( - ndata.Degree, - knots, - ndata.GetControlPoints(), - ndata.GetWeights(), - ndata.Periodic); - } - else - { - nc3d = - new NurbCurve3d( - ndata.Degree, - knots, - ndata.GetControlPoints(), - ndata.Periodic); - } - - if (spl.HasFitData) - { - var fdata = spl.FitData; - var vec = new Vector3d(); - if (fdata.TangentsExist && (fdata.StartTangent != vec || fdata.EndTangent != vec)) - nc3d.SetFitData(fdata.GetFitPoints(), fdata.StartTangent, fdata.EndTangent); - } - return nc3d; - } - - #endregion Spline - - #region Polyline2d - - /// - /// 将二维多段线转换为三维ge曲线 - /// - /// 二维多段线 - /// 三维ge曲线 - public static Curve3d? ToCurve3d(this Polyline2d pl2d) - { - switch (pl2d.PolyType) - { - case Poly2dType.SimplePoly: - case Poly2dType.FitCurvePoly: - Polyline pl = new(); - pl.SetDatabaseDefaults(); - pl.ConvertFrom(pl2d, false); - return ToCurve3d(pl); - default: - return ToNurbCurve3d(pl2d); - } - - // Polyline pl = new Polyline(); - // pl.ConvertFrom(pl2d, false); - // return ToCurve3d(pl); - } - - /// - /// 将二维多段线转换为三维Nurb曲线 - /// - /// 二维多段线 - /// 三维Nurb曲线 - public static NurbCurve3d? ToNurbCurve3d(this Polyline2d pl2d) - { - switch (pl2d.PolyType) - { - case Poly2dType.SimplePoly: - case Poly2dType.FitCurvePoly: - Polyline pl = new(); - pl.SetDatabaseDefaults(); - pl.ConvertFrom(pl2d, false); - return ToNurbCurve3d(pl); - - default: - return ToCurve3d(pl2d.Spline); - } - } - - /// - /// 将二维多段线转换为三维ge多段线 - /// - /// 二维多段线 - /// 三维ge多段线 - public static PolylineCurve3d ToPolylineCurve3d(this Polyline2d pl) - { - using Point3dCollection pnts = new(); - foreach (Vertex2d ver in pl) - pnts.Add(ver.Position); - return new PolylineCurve3d(pnts); - } - - #endregion Polyline2d - - #region Polyline3d - - /// - /// 将三维多段线转换为三维曲线 - /// - /// 三维多段线 - /// 三维曲线 - public static Curve3d ToCurve3d(this Polyline3d pl3d) - { - return pl3d.PolyType switch - { - Poly3dType.SimplePoly => ToPolylineCurve3d(pl3d), - _ => ToNurbCurve3d(pl3d), - }; - } - - /// - /// 将三维多段线转换为三维Nurb曲线 - /// - /// 三维多段线 - /// 三维Nurb曲线 - public static NurbCurve3d ToNurbCurve3d(this Polyline3d pl3d) - { - return ToCurve3d(pl3d.Spline); - } - - /// - /// 将三维多段线转换为三维ge多段线 - /// - /// 三维多段线 - /// 三维ge多段线 - public static PolylineCurve3d ToPolylineCurve3d(this Polyline3d pl) - { - using Point3dCollection pnts = new(); - foreach (ObjectId id in pl) - { - if (id.GetObject(OpenMode.ForRead) is PolylineVertex3d ver) - pnts.Add(ver.Position); - } - return new PolylineCurve3d(pnts); - } - - #endregion Polyline3d - - #region Polyline - - /// - /// 多段线转换为复合曲线 - /// - /// 多段线对象 - /// 复合曲线对象 - public static CompositeCurve3d ToCurve3d(this Polyline pl) - { - List c3ds = []; - - for (int i = 0; i < pl.NumberOfVertices; i++) - { - switch (pl.GetSegmentType(i)) - { - case SegmentType.Line: - c3ds.Add(pl.GetLineSegmentAt(i)); - break; - - case SegmentType.Arc: - c3ds.Add(pl.GetArcSegmentAt(i)); - break; - - default: - break; - } - } - return new CompositeCurve3d([.. c3ds]); - } - - /// - /// 多段线转换为Nurb曲线 - /// - /// 多段线 - /// Nurb曲线 - public static NurbCurve3d? ToNurbCurve3d(this Polyline pl) - { - NurbCurve3d? nc3d = null; - for (int i = 0; i < pl.NumberOfVertices; i++) - { - NurbCurve3d? nc3dtemp = null; - switch (pl.GetSegmentType(i)) - { - case SegmentType.Line: - nc3dtemp = new NurbCurve3d(pl.GetLineSegmentAt(i)); - break; - - case SegmentType.Arc: - nc3dtemp = pl.GetArcSegmentAt(i).ToNurbCurve3d(); - break; - - default: - break; - } - if (nc3d is null) - nc3d = nc3dtemp; - else if (nc3dtemp is not null) - nc3d.JoinWith(nc3dtemp); - } - return nc3d; - } - - /// - /// 为优化多段线倒角 - /// - /// 优化多段线 - /// 顶点索引号 - /// 倒角半径 - /// 倒角类型 - public static void ChamferAt(this Polyline polyline, int index, double radius, bool isFillet) - { - if (index < 1 || index > polyline.NumberOfVertices - 2) - throw new System.Exception("错误的索引号"); - - if (SegmentType.Line != polyline.GetSegmentType(index - 1) || - SegmentType.Line != polyline.GetSegmentType(index)) - throw new System.Exception("非直线段不能倒角"); - - // 获取当前索引号的前后两段直线,并组合为Ge复合曲线 - Curve3d[] c3ds = - [ - polyline.GetLineSegmentAt(index - 1), - polyline.GetLineSegmentAt(index) - ]; - CompositeCurve3d cc3d = new(c3ds); - - // 试倒直角 - // 子曲线的个数有三种情况: - // 1、=3时倒角方向正确 - // 2、=2时倒角方向相反 - // 3、=0或为直线时失败 - c3ds = - cc3d.GetTrimmedOffset - ( - radius, - Vector3d.ZAxis, - OffsetCurveExtensionType.Chamfer - ); - - if (c3ds.Length > 0 && c3ds[0] is CompositeCurve3d) - { - var newcc3d = c3ds[0] as CompositeCurve3d; - c3ds = newcc3d!.GetCurves(); - if (c3ds.Length == 3) - { - c3ds = cc3d.GetTrimmedOffset - ( - -radius, - Vector3d.ZAxis, - OffsetCurveExtensionType.Chamfer - ); - if (c3ds.Length == 0 || c3ds[0] is LineSegment3d) - throw new System.Exception("倒角半径过大"); - } - else if (c3ds.Length == 2) - { - radius = -radius; - } - } - else - { - throw new System.Exception("倒角半径过大"); - } - - // GetTrimmedOffset会生成倒角+偏移,故先反方向倒角,再倒回 - c3ds = cc3d.GetTrimmedOffset - ( - -radius, - Vector3d.ZAxis, - OffsetCurveExtensionType.Extend - ); - OffsetCurveExtensionType type = - isFillet ? - OffsetCurveExtensionType.Fillet : OffsetCurveExtensionType.Chamfer; - c3ds = c3ds[0].GetTrimmedOffset - ( - radius, - Vector3d.ZAxis, - type - ); - - // 将结果Ge曲线转为Db曲线,并将相关的数值反映到原曲线 - if (c3ds[0].ToCurve() is not Polyline plTemp) - return; - polyline.RemoveVertexAt(index); - polyline.AddVertexAt(index, plTemp.GetPoint2dAt(1), plTemp.GetBulgeAt(1), 0, 0); - polyline.AddVertexAt(index + 1, plTemp.GetPoint2dAt(2), 0, 0, 0); - } - - #endregion Polyline - - #endregion -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBDictionaryEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBDictionaryEx.cs deleted file mode 100644 index 2a38c6a..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBDictionaryEx.cs +++ /dev/null @@ -1,377 +0,0 @@ -namespace IFoxCAD.Cad; - -/// -/// 字典扩展类 -/// -public static class DBDictionaryEx -{ - /// - /// 获取字典里的全部对象 - /// - /// 对象类型的泛型 - /// 字典 - /// 对象迭代器 - [System.Diagnostics.DebuggerStepThrough] - public static IEnumerable GetAllObjects(this DBDictionary dict) where T : DBObject - { - var tr = DBTrans.GetTopTransaction(dict.Database); - foreach (DBDictionaryEntry e in dict) - { - if(tr.GetObject(e.Value) is T tobj) - yield return tobj; - } - } - - /// - /// 获取字典内指定key的对象 - /// - /// 对象类型的泛型 - /// 字典 - /// 指定的键值 - /// T 类型的对象 - public static T? GetAt(this DBDictionary dict, string key) where T : DBObject - { - var tr = DBTrans.GetTopTransaction(dict.Database); - if (dict.Contains(key)) - { - ObjectId id = dict.GetAt(key); - if (!id.IsNull) - return tr.GetObject(id); - } - return null; - } - - /// - /// 添加条目(键值对)到字典 - /// - /// 对象类型 - /// 字典 - /// 键 - /// 值 - /// 字典项目的id - public static ObjectId SetAt(this DBDictionary dict, string key, T newValue) where T : DBObject - { - var tr = DBTrans.GetTopTransaction(dict.Database); - - using (dict.ForWrite()) - { - var id = dict.SetAt(key, newValue); - tr.AddNewlyCreatedDBObject(newValue, true); - return id; - } - } - - #region XRecord - - /// - /// 从字典中获取扩展数据 - /// - /// 字典 - /// 键值 - /// 扩展数据 - public static XRecordDataList? GetXRecord(this DBDictionary dict, string key) - { - var rec = dict.GetAt(key); - if (rec is null) - return null; - return rec.Data; - } - - /// - /// 保存扩展数据到字典 - /// - /// 扩展数据 - /// 字典 - /// 键值 - public static void SetXRecord(this DBDictionary dict, string key, XRecordDataList rb) - { - // DxfCode.300 字符串可以写 Data - // DxfCode.1004 内存流不给写 Data,只能去写 XData - using Xrecord newValue = new() { Data = rb }; - dict.SetAt(key, newValue); - } - #endregion - - /// - /// 获取扩展字典 - /// - /// 对象 - /// 打开模式 - /// 扩展字典对象 - public static DBDictionary GetXDictionary(this DBObject obj, OpenMode openMode = OpenMode.ForRead) - { - var tr = DBTrans.GetTopTransaction(obj.Database); - ObjectId id = obj.ExtensionDictionary; - if (id.IsNull) - { - using (obj.ForWrite()) - obj.CreateExtensionDictionary(); - - id = obj.ExtensionDictionary; - } - return (DBDictionary)tr.GetObject(id,openMode); - } - - #region 数据表 - - /// - /// 创建数据表 - /// - /// 原数据类型的字典 - /// 表元素(二维数组) - /// 数据表 - public static DataTable CreateDataTable(Dictionary colTypes, object[,] content) - { - DataTable table = new(); - foreach (var t in colTypes) - table.AppendColumn(t.Value, t.Key); - - var ncol = colTypes.Count; - var types = new CellType[ncol]; - colTypes.Values.CopyTo(types, 0); - - var nrow = content.GetLength(0); - for (int i = 0; i < nrow; i++) - { - DataCellCollection row = new(); - for (int j = 0; j < ncol; j++) - { - var cell = new DataCell(); - cell.SetValue(types[j], content[i, j]); - row.Add(cell); - } - table.AppendRow(row, true); - } - return table; - } - - /// - /// 设定单元格数据 - /// - /// 单元格 - /// 类型 - /// 数据 - public static void SetValue(this DataCell cell, CellType type, object value) - { - switch (type) - { - case CellType.Bool: - cell.SetBool((bool)value); - break; - - case CellType.CharPtr: - cell.SetString((string)value); - break; - - case CellType.Integer: - cell.SetInteger((int)value); - break; - - case CellType.Double: - cell.SetDouble((double)value); - break; - - case CellType.ObjectId: - cell.SetObjectId((ObjectId)value); - break; - - case CellType.Point: - cell.SetPoint((Point3d)value); - break; - - case CellType.Vector: - cell.SetVector((Vector3d)value); - break; - - case CellType.HardOwnerId: - cell.SetHardOwnershipId((ObjectId)value); - break; - - case CellType.HardPtrId: - cell.SetHardPointerId((ObjectId)value); - break; - - case CellType.SoftOwnerId: - cell.SetSoftOwnershipId((ObjectId)value); - break; - - case CellType.SoftPtrId: - cell.SetSoftPointerId((ObjectId)value); - break; - } - } - #endregion - - #region 子字典 - /// - /// 获取子字典 - /// - /// 根字典 - /// 是否创建子字典 - /// 键值列表 - /// 字典 - public static DBDictionary? GetSubDictionary(this DBDictionary dict, - bool createSubDictionary, - IEnumerable dictNames) - { - DBDictionary? newdict = null; - - if (createSubDictionary) - { - using (dict.ForWrite()) - dict.TreatElementsAsHard = true; - - foreach (string name in dictNames) - { - if (dict.Contains(name)) - { - newdict = dict.GetAt(name); - } - else - { - DBDictionary subDict = new(); - dict.SetAt(name, subDict); - newdict = subDict; - newdict.TreatElementsAsHard = true; - } - } - } - else - { - foreach (string name in dictNames) - { - if (dict.Contains(name)) - newdict = dict.GetAt(name); - else - return null; - } - } - return newdict; - } - - - ///// - ///// 获取对象扩展字典的子字典 - ///// - ///// 对象 - ///// 事务 - ///// 是否创建子字典 - ///// 键值列表 - ///// 字典 - // public static DBDictionary GetSubDictionary(this DBObject obj, bool createSubDictionary, params string[] dictNames) - // { - // return obj.GetXDictionary().GetSubDictionary(createSubDictionary, dictNames); - // } - - #endregion - - #region 组字典 - /// - /// 添加编组 - /// - /// 字典 - /// 组名 - /// 实体Id集合 - /// 编组Id - public static ObjectId AddGroup(this DBDictionary dict, string name, ObjectIdCollection ids) - { - if (dict.Contains(name)) - return ObjectId.Null; - - using (dict.ForWrite()) - { - Group g = new(); - g.Append(ids); - dict.SetAt(name, g); - var tr = DBTrans.GetTopTransaction(dict.Database); - tr.AddNewlyCreatedDBObject(g, true); - return g.ObjectId; - } - } - - /// - /// 添加编组 - /// - /// 字典 - /// 组名 - /// 实体Id集合 - /// 编组Id - public static ObjectId AddGroup(this DBDictionary dict, string name, IEnumerable ids) - { - if (dict.Contains(name)) - return ObjectId.Null; - - using ObjectIdCollection idc = new(ids.ToArray());//需要using吗? 暂无测试 - return dict.AddGroup(name, idc); - } - - - /// - /// 按选择条件获取编组集合 - /// - /// 字典 - /// 选择条件,过滤函数 - /// g.NumEntities < 2);]]> - /// 编组集合 - public static IEnumerable GetGroups(this DBDictionary dict, Func func) - { - return dict.GetAllObjects() - .Where(func); - } - - /// - /// 返回实体的所在编组的集合 - /// - /// 图元实体 - /// 编组集合 - public static IEnumerable GetGroups(this Entity ent) - { - return ent.GetPersistentReactorIds() - .Cast() - .Select(id => id.GetObject()) - .OfType(); - } - - /// - /// 移除所有的空组 - /// - /// 被移除编组的名称集合 - public static List RemoveNullGroup(this DBDictionary dict) - { - var groups = dict.GetGroups(g => g.NumEntities < 2); - List names = new(); - foreach (Group g in groups) - { - names.Add(g.Name); - using (g.ForWrite()) - g.Erase(); - } - return names; - } - - /// - /// 移除所有空组 - /// - /// - /// 过滤条件,过滤要删除的组名的规则函数 - /// - /// g.StartsWith("hah"));]]> - /// - /// 被移除编组的名称集合 - public static List RemoveNullGroup(this DBDictionary dict, Func func) - { - var groups = dict.GetGroups(g => g.NumEntities < 2); - List names = new(); - foreach (Group g in groups) - { - if (func(g.Name)) - { - names.Add(g.Name); - using (g.ForWrite()) - g.Erase(); - } - } - return names; - } - #endregion -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBObjectEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBObjectEx.cs deleted file mode 100644 index f152281..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBObjectEx.cs +++ /dev/null @@ -1,195 +0,0 @@ -namespace IFoxCAD.Cad; - -/// -/// 实体对象扩展类 -/// -public static class DBObjectEx -{ - /// - /// 获取块的有效名字 - /// - /// 块参照 - /// 名字 - public static string GetBlockName(this BlockReference blk) - { - ArgumentNullEx.ThrowIfNull(blk); - if (blk.IsDynamicBlock) - { - var btrid = blk.DynamicBlockTableRecord; - var tr = btrid.Database.TransactionManager.TopTransaction; - ArgumentNullEx.ThrowIfNull(tr); - var btr = (BlockTableRecord)tr.GetObject(btrid); - return btr.Name; - } - return blk.Name; - } - - #region Linq - /// - /// 删除数据库对象 - /// - /// 数据库对象列表 - public static void Erase(this IEnumerable dBObjects) - { - foreach (var dbo in dBObjects) - { - if (dbo.IsNewObject || dbo.IsErased) - continue; - using (dbo.ForWrite()) - { - dbo.Erase(); - } - } - } - #endregion - - #region Xdata扩展 - /// - /// 删除扩展数据 - /// - /// 对象实例 - /// 应用程序名称 - /// 要删除数据的组码 - public static void RemoveXData(this DBObject obj, string appName, DxfCode dxfCode) - { - if (obj.XData == null) - return; - XDataList data = obj.XData; - - // 测试命令 addxdata removexdata - // 移除指定App的扩展 - var indexs = data.GetXdataAppIndex(appName, new DxfCode[] { dxfCode }); - if (indexs.Count == 0) - return; - - for (int i = indexs.Count - 1; i >= 0; i--) - data.RemoveAt(indexs[i]); - - using (obj.ForWrite()) - obj.XData = data; - } - /// - /// 删除扩展数据 - /// - /// 对象实例 - /// 应用程序名称 - public static void RemoveXData(this DBObject obj, string appName) - { - if (obj.XData == null) - return; - - // 直接赋值进去等于清空名称 - using (obj.ForWrite()) - obj.XData = new XDataList() { { 1001, appName } }; - } - /// - /// 克隆对象 - /// - /// 对象类型 - /// 对象 - /// 克隆后的对象 - /// - public static T CloneEx(this T ent) where T : RXObject - { - return ent.Clone() is T tEnt ? tEnt : throw new ArgumentException(nameof(CloneEx) + "克隆出错"); - } - /// - /// 修改扩展数据 - /// - /// 对象实例 - /// 应用程序名称 - /// 要修改数据的组码 - /// 新的数据 - public static void ChangeXData(this DBObject obj, string appName, DxfCode dxfCode, object newvalue) - { - if (obj.XData == null) - return; - XDataList data = obj.XData; - - var indexs = data.GetXdataAppIndex(appName, new DxfCode[] { dxfCode }); - if (indexs.Count == 0) - return; - - for (int i = indexs.Count - 1; i >= 0; i--) - data[indexs[i]] = new TypedValue((short)dxfCode, newvalue); - - using (obj.ForWrite()) - obj.XData = data; - } - #endregion - - #region 读写模式切换 - -#line hidden // 调试的时候跳过它 - /// - /// 实体自动管理读写函数,此函数性能比using模式低一倍 - /// - /// 实体类型 - /// 实体对象 - /// 操作委托 - public static void ForWrite(this T obj, Action action) where T : DBObject - { - var _isNotifyEnabled = obj.IsNotifyEnabled; - var _isWriteEnabled = obj.IsWriteEnabled; - if (_isNotifyEnabled) - obj.UpgradeFromNotify(); - else if (!_isWriteEnabled) - obj.UpgradeOpen(); - - action?.Invoke(obj); - - if (_isNotifyEnabled) - obj.DowngradeToNotify(_isWriteEnabled); - else if (!_isWriteEnabled) - obj.DowngradeOpen(); - } - - /// - /// 打开模式提权 - /// - /// 实体对象 - /// 提权类对象 - public static UpgradeOpenManager ForWrite(this DBObject obj) - { - return new UpgradeOpenManager(obj); - } - - /// - /// 提权类 - /// - public class UpgradeOpenManager : IDisposable - { - private readonly DBObject _obj; - private readonly bool _isNotifyEnabled; - private readonly bool _isWriteEnabled; - - internal UpgradeOpenManager(DBObject obj) - { - _obj = obj; - _isNotifyEnabled = _obj.IsNotifyEnabled; - _isWriteEnabled = _obj.IsWriteEnabled; - if (_isNotifyEnabled) - _obj.UpgradeFromNotify(); - else if (!_isWriteEnabled) - _obj.UpgradeOpen(); - } - - #region IDisposable 成员 - - /// - /// 注销函数 - /// - public void Dispose() - { - if (_isNotifyEnabled) - _obj.DowngradeToNotify(_isWriteEnabled); - else if (!_isWriteEnabled) - _obj.DowngradeOpen(); - GC.SuppressFinalize(this); - } - - #endregion IDisposable 成员 - } -#line default - #endregion -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBTransEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBTransEx.cs deleted file mode 100644 index 1131399..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/DBTransEx.cs +++ /dev/null @@ -1,94 +0,0 @@ -#define lack_test - -namespace IFoxCAD.Cad; - -#if lack_test -/// -/// 事务类扩展 -/// -public static class DBTransEx -{ - /* - * 0x01 - * db.Purge(ids)是获取未硬引用(无引用?)的对象,也就可以删除的. - * 0x02 - * 如果一个图元引用一个图层, - * 假设这个图元是可以删除的(实际上它可能来自于词典记录的id) => 那么它被 db.Purge(ids) 识别, - * 但是这个图层因为有硬引用,所以不被 db.Purge(ids) 识别, - * 只能删除图元之后,循环第二次再通过 db.Purge(ids) 获取图层id. - * 0x03 - * 因为删除之后,符号表内的引用可能被修改,因此需要重复遍历符号表. - * 0x04 - * 试试循环事务 - * 0x05 - * 无法过滤外部参照图层,使得全部图层打开了 - */ - - /// - /// 清理符号表 - /// - /// - /// - /// 排除外部参照:默认true,为false时候会令图层全部显示再清理,包括冻结 - public static void Purge(this DBTrans tr, SymModes sym = SymModes.All, bool excludeXref = true) - { - using ObjectIdCollection ids = new(); - var db = tr.Database; - - if ((sym & SymModes.BlockTable) == SymModes.BlockTable) - { - if (!excludeXref) - GetAllIds(tr, tr.BlockTable, ids, excludeXref); - else - tr.BlockTable.ForEach(tabRec => { - if (!tabRec.IsFromExternalReference) - ids.Add(tabRec.Id); - }, checkIdOk: true); - } - if ((sym & SymModes.DimStyleTable) == SymModes.DimStyleTable) - GetAllIds(tr, tr.DimStyleTable, ids, excludeXref); - if ((sym & SymModes.LayerTable) == SymModes.LayerTable) - GetAllIds(tr, tr.LayerTable, ids, excludeXref); - if ((sym & SymModes.LinetypeTable) == SymModes.LinetypeTable) - GetAllIds(tr, tr.LinetypeTable, ids, excludeXref); - if ((sym & SymModes.TextStyleTable) == SymModes.TextStyleTable) - GetAllIds(tr, tr.TextStyleTable, ids, excludeXref); - if ((sym & SymModes.ViewportTable) == SymModes.ViewportTable) - GetAllIds(tr, tr.ViewportTable, ids, excludeXref); - if ((sym & SymModes.RegAppTable) == SymModes.RegAppTable) - GetAllIds(tr, tr.RegAppTable, ids, excludeXref); - - // SHUN007 说这两个表可能有错误 - if ((sym & SymModes.ViewTable) == SymModes.ViewTable) - GetAllIds(tr, tr.ViewTable, ids, excludeXref); - if ((sym & SymModes.UcsTable) == SymModes.UcsTable) - GetAllIds(tr, tr.UcsTable, ids, excludeXref); - - // Purge是查询能够清理的对象 - db.Purge(ids); - foreach (ObjectId id in ids) - id.Erase(); - } - - static void GetAllIds(DBTrans tr, - SymbolTable symbolTable, - ObjectIdCollection ids, - bool excludeXref = true) - where TTable : SymbolTable - where TRecord : SymbolTableRecord, new() - { - if (!excludeXref) - symbolTable.ForEach(id => ids.Add(id)); - else - { - symbolTable.ForEach(id => { - var tabRec = tr.GetObject(id); - if (tabRec == null) - return; - if (!tabRec.Name.Contains("|")) - ids.Add(tabRec.Id); - }); - } - } -} -#endif \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/DatabaseEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/DatabaseEx.cs deleted file mode 100644 index 6d9a14d..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/DatabaseEx.cs +++ /dev/null @@ -1,201 +0,0 @@ -namespace IFoxCAD.Cad; - -/// -/// 数据库扩展函数 -/// -public static class DatabaseEx -{ - - /// - /// 打开切换活动数据库 - /// - /// 当前数据库 - /// 切换数据库对象 - public static SwitchDatabase SwitchDatabase(this Database db) => new(db); - - - - /// - /// 保存文件 - /// - /// 数据库 - /// 文件版本 - public static void SaveDwgFile(this Database db, DwgVersion version = DwgVersion.AC1800) - { - db.SaveFile(version); - } - - /// - /// 保存文件
- ///
- /// 数据库 - /// 默认2004dwg;若保存dxf则需要在路径输入扩展名 - /// 为true时候无效,将变为自动识别环境变量 - /// 另存为文件,前台将调用时它将无效,将变为弹出面板 - /// 保存路径失败的提示 - public static void SaveFile(this Database db, DwgVersion version = DwgVersion.AC1800, - bool automatic = true, - string? saveAsFile = null, - bool echoes = true) - { - // 遍历当前所有文档,文档必然是前台的 - Document? doc = null; - foreach (Document docItem in Acaop.DocumentManager) - { - if (docItem.Database.Filename == db.Filename) - { - doc = docItem; - break; - } - } - // 前台开图,使用命令保存;不需要切换文档 - if (doc != null) - { - // 无法把 给这个面板 - doc.SendStringToExecute(saveAsFile == null ? "_qsave\n" : $"_Saveas\n", false, true, true); - return; - } - - // 后台开图,用数据库保存 - string? fileMsg; - bool creatFlag = false; - if (string.IsNullOrWhiteSpace(saveAsFile)) - { - fileMsg = db.Filename; - saveAsFile = fileMsg; - //creatFlag = true; - } - else - { - fileMsg = saveAsFile; - - // 路径失败也保存到桌面 - var path = Path.GetDirectoryName(saveAsFile); - if (string.IsNullOrWhiteSpace(path)) - { - creatFlag = true; - } - else if (!Directory.Exists(path)) - { - try { Directory.CreateDirectory(path); } - catch { creatFlag = true; } - } - - // 文件名缺失时 - if (!creatFlag && - string.IsNullOrWhiteSpace(Path.GetFileName(saveAsFile))) - creatFlag = true; - } - if (saveAsFile != null) - { - var fileNameWith = Path.GetFileNameWithoutExtension(saveAsFile); - if (string.IsNullOrWhiteSpace(fileNameWith)) - creatFlag = true; - } - else - { - creatFlag = true; - } - - if (creatFlag) - { - var (error, file) = db.GetOrCreateSaveAsFile(); - if (echoes && error) - System.Windows.Forms.MessageBox.Show($@"错误参数: -{fileMsg} - -它将保存: -{file}", "错误的文件路径"); - saveAsFile = file; - } - - if (Path.GetExtension(saveAsFile)!.ToLower().Contains("dxf")) - { - // dxf用任何版本号都会报错 -#if acad || gcad - db.DxfOut(saveAsFile, 7, true); -#endif - -#if zcad // 中望这里没有测试 - db.DxfOut(saveAsFile, 7, version, true); -#endif - return; - } - - if (automatic) - version = Env.GetDefaultDwgVersion(); - - // dwg需要版本号,而dxf不用,dwg用dxf版本号会报错 - // 若扩展名和版本号冲突,按照扩展名为准 - if (version.IsDxfVersion()) - version = DwgVersion.Current; - - db.SaveAs(saveAsFile, version); - } - - /// - /// 获取文件名,无效的话就制造 - /// - /// - private static (bool error, string path) GetOrCreateSaveAsFile(this Database db) - { - var file = db.Filename; - if (!string.IsNullOrWhiteSpace(file)) - return (false, file); - - // 为了防止用户输入了错误的路径造成无法保存, - // 所以此处将进行保存到桌面, - // 而不是弹出警告就结束 - // 防止前台关闭了所有文档导致没有Editor,所以使用 MessageBox 发送警告 - var fileName = Path.GetFileNameWithoutExtension(file); - var fileExt = Path.GetExtension(file); - - if (string.IsNullOrWhiteSpace(fileName)) - fileName = DateTime.Now.ToString("--yyMMdd--hhmmssffff"); - if (string.IsNullOrWhiteSpace(fileExt)) - fileExt = ".dwg"; - - // 构造函数(fileName)用了不存在的路径进行后台打开,就会出现此问题 - // 测试命令 FileNotExist - var dir = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) - + "\\后台保存出错的文件\\"; - - if (!Directory.Exists(dir)) - Directory.CreateDirectory(dir); - - file = dir + fileName + fileExt; - while (File.Exists(file)) - { - var time = DateTime.Now.ToString("--yyMMdd--hhmmssffff"); - file = dir + fileName + time + fileExt; - System.Threading.Thread.Sleep(100); - } - return (true, file); - } - -} - -/// -/// 自动切换活动数据库 -/// -public class SwitchDatabase : IDisposable -{ - private readonly Database db; - /// - /// 切换活动数据库 - /// - /// 当前数据库 - public SwitchDatabase(Database database) - { - db = HostApplicationServices.WorkingDatabase; - HostApplicationServices.WorkingDatabase = database; - } - /// - /// 恢复活动数据库为默认 - /// - public void Dispose() - { - HostApplicationServices.WorkingDatabase = db; - GC.SuppressFinalize(this); - } -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/DwgMark.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/DwgMark.cs deleted file mode 100644 index c82ed23..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/DwgMark.cs +++ /dev/null @@ -1,63 +0,0 @@ -namespace IFoxCAD.Cad; -/// -/// Ϊdwgļӱ -/// -public static class DwgMark -{ - - private const int FREESPACE = 0x15; - private const int FREESPACEDEFAULT = 0x00; - /// - /// Ϊdwgļӱʶ - /// - /// DWGļ - /// ASCIIʶֽ0X00~0X7F - /// dwgļᱨbiteҲ - public static void AddMark(FileInfo file, int bite) - { - if (file.Extension.ToLower() != ".dwg") - { - throw new ArgumentException("dwgļ"); - } - if (bite > 0x7F || bite < 0x00) - { - throw new ArgumentException("ַASCIIΧ"); - } - using BinaryWriter bw = new BinaryWriter(File.Open(file.FullName, FileMode.Open)); - bw.BaseStream.Position = FREESPACE;//ļͷ21ֽ - bw.Write(bite); //дݣһֽ - } - /// - /// dwgļǻָΪĬֵ - /// - /// ļ - /// dwgļᱨ - public static void RemoveMark(FileInfo file) - { - if (file.Extension.ToLower() != ".dwg") - { - throw new ArgumentException("dwgļ"); - } - using BinaryWriter bw = new BinaryWriter(File.Open(file.FullName, FileMode.Open)); - bw.BaseStream.Position = FREESPACE;//ļͷ21ֽ - bw.Write(FREESPACEDEFAULT); //дݣһֽ - } - /// - /// ȡõdwgļ - /// - /// ļ - /// - /// dwgļᱨ - public static int GetMark(FileInfo file) - { - if (file.Extension.ToLower() != ".dwg") - { - throw new ArgumentException("dwgļ"); - } - using FileStream fs = File.OpenRead(file.FullName); - fs.Seek(FREESPACE, SeekOrigin.Begin); - byte[] mark = new byte[1]; - fs.Read(mark, 0, mark.Length); - return mark[0]; - } -} diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs deleted file mode 100644 index d9a92b0..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/EditorEx.cs +++ /dev/null @@ -1,1184 +0,0 @@ -namespace IFoxCAD.Cad; - -/// -/// 命令行扩展类 -/// -public static class EditorEx -{ - #region 选择集 - /// - /// 选择穿过一个点的对象 - /// - /// 命令行对象 - /// 点 - /// 过滤器 - /// 选择集结果类 - public static PromptSelectionResult SelectAtPoint(this Editor editor, Point3d point, - SelectionFilter? filter = default) - { - return editor.SelectCrossingWindow(point, point, filter); - } - - /// - /// 根据线宽创建图层选择集 - /// - /// 命令行对象 - /// 线宽 - /// 图层选择集 - public static SelectionSet SelectByLineWeight(this Editor editor, LineWeight lineWeight) - { - OpFilter filter = new OpEqual(370, lineWeight); - - var lays = - DBTrans.Top.LayerTable - .GetRecords() - .Where(ltr => ltr.LineWeight == lineWeight) - .Select(ltr => ltr.Name) - .ToArray(); - - if (lays.Length > 0) - { - filter = - new OpOr - { - filter, - new OpAnd - { - { 8, string.Join(",", lays) }, - { 370, LineWeight.ByLayer } - } - }; - } - - var res = editor.SelectAll(filter); - return res.Value; - } - - /// - /// 选择集 - /// - /// 命令行对象 - /// 模式 - /// 过滤器 - /// 消息 - /// - /// 关键字和回调函数 - /// 不用使用下列关键字 "Window/Last/Crossing/BOX/ALL/Fence/WPolygon/CPolygon/Group/Add/Remove/Multiple/Previous/Undo/AUto/Single" - /// - /// - public static PromptSelectionResult SSGet(this Editor editor, - string? mode = null, - SelectionFilter? filter = null, - (string add, string remove)? messages = null, - Dictionary? keywords = null) - { - PromptSelectionOptions pso = new(); - PromptSelectionResult ss; - if (mode is not null) - { - mode = mode.ToUpper(); - pso.SinglePickInSpace = mode.Contains(":A"); - pso.RejectObjectsFromNonCurrentSpace = mode.Contains(":C"); - pso.AllowDuplicates = mode.Contains(":D"); - pso.SelectEverythingInAperture = mode.Contains(":E"); - pso.RejectObjectsOnLockedLayers = mode.Contains(":L"); - pso.PrepareOptionalDetails = mode.Contains(":N"); - pso.SingleOnly = mode.Contains(":S"); - pso.RejectPaperspaceViewport = mode.Contains(":V"); - pso.AllowSubSelections = mode.Contains("-A"); - pso.ForceSubSelections = mode.Contains("-F"); - } - if (messages is not null) - { - pso.MessageForAdding = messages.Value.add; - pso.MessageForRemoval = messages.Value.remove; - } - - if (keywords is not null) - { - foreach (var keyword in keywords.Keys) - pso.Keywords.Add(keyword); - if (pso.MessageForRemoval is null) - pso.MessageForAdding = "选择对象"; - - var str = keywords.Keys.Select(key => { - keywords.TryGetValue(key, out (string, Action) value); - return $"{value.Item1}({key})"; - }); - - - pso.MessageForAdding += $" [{string.Join("/", str)}]"; - pso.KeywordInput += (s, e) => { - if (keywords.TryGetValue(e.Input, out (string, Action) value)) - value.Item2.Invoke(); - }; - } - try - { - ss = filter is not null ? editor.GetSelection(pso, filter) : editor.GetSelection(pso); - } - catch - { - //editor.WriteMessage($"\nKey is {e.Message}"); - throw; - } - return ss; - } - - - /* - * // 定义选择集选项 - * var pso = new PromptSelectionOptions - * { - * AllowDuplicates = false, // 重复选择 - * }; - * - * // getai遍历全图选择块有用到 - * var dic = new Dictionary() { - * { "Z,全部同名", ()=> { - * getai = BlockHelper.EnumAttIdentical.AllBlockName; - * SendEsc.Esc(); - * }}, - * { "X,动态块显示", ()=> { - * getai = BlockHelper.EnumAttIdentical.Display; - * }}, - * { "V,属性值-默认", ()=> { - * getai = BlockHelper.EnumAttIdentical.DisplayAndTagText; - * }}, - * // 允许以下操作,相同的会加入前面的 - * // { "V,属性值-默认|X,啊啊啊啊", ()=> { - * - * // }}, - * }; - * pso.SsgetAddKeys(dic); - * - * // 创建选择集过滤器,只选择块对象 - * var filList = new TypedValue[] { new TypedValue((int)DxfCode.Start, "INSERT") }; - * var filter = new SelectionFilter(filList); - * ssPsr = ed.GetSelection(pso, filter); - */ - - /// - /// 添加选择集关键字和回调 - /// - /// 选择集配置 - /// 关键字,回调委托 - /// - public static void SsgetAddKeys(this PromptSelectionOptions pso, - Dictionary dicActions) - { - Dictionary tmp = new(); - // 后缀名的|号切割,移除掉,组合成新的加入tmp - for (int i = dicActions.Count - 1; i >= 0; i--) - { - var pair = dicActions.ElementAt(i); - var key = pair.Key; - var keySp = key.Split('|'); - if (keySp.Length < 2) - continue; - - for (int j = 0; j < keySp.Length; j++) - { - var item = keySp[j]; - // 防止多个后缀通过|符越过词典约束同名 - // 后缀(key)含有,而且Action(value)不同,就把Action(value)累加到后面. - if (dicActions.TryGetValue(item, out Action value)) - { - if (dicActions[item] != dicActions[key]) - dicActions[item] += dicActions[key]; - } - else - tmp.Add(item, value); - } - dicActions.Remove(key); - } - - foreach (var item in tmp) - dicActions.Add(item.Key, item.Value); - - // 去除关键字重复的,把重复的执行动作移动到前面 - for (int i = 0; i < dicActions.Count; i++) - { - var pair1 = dicActions.ElementAt(i); - var key1 = pair1.Key; - - for (int j = dicActions.Count - 1; j > i; j--) - { - var pair2 = dicActions.ElementAt(j); - var key2 = pair2.Key; - - if (key1.Split(',')[0] == key2.Split(',')[0]) - { - if (dicActions[key1] != dicActions[key2]) - dicActions[key1] += dicActions[key2]; - dicActions.Remove(key2); - } - } - } - - foreach (var item in dicActions) - { - var keySplitS = item.Key.Split(new string[] { ",", "|" }, StringSplitOptions.RemoveEmptyEntries); - for (int i = 0; i < keySplitS.Length; i += 2) - pso.Keywords.Add(keySplitS[i], keySplitS[i], - keySplitS[i + 1] + "(" + keySplitS[i] + ")"); - } - - // 回调的时候我想用Dict的O(1)索引, - // 但是此函数内进行new Dictionary() 在函数栈释放的时候,它被释放掉了. - // 因此 dicActions 参数的生命周期 - tmp = new(dicActions); - dicActions.Clear(); - foreach (var item in tmp) - dicActions.Add(item.Key.Split(',')[0], item.Value); - - var keyWords = pso.Keywords; - // 从选择集命令中显示关键字 - pso.MessageForAdding = keyWords.GetDisplayString(true); - // 关键字回调事件 ssget关键字 - pso.KeywordInput += (sender, e) => { - dicActions[e.Input].Invoke(); - }; - } - - - - - - - // #region 即时选择样板 - // /// - // /// 即时选择,框选更新关键字 - // /// - // public static void SelectTest() - // { - // Env.Editor.WriteMessage("\n[白嫖工具]--测试"); - // // 激活选中事件 - // Env.Editor.SelectionAdded += SelectTest_SelectionAdded; - // // 初始化坐标系 - // Env.Editor.CurrentUserCoordinateSystem = Matrix3d.Identity; - - // // 创建过滤器 - // var sf = new OpEqual(0, "arc"); - // var pso = new PromptSelectionOptions - // { - // MessageForAdding = "\n请选择对象:" - // }; - - // pso.Keywords.Add("Z"); - // pso.Keywords.Add("X"); - // pso.Keywords.Add("Q"); - // // 注册关键字 - // pso.KeywordInput += SelectTest_KeywordInput; - // try - // { - // // 用户选择 - // var psr = Env.Editor.GetSelection(pso, sf); - // // 处理代码 - - - // } - // catch (Exception ex)// 捕获关键字 - // { - // if (ex.Message == "XuError") - // { - // // 关闭关键字事件 - // pso.KeywordInput -= SelectTest_KeywordInput; - // // 关闭选中事件 - // Env.Editor.SelectionAdded -= SelectTest_SelectionAdded; - // // 重新调用自身 - // ZengLiangYuanJiao(); - // } - // } - // // 关闭关键字事件 - // pso.KeywordInput -= SelectTest_KeywordInput; - // // 关闭选中事件 - // Env.Editor.SelectionAdded -= SelectTest_SelectionAdded; - // } - - // /// - // /// 即时选择 - // /// - // /// - // /// - // private static void SelectTest_SelectionAdded(object sender, SelectionAddedEventArgs e) - // { - // // 关闭选中事件 - // Env.Editor.SelectionAdded -= SelectTest_SelectionAdded; - // using (var tr = new DBTrans()) - // { - // // 处理代码 - // for (int i = 0; i < e.AddedObjects.Count; i++) - // { - // // 处理完移除已处理的对象 - // e.Remove(i); - // } - // } - // // 激活选中事件 - // Env.Editor.SelectionAdded += SelectTest_SelectionAdded; - // } - - // /// - // /// 关键字响应 - // /// - // /// - // /// - // private static void SelectTest_KeywordInput(object sender, SelectionTextInputEventArgs e) - // { - // // 获取关键字 - // switch (e.Input) - // { - // case "Z": - // break; - // case "X": - // break; - - // case "Q": - // break; - // } - // // 抛出异常,用于更新提示信息 - // throw new ArgumentException("XuError"); - // } - // #endregion - #endregion - - #region Info - - /// - /// 带错误提示对话框的打印信息函数 - /// - /// 带格式项的字符串 - /// 指定格式化的对象数组 - public static void StreamMessage(string format, params object[] args) - { - StreamMessage(string.Format(format, args)); - } - - /// - /// 带错误提示对话框的打印信息函数 - /// - /// 打印信息 - public static void StreamMessage(string message) - { - try - { - if (HasEditor()) - WriteMessage(message); - else - InfoMessageBox(message); - } - catch (System.Exception ex) - { - Message(ex); - } - } - - /// - /// 异常信息对话框 - /// - /// 异常 - public static void Message(System.Exception ex) - { - try - { - System.Windows.Forms.MessageBox.Show( - ex.ToString(), - "Error", - System.Windows.Forms.MessageBoxButtons.OK, - System.Windows.Forms.MessageBoxIcon.Error); - } - catch - { - } - } - - /// - /// 提示信息对话框 - /// - /// 对话框的标题 - /// 对话框文本 - public static void InfoMessageBox(string caption, string message) - { - try - { - System.Windows.Forms.MessageBox.Show( - message, - caption, - System.Windows.Forms.MessageBoxButtons.OK, - System.Windows.Forms.MessageBoxIcon.Information); - } - catch (System.Exception ex) - { - Message(ex); - } - } - - /// - /// 提示信息对话框 - /// - /// 对话框的标题 - /// 带格式化项的对话框文本 - /// 指定格式化的对象数组 - public static void InfoMessageBox(string caption, string format, params object[] args) - { - InfoMessageBox(caption, string.Format(format, args)); - } - - /// - /// 提示信息对话框,默认标题为NFox.Cad - /// - /// 对话框文本 - public static void InfoMessageBox(string message) - { - InfoMessageBox("NFox.Cad", message); - } - - /// - /// 提示信息对话框 - /// - /// 带格式化项的对话框文本 - /// 指定格式化的对象数组 - public static void InfoMessageBox(string format, params object[] args) - { - InfoMessageBox(string.Format(format, args)); - } - - /// - /// 命令行打印字符串 - /// - /// 字符串 - public static void WriteMessage(string message) - { - try - { - if (Acceptable()) - Acap.DocumentManager.MdiActiveDocument.Editor.WriteMessage("\n" + message); - else - return; - } - catch (System.Exception ex) - { - Message(ex); - } - } - - /// - /// 命令行打印字符串 - /// - /// 带格式化项的文本 - /// 指定格式化的对象数组 - public static void WriteMessage(string format, params object[] args) - { - WriteMessage(string.Format(format, args)); - } - - /// - /// 判断是否有活动的编辑器对象 - /// - /// 有,没有 - public static bool HasEditor() - { - return Acap.DocumentManager.MdiActiveDocument is not null - && Acap.DocumentManager.Count != 0 - && Acap.DocumentManager.MdiActiveDocument.Editor is not null; - } - - /// - /// 判断是否可以打印字符串 - /// - /// 可以打印,不可以打印 - public static bool Acceptable() - { - return HasEditor() - && !Acap.DocumentManager.MdiActiveDocument.Editor.IsDragging; - } - - #endregion Info - - #region 画矢量线 - - /// - /// 根据点表返回矢量线的列表 - /// - /// 点表 - /// 是否闭合, 为闭合, 为不闭合 - /// - public static List GetLines(IEnumerable pnts, bool isClosed) - { - var itor = pnts.GetEnumerator(); - if (!itor.MoveNext()) - return new List(); - - List values = new(); - - TypedValue tvFirst = new((int)LispDataType.Point2d, itor.Current); - TypedValue tv1; - TypedValue tv2 = tvFirst; - - while (itor.MoveNext()) - { - tv1 = tv2; - tv2 = new TypedValue((int)LispDataType.Point2d, itor.Current); - values.Add(tv1); - values.Add(tv2); - } - - if (isClosed) - { - values.Add(tv2); - values.Add(tvFirst); - } - - return values; - } - - /// - /// 画矢量线 - /// - /// 编辑器对象 - /// 点表 - /// 颜色码 - /// 是否闭合, 为闭合, 为不闭合 - public static void DrawVectors(this Editor editor, IEnumerable pnts, short colorIndex, bool isClosed) - { - var rlst = - new LispList { { LispDataType.Int16, colorIndex } }; - rlst.AddRange(GetLines(pnts, isClosed)); - editor.DrawVectors(new(rlst.ToArray()), Matrix3d.Identity); - } - - /// - /// 画矢量线 - /// - /// 编辑器对象 - /// 点表 - /// 颜色码 - public static void DrawVectors(this Editor editor, IEnumerable pnts, short colorIndex) - { - editor.DrawVectors(pnts, colorIndex, false); - } - - /// - /// 用矢量线画近似圆(正多边形) - /// - /// 编辑器对象 - /// 点表 - /// 颜色码 - /// 半径 - /// 多边形边的个数 - public static void DrawCircles(this Editor editor, IEnumerable pnts, short colorIndex, double radius, int numEdges) - { - var rlst = - new LispList { { LispDataType.Int16, colorIndex } }; - - foreach (Point2d pnt in pnts) - { - Vector2d vec = Vector2d.XAxis * radius; - double angle = Math.PI * 2 / numEdges; - - List tpnts = new() - { - pnt + vec - }; - for (int i = 1; i < numEdges; i++) - { - tpnts.Add(pnt + vec.RotateBy(angle * i)); - } - - rlst.AddRange(GetLines(tpnts, true)); - } - editor.DrawVectors(new(rlst.ToArray()), editor.CurrentUserCoordinateSystem); - } - - /// - /// 用矢量线画近似圆(正多边形) - /// - /// 编辑器对象 - /// 点 - /// 颜色码 - /// 半径 - /// 多边形边的个数 - public static void DrawCircle(this Editor editor, Point2d pnt, short colorIndex, double radius, int numEdges) - { - Vector2d vec = Vector2d.XAxis * radius; - double angle = Math.PI * 2 / numEdges; - - List pnts = new() - { - pnt + vec - }; - for (int i = 1; i < numEdges; i++) - pnts.Add(pnt + vec.RotateBy(angle * i)); - - editor.DrawVectors(pnts, colorIndex, true); - } - /// - /// 根据点表绘制矢量线段(每两点为一条线段的起始点和终止点) - /// - /// 用户交互对象 - /// 点表 - /// CAD颜色索引;默认:1为红色 - /// 是否高亮显示;为高亮显示,默认:为不高亮显示 - public static void DrawLineVectors(this Editor editor, IEnumerable points, int colorIndex = 1, - bool drawHighlighted = false) - { - Point3d endPoint1, endPoint2; - var itor = points.GetEnumerator(); - while (itor.MoveNext()) - { - endPoint1 = itor.Current; - if (!itor.MoveNext()) return; - endPoint2 = itor.Current; - editor.DrawVector(endPoint1, endPoint2, colorIndex, drawHighlighted); - } - } - /// - /// 根据点表绘制首尾相连的矢量 - /// - /// 用户交互对象 - /// 点表 - /// CAD颜色索引;默认:1为红色 - /// 是否闭合; 为闭合,默认: 为不闭合 - /// 是否高亮显示;为高亮显示,默认:为不高亮显示 - public static void DrawEndToEndVectors(this Editor editor, IEnumerable points, int colorIndex = 1, - bool isclose = false, bool drawHighlighted = false) - { - var itor = points.GetEnumerator(); - if (!points.Any() || !itor.MoveNext()) return; - Point3d endPoint1 = itor.Current, endPoint2 = new(), firstEndPoint = endPoint1; - while (itor.MoveNext()) - { - endPoint2 = itor.Current; - editor.DrawVector(endPoint1, endPoint2, colorIndex, drawHighlighted); - endPoint1 = endPoint2; - } - if (isclose) - editor.DrawVector(endPoint2, firstEndPoint, colorIndex, drawHighlighted); - } - #endregion - - #region 矩阵 - - /// - /// 获取UCS到WCS的矩阵 - /// - /// 命令行对象 - /// 变换矩阵 - public static Matrix3d GetMatrixFromUcsToWcs(this Editor editor) - { - return editor.CurrentUserCoordinateSystem; - } - - /// - /// 获取WCS到UCS的矩阵 - /// - /// 命令行对象 - /// 变换矩阵 - public static Matrix3d GetMatrixFromWcsToUcs(this Editor editor) - { - return editor.CurrentUserCoordinateSystem.Inverse(); - } - - /// - /// 获取MDCS(模型空间)到WCS的矩阵 - /// - /// 命令行对象 - /// 变换矩阵 - public static Matrix3d GetMatrixFromMDcsToWcs(this Editor editor) - { - Matrix3d mat; - using ViewTableRecord vtr = editor.GetCurrentView(); - mat = Matrix3d.PlaneToWorld(vtr.ViewDirection); - mat = Matrix3d.Displacement(vtr.Target - Point3d.Origin) * mat; - return Matrix3d.Rotation(-vtr.ViewTwist, vtr.ViewDirection, vtr.Target) * mat; - } - - /// - /// 获取WCS到MDCS(模型空间)的矩阵 - /// - /// 命令行对象 - /// 变换矩阵 - public static Matrix3d GetMatrixFromWcsToMDcs(this Editor editor) - { - return editor.GetMatrixFromMDcsToWcs().Inverse(); - } - - /// - /// 获取MDCS(模型空间)到PDCS(图纸空间)的矩阵 - /// - /// 命令行对象 - /// 变换矩阵 - public static Matrix3d GetMatrixFromMDcsToPDcs(this Editor editor) - { - if ((short)Env.GetVar("TILEMODE") == 1) - throw new ArgumentException("TILEMODE == 1..Espace papier uniquement"); - - Matrix3d mat = Matrix3d.Identity; - //using DBTrans tr = new(); - var tr = DBTrans.GetTopTransaction(editor.Document.Database); - var vp = tr.GetObject(editor.CurrentViewportObjectId); - if (vp == null) - return mat; - - if (vp.Number == 1) - { - try - { - editor.SwitchToModelSpace(); - vp = tr.GetObject(editor.CurrentViewportObjectId); - editor.SwitchToPaperSpace(); - } - catch - { - throw new Exception("Aucun fenêtre active...ErrorStatus.InvalidInput"); - } - } - if (vp == null) - return mat; - - Point3d vCtr = new(vp.ViewCenter.X, vp.ViewCenter.Y, 0.0); - mat = Matrix3d.Displacement(vCtr.GetAsVector().Negate()); - mat = Matrix3d.Displacement(vp.CenterPoint.GetAsVector()) * mat; - mat = Matrix3d.Scaling(vp.CustomScale, vp.CenterPoint) * mat; - return mat; - } - - /// - /// 获取PDCS(图纸空间)到MDCS(模型空间)的矩阵 - /// - /// 命令行对象 - /// 变换矩阵 - public static Matrix3d GetMatrixFromPDcsToMDcs(this Editor editor) - { - return editor.GetMatrixFromMDcsToPDcs().Inverse(); - } - - /// - /// 获取变换矩阵 - /// - /// 命令行对象 - /// 源坐标系 - /// 目标坐标系 - /// 变换矩阵 - public static Matrix3d GetMatrix(this Editor editor, CoordinateSystemCode from, CoordinateSystemCode to) - { - return (from, to) switch - { - (CoordinateSystemCode.Wcs, CoordinateSystemCode.Ucs) => editor.GetMatrixFromWcsToUcs(), - (CoordinateSystemCode.Wcs, CoordinateSystemCode.MDcs) => editor.GetMatrixFromWcsToMDcs(), - (CoordinateSystemCode.Ucs, CoordinateSystemCode.Wcs) => editor.GetMatrixFromUcsToWcs(), - (CoordinateSystemCode.Ucs, CoordinateSystemCode.MDcs) => editor.GetMatrixFromUcsToWcs() * editor.GetMatrixFromWcsToMDcs(), - (CoordinateSystemCode.MDcs, CoordinateSystemCode.Wcs) => editor.GetMatrixFromMDcsToWcs(), - (CoordinateSystemCode.MDcs, CoordinateSystemCode.Ucs) => editor.GetMatrixFromMDcsToWcs() * editor.GetMatrixFromWcsToUcs(), - (CoordinateSystemCode.MDcs, CoordinateSystemCode.PDcs) => editor.GetMatrixFromMDcsToPDcs(), - (CoordinateSystemCode.PDcs, CoordinateSystemCode.MDcs) => editor.GetMatrixFromPDcsToMDcs(), - (CoordinateSystemCode.PDcs, CoordinateSystemCode.Wcs or CoordinateSystemCode.Ucs) - or (CoordinateSystemCode.Wcs or CoordinateSystemCode.Ucs, CoordinateSystemCode.PDcs) => throw new Exception("To be used only with DCS...ErrorStatus.InvalidInput"), - (_, _) => Matrix3d.Identity - }; - } - - #endregion - - #region 缩放 - - // todo 暂时先屏蔽这个又臭又长的代码,待搞明白为什么都这么写之后再说 -#if false - /// - /// 缩放窗口范围 - /// - /// 命令行对象 - /// 窗口左下点 - /// 窗口右上点 - public static void ZoomWindow(this Editor ed, Point3d minPoint, Point3d maxPoint) - { - ViewTableRecord vtr = new(); - vtr.CopyFrom(ed.GetCurrentView()); - - var oldpnts = new Point3d[] { minPoint, maxPoint }; - var pnts = new Point3d[8]; - var dpnts = new Point3d[8]; - - var mat = ed.GetMatrixFromWcsToMDcs(); - for (int i = 0; i < 2; i++) - for (int j = 0; j < 2; j++) - for (int k = 0; k < 2; k++) - { - int n = i * 4 + j * 2 + k; - pnts[n] = new Point3d(oldpnts[i][0], oldpnts[j][1], oldpnts[k][2]); - dpnts[n] = pnts[n].TransformBy(mat); - } - - double xmin, xmax, ymin, ymax; - xmin = xmax = dpnts[0][0]; - ymin = ymax = dpnts[0][1]; - for (int i = 1; i < 8; i++) - { - xmin = Math.Min(xmin, dpnts[i][0]); - xmax = Math.Max(xmax, dpnts[i][0]); - ymin = Math.Min(ymin, dpnts[i][1]); - ymax = Math.Max(ymax, dpnts[i][1]); - } - - vtr.Width = xmax - xmin; - vtr.Height = ymax - ymin; - vtr.CenterPoint = (dpnts[0] + (dpnts[7] - dpnts[0]) / 2) - .Convert2d(Curve2dEx._planeCache); - - ed.SetCurrentView(vtr); - //ed.Regen(); - } -#endif - - /// - /// 缩放窗口范围 - /// - /// 命令行对象 - /// 窗口范围点 - public static void ZoomWindow(this Editor ed, Extents3d ext) - { - ZoomWindow(ed, ext.MinPoint, ext.MaxPoint); - } - - /// - /// 按范围缩放 - /// - /// 命令行对象 - /// 中心点 - /// 窗口宽 - /// 窗口高 - public static void Zoom(this Editor ed, Point3d CenPt, double width, double height) - { - using ViewTableRecord view = ed.GetCurrentView(); - view.Width = width; - view.Height = height; - view.CenterPoint = new Point2d(CenPt.X, CenPt.Y); - ed.SetCurrentView(view);// 更新当前视图 - } - - /// - /// 缩放窗口范围 - /// - /// 命令行对象 - /// 第一点 - /// 对角点 - /// 偏移距离 - public static void ZoomWindow(this Editor ed, Point3d lpt, Point3d rpt, double offsetDist = 0.00) - { - Extents3d extents = new(); - extents.AddPoint(lpt); - extents.AddPoint(rpt); - rpt = extents.MaxPoint + new Vector3d(offsetDist, offsetDist, 0); - lpt = extents.MinPoint - new Vector3d(offsetDist, offsetDist, 0); - Vector3d ver = rpt - lpt; - ed.Zoom(lpt + ver / 2, ver.X, ver.Y); - } - - - /// - /// 获取有效的数据库范围 - /// - /// 数据库 - /// 容差值:图元包围盒会超过数据库边界,用此参数扩大边界 - /// - public static Extents3d? GetValidExtents3d(this Database db, double extention = 1e-6) - { - db.UpdateExt(true);// 更新当前模型空间的范围 - var ve = new Vector3d(extention, extention, extention); - // 数据库没有图元的时候,min是大,max是小,导致新建出错 - // 数据如下: - // min.X == 1E20 && min.Y == 1E20 && min.Z == 1E20 && - // max.X == -1E20 && max.Y == -1E20 && max.Z == -1E20) - var a = db.Extmin; - var b = db.Extmax; - if (a.X < b.X && a.Y < b.Y) - return new Extents3d(db.Extmin - ve, db.Extmax + ve); - - return null; - } - - /// - /// 动态缩放 - /// - /// 命令行对象 - /// 偏移距离 - public static void ZoomExtents(this Editor ed, double offsetDist = 0.00) - { - Database db = ed.Document.Database; - // db.UpdateExt(true); // GetValidExtents3d内提供了 - var dbExtent = db.GetValidExtents3d(); - if (dbExtent == null) - ed.ZoomWindow(Point3d.Origin, new Point3d(1, 1, 0), offsetDist); - else - ed.ZoomWindow(db.Extmin, db.Extmax, offsetDist); - } - - /// - /// 根据实体对象的范围显示视图 - /// - /// 命令行对象 - /// Entity对象 - /// 偏移距离 - public static void ZoomObject(this Editor ed, Entity ent, double offsetDist = 0.00) - { - Extents3d ext = ent.GeometricExtents; - ed.ZoomWindow(ext.MinPoint, ext.MaxPoint, offsetDist); - } - -#endregion - - #region Get交互类 - - /// - /// 获取Point - /// - /// 命令行对象 - /// 提示信息 - /// 提示使用的基点 - /// - public static PromptPointResult GetPoint(this Editor ed, string Message, Point3d BasePoint) - { - PromptPointOptions ptOp = new(Message) - { - BasePoint = BasePoint, - UseBasePoint = true - }; - return ed.GetPoint(ptOp); - } - - /// - /// 获取double值 - /// - /// 命令行对象 - /// 提示信息 - /// double默认值 - /// - public static PromptDoubleResult GetDouble(this Editor ed, string Message, double DefaultValue = 1.0) - { - PromptDoubleOptions douOp = new(Message) - { - DefaultValue = DefaultValue - }; - return ed.GetDouble(douOp); - } - - /// - /// 获取int值 - /// - /// 命令行对象 - /// 提示信息 - /// double默认值 - /// - public static PromptIntegerResult GetInteger(this Editor ed, string Message, int DefaultValue = 1) - { - PromptIntegerOptions douOp = new(Message) - { - DefaultValue = DefaultValue - }; - return ed.GetInteger(douOp); - } - - /// - /// 获取string值 - /// - /// 命令行对象 - /// 提示信息 - /// string默认值 - /// - public static PromptResult GetString(this Editor ed, string Message, string DefaultValue = "") - { - PromptStringOptions strOp = new(Message) - { - DefaultValue = DefaultValue - }; - return ed.GetString(strOp); - } - - #endregion - - #region 执行lisp - [DllImport("accore.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "acedInvoke")] - static extern int AcedInvoke(IntPtr args, out IntPtr result); - - - // 高版本此接口不能使用lisp(command "xx"),但是可以直接在自动运行接口上 - [DllImport("accore.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, - EntryPoint = "?acedEvaluateLisp@@YAHPEB_WAEAPEAUresbuf@@@Z")] - [System.Security.SuppressUnmanagedCodeSecurity]// 初始化默认值 - static extern int AcedEvaluateLisp(string lispLine, out IntPtr result); - - - [DllImport("accore.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ads_queueexpr")] - static extern int Ads_queueexpr(string strExpr); - /// - /// 执行lisp的方式枚举 - /// - public enum RunLispFlag : byte - { - /// - /// AdsQueueexpr - /// - AdsQueueexpr = 1, - /// - /// AcedEvaluateLisp - /// - AcedEvaluateLisp = 2, - /// - /// SendStringToExecute - /// - SendStringToExecute = 4, - } - - /* - * 测试命令: - * [CommandMethod(nameof(CmdTest_RunLisp))] - * public static void CmdTest_RunLisp() - * { - * var res = RunLisp("(setq abc 10)"); - * } - * 调用方式: - * (command "CmdTest_RunLisp1") - * bug说明: - * AcedEvaluateLisp 接口 - * 在高版本调用时候没有运行成功,使得 !abc 没有值 - * 在cad08成功,此bug与CommandFlags无关 - * 解决方案: - * 0x01 用异步接口,但是这样是显式调用了: - * (setq thisdrawing (vla-get-activedocument (vlax-get-acad-object)))(vla-SendCommand thisdrawing "CmdTest_RunLisp1 ") - * 0x02 使用 Ads_queueexpr 接口 - */ - /// - /// 发送lisp语句字符串到cad执行 - /// - /// 编辑器对象 - /// lisp语句 - /// 运行方式 - /// 缓冲结果,返回值 - public static ResultBuffer? RunLisp(this Editor ed, string lispCode, RunLispFlag flag = RunLispFlag.AdsQueueexpr) - { - if ((flag & RunLispFlag.AdsQueueexpr) == RunLispFlag.AdsQueueexpr) - { - // 这个在08/12发送lisp不会出错,但是发送bo命令出错了. - // 0x01 设置RunLispFlag特性为RunLispFlag.AcedEvaluateLisp即可同步执行 - // 0x02 自执行发送lisp都是异步,用来发送 含有(command)的lisp的 - _ = Ads_queueexpr(lispCode + "\n"); - } - if ((flag & RunLispFlag.AcedEvaluateLisp) == RunLispFlag.AcedEvaluateLisp) - { - _ = AcedEvaluateLisp(lispCode, out IntPtr rb); - if (rb != IntPtr.Zero) - return (ResultBuffer)DisposableWrapper.Create(typeof(ResultBuffer), rb, true); - } - if ((flag & RunLispFlag.SendStringToExecute) == RunLispFlag.SendStringToExecute) - { - var dm = Acap.DocumentManager; - var doc = dm.MdiActiveDocument; - doc?.SendStringToExecute(lispCode + "\n", false, false, false); - } - return null; - } - #endregion - - #region Export - /// - /// 输出WMF
- /// 此函数不适用于后台 - ///
- /// 命令行对象 - /// 保存文件 - /// 选择集的对象,为null时候手选 - /// 是否清空选择集 - /// - public static void ComExportWMF(this Editor editor, string saveFile, - ObjectId[]? ids = null, bool wmfSetDel = false) - { - if (string.IsNullOrWhiteSpace(saveFile)) - throw new ArgumentNullException(nameof(saveFile)); - if (File.Exists(saveFile)) - throw new FileFormatException("文件重复:" + saveFile); - - var dm = Acap.DocumentManager; - if (dm.Count == 0) - return; - - // 剔除后缀 - saveFile = Path.Combine(Path.GetDirectoryName(saveFile), Path.GetFileNameWithoutExtension(saveFile)); - // ActiveSelectionSet: - // 第一次执行会触发选择,再次重复命令执行的时候,它会无法再选择(即使清空选择集). - // 因此此处netAPI进行选择,它就能读取当前选择集缓冲区的对象 - if (ids == null || ids.Length == 0) - { - var psr = editor.SelectImplied();// 预选 - if (psr.Status != PromptStatus.OK) - psr = editor.GetSelection();// 手选 - if (psr.Status != PromptStatus.OK) - return; - ids = psr.Value.GetObjectIds(); - } - editor.SetImpliedSelection(ids); - -#if zcad - dynamic com = Acap.ZcadApplication; -#else - dynamic com = Acap.AcadApplication; -#endif - dynamic doc = com.ActiveDocument; - dynamic wmfSet = doc.ActiveSelectionSet; - // TODO 20221007 导出wmf的bug - // cad21 先net选择,再进行,此处再选择一次? - // cad21 调试期间无法选择性粘贴? - doc.Export(saveFile, "wmf", wmfSet); - if (wmfSetDel) - wmfSet.Delete(); - } - #endregion - - #region JigEx - /// - /// jig前的准备工作,使图元暗显 - /// - /// 命令栏 - /// 实体(已存在数据库中) - public static void PrepareForJig(this Editor ed, params Entity[] ents) - { - ed.PrepareForJig(ents.ToList()); - } - /// - /// jig前的准备工作,使图元暗显 - /// - /// 命令栏 - /// 实体(已存在数据库中) - public static void PrepareForJig(this Editor ed, IEnumerable ents) - { - var dic = new Dictionary(); - foreach (var ent in ents) - { - if (ent.IsNewObject) - continue; - dic.Add(ent, ent.ColorIndex); - ent.ColorIndex = 250; - ent.Draw(); - } - ed.Redraw(); - foreach (var kvp in dic) - { - kvp.Key.ColorIndex = kvp.Value; - } - } - #endregion - - #region Extension - - /// - /// 获取CAD鼠标当前位置坐标 - /// - /// 命令栏 - /// 坐标(可能为null) - public static Point3d? GetCurrentMouthPoint(this Editor ed) - { - return ed.RunLisp("(grread T)", RunLispFlag.AcedEvaluateLisp)?.AsArray() - .FirstOrDefault(tv => tv.TypeCode == 5009).Value as Point3d?; - } - - #endregion -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/ArcEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/ArcEx.cs deleted file mode 100644 index 53f5825..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/ArcEx.cs +++ /dev/null @@ -1,86 +0,0 @@ -namespace IFoxCAD.Cad; - -/// -/// 圆弧扩展类 -/// -public static class ArcEx -{ - #region 圆弧 - - /// - /// 根据圆心、起点、终点来创建圆弧(二维) - /// - /// 起点 - /// 圆心 - /// 终点 - /// 圆弧 - public static Arc CreateArcSCE(Point3d startPoint, Point3d centerPoint, Point3d endPoint) - { - Arc arc = new(); - arc.SetDatabaseDefaults(); - arc.Center = centerPoint; - arc.Radius = centerPoint.DistanceTo(startPoint); - Vector2d startVector = new(startPoint.X - centerPoint.X, startPoint.Y - centerPoint.Y); - Vector2d endVector = new(endPoint.X - centerPoint.X, endPoint.Y - centerPoint.Y); - // 计算起始和终止角度 - arc.StartAngle = startVector.Angle; - arc.EndAngle = endVector.Angle; - return arc; - } - /// - /// 三点法创建圆弧(二维) - /// - /// 起点 - /// 圆弧上的点 - /// 终点 - /// 圆弧 - public static Arc CreateArc(Point3d startPoint, Point3d pointOnArc, Point3d endPoint) - { - // 创建一个几何类的圆弧对象 - CircularArc3d geArc = new(startPoint, pointOnArc, endPoint); - // 将几何类圆弧对象的圆心和半径赋值给圆弧 -#if !gcad - - return (Arc)Curve.CreateFromGeCurve(geArc); -#else - return (Arc)geArc.ToCurve(); -#endif - } - - /// - /// 根据起点、圆心和圆弧角度创建圆弧(二维) - /// - /// 起点 - /// 圆心 - /// 圆弧角度 - /// 圆弧 - public static Arc CreateArc(Point3d startPoint, Point3d centerPoint, double angle) - { - Arc arc = new(); - arc.SetDatabaseDefaults(); - arc.Center = centerPoint; - arc.Radius = centerPoint.DistanceTo(startPoint); - Vector2d startVector = new(startPoint.X - centerPoint.X, startPoint.Y - centerPoint.Y); - arc.StartAngle = startVector.Angle; - arc.EndAngle = startVector.Angle + angle; - return arc; - } - /// - /// 圆弧转为多段线 - /// - /// 圆弧 - /// 多段线 - public static Polyline ToPolyline(this Arc arc) - { - var plane = new Plane(arc.Center, arc.Normal); - var pl = new Polyline(); - pl.Normal = arc.Normal; - pl.AddVertexAt(0, arc.StartPoint.Convert2d(plane), - Math.Tan(arc.TotalAngle * 0.25), 0, 0); - pl.AddVertexAt(1, arc.EndPoint.Convert2d(plane), 0, 0, 0); - pl.TransformBy(Matrix3d.Displacement(pl.StartPoint.GetVectorTo(arc.StartPoint))); - pl.SetPropertiesFrom(arc); - return pl; - } - #endregion -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs deleted file mode 100644 index 21ebb19..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BlockReferenceEx.cs +++ /dev/null @@ -1,236 +0,0 @@ - - -namespace IFoxCAD.Cad; - -/// -/// 块参照扩展类 -/// -public static class BlockReferenceEx -{ - #region 裁剪块参照 - - private const string filterDictName = "ACAD_FILTER"; - private const string spatialName = "SPATIAL"; - - /// - /// 裁剪块参照 - /// - /// 块参照 - /// 裁剪多边形点表 - public static void ClipBlockRef(this BlockReference bref, IEnumerable pt3ds) - { - Matrix3d mat = bref.BlockTransform.Inverse(); - var pts = - pt3ds - .Select(p => p.TransformBy(mat).Point2d()) - .ToCollection(); - - SpatialFilterDefinition sfd = new(pts, Vector3d.ZAxis, 0.0, 0.0, 0.0, true); - using SpatialFilter sf = new() { Definition = sfd }; - var dict = bref.GetXDictionary().GetSubDictionary(true, new string[] { filterDictName })!; - dict.SetAt(spatialName, sf); - // SetToDictionary(dict, spatialName, sf); - } - - /// - /// 裁剪块参照 - /// - /// 块参照 - /// 第一角点 - /// 第二角点 - public static void ClipBlockRef(this BlockReference bref, Point3d pt1, Point3d pt2) - { - Matrix3d mat = bref.BlockTransform.Inverse(); - pt1 = pt1.TransformBy(mat); - pt2 = pt2.TransformBy(mat); - - Point2dCollection pts = new() - { - new Point2d(Math.Min(pt1.X, pt2.X), Math.Min(pt1.Y, pt2.Y)), - new Point2d(Math.Max(pt1.X, pt2.X), Math.Max(pt1.Y, pt2.Y)) - }; - - using SpatialFilter sf = new() - { - Definition = new(pts, Vector3d.ZAxis, 0.0, 0.0, 0.0, true) - }; - var dict = bref.GetXDictionary()! - .GetSubDictionary(true, new string[] { filterDictName })!; - dict.SetAt(spatialName, sf); - // SetToDictionary(dict, spatialName, sf); -#if !acad - pts.Dispose(); -#endif - } - #endregion - - #region 属性 - /// - /// 更新动态块属性值 - /// - public static void ChangeDynamicBlockProperty(this BlockReference blockReference, - Dictionary propertyNameValues) - { - using (blockReference.ForWrite()) - { - foreach (DynamicBlockReferenceProperty item in blockReference.DynamicBlockReferencePropertyCollection) - if (propertyNameValues.TryGetValue(item.PropertyName, out T? value)) - item.Value = value; - } - } - /// - /// 更新普通块的属性值 - /// - public static void ChangeBlockProperty(this BlockReference blockReference, Dictionary propertyNameValues) - { - var tr = DBTrans.GetTopTransaction(blockReference.Database); - AttributeReference att; - foreach (var item in blockReference.AttributeCollection) - { - if (item is ObjectId id) - { - // 通常情况下返回的都是 ObjectId - att = (AttributeReference)tr.GetObject(id); - } - else - { - // 某些情况下,比如你exploded炸开块后的子块块参照是没有在数据库里的,这时候返回的结果就是 AttributeReference - att = (AttributeReference)item; - } - using (att.ForWrite()) - { - if (propertyNameValues.TryGetValue(att.Tag, out string value)) - { - att.TextString = value; - } - } - } - } - - /// - /// 获取嵌套块的位置(wcs) - /// - /// 父块 - /// 子块名 - /// 子块的位置 - /// - public static Point3d? GetNestedBlockPosition(this BlockReference parentBlockRef, string nestedBlockName) - { - var tr = DBTrans.GetTopTransaction(parentBlockRef.Database); - - var btr = tr.GetObject(parentBlockRef.BlockTableRecord); - if (btr == null) return null; - foreach (ObjectId id in btr) - { - if (id.ObjectClass.Name == "AcDbBlockReference") - { - var nestedBlockRef = tr.GetObject(id); - if (nestedBlockRef?.Name == nestedBlockName) - { - return nestedBlockRef.Position.TransformBy(parentBlockRef.BlockTransform); - } - } - } - return null; - } - /// - /// 获取普通块参照的属性集合 - /// - /// 普通块参照 - /// 属性集合 - public static IEnumerable GetAttributes(this BlockReference owner) - { - if (owner.Database != null) - { - var trans = DBTrans.GetTopTransaction(owner.Database); - foreach (ObjectId id in owner.AttributeCollection) - yield return (AttributeReference)trans.GetObject(id); - } - else - { - foreach (AttributeReference att in owner.AttributeCollection) - yield return att; - } - } - #endregion - - /// - /// 遍历块内 - /// - /// - /// - /// - [System.Diagnostics.DebuggerStepThrough] - public static void ForEach(this BlockReference brf, Action action) - { - ArgumentNullEx.ThrowIfNull(action); - var tr = DBTrans.GetTopTransaction(brf.Database); - if (tr.GetObject(brf.BlockTableRecord) is BlockTableRecord btr) - { - btr.ForEach(action); - } - } - /// - /// 遍历块内 - /// - /// - /// - /// - [System.Diagnostics.DebuggerStepThrough] - public static void ForEach(this BlockReference brf, Action action) - { - ArgumentNullEx.ThrowIfNull(action); - var tr = DBTrans.GetTopTransaction(brf.Database); - if (tr.GetObject(brf.BlockTableRecord) is BlockTableRecord btr) - { - btr.ForEach(action); - } - } - /// - /// 遍历块内 - /// - /// - /// - /// - [System.Diagnostics.DebuggerStepThrough] - public static void ForEach(this BlockReference brf, Action action) - { - ArgumentNullEx.ThrowIfNull(action); - var tr = DBTrans.GetTopTransaction(brf.Database); - if (tr.GetObject(brf.BlockTableRecord) is BlockTableRecord btr) - { - btr.ForEach(action); - } - - } - /// - /// 遍历嵌套块中块图元 - /// - /// 块参照 - /// 委托 - /// 事务 - public static void NestedForEach(this Entity blockReference, Action action, DBTrans? tr = null) - { - tr ??= DBTrans.GetTop(blockReference.IsNewObject ? Env.Database : blockReference.Database); - var queue = new Queue<(Entity, Matrix3d)>(); - queue.Enqueue((blockReference, Matrix3d.Identity)); - while (queue.Any()) - { - var (ent, mt) = queue.Dequeue(); - action?.Invoke(ent, mt); - if (ent is BlockReference brfTemp) - { - var mtNext = mt * brfTemp.BlockTransform; - tr.BlockTable.Change(brfTemp.BlockTableRecord, btr => { - foreach (var id in btr) - { - if (tr.GetObject(id) is Entity entNext) - { - queue.Enqueue((entNext, mtNext)); - } - } - }); - } - } - } -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BoundingInfo.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BoundingInfo.cs deleted file mode 100644 index a6eebd5..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/BoundingInfo.cs +++ /dev/null @@ -1,179 +0,0 @@ -namespace IFoxCAD.Cad; - -/// -/// 和尚777 重构 -/// 包围盒信息 -/// -public struct BoundingInfo -{ - #region 成员 - - - /// - /// MinPoint.X - /// - public double MinX { get; private set; } - /// - /// MinPoint.Y - /// - public double MinY { get; private set; } - /// - /// MinPoint.Z - /// - public double MinZ { get; private set; } - /// - /// MaxPoint.X - /// - public double MaxX { get; private set; } - /// - /// MaxPoint.Y - /// - public double MaxY { get; private set; } - /// - /// MaxPoint.Z - /// - public double MaxZ { get; private set; } - - #region 包围盒9位码坐标 - /* - * 包围盒9位码坐标 - * P7---------------P8----------------P9 - * | | | - * | | | - * | | | - * P4---------------P5----------------P6 - * | | | - * | | | - * | | | - * P1---------------P2----------------P3 - */ - /// - /// MinPoint 左下点 P1 - /// - public readonly Point3d BottomLeft => new(MinX, MinY, MinZ); - /// - /// P2 - /// - public readonly Point3d BottomCenter => BottomLeft.GetMidPointTo(BottomRight); - /// - /// P3 - /// - public readonly Point3d BottomRight => new(MaxX, MinY, MinZ); - /// - /// P4 - /// - public readonly Point3d MidLeft => BottomLeft.GetMidPointTo(TopLeft); - /// - /// P5 - /// - public readonly Point3d MidCenter => BottomLeft.GetMidPointTo(TopRight); - /// - /// P6 - /// - public readonly Point3d MidRight => BottomRight.GetMidPointTo(TopRight); - /// - /// P7 - /// - public readonly Point3d TopLeft => new(MinX, MaxY, MinZ); - /// - /// P8 - /// - public readonly Point3d TopCenter => TopLeft.GetMidPointTo(TopRight); - /// - /// MaxPoint 右上点 P9 - /// - public readonly Point3d TopRight => new(MaxX, MaxY, MaxZ); - - // public Point3d Min => new(MinX, MinY, MinZ); - - // public Point3d Max => new(MaxX, MaxY, MaxZ); - #endregion - - /// - /// 高 - /// - public readonly double Height => Math.Abs(MaxY - MinY); - - /// - /// 宽 - /// - public readonly double Width => Math.Abs(MaxX - MinX); - - /// - /// 面积 - /// - public readonly double Area => Height * Width; - - /// - /// 3D包围盒 - /// - public Extents3d Extents3d { get; } - - /// - /// 2D包围盒 - /// - public readonly Extents2d Extents2d => new(MinX, MinY, MaxX, MaxY); - - #endregion - - #region 构造 - - /// - /// 包围盒信息3D构造 - /// - /// 包围盒 - public BoundingInfo(Extents3d ext) - { - MinX = ext.MinPoint.X; - MinY = ext.MinPoint.Y; - MinZ = ext.MinPoint.Z; - MaxX = ext.MaxPoint.X; - MaxY = ext.MaxPoint.Y; - MaxZ = ext.MaxPoint.Z; - Extents3d = ext; - } - - /// - /// 包围盒信息2D构造 - /// - /// 包围盒 - public BoundingInfo(Extents2d ext) - { - MinX = ext.MinPoint.X; - MinY = ext.MinPoint.Y; - MinZ = 0; - MaxX = ext.MaxPoint.X; - MaxY = ext.MaxPoint.Y; - MaxZ = 0; - var pt1 = new Point3d(MinX, MinY, 0); - var pt9 = new Point3d(MaxX, MaxY, 0); - Extents3d = new Extents3d(pt1, pt9); - } - - #endregion - - /// - /// 重写ToString - /// - /// 返回MinPoint,MaxPoint坐标 - public override string ToString() - { - return Extents3d.ToString(); - } - /// - /// 移动包围盒 - /// - /// 基点 - /// 目标点 - public void Move(Point3d pt1, Point3d pt2) - { - var ve = pt1 - pt2; - MinX -= ve.X; - MinY -= ve.Y; - MinZ -= ve.Z; - MaxX -= ve.X; - MaxY -= ve.Y; - MaxZ -= ve.Z; - } - -} diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/CircleEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/CircleEx.cs deleted file mode 100644 index 5115ba8..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/CircleEx.cs +++ /dev/null @@ -1,59 +0,0 @@ -namespace IFoxCAD.Cad; - -/// -/// 圆扩展类 -/// -public static class CircleEx -{ - - /// - /// 两点创建圆(两点中点为圆心) - /// - /// 起点 - /// 终点 - /// - public static Circle CreateCircle(Point3d startPoint, Point3d endPoint) - { - Circle circle = new(); - circle.SetDatabaseDefaults(); - circle.Center = startPoint.GetMidPointTo(endPoint); - circle.Radius = startPoint.DistanceTo(endPoint) * 0.5; - return circle; - } - - /// - /// 三点法创建圆(失败则返回Null) - /// - /// 第一点 - /// 第二点 - /// 第三点 - /// - public static Circle? CreateCircle(Point3d pt1, Point3d pt2, Point3d pt3) - { - // 先判断三点是否共线,得到pt1点指向pt2、pt2点的矢量 - Vector3d va = pt1.GetVectorTo(pt2); - Vector3d vb = pt1.GetVectorTo(pt3); - // 如两矢量夹角为0或180度(π弧度),则三点共线. - if (va.GetAngleTo(vb) == 0 | va.GetAngleTo(vb) == Math.PI) - return null; - - // 创建一个几何类的圆弧对象 - CircularArc3d geArc = new(pt1, pt2, pt3); - return geArc.ToCircle(); - } - - /// - /// 通过圆心,半径绘制圆形 - /// - /// 圆心 - /// 半径 - /// 法向量的X - /// 法向量的Y - /// 法向量的Z - /// - public static Circle CreateCircle(Point3d center, double radius, double vex = 0, double vey = 0, double vez = 1) - { - return new Circle(center, new Vector3d(vex, vey, vez), radius);// 平面法向量XY方向 - } - -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/DBTextEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/DBTextEx.cs deleted file mode 100644 index b338566..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/DBTextEx.cs +++ /dev/null @@ -1,59 +0,0 @@ -namespace IFoxCAD.Cad; - -/// -/// 单行文字扩展类 -/// -public static class DBTextEx -{ - /// - /// 创建单行文字 - /// - /// 插入点 - /// 文本内容 - /// 文字高度 - /// 对齐方式 - /// 文字所在的数据库 - /// 文字属性设置委托 - /// 文字对象 - /// - public static DBText CreateDBText(Point3d position, string text, double height,AttachmentPoint justify = AttachmentPoint.BaseLeft, Database? database = null,Action? action = null) - { - if (string.IsNullOrEmpty(text)) - throw new ArgumentNullException(nameof(text), "创建文字无内容"); - - var workdb = database ?? HostApplicationServices.WorkingDatabase; - using var _ = new SwitchDatabase(workdb); - - var acText = new DBText(); - acText.SetDatabaseDefaults(workdb); - - acText.Height = height; - acText.TextString = text; - acText.Position = position; // 插入点(一定要先设置) - - acText.Justify = justify; // 使他们对齐 - - action?.Invoke(acText); - - if (acText.Justify != AttachmentPoint.BaseLeft) - acText.AlignmentPoint = position; - - acText.AdjustAlignment(workdb); - - return acText; - } - - /// - /// 更正单行文字的镜像属性 - /// - /// 单行文字 - public static void ValidateMirror(this DBText txt) - { - if (!txt.Database.Mirrtext) - { - txt.IsMirroredInX = false; - txt.IsMirroredInY = false; - } - } - -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs deleted file mode 100644 index be4b770..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityBoundingInfo.cs +++ /dev/null @@ -1,228 +0,0 @@ -namespace IFoxCAD.Cad; - -/// -/// 获取实体包围盒信息方法 -/// -public static class EntityBoundingInfo -{ - - /// - /// 获取包围盒信息 - /// - /// 包围盒 - /// 包围盒信息 - public static BoundingInfo? GetBoundingInfo(this Extents3d ext) - { - return new(ext); - } - /// - /// 获取多行文本的正交包围盒 - /// - /// 多行文本 - /// 包围盒 - static Extents3d GetMTextBox(MText mText) - { - var ext = new Extents3d(); - GetMTextBoxCorners(mText).ForEach(p=>ext.AddPoint(p)); - return ext; - } - /// - /// 获取块的包围盒 - /// - /// 实体 - /// - /// - static void GetBlockBox(this Entity en, ref Extents3d ext, ref Matrix3d mat) - { - if (en is BlockReference block) - { - var matins = mat * block.BlockTransform; - if (block.BlockTableRecord.GetObject() is BlockTableRecord btr) - foreach (ObjectId id in btr) - { - if (id.GetObject() is Entity ent1) - { - if (ent1.Visible != true) - continue; - if (ent1 is AttributeDefinition att) - { - if (att != null && (!att.Constant || att.Invisible)) - continue; - } - GetBlockBox(ent1, ref ext, ref matins); - } - } - if (block.AttributeCollection.Count > 0) - { - foreach (var att in block.GetAttributes()) - { - if (!att.Invisible && att.Visible) - GetBlockBox(att, ref ext, ref mat); - } - } - } - else - { - if (mat.IsUniscaledOrtho()) - { - using (var ent1 = en.GetTransformedCopy(mat)) - { - if (ext.IsEmptyExt()) - { - //var e = ent1.GetEntityBox(); - var e = GetEntityBoxEx(ent1); - if (e.HasValue) - ext = e.Value; - } - else - { - //var e = ent1.GetEntityBox(); - var e = GetEntityBoxEx(ent1); - if (e.HasValue) - ext.AddExtents(e.Value); - } - } - } - else - { - //var e = en.GetEntityBox(); - var e = GetEntityBoxEx(en); - if (e.HasValue) - { - Extents3d entext = e.Value; - entext.TransformBy(mat); - if (ext.IsEmptyExt()) - ext = entext; - else - ext.AddExtents(entext); - } - return; - } - } - return; - } - /// - /// 获取多行文字最小包围盒4点坐标 - /// - /// 多行文本 - /// 最小包围盒4点坐标 - public static Point3d[] GetMTextBoxCorners(MText mtext) - { - double width = mtext.ActualWidth; - double height = mtext.ActualHeight; - Point3d point1, point2; - switch (mtext.Attachment) - { - case AttachmentPoint.TopLeft: - default: - point1 = new Point3d(0.0, -height, 0.0); - point2 = new Point3d(width, 0.0, 0.0); - break; - case AttachmentPoint.TopCenter: - point1 = new Point3d(-width * 0.5, -height, 0.0); - point2 = new Point3d(width * 0.5, 0.0, 0.0); - break; - case AttachmentPoint.TopRight: - point1 = new Point3d(-width, -height, 0.0); - point2 = new Point3d(0.0, 0.0, 0.0); - break; - case AttachmentPoint.MiddleLeft: - point1 = new Point3d(0.0, -height * 0.5, 0.0); - point2 = new Point3d(width, height * 0.5, 0.0); - break; - case AttachmentPoint.MiddleCenter: - point1 = new Point3d(-width * 0.5, -height * 0.5, 0.0); - point2 = new Point3d(width * 0.5, height * 0.5, 0.0); - break; - case AttachmentPoint.MiddleRight: - point1 = new Point3d(-width, -height * 0.5, 0.0); - point2 = new Point3d(0.0, height * 0.5, 0.0); - break; - case AttachmentPoint.BottomLeft: - point1 = new Point3d(0.0, 0.0, 0.0); - point2 = new Point3d(width, height, 0.0); - break; - case AttachmentPoint.BottomCenter: - point1 = new Point3d(-width * 0.5, 0.0, 0.0); - point2 = new Point3d(width * 0.5, height, 0.0); - break; - case AttachmentPoint.BottomRight: - point1 = new Point3d(-width, 0.0, 0.0); - point2 = new Point3d(0.0, height, 0.0); - break; - } - - var xform = - Matrix3d.Displacement(mtext.Location.GetAsVector()) * - Matrix3d.Rotation(mtext.Rotation, mtext.Normal, Point3d.Origin) * - Matrix3d.PlaneToWorld(new Plane(Point3d.Origin, mtext.Normal)); - - return new[] - { - point1.TransformBy(xform), - new Point3d(point2.X, point1.Y, 0.0).TransformBy(xform), - point2.TransformBy(xform), - new Point3d(point1.X, point2.Y, 0.0).TransformBy(xform) - }; - } - /// - /// 获取实体包围盒 - /// - /// 实体 - /// 包围盒 - public static Extents3d? GetEntityBoxEx(Entity ent) - { - Extents3d? ext = null; - switch (ent) - { - case Spline spl: - ext = spl.ToPolyline().GeometricExtents; - break; - case MText mtext: - ext = GetMTextBox(mtext); - break; - case Table table: - if (table.IsNewObject) - table.GenerateLayout(); - table.RecomputeTableBlock(true); - ext = table.GeometricExtents; - break; - case Dimension dim: - if (dim.IsNewObject) - dim.GenerateLayout(); // 新new的实体生成布局,即可获取包围盒 - dim.RecomputeDimensionBlock(true); - ext = dim.GeometricExtents; - break; - case BlockReference block: - Extents3d blockExt = default; - var mat = Matrix3d.Identity; - block!.GetBlockBox(ref blockExt, ref mat); - if (!blockExt.IsEmptyExt()) - ext = blockExt; - break; - default: - if (ent.Bounds.HasValue) - ext = ent.GeometricExtents; - break; - } - if (ext != null) - //实体不是点时,pass - if (ent is not DBPoint && ext.Value.MinPoint.IsEqualTo(ext.Value.MaxPoint)) - return null; - return ext; - } - - /// - /// 判断包围盒是否有效 - /// - /// 包围盒 - /// - static bool IsEmptyExt(this Extents3d ext) - { - if (ext.MinPoint.DistanceTo(ext.MaxPoint) < Tolerance.Global.EqualPoint) - return true; - else - return false; - } - -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityEx.cs deleted file mode 100644 index c3a2834..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/EntityEx.cs +++ /dev/null @@ -1,166 +0,0 @@ -namespace IFoxCAD.Cad; - - -/// -/// 实体图元扩展类 -/// -public static class EntityEx -{ - - - #region 实体线性变换 - - /// - /// 移动实体 - /// - /// 实体 - /// 基点 - /// 目标点 - public static void Move(this Entity ent, Point3d from, Point3d to) - { - using (ent.ForWrite()) - { - ent.TransformBy(Matrix3d.Displacement(to - from)); - } - } - /// - /// 移动实体 - /// - /// 实体 - /// 向量 - public static void Move(this Entity ent, Vector3d vector) - { - using (ent.ForWrite()) - { - ent.TransformBy(Matrix3d.Displacement(vector)); - } - } - - /// - /// 缩放实体 - /// - /// 实体 - /// 缩放基点坐标 - /// 缩放比例 - public static void Scale(this Entity ent, Point3d center, double scaleValue) - { - using (ent.ForWrite()) - { - ent.TransformBy(Matrix3d.Scaling(scaleValue, center)); - } - } - - /// - /// 旋转实体 - /// - /// 实体 - /// 旋转中心 - /// 转角,弧度制,正数为顺时针 - /// 旋转平面的法向矢量 - public static void Rotation(this Entity ent, Point3d center, double angle, Vector3d normal) - { - using (ent.ForWrite()) - { - ent.TransformBy(Matrix3d.Rotation(angle, normal, center)); - } - } - - /// - /// 在XY平面内旋转实体 - /// - /// 实体 - /// 旋转中心 - /// 转角,弧度制,正数为顺时针 - public static void Rotation(this Entity ent, Point3d center, double angle) - { - using (ent.ForWrite()) - { - ent.TransformBy(Matrix3d.Rotation(angle, Vector3d.ZAxis.TransformBy(ent.Ecs), center)); - } - } - - /// - /// 按对称轴镜像实体 - /// - /// 实体 - /// 对称轴起点 - /// 对称轴终点 - public static void Mirror(this Entity ent, Point3d startPoint, Point3d endPoint) - { - using (ent.ForWrite()) - { - ent.TransformBy(Matrix3d.Mirroring(new Line3d(startPoint, endPoint))); - } - } - - /// - /// 按对称面镜像实体 - /// - /// 实体 - /// 对称平面 - public static void Mirror(this Entity ent, Plane plane) - { - using (ent.ForWrite()) - { - ent.TransformBy(Matrix3d.Mirroring(plane)); - } - } - - /// - /// 按对称点镜像实体 - /// - /// 实体 - /// 对称点 - public static void Mirror(this Entity ent, Point3d basePoint) - { - using (ent.ForWrite()) - { - ent.TransformBy(Matrix3d.Mirroring(basePoint)); - } - } - - #endregion - - #region 实体范围 - /// - /// 获取实体集合的范围 - /// - /// 实体迭代器 - /// 实体集合的范围 - public static Extents3d GetExtents(this IEnumerable ents) - { - var ext = new Extents3d(); - foreach (var item in ents) - { - var e = item.GetBoundingBoxEx(); - if (e.HasValue) - ext.AddExtents(e.Value.Extents3d); - } - return ext; - } - #endregion - - - - /// - /// 获取图元包围盒 - /// - /// - /// 包围盒信息 - public static BoundingInfo? GetBoundingBoxEx(this Entity ent) - { - return EntityBoundingInfo.GetEntityBoxEx(ent)?.GetBoundingInfo(); - } - - /// - /// 获取拉伸点 - /// - /// 实体 - /// 点集 - public static IEnumerable GetStretchPoints(this Entity ent) - { - var p3dc = new Point3dCollection(); - ent.GetStretchPoints(p3dc); - return p3dc.Cast(); - } -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/MTextEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/MTextEx.cs deleted file mode 100644 index 3d05584..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/MTextEx.cs +++ /dev/null @@ -1,76 +0,0 @@ -namespace IFoxCAD.Cad; - -/// -/// 多行文字扩展类 -/// -public static class MTextEx -{ - - /// - /// 创建多行文字 - /// - /// 插入点 - /// 文本内容 - /// 文字高度 - /// 文字所在的数据库 - /// 文字属性设置委托 - /// 文字对象id - /// - public static MText CreateMText(Point3d position, string text, double height, Database? database = null, Action? action = null) - { - if (string.IsNullOrEmpty(text)) - throw new ArgumentNullException(nameof(text), "创建文字无内容"); - - var db = database ?? DBTrans.Top.Database; - using var _ = new SwitchDatabase(db); - - var mText = new MText(); - - mText.SetDatabaseDefaults(db); - - mText.TextHeight = height; // 高度 - mText.Contents = text; // 内容 - mText.Location = position; // 插入点 - - action?.Invoke(mText); - - return mText; - } - - /// - /// 炸散多行文字 - /// - /// 存储多行文字炸散之后的对象的类型 - /// 多行文字 - /// 存储对象变量 - /// 回调函数,用于处理炸散之后的对象 - /// - /// 多行文字炸散后的对象
- /// 回调函数处理的结果 - ///
- /// - public static void ExplodeFragments(this MText mt, T obj, Func mTextFragmentCallback) - { - mt.ExplodeFragments( - (f, o) => - mTextFragmentCallback(f, (T)o), obj); - } - - /// - /// 获取多行文字的无格式文本 - /// - /// 多行文字 - /// 文本 - public static string GetUnFormatString(this MText mt) - { - List strs = new(); - mt.ExplodeFragments( - strs, - (f, o) => { - o.Add(f.Text); - return MTextFragmentCallbackStatus.Continue; - }); - return string.Join("", strs.ToArray()); - } - -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/PolylineEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/PolylineEx.cs deleted file mode 100644 index b2a5ba1..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Entity/PolylineEx.cs +++ /dev/null @@ -1,122 +0,0 @@ -namespace IFoxCAD.Cad; - -/// -/// 多段线扩展类 -/// -public static class PolylineEx -{ - #region 获取多段线端点 - - /// - /// 获取二维多段线的端点坐标 - /// - /// 二维多段线 - /// 端点坐标集合 - public static IEnumerable GetPoints(this Polyline2d pl2d) - { - var tr = DBTrans.GetTopTransaction(pl2d.Database); - foreach (ObjectId id in pl2d) - { - if (tr.GetObject(id) is Vertex2d vertex) - { - yield return vertex.Position; - } - } - } - - /// - /// 获取三维多段线的端点坐标 - /// - /// 三维多段线 - /// 端点坐标集合 - public static IEnumerable GetPoints(this Polyline3d pl3d) - { - var tr = DBTrans.GetTopTransaction(pl3d.Database); - foreach (ObjectId id in pl3d) - { - if (tr.GetObject(id) is PolylineVertex3d vertex) - yield return vertex.Position; - } - } - - /// - /// 获取多段线的端点坐标 - /// - /// 多段线 - /// 端点坐标集合 - public static List GetPoints(this Polyline pl) - { - return - Enumerable - .Range(0, pl.NumberOfVertices) - .Select(pl.GetPoint3dAt) - .ToList(); - } - - #endregion - - #region 创建多段线 - - /// - /// 根据点集创建多段线
- /// 此多段线无默认全局宽度0,无圆弧段 - ///
- /// 点集 - /// 多段线属性设置委托 - /// 多段线对象 - public static Polyline CreatePolyline(this IEnumerable points, Action? action = null) - { - Polyline pl = new(); - pl.SetDatabaseDefaults(); - points.ForEach((index, pt) => { pl.AddVertexAt(index, pt.Point2d(), 0, 0, 0); }); - action?.Invoke(pl); - return pl; - } - - /// - /// 根据点集创建多段线 - /// - /// 端点表,利用元组(Point3d pt, double bulge, double startWidth, double endWidth) - /// 轻多段线属性设置委托 - /// 轻多段线对象 - public static Polyline CreatePolyline( - this IEnumerable<(Point3d pt, double bulge, double startWidth, double endWidth)> pts, - Action? action = null) - { - Polyline pl = new(); - pl.SetDatabaseDefaults(); - - pts.ForEach((index, vertex) => - { - pl.AddVertexAt(index, vertex.pt.Point2d(), vertex.bulge, vertex.startWidth, vertex.endWidth); - }); - action?.Invoke(pl); - return pl; - } - - /// - /// 根据Extents3d创建多段线
- /// 此多段线无默认全局宽度0,无圆弧段,标高为0 - ///
- /// Extents3d - /// 多段线属性设置委托 - /// 多段线对象 - public static Polyline CreatePolyline(this Extents3d points, Action? action = null) - { - List pts = - [ - points.MinPoint.Point2d(), - new(points.MinPoint.X, points.MaxPoint.Y), - points.MaxPoint.Point2d(), - new(points.MaxPoint.X, points.MinPoint.Y) - ]; - - Polyline pl = new() { Closed = true }; - pl.SetDatabaseDefaults(); - pts.ForEach((index, pt) => { pl.AddVertexAt(index, pt, 0, 0, 0); }); - action?.Invoke(pl); - return pl; - } - - #endregion -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Enums.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Enums.cs deleted file mode 100644 index 87f02c3..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Enums.cs +++ /dev/null @@ -1,202 +0,0 @@ -namespace IFoxCAD.Cad; - -/// -/// 参照路径转换 -/// -public enum PathConverterModes : byte -{ - /// - /// 相对路径 - /// - Relative, - /// - /// 绝对路径 - /// - Complete -} - -/// -/// 参照绑定 -/// -public enum XrefModes : byte -{ - /// - /// 卸载 - /// - Unload, - /// - /// 重载 - /// - Reload, - /// - /// 拆离 - /// - Detach, - /// - /// 绑定 - /// - Bind, -} -/// -/// 符号表模式 -/// -[Flags] -public enum SymModes : ushort -{ - /// - /// 块表 - /// - BlockTable = 1, - - /// - /// 图层表 - /// - LayerTable = 2, - /// - /// 文字样式表 - /// - TextStyleTable = 4, - /// - /// 注册应用程序表 - /// - RegAppTable = 8, - /// - /// 标注样式表 - /// - DimStyleTable = 16, - /// - /// 线型表 - /// - LinetypeTable = 32, - /// - /// 图层|字体|标注|线型|应用 - /// - Option1 = LayerTable | TextStyleTable | DimStyleTable | LinetypeTable | RegAppTable, - - /// - /// 用户坐标系表 - /// - UcsTable = 64, - /// - /// 视图表 - /// - ViewTable = 128, - /// - /// 视口表 - /// - ViewportTable = 256, - /// - /// 坐标|视口|视图 - /// - Option2 = UcsTable | ViewTable | ViewportTable, - - /// - /// 全部 - /// - All = BlockTable | Option1 | Option2 -} - - -/// -/// 坐标系类型枚举 -/// -public enum CoordinateSystemCode -{ - /// - /// 世界坐标系 - /// - Wcs = 0, - - /// - /// 用户坐标系 - /// - Ucs, - - /// - /// 模型空间坐标系 - /// - MDcs, - - /// - /// 图纸空间坐标系 - /// - PDcs -} - -/// -/// 方向的枚举 -/// -public enum OrientationType -{ - /// - /// 左转或逆时针 - /// - CounterClockWise, - /// - /// 右转或顺时针 - /// - ClockWise, - /// - /// 重合或平行 - /// - Parallel -} - -/// -/// 点与多边形的关系类型枚举 -/// -public enum PointOnRegionType -{ - /// - /// 多边形内部 - /// - Inside, - - /// - /// 多边形上 - /// - On, - - /// - /// 多边形外 - /// - Outside, - - /// - /// 错误 - /// - Error -} - - -/// -/// ttf字体枚举 -/// -public enum FontTTF -{ - /// - /// 宋体 - /// - [Description("宋体.ttf")] - 宋体, - /// - /// 仿宋 - /// - [Description("simfang.ttf")] - 仿宋, - /// - /// 仿宋GB2312 - /// - [Description("FSGB2312.ttf")] - 仿宋GB2312, - /// - /// Arial - /// - [Description("Arial.ttf")] - Arial, - /// - /// Romans - /// - [Description("Romans")] - Romans -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ErrorInfoEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ErrorInfoEx.cs deleted file mode 100644 index 00da86e..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ErrorInfoEx.cs +++ /dev/null @@ -1,421 +0,0 @@ -namespace IFoxCAD.Cad; - -/// -/// CAD错误大全 -/// -public static class ErrorInfoEx -{ - /// - /// 打印CAD错误信息到命令行 - /// 使用方法: - /// try - /// { - /// //你的代码 - /// } - /// catch (AcException acex) { acex.AcErrorInfo(); } - /// catch (Exception) { throw; } - /// - /// - /// AcException - internal static void AcErrorInfo(this AcException acex) - { - string infostr = acex.Message switch - { - "eAlreadyInDb" => "已经在数据库中了", - "eAmbiguousInput" => "模糊不清的输入", - "eAmbiguousOutput" => "模糊不清的输出", - "eAnonymousEntry" => "多重入口", - "eBrokenHandle" => "损坏的句柄", - "eBufferTooSmall" => "缓冲区太小", - "eContainerNotEmpty" => "容器不为空", - "eDeletedEntry" => "已经删除的函数入口", - "eDuplicateDxfField" => "DXF字段重复", - "eDuplicateIndex" => "重复的索引", - "eDuplicateKey" => "重复的关键字", - "eEndOfFile" => "文件结束", - "eEndOfObject" => "对象结束", - "eEntityInInactiveLayout" => "实体不在活动布局上", - "eHandleExists" => "句柄已存在", - "eHandleInUse" => "句柄被占用", - "eIllegalEntityType" => "非法的实体类型", - "eIllegalReplacement" => "非法的替代者", - "eInvalidAdsName" => "无效的ADS名称", - "eInvalidBlockName" => "不合理的块名称", - "eInvalidDwgVersion" => "不合理的DWG版本", - "eInvalidDxfCode" => "不合理的DXF编码", - "eInvalidExtents" => "无效的空间范围", - "eInvalidIndex" => "无效的索引", - "eInvalidInput" => "无效的输入", - "eInvalidKey" => "无效的关键字", - "eInvalidOpenState" => "无效的打开状态", - "eInvalidSymbolTableName" => "无效的符号名称", - "eIsReading" => "正在读取", - "eIsWriting" => "正在写入", - "eKeyNotFound" => "关键字未找到", - "eMissingDxfField" => "DXF字段缺失", - "eNegativeValueNotAllowed" => "不允许输入负数", - "eNotApplicable" => "不合适的", - "eNotImplementedYet" => "尚未实现", - "eNotOpenForRead" => "不是只读打开", - "eNotOpenForWrite" => "不是可写打开", - "eNotThatKindOfClass" => "类型不匹配", - "eNullBlockName" => "块名称为空", - "eNullEntityPointer" => "实体指针为空", - "eNullHandle" => "空句柄", - "eNullObjectId" => "对象ID为空", - "eNullObjectPointer" => "对象指针为空", - "eObjectToBeDeleted" => "对象即将被删除", - "eOk" => "正确", - "eOutOfDisk" => "硬盘容量不足", - "eOutOfMemory" => "内存不足", - "eUnknownHandle" => "未知句柄", - "eWrongDatabase" => "错误的数据库", - "eWrongObjectType" => "错误的类型", - "eInvalidResBuf" => "不合理的ResBuf", - "eBadDxfSequence" => "不正确的DXF顺序", - "eFilerError" => "文件错误", - "eVertexAfterFace" => "顶点在面后面", - "eInvalidFaceVertexIndex" => "不合理的面顶点顺序", - "eInvalidMeshVertexIndex" => "不合理的mesh顺序", - "eOtherObjectsBusy" => "其它对象忙", - "eMustFirstAddBlockToDb" => "必须先把块加入到数据库", - "eCannotNestBlockDefs" => "不可以嵌套块定义", - "eDwgRecoveredOK" => "修复DWG完成", - "eDwgNotRecoverable" => "无法修复DWG", - "eDxfPartiallyRead" => "DXF部分读取", - "eDxfReadAborted" => "读取DXF终止", - "eDxbPartiallyRead" => "DXB部分读取", - "eDwgCRCDoesNotMatch" => "DWG文件的CRC不匹配", - "eDwgSentinelDoesNotMatch" => "DWG文件的校验不匹配", - "eDwgObjectImproperlyRead" => "DWG文件错误读取", - "eNoInputFiler" => "没有找到输入过滤", - "eDwgNeedsAFullSave" => "DWG需要完全保存", - "eDxbReadAborted" => "DXB读取终止", - "eFileLockedByACAD" => "文件被ACAD锁定", - "eFileAccessErr" => "无法读取文件", - "eFileSystemErr" => "文件系统错误", - "eFileInternalErr" => "文件内部错误", - "eFileTooManyOpen" => "文件被打开太多次", - "eFileNotFound" => "未找到文件", - "eDwkLockFileFound" => "找到DWG锁定文件", - "eWasErased" => "对象被删除", - "ePermanentlyErased" => "对象被永久删除", - "eWasOpenForRead" => "对象只读打开", - "eWasOpenForWrite" => "对象可写打开", - "eWasOpenForUndo" => "对象撤销打开", - "eWasNotifying" => "对象被通知", - "eWasOpenForNotify" => "对象通知打开", - "eOnLockedLayer" => "对象在锁定图层上", - "eMustOpenThruOwner" => "必须经过所有者打开", - "eSubentitiesStillOpen" => "子对象依然打开着", - "eAtMaxReaders" => "超过最大打开次数", - "eIsWriteProtected" => "对象被写保护", - "eIsXRefObject" => "对象是XRef", - "eNotAnEntity" => "对象不是实体", - "eHadMultipleReaders" => "被多重打开", - "eDuplicateRecordName" => "重复的记录名称", - "eXRefDependent" => "依赖于XREF", - "eSelfReference" => "引用自身", - "eMissingSymbolTable" => "丢失符号化表", - "eMissingSymbolTableRec" => "丢失符号化记录", - "eWasNotOpenForWrite" => "不是可写打开", - "eCloseWasNotifying" => "对象关闭,正在执行通知", - "eCloseModifyAborted" => "对象关闭,修改被取消", - "eClosePartialFailure" => "对象关闭,部分操作未成功", - "eCloseFailObjectDamaged" => "对象被损坏,关闭失败", - "eCannotBeErasedByCaller" => "对象不可以被当前呼叫者删除", - "eCannotBeResurrected" => "不可以复活", - "eWasNotErased" => "对象未删除", - "eInsertAfter" => "在后面插入", - "eFixedAllErrors" => "修复了所有错误", - "eLeftErrorsUnfixed" => "剩下一些错误未修复", - "eUnrecoverableErrors" => "不可恢复的错误", - "eNoDatabase" => "没有数据库", - "eXdataSizeExceeded" => "扩展数据长度太大", - "eRegappIdNotFound" => "没有找到扩展数据注册ID", - "eRepeatEntity" => "重复实体", - "eRecordNotInTable" => "表中未找到记录", - "eIteratorDone" => "迭代器完成", - "eNullIterator" => "空的迭代器", - "eNotInBlock" => "不在块中", - "eOwnerNotInDatabase" => "所有者不在数据库中", - "eOwnerNotOpenForRead" => "所有者不是只读打开", - "eOwnerNotOpenForWrite" => "所有者不是可写打开", - "eExplodeBeforeTransform" => "在变换之前就被炸开了", - "eCannotScaleNonUniformly" => "不可以不同比例缩放", - "eNotInDatabase" => "不在数据库中", - "eNotCurrentDatabase" => "不是当前数据库", - "eIsAnEntity" => "是一个实体", - "eCannotChangeActiveViewport" => "不可以改变活动视口", - "eNotInPaperspace" => "不在图纸空间中", - "eCommandWasInProgress" => "正在执行命令", - "eGeneralModelingFailure" => "创建模型失败", - "eOutOfRange" => "超出范围", - "eNonCoplanarGeometry" => "没有平面几何对象", - "eDegenerateGeometry" => "退化的几何对象", - "eInvalidAxis" => "无效的轴线", - "ePointNotOnEntity" => "点不在实体上", - "eSingularPoint" => "单一的点", - "eInvalidOffset" => "无效的偏移", - "eNonPlanarEntity" => "没有平面的实体", - "eCannotExplodeEntity" => "不可分解的实体", - "eStringTooLong" => "字符串太短", - "eInvalidSymTableFlag" => "无效的符号化表标志", - "eUndefinedLineType" => "没有定义的线型", - "eInvalidTextStyle" => "无效的字体样式", - "eTooFewLineTypeElements" => "太少的线型要素", - "eTooManyLineTypeElements" => "太多的线型要素", - "eExcessiveItemCount" => "过多的项目", - "eIgnoredLinetypeRedef" => "忽略线型定义描述", - "eBadUCS" => "不好的用户坐标系", - "eBadPaperspaceView" => "不好的图纸空间视图", - "eSomeInputDataLeftUnread" => "一些输入数据未被读取", - "eNoInternalSpace" => "不是内部空间", - "eInvalidDimStyle" => "无效的标注样式", - "eInvalidLayer" => "无效的图层", - "eUserBreak" => "用户打断", - "eDwgNeedsRecovery" => "DWG文件需要修复", - "eDeleteEntity" => "删除实体", - "eInvalidFix" => "无效的方位", - "eFSMError" => "FSM错误", - "eBadLayerName" => "不好的图层名称", - "eLayerGroupCodeMissing" => "图层分组编码丢失", - "eBadColorIndex" => "不好的颜色索引号", - "eBadLinetypeName" => "不好的线型名称", - "eBadLinetypeScale" => "不好的线型缩放比例", - "eBadVisibilityValue" => "不好的可见性值", - "eProperClassSeparatorExpected" => "本身类未找到预期的分割符号(?)", - "eBadLineWeightValue" => "不好的线宽值", - "eBadColor" => "不好的颜色", - "ePagerError" => "页面错误", - "eOutOfPagerMemory" => "页面内存不足", - "ePagerWriteError" => "页面不可写", - "eWasNotForwarding" => "不是促进(?)", - "eInvalidIdMap" => "无效的ID字典", - "eInvalidOwnerObject" => "无效的所有者", - "eOwnerNotSet" => "未设置所有者", - "eWrongSubentityType" => "错误的子对象类型", - "eTooManyVertices" => "太多节点", - "eTooFewVertices" => "太少节点", - "eNoActiveTransactions" => "不活动的事务", - "eNotTopTransaction" => "不是最顶层的事务", - "eTransactionOpenWhileCommandEnded" => "在命令结束的时候打开(/开始)事务", - "eInProcessOfCommitting" => "在提交事务的过程中", - "eNotNewlyCreated" => "不是新创建的", - "eLongTransReferenceError" => "长事务引用错误", - "eNoWorkSet" => "没有工作集", - "eAlreadyInGroup" => "已经在组中了", - "eNotInGroup" => "不在组中", - "eInvalidREFIID" => "无效的REFIID", - "eInvalidNormal" => "无效的标准", - "eInvalidStyle" => "无效的样式", - "eCannotRestoreFromAcisFile" => "不可以从Acis(?)文件中恢复", - "eMakeMeProxy" => "自我代理", - "eNLSFileNotAvailable" => "无效的NLS文件", - "eNotAllowedForThisProxy" => "不允许这个代理", - "eNotSupportedInDwgApi" => "在Dwg Api中不支持", - "ePolyWidthLost" => "多段线宽度丢失", - "eNullExtents" => "空的空间范围", - "eExplodeAgain" => "再一次分解", - "eBadDwgHeader" => "坏的DWG文件头", - "eLockViolation" => "锁定妨碍当前操作", - "eLockConflict" => "锁定冲突", - "eDatabaseObjectsOpen" => "数据库对象打开", - "eLockChangeInProgress" => "锁定改变中", - "eVetoed" => "禁止", - "eNoDocument" => "没有文档", - "eNotFromThisDocument" => "不是从这个文档", - "eLISPActive" => "LISP活动", - "eTargetDocNotQuiescent" => "目标文档活动中", - "eDocumentSwitchDisabled" => "禁止文档转换", - "eInvalidContext" => "无效的上下文环境", - "eCreateFailed" => "创建失败", - "eCreateInvalidName" => "创建无效名称", - "eSetFailed" => "设置失败", - "eDelDoesNotExist" => "删除对象不存在", - "eDelIsModelSpace" => "删除模型空间", - "eDelLastLayout" => "删除最后一个布局", - "eDelUnableToSetCurrent" => "删除后无法设置当前对象", - "eDelUnableToFind" => "没有找到删除对象", - "eRenameDoesNotExist" => "重命名对象不存在", - "eRenameIsModelSpace" => "不可以重命令模型空间", - "eRenameInvalidLayoutName" => "重命名无效的布局名称", - "eRenameLayoutAlreadyExists" => "重命名布局名称已存在", - "eRenameInvalidName" => "重命名无效名称", - "eCopyDoesNotExist" => "拷贝不存在", - "eCopyIsModelSpace" => "拷贝是模型空间", - "eCopyFailed" => "拷贝失败", - "eCopyInvalidName" => "拷贝无效名称", - "eCopyNameExists" => "拷贝名称存在", - "eProfileDoesNotExist" => "配置名称不存在", - "eInvalidFileExtension" => "无效的文件后缀名成", - "eInvalidProfileName" => "无效的配置文件名称", - "eFileExists" => "文件存在", - "eProfileIsInUse" => "配置文件存在", - "eCantOpenFile" => "打开文件失败", - "eNoFileName" => "没有文件名称", - "eRegistryAccessError" => "读取注册表错误", - "eRegistryCreateError" => "创建注册表项错误", - "eBadDxfFile" => "坏的DXF文件", - "eUnknownDxfFileFormat" => "未知的DXF文件格式", - "eMissingDxfSection" => "丢失DXF分段", - "eInvalidDxfSectionName" => "无效的DXF分段名称", - "eNotDxfHeaderGroupCode" => "无效的DXF组码", - "eUndefinedDxfGroupCode" => "没有定义DXF组码", - "eNotInitializedYet" => "没有初始化", - "eInvalidDxf2dPoint" => "无效的DXF二维点", - "eInvalidDxf3dPoint" => "无效的DXD三维点", - "eBadlyNestedAppData" => "坏的嵌套应用程序数据", - "eIncompleteBlockDefinition" => "不完整的块定义", - "eIncompleteComplexObject" => "不完整的合成(?复杂)对象", - "eBlockDefInEntitySection" => "块定义在实体段中", - "eNoBlockBegin" => "没有块开始", - "eDuplicateLayerName" => "重复的图层名称", - "eBadPlotStyleName" => "不好的打印样式名称", - "eDuplicateBlockName" => "重复的块名称", - "eBadPlotStyleType" => "不好的打印样式类型", - "eBadPlotStyleNameHandle" => "不好的打印样式名称句柄", - "eUndefineShapeName" => "没有定义形状名称", - "eDuplicateBlockDefinition" => "重复的块定义", - "eMissingBlockName" => "丢失了块名称", - "eBinaryDataSizeExceeded" => "二进制数据长度太长", - "eObjectIsReferenced" => "对象被引用", - "eNoThumbnailBitmap" => "没有缩略图", - "eGuidNoAddress" => "未找到GUID地址", - "eMustBe0to2" => "必须是0到2", - "eMustBe0to3" => "必须是0到3", - "eMustBe0to4" => "必须是0到4", - "eMustBe0to5" => "必须是0到5", - "eMustBe0to8" => "必须是0到8", - "eMustBe1to8" => "必须是1到8", - "eMustBe1to15" => "必须是1到15", - "eMustBePositive" => "必须为正数", - "eMustBeNonNegative" => "必须为非负数", - "eMustBeNonZero" => "不可以等于0", - "eMustBe1to6" => "必须是1到6", - "eNoPlotStyleTranslationTable" => "没有打印样式事务表(?)", - "ePlotStyleInColorDependentMode" => "打印样式依赖颜色", - "eMaxLayouts" => "最大布局数量", - "eNoClassId" => "没有类ID", - "eUndoOperationNotAvailable" => "撤销操作无效", - "eUndoNoGroupBegin" => "撤销操作没有组开始", - "eHatchTooDense" => "填充太密集", - "eOpenFileCancelled" => "打开文件取消", - "eNotHandled" => "没有处理", - "eMakeMeProxyAndResurrect" => "将自己变成代理然后复活", - "eFileMissingSections" => "文件丢失分段", - "eRepeatedDwgRead" => "重复的读取DWG文件", - "eWrongCellType" => "错误的单元格类型", - "eCannotChangeColumnType" => "不可以改变列类型", - "eRowsMustMatchColumns" => "行必须匹配列", - "eFileSharingViolation" => "文件共享妨碍", - "eUnsupportedFileFormat" => "不支持的文件格式", - "eObsoleteFileFormat" => "废弃的文件格式", - "eDwgShareDemandLoad" => "DWG共享要求加载(?)", - "eDwgShareReadAccess" => "DWG共享读取", - "eDwgShareWriteAccess" => "DWG共享写入", - "eLoadFailed" => "加载失败", - "eDeviceNotFound" => "驱动未找到", - "eNoCurrentConfig" => "没有当前配置", - "eNullPtr" => "空指针", - "eNoLayout" => "没有布局", - "eIncompatiblePlotSettings" => "不兼容的打印设置", - "eNonePlotDevice" => "没有打印驱动", - "eNoMatchingMedia" => "没有匹配的打印尺寸", - "eInvalidView" => "无效的视图", - "eInvalidWindowArea" => "无效的窗口范围", - "eInvalidPlotArea" => "无效的打印范围", - "eCustomSizeNotPossible" => "用户输入的打印尺寸不可能存在", - "ePageCancelled" => "纸张取消", - "ePlotCancelled" => "打印取消", - "eInvalidEngineState" => "无效的引擎状态", - "ePlotAlreadyStarted" => "已经开始在打印了", - "eNoErrorHandler" => "没有错误处理", - "eInvalidPlotInfo" => "无效的打印信息", - "eNumberOfCopiesNotSupported" => "不支持打印份数", - "eLayoutNotCurrent" => "不是当前布局", - "eGraphicsNotGenerated" => "绘图对象创建失败(?)", - "eCannotPlotToFile" => "不可以打印到文件", - "eMustPlotToFile" => "必须打印到文件", - "eNotMultiPageCapable" => "不支持多种纸张", - "eBackgroundPlotInProgress" => "正在后台打印", - "eSubSelectionSetEmpty" => "子选择集被设置为空", - "eInvalidObjectId" => "无效的对象ID或者对象ID不在当前数据库", - "eInvalidXrefObjectId" => "无效的XREF对象ID或者XREF对象ID不在当前数据库", - "eNoViewAssociation" => "未找到对应的视图对象", - "eNoLabelBlock" => "视口未找到关联的块", - "eUnableToSetViewAssociation" => "设置视图关联视口失败", - "eUnableToGetViewAssociation" => "无法找到关联的视图", - "eUnableToSetLabelBlock" => "无法设置关联的块", - "eUnableToGetLabelBlock" => "无法获取关联的块", - "eUnableToRemoveAssociation" => "无法移除视口关联对象", - "eUnableToSyncModelView" => "无法同步视口和模型空间视图", - "eSecInitializationFailure" => "SEC(?)初始化错误", - "eSecErrorReadingFile" => "SEC(?)读取文件错误", - "eSecErrorWritingFile" => "SEC(?)写入文件错误", - "eSecInvalidDigitalID" => "SEC(?)无效的数字ID", - "eSecErrorGeneratingTimestamp" => "SEC(?)创建时间戳错误", - "eSecErrorComputingSignature" => "SEC(?)电子签名错误", - "eSecErrorWritingSignature" => "SEC(?)写入签名错误", - "eSecErrorEncryptingData" => "SEC(?)加密数据错误", - "eSecErrorCipherNotSupported" => "SEC(?)不支持的密码", - "eSecErrorDecryptingData" => "SEC(?)解密数据错误", - "eInetBase" => "网络错误", - "eInetOk" => "网络正常", - "eInetInCache" => "在缓冲区中", - "eInetFileNotFound" => "网络文件不存在", - "eInetBadPath" => "不好的网络路径", - "eInetTooManyOpenFiles" => "打开太多网络文件", - "eInetFileAccessDenied" => "打开网络文件被拒绝", - "eInetInvalidFileHandle" => "无效的网络文件句柄", - "eInetDirectoryFull" => "网络文件夹目录已满", - "eInetHardwareError" => "网络硬件错误", - "eInetSharingViolation" => "违反网络共享", - "eInetDiskFull" => "网络硬盘满了", - "eInetFileGenericError" => "网络文件创建错误", - "eInetValidURL" => "无效的URL地址", - "eInetNotAnURL" => "不是URL地址", - "eInetNoWinInet" => "没有WinInet(?)", - "eInetOldWinInet" => "旧的WinInet(?)", - "eInetNoAcadInet" => "无法连接ACAD网站", - "eInetNotImplemented" => "无法应用网络", - "eInetProtocolNotSupported" => "网络协议不支持", - "eInetCreateInternetSessionFailed" => "创建网络会话失败", - "eInetInternetSessionConnectFailed" => "连接网络会话失败", - "eInetInternetSessionOpenFailed" => "打开网络会话失败", - "eInetInvalidAccessType" => "无效的网络接收类型", - "eInetFileOpenFailed" => "打开网络文件失败", - "eInetHttpOpenRequestFailed" => "打开HTTP协议失败", - "eInetUserCancelledTransfer" => "用户取消了网络传输", - "eInetHttpBadRequest" => "不合理的网络请求", - "eInetHttpAccessDenied" => "HTTP协议拒绝", - "eInetHttpPaymentRequired" => "HTTP协议要求付费", - "eInetHttpRequestForbidden" => "禁止HTTP请求", - "eInetHttpObjectNotFound" => "HTTP对象未找到", - "eInetHttpBadMethod" => "不合理的HTTP请求方法", - "eInetHttpNoAcceptableResponse" => "不接受的HTTP回复", - "eInetHttpProxyAuthorizationRequired" => "要求HTTP代理授权", - "eInetHttpTimedOut" => "HTTP超时", - "eInetHttpConflict" => "HTTP冲突", - "eInetHttpResourceGone" => "网络资源被用光", - "eInetHttpLengthRequired" => "HTTP请求长度是必须的", - "eInetHttpPreconditionFailure" => "HTTP预处理失败", - "eInetHttpRequestTooLarge" => "HTTP请求太大", - "eInetHttpUriTooLong" => "URL地址太长", - "eInetHttpUnsupportedMedia" => "HTTP不支持的媒体", - "eInetHttpServerError" => "HTTP服务器错误", - "eInetHttpNotSupported" => "HTTP不支持", - "eInetHttpBadGateway" => "HTTP网关错误", - "eInetHttpServiceUnavailable" => "HTTP服务当前不可用", - "eInetHttpGatewayTimeout" => "HTTP网关超时", - "eInetHttpVersionNotSupported" => "HTTP版本不支持", - "eInetInternetError" => "HTTP网络错误", - "eInetGenericException" => "HTTP常规异常", - "eInetUnknownError" => "HTTP未知错误", - "eAlreadyActive" => "已经是活动的了", - "eAlreadyInactive" => "已经是不活动的了", - _ => acex.Message, - }; - Acap.ShowAlertDialog($"{acex.Message}:{infostr}"); - } -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Filer/DwgFiler.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Filer/DwgFiler.cs deleted file mode 100644 index 7f9c07c..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Filer/DwgFiler.cs +++ /dev/null @@ -1,496 +0,0 @@ -#if false -namespace IFoxCAD.Cad; - -/* - Arx自定义实体类,加 读函数(assertReadEnabled)和写函数(assertWriteEnabled) - - 所有属性位置都不要改动位置,因为涉及序列化 - [Serializable] 设置类 可以序列化 - [Newtonsoft.Json.JsonIgnore] 设置成员 不可序列化 -*/ - -#if NewtonsoftJson -[JsonConverter(typeof(ObjectIdConverter))] -#endif -[Serializable] -public class DwgFiler : Cad_DwgFiler -{ - - public long m_Position; - public FilerType m_FilerType; - public Cad_ErrorStatus m_FilerStatus; - public List AddressList; - public int AddressListPt = 0; - public List BinaryChunkList; - public int BinaryChunkListPt = 0; - public List BooleanList; - public int BooleanListPt = 0; - public List ByteList; - public int ByteListPt = 0; - public List BytesList; - public int BytesListPt = 0; - public List DoubleList; - public int DoubleListPt = 0; - public List HandleList; - public int HandleListPt = 0; - //[NonSerialized] - //[ScriptIgnore] - public List HardOwnershipIdList; - public int HardOwnershipIdListPt = 0; - //[NonSerialized] - //[ScriptIgnore] - public List HardPointerIdList; - public int HardPointerIdListPt = 0; - public List Int16List; - public int Int16ListPt = 0; - public List Int32List; - public int Int32ListPt = 0; - - public List Int64List; - public int Int64ListPt = 0; - - public List Point2dList; - public int Point2dListPt = 0; - public List Point3dList; - public int Point3dListPt = 0; - public List Scale3dList; - public int Scale3dListPt = 0; - //[NonSerialized] - //[ScriptIgnore] - public List SoftOwnershipIdList; - public int SoftOwnershipIdListPt = 0; - //[NonSerialized] - //[ScriptIgnore] - public List SoftPointerIdList; - public int SoftPointerIdListPt = 0; - public List StringList; - public int StringListPt = 0; - public List Uint16List; - public int uint16ListPt = 0; - public List Uint32List; - public int uint32ListPt = 0; - - public List Uint64List; - public int uint64ListPt = 0; - - public List Vector2dList; - public int Vector2dListPt = 0; - public List Vector3dList; - public int Vector3dListPt = 0; - - public DwgFiler() - { - m_Position = 0; - m_FilerType = FilerType.CopyFiler; - m_FilerStatus = Cad_ErrorStatus.OK; - AddressList = new(); - BinaryChunkList = new(); - BooleanList = new(); - ByteList = new(); - BytesList = new(); - DoubleList = new(); - HandleList = new(); - HardOwnershipIdList = new(); - HardPointerIdList = new(); - Int16List = new(); - Int32List = new(); - - Int64List = new(); - - Point2dList = new(); - Point3dList = new(); - Scale3dList = new(); - SoftOwnershipIdList = new(); - SoftPointerIdList = new(); - StringList = new(); - Uint16List = new(); - Uint32List = new(); - - Uint64List = new(); - - Vector2dList = new(); - Vector3dList = new(); - } - - - public override long Position => m_Position; - public override FilerType FilerType => m_FilerType; - - public override Cad_ErrorStatus FilerStatus - { - get { return m_FilerStatus; } - set { m_FilerStatus = value; } - } - - public override IntPtr ReadAddress() - { - if (AddressList.Count == 0) - return new(); - return AddressList[AddressListPt++]; - } - - public override byte[]? ReadBinaryChunk() - { - if (BinaryChunkList.Count == 0) - return null; - return BinaryChunkList[BinaryChunkListPt++]; - } - - public override bool ReadBoolean() - { - if (BooleanList.Count == 0) - return false; - return BooleanList[BooleanListPt++]; - } - - public override byte ReadByte() - { - if (ByteList.Count == 0) - return 0; - return ByteList[ByteListPt++]; - } - - public override void ReadBytes(byte[] value) - { - if (ByteList.Count == 0) - return; - value = new byte[BytesList[BytesListPt].Length]; - BytesList[BytesListPt++].CopyTo(value, 0); - } - - public override double ReadDouble() - { - if (DoubleList.Count == 0) - return 0; - return DoubleList[DoubleListPt++]; - } - - public override Handle ReadHandle() - { - if (HandleList.Count == 0) - return new(); - return HandleList[HandleListPt++]; - } - - public override ObjectId ReadHardOwnershipId() - { - if (HardOwnershipIdList.Count == 0) - return new(); - return HardOwnershipIdList[HardOwnershipIdListPt++]; - } - - public override ObjectId ReadHardPointerId() - { - if (HardPointerIdList.Count == 0) - return new(); - return HardPointerIdList[HardPointerIdListPt++]; - } - - public override short ReadInt16() - { - if (Int16List.Count == 0) - return 0; - return Int16List[Int16ListPt++]; - } - - public override int ReadInt32() - { - if (Int32List.Count == 0) - return 0; - return Int32List[Int32ListPt++]; - } - - - public override long ReadInt64() - { - if (Int64List.Count == 0) - return 0; - return Int64List[Int64ListPt++]; - } - - - public override Point2d ReadPoint2d() - { - if (Point2dList.Count == 0) - return new(); - return Point2dList[Point2dListPt++]; - } - - public override Point3d ReadPoint3d() - { - if (Point3dList.Count == 0) - return new(); - return Point3dList[Point3dListPt++]; - } - - public override Scale3d ReadScale3d() - { - if (Scale3dList.Count == 0) - return new(); - return Scale3dList[Scale3dListPt++]; - } - - public override ObjectId ReadSoftOwnershipId() - { - if (SoftOwnershipIdList.Count == 0) - return new(); - return SoftOwnershipIdList[SoftOwnershipIdListPt++]; - } - - public override ObjectId ReadSoftPointerId() - { - if (SoftPointerIdList.Count == 0) - return new(); - return SoftPointerIdList[SoftPointerIdListPt++]; - } - - public override string? ReadString() - { - if (StringList.Count == 0) - return null; - return StringList[StringListPt++]; - } - - public override ushort ReadUInt16() - { - if (Uint16List.Count == 0) - return 0; - return Uint16List[uint16ListPt++]; - } - - public override uint ReadUInt32() - { - if (Uint32List.Count == 0) - return 0; - return Uint32List[uint32ListPt++]; - } - - - public override ulong ReadUInt64() - { - if (Uint64List.Count == 0) - return 0; - return Uint64List[uint64ListPt++]; - } - - - public override Vector2d ReadVector2d() - { - if (Vector2dList.Count == 0) - return new(); - return Vector2dList[Vector2dListPt++]; - } - - public override Vector3d ReadVector3d() - { - if (Vector3dList.Count == 0) - return new(); - return Vector3dList[Vector3dListPt++]; - } - - public override void ResetFilerStatus() - { - AddressList.Clear(); - AddressListPt = 0; - BinaryChunkList.Clear(); - BinaryChunkListPt = 0; - BooleanList.Clear(); - BooleanListPt = 0; - ByteList.Clear(); - ByteListPt = 0; - BytesList.Clear(); - BytesListPt = 0; - DoubleList.Clear(); - DoubleListPt = 0; - HandleList.Clear(); - HandleListPt = 0; - HardOwnershipIdList.Clear(); - HardOwnershipIdListPt = 0; - HardPointerIdList.Clear(); - HardPointerIdListPt = 0; - Int16List.Clear(); - Int16ListPt = 0; - Int32List.Clear(); - Int32ListPt = 0; - - Int64List.Clear(); - Int64ListPt = 0; - - Point2dList.Clear(); - Point2dListPt = 0; - Point3dList.Clear(); - Point3dListPt = 0; - Scale3dList.Clear(); - Scale3dListPt = 0; - SoftOwnershipIdList.Clear(); - SoftOwnershipIdListPt = 0; - SoftPointerIdList.Clear(); - SoftPointerIdListPt = 0; - StringList.Clear(); - StringListPt = 0; - Uint16List.Clear(); - uint16ListPt = 0; - Uint32List.Clear(); - uint32ListPt = 0; - - Uint64List.Clear(); - uint64ListPt = 0; - - Vector2dList.Clear(); - Vector2dListPt = 0; - Vector3dList.Clear(); - Vector3dListPt = 0; - - m_FilerType = FilerType.CopyFiler; - } - -#if zcad // 中望官方的问题 - public override void Seek(int offset, int method) - { - var ed = Acap.DocumentManager.MdiActiveDocument.Editor; - ed.WriteMessage(MethodInfo.GetCurrentMethod().Name + " = " + " \n "); - } - public override void Seek(long offset, int method) - { - Seek((int)offset, method); - } -#endif - -#if acad || gcad - public override void Seek(long offset, int method) - { - var ed = Acap.DocumentManager.MdiActiveDocument.Editor; - ed.WriteMessage(MethodInfo.GetCurrentMethod().Name + " = " + " \n "); - } -#endif - - public override void WriteAddress(IntPtr value) - { - AddressList.Add(value); - } - - public override void WriteBinaryChunk(byte[] chunk) - { - BinaryChunkList.Add(chunk); - } - - public override void WriteBoolean(bool value) - { - BooleanList.Add(value); - } - - public override void WriteByte(byte value) - { - ByteList.Add(value); - } - - public override void WriteBytes(byte[] value) - { - BytesList.Add(value); - } - - public override void WriteDouble(double value) - { - DoubleList.Add(value); - } - - public override void WriteHandle(Handle handle) - { - HandleList.Add(handle); - } - - public override void WriteHardOwnershipId(ObjectId value) - { - HardOwnershipIdList.Add(value); - } - - public override void WriteHardPointerId(ObjectId value) - { - HardPointerIdList.Add(value); - } - - public override void WriteInt16(short value) - { - Int16List.Add(value); - } - - public override void WriteInt32(int value) - { - Int32List.Add(value); - } - - public override void WriteInt64(long value) - { - Int64List.Add(value); - } - - public override void WritePoint2d(Point2d value) - { - Point2dList.Add(value); - } - - public override void WritePoint3d(Point3d value) - { - Point3dList.Add(value); - } - - public override void WriteScale3d(Scale3d value) - { - Scale3dList.Add(value); - } - - public override void WriteSoftOwnershipId(ObjectId value) - { - SoftOwnershipIdList.Add(value); - } - - public override void WriteSoftPointerId(ObjectId value) - { - SoftPointerIdList.Add(value); - } - - public override void WriteString(string value) - { - StringList.Add(value); - } - - public override void WriteUInt16(ushort value) - { - Uint16List.Add(value); - } - - public override void WriteUInt32(uint value) - { - Uint32List.Add(value); - } - - - public override void WriteUInt64(ulong value) - { - Uint64List.Add(value); - } - - - public override void WriteVector2d(Vector2d value) - { - Vector2dList.Add(value); - } - - public override void WriteVector3d(Vector3d value) - { - Vector3dList.Add(value); - } - - public override string ToString() - { -#if NewtonsoftJson - return JsonConvert.SerializeObject(this, Formatting.Indented); -#else - JavaScriptSerializer serializer = new(); - serializer.RegisterConverters(new[] { new ObjectIdConverter() }); - return serializer.Serialize(this); -#endif - } -} - -#endif \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Filer/DwgFilerEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Filer/DwgFilerEx.cs deleted file mode 100644 index 28526d8..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Filer/DwgFilerEx.cs +++ /dev/null @@ -1,91 +0,0 @@ -#if false - -namespace IFoxCAD.Cad; - -/// -/// Dwg序列化 -/// -public class DwgFilerEx -{ - #region 成员 - DBObject? _entity; - public DwgFiler DwgFiler { get; private set; } - #endregion - - #region 构造 - /// - /// Dwg序列化 - /// - public DwgFilerEx(DwgFiler? Cad_DwgFiler = null) - { - if (Cad_DwgFiler == null) - Cad_DwgFiler = new(); - DwgFiler = Cad_DwgFiler; - } - - /// - /// Dwg序列化 - /// - public DwgFilerEx(DBObject entity) : this() - { - DwgOut(entity); - } - - #endregion - - #region 方法 - public void DwgOut(DBObject entity) - { - _entity = entity; - _entity.DwgOut(DwgFiler); - } - - public void DwgIn() - { - _entity?.DwgIn(DwgFiler); - } - - /// - /// 反序列化 - /// - /// - /// - public static DwgFilerEx? DeserializeObject(string json) - { -#if NewtonsoftJson - return JsonConvert.DeserializeObject(json); -#else - JavaScriptSerializer serializer = new(); - serializer.RegisterConverters(new[] { new ObjectIdConverter() }); - return serializer.Deserialize(json); -#endif - } - - /// - /// 序列化 - /// - /// - public string SerializeObject() - { -#if NewtonsoftJson - return JsonConvert.SerializeObject(DwgFiler, Formatting.Indented); -#else - JavaScriptSerializer serializer = new(); - serializer.RegisterConverters(new[] { new ObjectIdConverter() }); - return serializer.Serialize(DwgFiler); -#endif - } - - public override string ToString() - { - return DwgFiler.ToString(); - } - - public static implicit operator Cad_DwgFiler(DwgFilerEx df) - { - return df.DwgFiler; - } - #endregion -} - -#endif \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Filer/DxfFiler.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Filer/DxfFiler.cs deleted file mode 100644 index 7956a4a..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Filer/DxfFiler.cs +++ /dev/null @@ -1,225 +0,0 @@ -#if false - -#if acad -namespace IFoxCAD.Cad; - -/* 此处暂未完成,无任何测试,尚且不知道怎么用 */ -using System.Runtime.Remoting; - -public class DxfFiler : Cad_DxfFiler -{ - public DxfFiler(IntPtr unmanagedPointer, [MarshalAs(UnmanagedType.U1)] bool autoDelete) : base(unmanagedPointer, autoDelete) - { - } - - public override bool IsModifyingExistingObject => base.IsModifyingExistingObject; - - public override double Thickness => base.Thickness; - - public override double Elevation => base.Elevation; - - public override bool AtEmbeddedObjectStart => base.AtEmbeddedObjectStart; - - public override bool AtEndOfObject => base.AtEndOfObject; - - public override bool AtExtendedData => base.AtExtendedData; - - public override bool AtEndOfFile => base.AtEndOfFile; - - public override int Precision { get => base.Precision; set => base.Precision = value; } - - public override string ErrorMessage => base.ErrorMessage; - - public override bool AtSubclassData(string value) - { - return base.AtSubclassData(value); - } - - public override object Clone() - { - return base.Clone(); - } - - public override void CopyFrom(RXObject source) - { - base.CopyFrom(source); - } - - public override ObjRef CreateObjRef(Type requestedType) - { - return base.CreateObjRef(requestedType); - } - - public override bool Equals(object obj) - { - return base.Equals(obj); - } - - public override void FilerStatus() - { - base.FilerStatus(); - } - - public override int GetHashCode() - { - return base.GetHashCode(); - } - - public override void HaltAtClassBoundaries(bool value) - { - base.HaltAtClassBoundaries(value); - } - - public override object InitializeLifetimeService() - { - return base.InitializeLifetimeService(); - } - - public override void PushBackItem() - { - base.PushBackItem(); - } - - public override ResultBuffer ReadResultBuffer() - { - return base.ReadResultBuffer(); - } - - public override void ResetFilerStatus() - { - base.ResetFilerStatus(); - } - - public override int RewindFiler() - { - return base.RewindFiler(); - } - - public override void SetError(string format, params string[] values) - { - base.SetError(format, values); - } - - public override void SetError(Cad_ErrorStatus value, string format, params string[] values) - { - base.SetError(value, format, values); - } - - public override string ToString() - { - return base.ToString(); - } - - public override void WriteBool(DxfCode opCode, bool value) - { - base.WriteBool(opCode, value); - } - - public override void WriteBoolean(DxfCode opCode, bool value) - { - base.WriteBoolean(opCode, value); - } - - public override void WriteByte(DxfCode opCode, byte value) - { - base.WriteByte(opCode, value); - } - - public override void WriteBytes(DxfCode opCode, byte[] chunk) - { - base.WriteBytes(opCode, chunk); - } - - public override void WriteDouble(DxfCode opCode, double value, int precision) - { - base.WriteDouble(opCode, value, precision); - } - - public override void WriteEmbeddedObjectStart() - { - base.WriteEmbeddedObjectStart(); - } - - public override void WriteHandle(DxfCode opCode, Handle value) - { - base.WriteHandle(opCode, value); - } - - public override void WriteInt16(DxfCode opCode, short value) - { - base.WriteInt16(opCode, value); - } - - public override void WriteInt32(DxfCode opCode, int value) - { - base.WriteInt32(opCode, value); - } - - public override void WriteObjectId(DxfCode opCode, ObjectId value) - { - base.WriteObjectId(opCode, value); - } - - public override void WritePoint2d(DxfCode opCode, Point2d value, int precision) - { - base.WritePoint2d(opCode, value, precision); - } - - public override void WritePoint3d(DxfCode opCode, Point3d value, int precision) - { - base.WritePoint3d(opCode, value, precision); - } - - public override void WriteResultBuffer(ResultBuffer buffer) - { - base.WriteResultBuffer(buffer); - } - - public override void WriteScale3d(DxfCode opCode, Scale3d value, int precision) - { - base.WriteScale3d(opCode, value, precision); - } - - public override void WriteString(DxfCode opCode, string value) - { - base.WriteString(opCode, value); - } - - public override void WriteUInt16(DxfCode opCode, ushort value) - { - base.WriteUInt16(opCode, value); - } - - public override void WriteUInt32(DxfCode opCode, uint value) - { - base.WriteUInt32(opCode, value); - } - - public override void WriteVector2d(DxfCode opCode, Vector2d value, int precision) - { - base.WriteVector2d(opCode, value, precision); - } - - public override void WriteVector3d(DxfCode opCode, Vector3d value, int precision) - { - base.WriteVector3d(opCode, value, precision); - } - - public override void WriteXDataStart() - { - base.WriteXDataStart(); - } - - protected override void DeleteUnmanagedObject() - { - base.DeleteUnmanagedObject(); - } - - protected override void Dispose(bool disposing) - { - base.Dispose(disposing); - } -} -#endif - -#endif \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs deleted file mode 100644 index d5e213e..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/GeometryEx.cs +++ /dev/null @@ -1,679 +0,0 @@ -namespace IFoxCAD.Cad; - -using System.Drawing; - -/// -/// 图形扩展类 -/// -public static class GeometryEx -{ - #region Point&Circle - - /// - /// 判断点与多边形的关系 - /// - /// 多边形顶点集合 - /// 点 - /// 点与多边形的关系 - public static PointOnRegionType PointOnRegion(this IEnumerable pts, Point2d pt) - { - // 遍历点集并生成首尾连接的多边形 - var ptlst = new LoopList(pts); - if (ptlst.Count < 3) - return PointOnRegionType.Error; - - List ls2ds = []; - foreach (var node in ptlst.GetNodes()) - { - ls2ds.Add(new LineSegment2d(node.Value, node.Next!.Value)); - } - var cc2d = new CompositeCurve2d(ls2ds.ToArray()); - - // 在多边形上? - if (cc2d.IsOn(pt)) - return PointOnRegionType.On; - - // 在最小包围矩形外? - var bb2d = cc2d.BoundBlock; - if (!bb2d.Contains(pt)) - return PointOnRegionType.Outside; - - // - bool flag = false; - foreach (var node in ptlst.GetNodes()) - { - var pt1 = node.Value; - var pt2 = node.Next!.Value; - if (pt.Y < pt1.Y && pt.Y < pt2.Y) - continue; - if (pt1.X < pt.X && pt2.X < pt.X) - continue; - Vector2d vec = pt2 - pt1; - double t = (pt.X - pt1.X) / vec.X; - double y = t * vec.Y + pt1.Y; - if (y < pt.Y && t >= 0 && t <= 1) - flag = !flag; - } - return - flag ? - PointOnRegionType.Inside : PointOnRegionType.Outside; - } - - /// - /// 判断点与多边形的关系 - /// - /// 多边形顶点集合 - /// 点 - /// 点与多边形的关系 - public static PointOnRegionType PointOnRegion(this IEnumerable pts, Point3d pt) - { - // 遍历点集并生成首尾连接的多边形 - var ptlst = new LoopList(pts); - if (ptlst.First!.Value == ptlst.Last!.Value) - ptlst.RemoveLast(); - if (ptlst.Count < 3) - return PointOnRegionType.Error; - - List ls3ds = []; - foreach (var node in ptlst.GetNodes()) - ls3ds.Add(new LineSegment3d(node.Value, node.Next!.Value)); - var cc3d = new CompositeCurve3d(ls3ds.ToArray()); - - // 在多边形上? - if (cc3d.IsOn(pt)) - return PointOnRegionType.On; - - // 在最小包围矩形外? - var bb2d = cc3d.BoundBlock; - if (!bb2d.Contains(pt)) - return PointOnRegionType.Outside; - - // - bool flag = false; - foreach (var node in ptlst.GetNodes()) - { - var pt1 = node.Value; - var pt2 = node.Next!.Value; - if (pt.Y < pt1.Y && pt.Y < pt2.Y) - continue; - if (pt1.X < pt.X && pt2.X < pt.X) - continue; - Vector3d vec = pt2 - pt1; - double t = (pt.X - pt1.X) / vec.X; - double y = t * vec.Y + pt1.Y; - if (y < pt.Y && t >= 0 && t <= 1) - flag = !flag; - } - return - flag ? - PointOnRegionType.Inside : PointOnRegionType.Outside; - } - - /// - /// 按两点返回最小包围圆 - /// - /// 基准点 - /// 基准点 - /// 输出圆上的点 - /// 解析类圆对象 - public static CircularArc2d GetMinCircle(Point2d pt1, Point2d pt2, out LoopList ptlst) - { - ptlst = new LoopList { pt1, pt2 }; - return - new CircularArc2d - ( - (pt1 + pt2.GetAsVector()) / 2, - pt1.GetDistanceTo(pt2) / 2 - ); - } - - /// - /// 按三点返回最小包围圆 - /// - /// 基准点 - /// 基准点 - /// 基准点 - /// 输出圆上的点 - /// 解析类圆对象 - public static CircularArc2d GetMinCircle(Point2d pt1, Point2d pt2, Point2d pt3, out LoopList ptlst) - { - ptlst = new LoopList { pt1, pt2, pt3 }; - - // 遍历各点与下一点的向量长度,找到距离最大的两个点 - LoopListNode maxNode = - ptlst.GetNodes().FindByMax - ( - out double maxLength, - node => node.Value.GetDistanceTo(node.Next!.Value) - ); - - // 以两点做最小包围圆 - CircularArc2d ca2d = - GetMinCircle(maxNode.Value, maxNode.Next!.Value, out LoopList tptlst); - - // 如果另一点属于该圆 - if (ca2d.IsIn(maxNode.Previous!.Value)) - { - // 返回 - ptlst = tptlst; - return ca2d; - } - // 否则按三点做圆 - // ptlst.SetFirst(maxNode); - ptlst = new LoopList { maxNode.Value, maxNode.Next.Value, maxNode.Previous.Value }; - ca2d = new CircularArc2d(pt1, pt2, pt3); - ca2d.SetAngles(0, Math.PI * 2); - return ca2d; - } - - /// - /// 按四点返回最小包围圆 - /// - /// 基准点 - /// 基准点 - /// 基准点 - /// 基准点 - /// 输出圆上的点 - /// 解析类圆对象 - public static CircularArc2d? GetMinCircle(Point2d pt1, Point2d pt2, Point2d pt3, Point2d pt4, out LoopList? ptlst) - { - var iniptlst = new LoopList() { pt1, pt2, pt3, pt4 }; - ptlst = null; - CircularArc2d? ca2d = null; - - // 遍历C43的组合,环链表的优势在这里 - foreach (var firstNode in iniptlst.GetNodes()) - { - // 获取各组合下三点的最小包围圆 - var secondNode = firstNode.Next; - var thirdNode = secondNode!.Next; - var tca2d = GetMinCircle(firstNode.Value, secondNode.Value, thirdNode!.Value, out LoopList tptlst); - - // 如果另一点属于该圆,并且半径小于当前值就把它做为候选解 - if (!tca2d.IsIn(firstNode.Previous!.Value)) - continue; - if (ca2d is null || tca2d.Radius < ca2d.Radius) - { - ca2d = tca2d; - ptlst = tptlst; - } - } - - // 返回直径最小的圆 - return ca2d; - } - - /// - /// 计算三点围成的有向面积 - /// - /// 基准点 - /// 第一点 - /// 第二点 - /// 三点围成的三角形的有向面积 - private static double CalArea(Point2d ptBase, Point2d pt1, Point2d pt2) - { - return (pt2 - ptBase).DotProduct((pt1 - ptBase).GetPerpendicularVector()) * 0.5; - } - /// - /// 计算三点围成的三角形的真实面积 - /// - /// 基准点 - /// 第一点 - /// 第二点 - /// 三点围成的三角形的真实面积 - public static double GetArea(this Point2d ptBase, Point2d pt1, Point2d pt2) - { - return Math.Abs(CalArea(ptBase, pt1, pt2)); - } - - /// - /// 判断三点是否为逆时针,也就是说判断三点是否为左转 - /// - /// 基点 - /// 第一点 - /// 第二点 - /// OrientationType 类型值 - public static OrientationType IsClockWise(this Point2d ptBase, Point2d pt1, Point2d pt2) - { - return CalArea(ptBase, pt1, pt2) switch - { - > 0 => OrientationType.CounterClockWise, - < 0 => OrientationType.ClockWise, - _ => OrientationType.Parallel - }; - } - - /// - /// 计算两个二维向量围成的平行四边形的有向面积 - /// - /// 基向量 - /// 向量 - /// 有向面积 - private static double CalArea(Vector2d vecBase, Vector2d vec) - { - return vec.DotProduct(vecBase.GetPerpendicularVector()) / 2; - } - - /// - /// 计算两个二维向量围成的平行四边形的真实面积 - /// - /// 基向量 - /// 向量 - /// 真实面积 - public static double GetArea(Vector2d vecBase, Vector2d vec) - { - return Math.Abs(CalArea(vecBase, vec)); - } - - /// - /// 判断两个二维向量是否左转 - /// - /// 基向量 - /// 向量 - /// OrientationType 类型值 - public static OrientationType IsClockWise(Vector2d vecBase, Vector2d vec) - { - return CalArea(vecBase, vec) switch - { - > 0 => OrientationType.CounterClockWise, - < 0 => OrientationType.ClockWise, - _ => OrientationType.Parallel - }; - } - - #region PointList - - /// - /// 计算点集的有向面积 - /// - /// 点集 - /// 有向面积 - private static double CalArea(IEnumerable pnts) - { - var itor = pnts.GetEnumerator(); - if (!itor.MoveNext()) - throw new ArgumentNullException(nameof(pnts)); - var start = itor.Current; - Point2d p1, p2 = start; - double area = 0; - - while (itor.MoveNext()) - { - p1 = p2; - p2 = itor.Current; - area += (p1.X * p2.Y - p2.X * p1.Y); - } - - area = (area + (p2.X * start.Y - start.X * p2.Y)) / 2.0; - return area; - } - /// - /// 计算点集的真实面积 - /// - /// 点集 - /// 面积 - public static double GetArea(this IEnumerable pnts) - { - return Math.Abs(CalArea(pnts)); - } - - /// - /// 判断点集的点序 - /// - /// 点集 - /// OrientationType 类型值 - public static OrientationType IsClockWise(this IEnumerable pnts) - { - return CalArea(pnts) switch - { - < 0 => OrientationType.ClockWise, - > 0 => OrientationType.CounterClockWise, - _ => OrientationType.Parallel - }; - } - - /// - /// 按点集返回最小包围圆 - /// - /// 点集 - /// 输出圆上的点 - /// 解析类圆对象 - public static CircularArc2d? GetMinCircle(this List pnts, out LoopList? ptlst) - { - // 点数较小时直接返回 - switch (pnts.Count) - { - case 0: - ptlst = null; - return null; - - case 1: - ptlst = new LoopList { pnts[0] }; - return new CircularArc2d(pnts[0], 0); - - case 2: - return GetMinCircle(pnts[0], pnts[1], out ptlst); - - case 3: - return GetMinCircle(pnts[0], pnts[1], pnts[2], out ptlst); - - case 4: - return GetMinCircle(pnts[0], pnts[1], pnts[2], pnts[3], out ptlst); - } - - // 按前三点计算最小包围圆 - var tpnts = new Point2d[4]; - pnts.CopyTo(0, tpnts, 0, 3); - var ca2d = GetMinCircle(tpnts[0], tpnts[1], tpnts[2], out ptlst); - - // 找到点集中距离圆心的最远点为第四点 - tpnts[3] = pnts.FindByMax(pnt => ca2d.Center.GetDistanceTo(pnt)); - - // 如果最远点属于圆结束 - while (!ca2d.IsIn(tpnts[3])) - { - // 如果最远点不属于圆,按此四点计算最小包围圆 - ca2d = GetMinCircle(tpnts[0], tpnts[1], tpnts[2], tpnts[3], out ptlst); - - // 将结果作为新的前三点 - if (ptlst!.Count == 3) - { - tpnts[2] = ptlst.Last!.Value; - } - else - { - // 第三点取另两点中距离圆心较远的点 - // 按算法中描述的任选其中一点的话,还是无法收敛...... - tpnts[2] = - tpnts.Except(ptlst) - .FindByMax(pnt => ca2d!.Center.GetDistanceTo(pnt)); - } - tpnts[0] = ptlst.First!.Value; - tpnts[1] = ptlst.First.Next!.Value; - - // 按此三点计算最小包围圆 - ca2d = GetMinCircle(tpnts[0], tpnts[1], tpnts[2], out ptlst); - - // 找到点集中圆心的最远点为第四点 - tpnts[3] = pnts.FindByMax(pnt => ca2d.Center.GetDistanceTo(pnt)); - } - - return ca2d; - } - - /// - /// 获取点集的凸包 - /// - /// 点集 - /// 凸包 - public static List? ConvexHull(this List points) - { - if (points is null) - return null; - - if (points.Count <= 1) - return points; - - int n = points.Count, k = 0; - List H = new(new Point2d[2 * n]); - - points.Sort((a, b) => - a.X == b.X ? a.Y.CompareTo(b.Y) : a.X.CompareTo(b.X)); - - // Build lower hull - for (int i = 0; i < n; ++i) - { - while (k >= 2 && IsClockWise(H[k - 2], H[k - 1], points[i]) == OrientationType.CounterClockWise) - k--; - H[k++] = points[i]; - } - - // Build upper hull - for (int i = n - 2, t = k + 1; i >= 0; i--) - { - while (k >= t && IsClockWise(H[k - 2], H[k - 1], points[i]) == OrientationType.CounterClockWise) - k--; - H[k++] = points[i]; - } - return H.Take(k - 1).ToList(); - } - - - #endregion PointList - - #endregion Point&Circle - - #region Ucs - - /// - /// ucs到wcs的点变换 - /// - /// 点 - /// 变换后的点 - public static Point3d Ucs2Wcs(this Point3d point) - { - return point.TransformBy(Env.Editor.CurrentUserCoordinateSystem); - } - - /// - /// wcs到ucs的点变换 - /// - /// 点 - /// 变换后的点 - public static Point3d Wcs2Ucs(this Point3d point) - { - return point.TransformBy(Env.Editor.CurrentUserCoordinateSystem.Inverse()); - } - - /// - /// ucs到wcs的向量变换 - /// - /// 向量 - /// 变换后的向量 - public static Vector3d Ucs2Wcs(this Vector3d vec) - { - return vec.TransformBy(Env.Editor.CurrentUserCoordinateSystem); - } - - /// - /// wcs到ucs的向量变换 - /// - /// 向量 - /// 变换后的向量 - public static Vector3d Wcs2Ucs(this Vector3d vec) - { - return vec.TransformBy(Env.Editor.CurrentUserCoordinateSystem.Inverse()); - } - - /// - /// 模拟 trans 函数 - /// - /// 点 - /// 源坐标系 - /// 目标坐标系 - /// 变换后的点 - public static Point3d Trans(this Point3d point, CoordinateSystemCode from, CoordinateSystemCode to) - { - return Env.Editor.GetMatrix(from, to) * point; - } - - /// - /// 模拟 trans 函数 - /// - /// 向量 - /// 源坐标系 - /// 目标坐标系 - /// 变换后的向量 - public static Vector3d Trans(this Vector3d vec, CoordinateSystemCode from, CoordinateSystemCode to) - { - return vec.TransformBy(Env.Editor.GetMatrix(from, to)); - } - - /// - /// wcs到dcs的点变换 - /// - /// 点 - /// 是否为图纸空间 - /// 变换后的点 - public static Point3d Wcs2Dcs(this Point3d point, bool atPaperSpace) - { - return - Trans( - point, - CoordinateSystemCode.Wcs, atPaperSpace ? CoordinateSystemCode.PDcs : CoordinateSystemCode.MDcs - ); - } - - /// - /// wcs到dcs的向量变换 - /// - /// 向量 - /// 是否为图纸空间 - /// 变换后的向量 - public static Vector3d Wcs2Dcs(this Vector3d vec, bool atPaperSpace) - { - return - Trans( - vec, - CoordinateSystemCode.Wcs, atPaperSpace ? CoordinateSystemCode.PDcs : CoordinateSystemCode.MDcs - ); - } - - #endregion Ucs - - - /// - /// 返回不等比例变换矩阵 - /// - /// 基点 - /// x方向比例 - /// y方向比例 - /// z方向比例 - /// 三维矩阵 - public static Matrix3d GetScaleMatrix(this Point3d point, double x, double y, double z) - { - double[] matdata = new double[16]; - matdata[0] = x; - matdata[3] = point.X * (1 - x); - matdata[5] = y; - matdata[7] = point.Y * (1 - y); - matdata[10] = z; - matdata[11] = point.Z * (1 - z); - matdata[15] = 1; - return new(matdata); - } - - /// - /// 获取坐标范围的大小 - /// - /// 坐标范围 - /// 尺寸对象 - public static Size GetSize(this Extents3d ext) - { - int width = (int)Math.Floor(ext.MaxPoint.X - ext.MinPoint.X); - int height = (int)Math.Ceiling(ext.MaxPoint.Y - ext.MinPoint.Y); - return new(width, height); - } - - /// - /// 重绘 - /// - /// 图形界面几何 - /// 可绘制的对象列表 - public static void Draw(this Geometry geometry, IEnumerable drawables) - { - drawables.ForEach(d => geometry.Draw(d)); - } - /// - /// 重绘 - /// - /// 图形界面几何 - /// 可绘制的对象列表 - public static void Draw(this Geometry geometry, params Drawable[] drawables) - { - drawables.ForEach(d => geometry.Draw(d)); - } -} -/// -/// 向量扩展类 -/// -public static class VectorEx -{ - /// - /// 转换为2d向量 - /// - /// 3d向量 - /// 2d向量 - public static Vector2d Convert2d(this Vector3d vector3d) - { - return new Vector2d(vector3d.X, vector3d.Y); - } - - /// - /// 转换为3d向量 - /// - /// 2d向量 - /// z值 - /// 3d向量 - public static Vector3d Convert3d(this Vector2d vector2d, double z = 0) - { - return new Vector3d(vector2d.X, vector2d.Y, z); - } - /// - /// 2d叉乘 - /// - /// 向量a - /// 向量b - /// 叉乘值 - public static double Cross2d(this Vector3d a, Vector3d b) - { - return a.X * b.Y - b.X * a.Y; - } - /// - /// 2d叉乘 - /// - /// 向量a - /// 向量b - /// 叉乘值 - public static double Cross2d(this Vector2d a, Vector2d b) - { - return a.X * b.Y - b.X * a.Y; - } - /// - /// 向量Z值归零 - /// - /// 向量 - /// - public static Vector3d Z20(this Vector3d vector3d) - { - return new Vector3d(vector3d.X, vector3d.Y, 0); - } - /// - /// 向量在平面上的弧度 - /// - /// 向量 - /// 平面 - /// 弧度 - public static double AngleOnPlane(this Vector3d vector, Plane? plane = null) - { - return vector.AngleOnPlane(plane ?? PlaneEx.Z); - } -} -/// -/// 平面 -/// -public static class PlaneEx -{ - /// - /// X - /// - public static readonly Plane X = new (Point3d.Origin, Vector3d.XAxis); - /// - /// Y - /// - public static readonly Plane Y = new (Point3d.Origin, Vector3d.YAxis); - /// - /// Z - /// - public static readonly Plane Z = new (Point3d.Origin, Vector3d.ZAxis); -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/IdleAction.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/IdleAction.cs deleted file mode 100644 index 95284f1..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/IdleAction.cs +++ /dev/null @@ -1,67 +0,0 @@ -using Cursor = System.Windows.Forms.Cursor; - -namespace IFoxCAD.Cad; - -/// -/// 空闲执行 -/// by DYH -/// 20230114 -/// -public static class IdleAction -{ - /// - /// 是否已经加载 - /// - private static bool alreadyLoad; - - /// - /// 委托列表 - /// - private static readonly List _actions = new(); - - /// - /// 未处理的委托数量 - /// - public static int Count => _actions.Count; - - /// - /// 添加空闲执行委托 - /// - /// 委托 - public static void Add(Action action) - { - _actions.Add(action); - if (!alreadyLoad) - { - Acaop.Idle -= Acap_Idle; - Acaop.Idle += Acap_Idle; - alreadyLoad = true; - } - } - - /// - /// 空闲处理事件 - /// - /// Acap - /// 事件参数 - private static void Acap_Idle(object sender, EventArgs e) - { - if (Count == 0) - { - alreadyLoad = false; - Acaop.Idle -= Acap_Idle; - return; - } - - try - { - _actions[0]?.Invoke(); - } - finally - { - _actions.RemoveAt(0); - } - - Cursor.Position = Cursor.Position; - } -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigEx.cs deleted file mode 100644 index 241277b..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigEx.cs +++ /dev/null @@ -1,419 +0,0 @@ - - -namespace IFoxCAD.Cad; - -/* 封装jig - * 20220726 隐藏事件,利用函数进行数据库图元重绘 - * 20220710 修改SetOption()的空格结束,并添加例子到IFox - * 20220503 cad22需要防止刷新过程中更改队列,是因为允许函数重入导致,08不会有. - * 20220326 重绘图元的函数用错了,现在修正过来 - * 20211216 加入块表时候做一个差集,剔除临时图元 - * 20211209 补充正交变量设置和回收设置 - * 作者: 惊惊⎛⎝◕⏝⏝◕。⎠⎞ ⎛⎝≥⏝⏝0⎠⎞ ⎛⎝⓿⏝⏝⓿。⎠⎞ ⎛⎝≥⏝⏝≤⎠⎞ - * 博客: https://www.cnblogs.com/JJBox/p/15650770.html - */ -/// -/// 重绘事件 -/// -/// -public delegate void WorldDrawEvent(WorldDraw draw); -/// -/// jig扩展类 -/// -public class JigEx : DrawJig, IDisposable -{ - #region 成员 - /// - /// 事件:亮显/暗显会被刷新冲刷掉,所以这个事件用于补充非刷新的工作 - /// - event WorldDrawEvent? WorldDrawEvent; - /// - /// 最后的鼠标点,用来确认长度 - /// - public Point3d MousePointWcsLast; - /// - /// 最后的图元,用来生成 - /// - public Entity[] Entitys => _drawEntitys.ToArray(); - - - readonly Action>? _mouseAction; - readonly Tolerance _tolerance;// 容差 - - readonly Queue _drawEntitys;// 重复生成的图元,放在这里刷新 - JigPromptPointOptions? _options;// jig鼠标配置 - bool _worldDrawFlag = false; // 20220503 - - bool _systemVariables_Orthomode = false; - bool SystemVariables_Orthomode // 正交修改还原 - { - get => _systemVariables_Orthomode; - set - { - // 1正交,0非正交 // setvar: https://www.cnblogs.com/JJBox/p/10209541.html - if (Env.OrthoMode != value) - Env.OrthoMode = _systemVariables_Orthomode = value; - } - } - #endregion - - #region 构造 - /// - /// 在界面绘制图元 - /// - JigEx() - { - _drawEntitys = new(); - DimensionEntitys = new(); - } - - /// - /// 在界面绘制图元 - /// - /// - /// 用来频繁执行的回调:
- /// 鼠标点;
- /// 加入新建的图元,鼠标采样期间会Dispose图元的;
- /// 所以已经在数据库图元利用事件加入,不要在此加入;
- /// - /// 鼠标移动的容差 - public JigEx(Action>? action = null, double tolerance = 1e-6) : this() - { - _mouseAction = action; - _tolerance = new(tolerance, tolerance); - } - #endregion - /// - /// 因为是worldDraw触发sampler不是Sample触发worldDraw,所以要记一次上次的状态 - /// - static bool lastIsKw = false; - #region 重写 - /// - /// 鼠标采样器 - /// - /// - /// 返回状态:令频繁刷新结束 - protected override SamplerStatus Sampler(JigPrompts prompts) - { - if (_worldDrawFlag) - return SamplerStatus.NoChange;// OK的时候拖动鼠标与否都不出现图元 - if (_options is null) - throw new NullReferenceException(nameof(_options)); - var pro = prompts.AcquirePoint(_options); - if (pro.Status != PromptStatus.OK && pro.Status != PromptStatus.Keyword) - return SamplerStatus.Cancel; - // 记上次的状态,因为马上要还原 - bool isOk = !lastIsKw; - lastIsKw = pro.Status == PromptStatus.Keyword; - - // 上次鼠标点不同(一定要这句,不然图元刷新太快会看到奇怪的边线) - var mousePointWcs = pro.Value; - - // == 是比较类字段,但是最好转为哈希比较. - // IsEqualTo 是方形判断(仅加法),但是cad是距离. - // Distance 是圆形判断(会求平方根,使用了牛顿迭代), - // 大量数据(十万以上/频繁刷新)面前会显得非常慢. - if (isOk && mousePointWcs.IsEqualTo(MousePointWcsLast, _tolerance)) - { - return SamplerStatus.NoChange; - } - // 上次循环的缓冲区图元清理,否则将会在vs输出遗忘 Dispose - while (_drawEntitys.Count > 0) - _drawEntitys.Dequeue().Dispose(); - - // 委托把容器扔出去接收新创建的图元,然后给重绘更新 - _mouseAction?.Invoke(mousePointWcs, _drawEntitys); - MousePointWcsLast = mousePointWcs; - - return SamplerStatus.OK; - } - - /// - /// 重绘已在数据库的图元 - /// - /// 0x01 此处不加入newEntity的,它们在构造函数的参数回调处加入,它们会进行频繁new和Dispose从而避免遗忘释放
- /// 0x02 此处用于重绘已经在数据的图元
- /// 0x03 此处用于图元亮显暗显,因为会被重绘冲刷掉所以独立出来不重绘,它们也往往已经存在数据库的 - ///
- ///
- /// - /// newEntity只会存在一个图元队列中,而数据库图元可以分多个集合 - /// 例如: 集合A亮显时 集合B暗显/集合B亮显时 集合A暗显,所以我没有设计多个"数据库图元集合"存放,而是由用户在构造函数外自行创建 - /// - /// - public void DatabaseEntityDraw(WorldDrawEvent action) - { - WorldDrawEvent = action; - } - - /* WorldDraw 封装外的操作说明: - * 0x01 - * 我有一个业务是一次性生成四个方向的箭头,因为cad08缺少瞬时图元, - * 那么可以先提交一次事务,再开一个事务,把Entity传给jig,最后选择删除部分. - * 虽然这个是可行的方案,但是Entity穿越事务本身来说是非必要不使用的. - * 0x02 - * 四个箭头最近鼠标的亮显,其余淡显, - * 在jig使用淡显ent.Unhighlight和亮显ent.Highlight() - * 需要绕过重绘,否则重绘将导致图元频闪,令这两个操作失效, - * 此时需要自定义一个集合 EntityList (不使用本函数的_drawEntitys) - * 再将 EntityList 传给 WorldDrawEvent 事件,事件内实现亮显和淡显(事件已经利用 DatabaseEntityDraw函数进行提供). - * 0x03 - * draw.Geometry.Draw(_drawEntitys[i]); - * 此函数有问题,acad08克隆一份数组也可以用来刷新, - * 而arx上面的jig只能一次改一个,所以可以用此函数. - * 起因是此函数属于异步刷新, - * 同步上下文的刷新是 RawGeometry - * 0x04 - * cad22测试出现,08不会, - * draw.RawGeometry.Draw(ent);会跳到 Sampler(),所以设置 _worldDrawFlag - * 但是禁止重绘重入的话(令图元不频繁重绘),那么鼠标停着的时候就看不见图元, - * 所以只能重绘结束的时候才允许鼠标采集,采集过程的时候不会触发重绘, - * 这样才可以保证容器在重绘中不被更改. - */ - /// - /// 重绘图形 - /// - protected override bool WorldDraw(WorldDraw draw) - { - _worldDrawFlag = true; - WorldDrawEvent?.Invoke(draw); - _drawEntitys.ForEach(ent => { -#if zcad - draw.Geometry.Draw(ent); -#else - draw.RawGeometry.Draw(ent); -#endif - }); - _worldDrawFlag = false; - return true; - } -#endregion - - #region 方法 - /// - /// 鼠标配置:基点 - /// - /// 基点 - /// 光标绑定 - /// 提示信息 - /// 正交开关 - public JigPromptPointOptions SetOptions(Point3d basePoint, - CursorType cursorType = CursorType.RubberBand, - string msg = "点选第二点", - bool orthomode = false) - { - if (orthomode) - SystemVariables_Orthomode = true; - - _options = JigPointOptions(); - _options.Message = Environment.NewLine + msg; - _options.Cursor = cursorType; // 光标绑定 - _options.UseBasePoint = true; // 基点打开 - _options.BasePoint = basePoint; // 基点设定 - return _options; - } - - /// - /// 鼠标配置:提示信息,关键字 - /// - /// 信息 - /// 关键字 - /// 正交开关 - /// - public JigPromptPointOptions SetOptions(string msg, - Dictionary? keywords = null, - bool orthomode = false) - { - if (orthomode) - SystemVariables_Orthomode = true; - - _options = JigPointOptions(); - _options.Message = Environment.NewLine + msg; - - - if (keywords != null) - foreach (var item in keywords) - _options.Keywords.Add(item.Key, item.Key, item.Value); - - // 因为默认配置函数导致此处空格触发是无效的, - // 但是用户如果想触发,就需要在外部减去默认UserInputControls配置 - // 要放最后,才能优先触发其他关键字 - - - // 外部设置减去配置 - // _options.UserInputControls = - // _options.UserInputControls - // ^ UserInputControls.NullResponseAccepted // 输入了鼠标右键,结束jig - // ^ UserInputControls.AnyBlankTerminatesInput; // 空格或回车,结束jig; - return _options; - } - - /// - /// 鼠标配置:自定义 - /// - /// - /// 正交开关 - public void SetOptions(Action action, bool orthomode = false) - { - if (orthomode) - SystemVariables_Orthomode = true; - - _options = new JigPromptPointOptions(); - action.Invoke(_options); - } - - /// - /// 执行 - /// - /// - public PromptResult Drag() - { - // jig功能必然是当前前台文档,所以封装内部更好调用 - var dm = Acap.DocumentManager; - var doc = dm.MdiActiveDocument; - var ed = doc.Editor; - var dr = ed.Drag(this); - - if (SystemVariables_Orthomode) - SystemVariables_Orthomode = !SystemVariables_Orthomode; - return dr; - } - - /// - /// 最后一次的图元加入数据库 - /// - /// 加入此空间 - /// 不生成的图元用于排除,例如刷新时候的提示文字 - /// 加入数据库的id集合 - public IEnumerable? AddEntityToMsPs(BlockTableRecord btrOfAddEntitySpace, - IEnumerable? removeEntity = null) - { - // 内部用 _drawEntitys 外部用 Entitys,减少一层转换 - if (_drawEntitys.Count == 0) - return null; - - IEnumerable es = _drawEntitys; - if (removeEntity != null) - es = es.Except(removeEntity);// 差集 - - return btrOfAddEntitySpace.AddEntity(es); - } - - - #region 配置 - /// - /// 用户输入控制默认配置 - /// 令jig.Drag().Status == - /// - /// - static JigPromptPointOptions JigPointOptions() - { - return new JigPromptPointOptions() - { - UserInputControls = - UserInputControls.GovernedByUCSDetect // 由UCS探测用 - | UserInputControls.Accept3dCoordinates // 接受三维坐标 - | UserInputControls.NullResponseAccepted // 输入了鼠标右键,结束jig - | UserInputControls.AnyBlankTerminatesInput // 空格或回车,结束jig; - }; - } - - /// - /// 空格默认是, - /// 将它设置为 - /// - public void SetSpaceIsKeyword() - { - var opt = _options; - ArgumentNullEx.ThrowIfNull(opt); - if ((opt.UserInputControls & UserInputControls.NullResponseAccepted) == UserInputControls.NullResponseAccepted) - opt.UserInputControls ^= UserInputControls.NullResponseAccepted; // 输入了鼠标右键,结束jig - if ((opt.UserInputControls & UserInputControls.AnyBlankTerminatesInput) == UserInputControls.AnyBlankTerminatesInput) - opt.UserInputControls ^= UserInputControls.AnyBlankTerminatesInput; // 空格或回车,结束jig - } - #endregion - - #region 注释数据 - /// - /// 注释数据,可以在缩放的时候不受影响 - /// - public DynamicDimensionDataCollection DimensionEntitys; - - /// - /// 重写注释数据 - /// - /// - /// - protected override DynamicDimensionDataCollection GetDynamicDimensionData(double dimScale) - { - base.GetDynamicDimensionData(dimScale); - return DimensionEntitys; - } - - #endregion - #endregion - - #region IDisposable接口相关函数 - /// - /// - /// - public bool IsDisposed { get; private set; } = false; - - /// - /// 手动调用释放 - /// - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - /// - /// 析构函数调用释放 - /// - ~JigEx() - { - Dispose(false); - } - /// - /// - /// - /// - protected virtual void Dispose(bool disposing) - { - // 不重复释放,并设置已经释放 - if (IsDisposed) return; - IsDisposed = true; - if(disposing) - { - // 最后一次的图元如果没有加入数据库,就在此销毁,所以JigEx调用的时候加using - _drawEntitys?.ForEach(ent => { - if (ent.Database == null && !ent.IsDisposed) - ent.Dispose(); - }); - } - _drawEntitys?.Clear(); - } - #endregion - - // 此处无测试 - // protected override void ViewportDraw(ViewportDraw draw) - // { - // base.ViewportDraw(draw); - // } -} - -#if false -| UserInputControls.DoNotEchoCancelForCtrlC // 不要取消CtrlC的回音 -| UserInputControls.DoNotUpdateLastPoint // 不要更新最后一点 -| UserInputControls.NoDwgLimitsChecking // 没有Dwg限制检查 -| UserInputControls.NoZeroResponseAccepted // 接受非零响应 -| UserInputControls.NoNegativeResponseAccepted // 不否定回复已被接受 -| UserInputControls.Accept3dCoordinates // 返回点的三维坐标,是转换坐标系了? -| UserInputControls.AcceptMouseUpAsPoint // 接受释放按键时的点而不是按下时 - -| UserInputControls.InitialBlankTerminatesInput // 初始 空格或回车,结束jig -| UserInputControls.AcceptOtherInputString // 接受其他输入字符串 -| UserInputControls.NoZDirectionOrtho // 无方向正射,直接输入数字时以基点到当前点作为方向 -| UserInputControls.UseBasePointElevation // 使用基点高程,基点的Z高度探测 -#endif \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigExTransient.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigExTransient.cs deleted file mode 100644 index 38ed391..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Jig/JigExTransient.cs +++ /dev/null @@ -1,148 +0,0 @@ -namespace IFoxCAD.Cad; - -/// -/// 瞬态容器 -/// -public class JigExTransient : IDisposable -{ - #region 私有字段 - // 整数集,暂时不知道有什么意义 - readonly IntegerCollection _integerCollection; - // 维护集合 - readonly HashSet _drawableSet; - readonly TransientManager _manager; - #endregion - - #region 公开属性 - /// - /// 图元集合 - /// - public Entity[] Entities => _drawableSet.OfType().ToArray(); - /// - /// 对象集合 - /// - public Drawable[] Drawables => _drawableSet.ToArray(); - /// - /// 数量 - /// - public int Count => _drawableSet.Count; - #endregion - - #region 构造函数 - /// - /// 瞬态容器 - /// - public JigExTransient() - { - _integerCollection = new(); - _drawableSet = new(); - _manager=TransientManager.CurrentTransientManager; - } - #endregion - - #region 方法 - /// - /// 判断瞬态容器里是否含有对象 - /// - /// 对象 - /// 含有返回true - public bool Contains(Drawable drawable) - { - return _drawableSet.Contains(drawable); - } - - /// - /// 向瞬态容器中添加对象 - /// - /// 图元 - /// 绘图模式 - public void Add(Drawable drawable, TransientDrawingMode tdm = TransientDrawingMode.Main) - { - if (_drawableSet.Add(drawable)) - { - _manager.AddTransient(drawable, tdm, 128, _integerCollection); - } - } - - - /// - /// 从瞬态容器中移除图元 - /// - /// 已经加入瞬态容器的图元 - public void Remove(Drawable drawable) - { - if (!Contains(drawable)) - return; - _manager.EraseTransient(drawable, _integerCollection); - _drawableSet.Remove(drawable); - } - - /// - /// 清空瞬态容器并移除图元显示 - /// - public void Clear() - { - foreach (var drawable in _drawableSet) - { - _manager.EraseTransient(drawable, _integerCollection); - } - _drawableSet.Clear(); - } - - - /// - /// 更新单个显示 - /// - /// 已经加入瞬态容器的图元 - public void Update(Drawable drawable) - { - if (!Contains(drawable)) - return; - _manager.UpdateTransient(drawable, _integerCollection); - } - - /// - /// 更新全部显示 - /// - public void UpdateAll() - { - foreach (var drawable in _drawableSet) - Update(drawable); - } - #endregion - - #region IDisposable接口相关函数 - /// - /// 是否注销 - /// - public bool IsDisposed { get; private set; } - - /// - /// 手动释放 - /// - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - /// - /// 析构函数调用释放 - /// - ~JigExTransient() - { - Dispose(false); - } - - /// - /// 销毁瞬态容器 - /// - protected virtual void Dispose(bool disposing) - { - if (IsDisposed) return; - IsDisposed = true; - - Clear();// 清空瞬态容器并移除对象在图纸上的显示 - } - #endregion -} diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/JsonConverter.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/JsonConverter.cs deleted file mode 100644 index 59daa7b..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/JsonConverter.cs +++ /dev/null @@ -1,120 +0,0 @@ -#if false - -namespace IFoxCAD.Cad; - -#if NewtonsoftJson -/* - * 参考 https://www.cnblogs.com/fps2tao/p/14798710.html - * json类型转换器,使用方法: - * 在类上面增加此特性: [JsonConverter(typeof(ObjectIdConverter))] - */ -/// -/// json转换器 -/// -public class ObjectIdConverter : JsonConverter -{ - /// - /// 约束类型 - /// - public override bool CanConvert(Type objectType) - { - return typeof(ObjectId) == objectType; - } - - /// - /// 反序列化_把字符串生成对象 - /// - public override object ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) - { - if (reader.Value == null) - return ObjectId.Null; - try - { - using DBTrans tr = new(); - var id = tr.GetObjectId(reader.Value.ToString()); - return id; - } - catch { return ObjectId.Null; } - } - - /// - /// 序列化_写入json - /// - public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) - { - if (value is ObjectId id) - writer.WriteValue(id == ObjectId.Null ? 0 : id.Handle.Value); - } -} -#else -/* - * 参考 https://developer.aliyun.com/article/51053 - * json类型转换器,使用方法: - * public static string SerializeToJson(object obj) - * { - * JavaScriptSerializer serializer = new(); - * serializer.RegisterConverters(new[] { new ObjectIdConverter() }); - * return serializer.Serialize(obj); - * } - * - * public static T DeserializeJson(string jsonString) - * { - * JavaScriptSerializer serializer = new(); - * serializer.RegisterConverters(new[] { new ObjectIdConverter() }); - * return serializer.Deserialize(jsonString); - * } - */ -/// -/// json转换器 -/// -public class ObjectIdConverter : JavaScriptConverter -{ - const string _id = nameof(ObjectId); - - /// - /// 约束类型 - /// - public override IEnumerable SupportedTypes => new[] { typeof(ObjectId) }; - - /// - /// 序列化_写入json - /// - public override IDictionary Serialize(object obj, JavaScriptSerializer serializer) - { - if (obj is not ObjectId id) - return null!; - - Dictionary result = new() - { - { _id, id == ObjectId.Null ? 0 : id.Handle.Value } - }; - return result; - } - - /// - /// 反序列化_把字符串生成对象 - /// - public override object Deserialize(IDictionary dictionary, Type type, JavaScriptSerializer serializer) - { - //if (dictionary == null) - // throw new ArgumentNullException(nameof(dictionary)); - dictionary.NotNull(nameof(dictionary)); - if (type != typeof(ObjectId)) - return null!; - - ObjectId id = ObjectId.Null; - try - { - if (dictionary.TryGetValue(_id, out object va)) - { - using DBTrans tr = new(); - id = tr.GetObjectId(va.ToString()); - } - } - catch { } - return id; - } -} -#endif - -#endif \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjEx.cs deleted file mode 100644 index 2a21c3c..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjEx.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace IFoxCAD.Cad; - -/// -/// 对象扩展类 -/// -public static class ObjEx -{ - /// - /// cad的打印 - /// - /// - public static void Print(this object obj) - { - Acap.DocumentManager.MdiActiveDocument?.Editor.WriteMessage($"\n{obj}\n"); - } - -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs deleted file mode 100644 index ebfa130..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/ObjectIdEx.cs +++ /dev/null @@ -1,141 +0,0 @@ -namespace IFoxCAD.Cad; - -/// -/// 对象id扩展类 -/// -public static class ObjectIdEx -{ - #region GetObject - /// - /// 获取指定类型对象 - /// - /// 指定的泛型 - /// 对象id - /// 打开模式 - /// 是否打开已删除对象,默认为不打开 - /// 是否打开锁定图层对象,默认为不打开 - /// 指定类型对象 - public static T? GetObject(this ObjectId id, - OpenMode openMode = OpenMode.ForRead, - bool openErased = false, - bool openLockedLayer = false) where T : DBObject - { - var tr = DBTrans.GetTopTransaction(id.Database); - return tr.GetObject(id, openMode, openErased, openLockedLayer); - } - - /// - /// 获取指定类型对象集合 - /// - /// 指定的泛型 - /// 对象id集合 - /// 打开模式 - /// 是否打开已删除对象,默认为不打开 - /// 是否打开锁定图层对象,默认为不打开 - /// 指定类型对象集合 - [System.Diagnostics.DebuggerStepThrough] - public static IEnumerable GetObject(this IEnumerable ids, - OpenMode openMode = OpenMode.ForRead, - bool openErased = false, - bool openLockedLayer = false) where T : DBObject - { - var rxc = RXObject.GetClass(typeof(T)); - return ids.Where(id => id.ObjectClass.IsDerivedFrom(rxc)) - .Select(id => id.GetObject(openMode, openErased, openLockedLayer)) - .OfType(); - } - /// - /// 获取指定类型对象集合 - /// - /// 指定的泛型 - /// 对象id集合 - /// 打开模式 - /// 是否打开已删除对象,默认为不打开 - /// 是否打开锁定图层对象,默认为不打开 - /// 指定类型对象集合 - [System.Diagnostics.DebuggerStepThrough] - public static IEnumerable GetObject(this ObjectIdCollection ids, - OpenMode openMode = OpenMode.ForRead, - bool openErased = false, - bool openLockedLayer = false) where T : DBObject - { - return ids.Cast().GetObject(openMode, openErased, openLockedLayer); - } - /// - /// 返回符合类型的对象id - /// - /// 对象类型 - /// 对象id集合 - /// 精确匹配 - /// 对象id集合 - public static IEnumerable OfType(this IEnumerable ids, bool exactMatch = false) where T : DBObject - { - var rxc = RXClass.GetClass(typeof(T)); - if (exactMatch) - { - var dxfName = rxc.DxfName; - return ids.Where(id => id.ObjectClass.DxfName == dxfName); - } - else - { - return ids.Where(id => id.ObjectClass.IsDerivedFrom(rxc)); - } - } - #endregion GetObject - - /// - /// 根据对象句柄字符串获取对象Id - /// - /// 数据库 - /// 句柄字符串 - /// 对象的ObjectId - public static ObjectId GetObjectId(this Database db, string handleString) - { - return db.GetObjectId(handleString.ConvertToHandle()); - } - /// - /// 根据对象句柄获取对象ObjectId - /// - /// 数据库 - /// 句柄 - /// 对象的ObjectId - public static ObjectId GetObjectId(this Database db, Handle? handle) - { - return handle is not null && db.TryGetObjectId(handle.Value, out ObjectId id) ? id : ObjectId.Null; - } - /// - /// 句柄字符串转句柄 - /// - /// 句柄字符串 - /// 句柄 - public static Handle? ConvertToHandle(this string handleString) - { - return long.TryParse(handleString, System.Globalization.NumberStyles.HexNumber, null, out long l) ? new Handle(l) : null; - } - /// - /// id是否有效,未被删除 - /// - /// 对象id - /// id有效返回 ,反之返回 - public static bool IsOk(this ObjectId id) - { - return id is { IsNull: false, IsValid: true, IsErased: false, IsEffectivelyErased: false, IsResident: true }; - } - - /// - /// 删除id代表的对象 - /// - /// 对象id - public static void Erase(this ObjectId id) - { - if (id.IsOk()) - { - var ent = id.GetObject()!; - using (ent.ForWrite()) - { - ent.Erase(); - }// 第一种读写权限自动转换写法 - // Env.Editor.Regen(); - } - } -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/PointEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/PointEx.cs deleted file mode 100644 index 87fc6bf..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/PointEx.cs +++ /dev/null @@ -1,247 +0,0 @@ -namespace IFoxCAD.Cad; -/// -/// 点 -/// -public static class PointEx -{ - /// - /// 获取点的hash字符串,同时可以作为pt的字符串表示 - /// - /// 点 - /// 指示计算几维坐标的标志,1为计算x,2为计算x,y,其他为计算x,y,z - /// 保留的小数位数 - /// hash字符串 - public static string GetHashString(this Point3d pt, int xyz = 3, int decimalRetain = 6) - { - var de = $"f{decimalRetain}"; - return xyz switch - { - 1 => $"({pt.X.ToString(de)})", - 2 => $"({pt.X.ToString(de)},{pt.Y.ToString(de)})", - _ => $"({pt.X.ToString(de)},{pt.Y.ToString(de)},{pt.Z.ToString(de)})" - }; - } - - // 为了频繁触发所以弄个缓存 - static Plane? _PlaneCache; - /// - /// 两点计算弧度范围0到2Pi - /// - /// 起点 - /// 终点 - /// 方向 - /// 弧度值 - public static double GetAngle(this Point3d startPoint, Point3d endPoint, Vector3d? direction = null) - { - if (direction != null) - _PlaneCache = new Plane(new Point3d(), direction.Value); - if (_PlaneCache == null) - _PlaneCache = new Plane(new Point3d(), Vector3d.ZAxis); - return startPoint.GetVectorTo(endPoint).AngleOnPlane(_PlaneCache); - } - /// - /// 两点计算弧度范围0到2Pi - /// - /// 起点 - /// 终点 - /// 弧度值 - public static double GetAngle(this Point2d startPoint, Point2d endPoint) - { - return startPoint.GetVectorTo(endPoint).Angle; - } - - /// - /// 获取中点 - /// - /// - /// - /// - public static Point2d GetMidPointTo(this Point2d a, Point2d b) - { - // (p1 + p2) / 2; // 溢出风险 - return new Point2d(a.X * 0.5 + b.X * 0.5, - a.Y * 0.5 + b.Y * 0.5); - } - - /// - /// 获取两个点之间的中点 - /// - /// 第一点 - /// 第二点 - /// 返回两个点之间的中点 - public static Point3d GetMidPointTo(this Point3d pt1, Point3d pt2) - { - return new(pt1.X * 0.5 + pt2.X * 0.5, - pt1.Y * 0.5 + pt2.Y * 0.5, - pt1.Z * 0.5 + pt2.Z * 0.5); - } - /// - /// Z值归零 - /// - /// 点 - /// 新点 - public static Point3d Z20(this Point3d point) - { - return new Point3d(point.X, point.Y, 0); - } - - /// - /// 将三维点转换为二维点 - /// - /// 三维点 - /// 二维点 - public static Point2d Point2d(this Point3d pt) - { - return new(pt.X, pt.Y); - } - /// - /// 将三维点集转换为二维点集 - /// - /// 三维点集 - /// 二维点集 - public static IEnumerable Point2d(this IEnumerable pts) - { - return pts.Select(pt => pt.Point2d()); - } - /// - /// 将二维点转换为三维点 - /// - /// 二维点 - /// Z值 - /// 三维点 - public static Point3d Point3d(this Point2d pt, double z = 0) - { - return new(pt.X, pt.Y, z); - } - - - - /// - /// 根据世界坐标计算用户坐标 - /// - /// 基点世界坐标 - /// 基点用户坐标 - /// 目标世界坐标 - /// 坐标网旋转角,按x轴正向逆时针弧度 - /// 目标用户坐标 - public static Point3d TransPoint(this Point3d basePt, Point3d userPt, Point3d transPt, double ang) - { - var transMat = Matrix3d.Displacement(userPt - basePt); - var roMat = Matrix3d.Rotation(-ang, Vector3d.ZAxis, userPt); - return transPt.TransformBy(roMat * transMat); - } - /// - /// 计算指定距离和角度的点 - /// - /// 本函数仅适用于x-y平面 - /// 基点 - /// 角度,x轴正向逆时针弧度 - /// 距离 - /// 目标点 - public static Point3d Polar(this Point3d pt, double ang, double len) - { - return pt + Vector3d.XAxis.RotateBy(ang, Vector3d.ZAxis) * len; - } - /// - /// 计算指定距离和角度的点 - /// - /// 本函数仅适用于x-y平面 - /// 基点 - /// 角度,x轴正向逆时针弧度 - /// 距离 - /// 目标点 - public static Point2d Polar(this Point2d pt, double ang, double len) - { - return pt + Vector2d.XAxis.RotateBy(ang) * len; - } - /// http://www.lee-mac.com/bulgeconversion.html - /// - /// 求凸度,判断三点是否一条直线上 - /// - /// 圆弧起点 - /// 圆弧腰点 - /// 圆弧尾点 - /// 容差 - /// 逆时针为正,顺时针为负 - public static double GetArcBulge(this Point2d arc1, Point2d arc2, Point2d arc3, double tol = 1e-10) - { - var dStartAngle = arc2.GetAngle(arc1); - var dEndAngle = arc2.GetAngle(arc3); - // 求的P1P2与P1P3夹角 - var talAngle = (Math.PI - dStartAngle + dEndAngle) / 2; - // 凸度==拱高/半弦长==拱高比值/半弦长比值 - // 有了比值就不需要拿到拱高值和半弦长值了,因为接下来是相除得凸度 - var bulge = Math.Sin(talAngle) / Math.Cos(talAngle); - - switch (bulge) - { - // 处理精度 - case > 0.9999 and < 1.0001: - bulge = 1; - break; - case < -0.9999 and > -1.0001: - bulge = -1; - break; - default: - { - if (Math.Abs(bulge) < tol) - bulge = 0; - break; - } - } - return bulge; - } - /// - /// 求两点在Z平面的距离 - /// - /// 点1 - /// 点2 - /// 距离 - public static double Distance2dTo(this Point3d pt1, Point3d pt2) - { - return new Vector2d(pt2.X - pt1.X, pt2.Y - pt1.Y).Length; - } - - #region 首尾相连 - /// - /// 首尾相连 - /// - [System.Diagnostics.DebuggerStepThrough] - public static void End2End(this Point2dCollection ptcol) - { - ArgumentNullEx.ThrowIfNull(ptcol); - - if (ptcol.Count == 0 || ptcol[0].Equals(ptcol[^1]))// 首尾相同直接返回 - return; - - // 首尾不同,去加一个到最后 - var lst = new Point2d[ptcol.Count + 1]; - for (int i = 0; i < ptcol.Count; i++) - lst[i] = ptcol[i]; - lst[^1] = lst[0]; - - ptcol.Clear(); - ptcol.AddRange(lst); - } - /// - /// 首尾相连 - /// - [System.Diagnostics.DebuggerStepThrough] - public static void End2End(this Point3dCollection ptcol) - { - ArgumentNullEx.ThrowIfNull(ptcol); - if (ptcol.Count == 0 || ptcol[0].Equals(ptcol[^1]))// 首尾相同直接返回 - return; - - // 首尾不同,去加一个到最后 - var lst = new Point3d[ptcol.Count + 1]; - for (int i = 0; i < ptcol.Count; i++) - lst[i] = ptcol[i]; - lst[^1] = lst[0]; - - ptcol.Clear(); - for (int i = 0; i < lst.Length; i++) - ptcol.Add(lst[i]); - } - #endregion -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/RedrawEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/RedrawEx.cs deleted file mode 100644 index 059b2a6..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/RedrawEx.cs +++ /dev/null @@ -1,200 +0,0 @@ -namespace IFoxCAD.Cad; -/// -/// 亮显模式 -/// -[Flags] -public enum BrightEntity : int -{ - /// - /// 块更新 - /// - RecordGraphicsModified = 1, - /// - /// 标注更新 - /// - RecomputeDimensionBlock = 2, - /// - /// 重画 - /// - Draw = 4, - /// - /// 亮显 - /// - Highlight = 8, - /// - /// 亮显取消 - /// - Unhighlight = 16, - /// - /// 显示图元 - /// - VisibleTrue = 32, - /// - /// 隐藏图元 - /// - VisibleFalse = 64, - /// - /// 平移更新,可以令ctrl+z撤回时候保证刷新 - /// - MoveZero = 128, -} -/// -/// 刷新模式 -/// -[Flags] -public enum BrightEditor : int -{ - /// - /// 刷新屏幕,图元不生成(例如块还是旧的显示) - /// - UpdateScreen = 1, - /// - /// 刷新全图 - /// - Regen = 2, - /// - /// 清空选择集 - /// - SelectionClean = 4, - /// - /// 视口外 - /// - ViewportsFrom = 8, - /// - /// 视口内 - /// - ViewportsIn = 16, -} -/// -/// 重绘扩展 -/// -public static class RedrawEx -{ - /// - /// 刷新屏幕 - /// - /// 编辑器 - /// 图元 - public static void Redraw(this Editor ed, Entity? ent = null) - { - using (ent?.ForWrite()) - { - // 刷新图元 - ent?.Redraw(BrightEntity.Draw | - BrightEntity.RecordGraphicsModified | - BrightEntity.RecomputeDimensionBlock | - BrightEntity.MoveZero); - // 刷新 - ed.Redraw(BrightEditor.UpdateScreen); - } - - - /* - * 我发现命令加 CommandFlags.Redraw 就不需要以下处理了: - * 数据库事务和文档事务不一样,文档事务有刷新函数. - * var doc = Acap.DocumentManager.MdiActiveDocument; - * var ed = doc.Editor; - * var tm = doc.TransactionManager; - * tm.QueueForGraphicsFlush();// 如果在最外层事务结束之前需要更新图形,此句把目前为止所做的更改放入 刷新队列 - * tm.FlushGraphics(); // 将当前 刷新队列 的图形提交到显示器 - * ed.UpdateScreen(); // 仅刷新屏幕,图元不生成(例如块还是旧的显示) - */ - var dm = Acap.DocumentManager; - var doc = dm.MdiActiveDocument; - var tm = doc.TransactionManager; - tm.QueueForGraphicsFlush(); - tm.FlushGraphics(); - - // acad2014及以上要加,立即处理队列上面的消息 - System.Windows.Forms.Application.DoEvents(); - } - - /// - /// 刷新屏幕 - /// - /// 编辑器 - /// 更新的方式 - public static void Redraw(this Editor ed, BrightEditor bright) - { - if ((bright & BrightEditor.UpdateScreen) == BrightEditor.UpdateScreen) - { - // 两个函数底层差不多 - // Acap.UpdateScreen(); - ed.UpdateScreen(); - } - - if ((bright & BrightEditor.Regen) == BrightEditor.Regen) - ed.Regen(); - - if ((bright & BrightEditor.SelectionClean) == BrightEditor.SelectionClean) - ed.SetImpliedSelection(new ObjectId[0]); - - if ((bright & BrightEditor.ViewportsFrom) == BrightEditor.ViewportsFrom) - ed.UpdateTiledViewportsFromDatabase(); // 更新视口外 - - if ((bright & BrightEditor.ViewportsIn) == BrightEditor.ViewportsIn) - ed.UpdateTiledViewportsInDatabase(); // 更新视口内 - } - - /// - /// 更改图元显示 - /// - /// 图元,调用时候图元必须提权 - /// 更新的方式 - public static void Redraw(this Entity ent, BrightEntity bright) - { - // 调用时候图元必须提权,参数true表示关闭图元后进行UpData,实现局部刷新块. - if ((bright & BrightEntity.RecordGraphicsModified) == BrightEntity.RecordGraphicsModified) - ent.RecordGraphicsModified(true); - - if ((bright & BrightEntity.RecomputeDimensionBlock) == BrightEntity.RecomputeDimensionBlock) - if (ent is Dimension dim) - dim.RecomputeDimensionBlock(true); - - if ((bright & BrightEntity.Draw) == BrightEntity.Draw) - ent.Draw(); - - if ((bright & BrightEntity.Highlight) == BrightEntity.Highlight) - ent.Highlight(); - - if ((bright & BrightEntity.Unhighlight) == BrightEntity.Unhighlight) - ent.Unhighlight(); - - if ((bright & BrightEntity.VisibleTrue) == BrightEntity.VisibleTrue) - ent.Visible = true; - - if ((bright & BrightEntity.VisibleFalse) == BrightEntity.VisibleFalse) - ent.Visible = false; - - // 戴耀辉: - // 删除块内图元的时候需要刷新块, - // 用 RecordGraphicsModified 显示是没有问题, - // 但是 ctrl+z 撤销会有显示问题, - // 所以平移0可以在撤回数据库的时候刷新指定图元 - if ((bright & BrightEntity.MoveZero) == BrightEntity.MoveZero) - ent.Move(Point3d.Origin, Point3d.Origin); - } - - - #region 实体刷新 - /// - /// 刷新实体显示 - /// - /// 实体对象 - [Obsolete("此处已经被RedrawEx代替")] - public static void Flush(this Entity entity) - { - var tr = DBTrans.GetTop(entity.Database); - entity.RecordGraphicsModified(true); - tr.Transaction.TransactionManager.QueueForGraphicsFlush(); - tr.Document?.TransactionManager.FlushGraphics(); - } - - /// - /// 刷新实体显示 - /// - /// 实体id - [Obsolete("此处已经被RedrawEx代替")] - public static void Flush(this ObjectId id) => Flush(id.GetObject()!); - #endregion -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SelectionSetEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SelectionSetEx.cs deleted file mode 100644 index a43b803..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SelectionSetEx.cs +++ /dev/null @@ -1,114 +0,0 @@ - - -namespace IFoxCAD.Cad; - -/// -/// 选择集扩展类 -/// -public static class SelectionSetEx -{ - #region 获取对象id - /// - /// 从选择集中获取对象id - /// - /// 图元类型 - /// 选择集 - /// 已选择的对象id集合 - [System.Diagnostics.DebuggerStepThrough] - public static IEnumerable GetObjectIds(this SelectionSet ss) where T : Entity - { - var rxc = RXObject.GetClass(typeof(T)); - - return ss.GetObjectIds() - .Where(id => id.ObjectClass.IsDerivedFrom(rxc)); - } - - /// - /// 将选择集的对象按类型分组 - /// - /// 选择集 - /// 分组后的类型/对象id集合 - [System.Diagnostics.DebuggerStepThrough] - public static IEnumerable> GetObjectIdGroup(this SelectionSet ss) - { - return ss.GetObjectIds() - .GroupBy(id => id.ObjectClass.DxfName); - } - #endregion - - #region 获取实体对象 - - /// - /// 获取指定类型图元 - /// - /// 指定类型 - /// 选择集 - /// 打开模式 - /// 是否打开已删除对象,默认为不打开 - /// 是否打开锁定图层对象,默认为不打开 - /// 图元集合 - [System.Diagnostics.DebuggerStepThrough] - public static IEnumerable GetEntities(this SelectionSet? ss, - OpenMode openMode = OpenMode.ForRead, - bool openErased = false, - bool openLockedLayer = false) where T : Entity - { - return ss?.GetObjectIds() - .Select(id => id.GetObject(openMode, openErased, openLockedLayer)) - .OfType() ?? []; - } - #endregion - - #region ForEach - /// - /// 遍历选择集 - /// - /// 指定图元类型 - /// 选择集 - /// 处理函数;(图元) - /// 打开模式 - /// 是否打开已删除对象,默认为不打开 - /// 是否打开锁定图层对象,默认为不打开 - [System.Diagnostics.DebuggerStepThrough] - public static void ForEach(this SelectionSet ss, - Action action, - OpenMode openMode = OpenMode.ForRead, - bool openErased = false, - bool openLockedLayer = false) where T : Entity - { - ForEach(ss, (ent, _) => - { - action.Invoke(ent); - }, openMode, openErased, openLockedLayer); - } - - /// - /// 遍历选择集 - /// - /// 指定图元类型 - /// 选择集 - /// 处理函数;(图元,终止方式) - /// 打开模式 - /// 是否打开已删除对象,默认为不打开 - /// 是否打开锁定图层对象,默认为不打开 - /// - [System.Diagnostics.DebuggerStepThrough] - public static void ForEach(this SelectionSet ss, - Action action, - OpenMode openMode = OpenMode.ForRead, - bool openErased = false, - bool openLockedLayer = false) where T : Entity - { - ArgumentNullEx.ThrowIfNull(action); - - LoopState state = new(); - var ents = ss.GetEntities(openMode, openErased, openLockedLayer); - foreach (var ent in ents) - { - action.Invoke(ent, state); - if (!state.IsRun) - break; - } - } - #endregion -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SingleKeyWordHook.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SingleKeyWordHook.cs deleted file mode 100644 index 2c9e969..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SingleKeyWordHook.cs +++ /dev/null @@ -1,180 +0,0 @@ -using Keys = System.Windows.Forms.Keys; -namespace IFoxCAD.Cad; -/// -/// 关键字不需要空格钩子 -/// By DYH 20230508 -/// -public class SingleKeyWordHook : IDisposable -{ - #region 私有字段 - /// - /// 关键字合集 - /// - private readonly HashSet _keyWords; - private bool _isResponsed; - private bool _working; - private Keys _key; - private readonly bool _escapeMode; - #endregion - - #region 公共属性 - /// - /// 上一个触发的关键字 - /// - public Keys Key => _key; - /// - /// 上一个触发的关键字字符串 - /// - public string StringResult => _key.ToString().ToUpper(); - /// - /// 是否响应了 - /// - public bool IsResponsed => _isResponsed && _working; - #endregion - - #region 构造 - /// - /// 单字母关键字免输回车钩子 - /// - /// 使用esc(填false则使用回车) - public SingleKeyWordHook(bool escapeMode = true) - { - _isDisposed = false; - _isResponsed = false; - _keyWords = new HashSet(); - _key = Keys.None; - _working = true; - _escapeMode = escapeMode; - Acap.PreTranslateMessage -= Acap_PreTranslateMessage; - Acap.PreTranslateMessage += Acap_PreTranslateMessage; - } - #endregion - - #region 方法 - /// - /// 添加Keys - /// - /// Keys集合 - public void AddKeys(params Keys[] values) => values.ForEach(value => _keyWords.Add(value)); - /// - /// 添加Keys - /// - /// 关键字集合 - public void AddKeys(KeywordCollection keywordCollection) - { - foreach (Keyword item in keywordCollection) - { - if (item.LocalName.Length == 1) - { - Keys k = (Keys)item.LocalName[0]; - _keyWords.Add(k); - } - } - } - /// - /// 移除Keys - /// - /// Keys集合 - public void Remove(params Keys[] values) => values.ForEach(value => _keyWords.Remove(value)); - /// - /// 清空Keys - /// - public void Clear() => _keyWords.Clear(); - /// - /// 复位响应状态,每个循环开始时使用 - /// - public void Reset() - { - _isResponsed = false; - } - /// - /// 暂停工作 - /// - public void Pause() - { - _working = false; - } - /// - /// 开始工作 - /// - public void Working() - { - _working = true; - } - #endregion - - #region 事件 - private void Acap_PreTranslateMessage(object sender, PreTranslateMessageEventArgs e) - { - if (!_working || e.Message.message != 256) return; - var tempKey = IntPtr.Size == 4 ? (Keys)e.Message.wParam.ToInt32() : (Keys)e.Message.wParam.ToInt64(); - bool contains = _keyWords.Contains(tempKey); - if (contains || tempKey == Keys.ProcessKey) - { - // 标记为true,表示此按键已经被处理,Windows不会再进行处理 - if (_escapeMode) - { - e.Handled = true; - } - if (contains) - _key = tempKey; - if (!_isResponsed) - { - // 此bool是防止按键被长按时出错 - _isResponsed = true; - // 这里选择发送回车或者ESC//ESC稳妥一些,但是要promptResult的判断顺序 - KeyBoardSendKey(_escapeMode ? Keys.Escape : Keys.Enter); - } - } - } - #endregion - - #region Dispose - private bool _isDisposed; - /// - /// 已经销毁 - /// - public bool IsDisposed => _isDisposed; - /// - /// - /// - /// - protected virtual void Dispose(bool disposing) - { - if (!_isDisposed) - { - if (disposing) - { - Acap.PreTranslateMessage -= Acap_PreTranslateMessage; - _keyWords.Clear(); - } - _isDisposed = true; - } - } - /// - /// - /// - public void Dispose() - { - Dispose(disposing: true); - GC.SuppressFinalize(this); - } - #endregion - - #region 静态方法 - /// - /// 发送按键 - /// - /// - /// - /// - /// - private static void KeyBoardSendKey(Keys key, byte bScan = 0, uint dwFlags = 0, uint dwExtraInfo = 0) - { - keybd_event(key, bScan, dwFlags, dwExtraInfo); - keybd_event(key, bScan, 2, dwExtraInfo); - } - [DllImport("user32.dll", EntryPoint = "keybd_event", SetLastError = true)] - private static extern void keybd_event(Keys bVk, byte bScan, uint dwFlags, uint dwExtraInfo); - #endregion -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableEx.cs deleted file mode 100644 index 7db088c..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableEx.cs +++ /dev/null @@ -1,368 +0,0 @@ -namespace IFoxCAD.Cad; - -/// -/// 符号表类扩展函数 -/// -public static class SymbolTableEx -{ - #region 图层表 - /// - /// 添加图层 - /// - /// 图层符号表 - /// 图层名 - /// 图层颜色 - /// 图层id - public static ObjectId Add(this SymbolTable table, string name, Color color) - { - return table.Add(name, lt => lt.Color = color); - } - /// - /// 添加图层 - /// - /// 图层符号表 - /// 图层名 - /// 图层颜色索引值 - /// 图层id - public static ObjectId Add(this SymbolTable table, string name, int colorIndex) - { - colorIndex %= 257;// 防止输入的颜色超出256 - colorIndex = Math.Abs(colorIndex);// 防止负数 - return table.Add(name, lt => lt.Color = Color.FromColorIndex(ColorMethod.ByColor, (short)colorIndex)); - } - /// - /// 更改图层名 - /// - /// 图层符号表 - /// 旧图层名 - /// 新图层名 - public static ObjectId Rename(this SymbolTable table, string oldName, string newName) - { - if (!table.Has(oldName)) - return ObjectId.Null; - - table.Change(oldName, layer => { - layer.Name = newName; - }); - return table[newName]; - } - /// - /// 删除图层 - /// - /// 层表 - /// 图层名 - /// 成功返回 ,失败返回 - public static bool Delete(this SymbolTable table, string name) - { - if (name == "0" || name == "Defpoints" || !table.Has(name) || table[name] == table.Database.Clayer) - return false; - - table.CurrentSymbolTable.GenerateUsageData(); - var ltr = table.GetRecord(name); - if (ltr is null) - return false; - - if (ltr.IsUsed) - return false; - using (ltr.ForWrite()) - ltr.Erase(); - return true; - } - #endregion - - #region 块表 - /// - /// 添加块定义 - /// - /// 块表 - /// 块名 - /// 对所添加块表的委托n - /// 添加图元的委托 - /// 添加属性定义的委托 - /// 块定义id - /// TODO: 需要测试匿名块等特殊的块是否能定义 - public static ObjectId Add(this SymbolTable table, - string name, - Action? action = null, - Func>? ents = null, - Func>? attdef = null) - { - return table.Add(name, btr => { - action?.Invoke(btr); - - var entsres = ents?.Invoke(); - if (entsres is not null) - btr.AddEntity(entsres); - - var adddefres = attdef?.Invoke(); - if (adddefres is not null) - btr.AddEntity(adddefres); - }); - } - /// - /// 添加块定义 - /// - /// 块表 - /// 块名 - /// 图元 - /// 属性定义 - /// - public static ObjectId Add(this SymbolTable table, - string name, - IEnumerable? ents = null, - IEnumerable? attdef = null) - { - return table.Add(name, btr => { - if (ents is not null) - btr.AddEntity(ents); - if (attdef is not null) - btr.AddEntity(attdef); - }); - } - - /// - /// 添加块定义 - /// - /// 块表 - /// 块名 - /// 图元(包括属性) - /// - public static ObjectId Add(this SymbolTable table, string name, params Entity[] ents) - { - return table.Add(name, null, () => ents); - } - - /// - /// 添加属性到块定义 - /// - /// 块表 - /// 块定义id - /// 属性列表 - public static void AddAttsToBlocks(this SymbolTable table, - ObjectId id, - List atts) - { - List attTags = []; - table.Change(id, btr => - { - btr.GetEntities() - .ForEach(def => attTags.Add(def.Tag.ToUpper())); - - foreach (var t in atts.Where(t => !attTags.Contains(t.Tag.ToUpper()))) - btr.AddEntity(t); - }); - } - /// - /// 添加属性到块定义 - /// - /// 块表 - /// 块定义名字 - /// 属性列表 - public static void AddAttsToBlocks(this SymbolTable table, - string name, - List atts) - { - List attTags = []; - table.Change(name, btr => - { - btr.GetEntities() - .ForEach(def => attTags.Add(def.Tag.ToUpper())); - - foreach (var t in atts.Where(t => !attTags.Contains(t.Tag.ToUpper()))) - btr.AddEntity(t); - }); - } - - /// - /// 从文件中获取块定义 - /// - /// 块表 - /// 文件名 - /// 是否覆盖 - /// 块定义Id - public static ObjectId GetBlockFrom(this SymbolTable table, string fileName, bool over) - { - - var blkdefname = SymbolUtilityServices.GetSymbolNameFromPathName(fileName, "dwg"); -#if acad - blkdefname = SymbolUtilityServices.RepairSymbolName(blkdefname, false); -#endif - var id = table[blkdefname]; - var has = id != ObjectId.Null; - - /* 每次看这里都要反应一阵 - 如果已经有这个id,并且要覆盖,或者没有这个id就执行下面的语句,不然就直接返回id - 其实就是如果有这个id,并且不覆盖,就直接返回,其他的情况都需要重新插入 - 所以原代码可以修改 - if (has && over || !has) - { - using Database db = new(false, true); - db.ReadDwgFile(fileName, FileShare.Read, true, null); - db.CloseInput(true); - id = table.Database.Insert(BlockTableRecord.ModelSpace, blkdefname, db, false); - - return id; - } */ - - if (has is true && over is false) - { - return id; - } - using Database db = new(false, true); - db.ReadDwgFile(fileName, FileShare.Read, true, null); - db.CloseInput(true); - id = table.Database.Insert(BlockTableRecord.ModelSpace, blkdefname, db, false); - return id; - } - - - - /// - /// 从文件中获取块定义 - /// - /// 块表 - /// 文件名 - /// 块定义名 - /// 是否覆盖 - /// 块定义Id - public static ObjectId GetBlockFrom(this SymbolTable table, - string fileName, - string blockName, - bool over) - { - return table.GetRecordFrom(t => t.BlockTable, fileName, blockName, over); - } - #endregion - - - #region 线型表 - /// - /// 添加线型 - /// - /// 线型表 - /// 线型名 - /// 线型说明 - /// 线型长度 - /// 笔画长度数组 - /// 线型id - public static ObjectId Add(this SymbolTable table, string name, string description, double length, double[] dash) - { - return table.Add( - name, - ltt => { - ltt.AsciiDescription = description; - ltt.PatternLength = length; // 线型的总长度 - ltt.NumDashes = dash.Length; // 组成线型的笔画数目 - for (int i = 0; i < dash.Length; i++) - { - ltt.SetDashLengthAt(i, dash[i]); - } - // ltt.SetDashLengthAt(0, 0.5); // 0.5个单位的划线 - // ltt.SetDashLengthAt(1, -0.25); // 0.25个单位的空格 - // ltt.SetDashLengthAt(2, 0); // 一个点 - // ltt.SetDashLengthAt(3, -0.25); // 0.25个单位的空格 - } - ); - } - #endregion - - #region 文字样式表 - /// - /// 添加文字样式记录 - /// - /// 文字样式表 - /// 文字样式名 - /// 字体名 - /// 宽度比例 - /// 文字样式Id - public static ObjectId Add(this SymbolTable table, - string textStyleName, - string font, - double xscale = 1.0) - { - return - table.Add( - textStyleName, - tstr => { - tstr.Name = textStyleName; - tstr.FileName = font; - tstr.XScale = xscale; - }); - } - /// - /// 添加文字样式记录 - /// - /// 文字样式表 - /// 文字样式名 - /// 字体名枚举 - /// 宽度比例 - /// 文字样式Id - public static ObjectId Add(this SymbolTable table, - string textStyleName, - FontTTF fontTTF, - double xscale = 1.0) - { - return table.Add(textStyleName, fontTTF.GetDesc(), xscale); - } - - /// - ///

添加文字样式记录,如果存在就默认强制替换

- /// 此函数为了 而设 - ///
- /// 文字样式表 - /// 文字样式名 - /// 字体名 - /// 大字体名 - /// 宽度比例 - /// 高度 - /// 是否强制替换 - /// 文字样式Id - public static ObjectId AddWithChange(this SymbolTable table, - string textStyleName, - string smallFont, - string bigFont = "", - double xScale = 1, - double height = 0, - bool forceChange = true) - { - if (forceChange && table.Has(textStyleName)) - { - table.Change(textStyleName, ttr => { - ttr.FileName = smallFont; - ttr.XScale = xScale; - ttr.TextSize = height; - if (bigFont != string.Empty) - ttr.BigFontFileName = bigFont; - }); - return table[textStyleName]; - } - return table.Add(textStyleName, ttr => { - ttr.FileName = smallFont; - ttr.XScale = xScale; - ttr.TextSize = height; - }); - } - - - #endregion - - #region 注册应用程序表 - - #endregion - - #region 标注样式表 - - #endregion - - #region 用户坐标系表 - - #endregion - - #region 视图表 - - #endregion - - #region 视口表 - - #endregion -} diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs deleted file mode 100644 index 9818df1..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/SymbolTableRecordEx.cs +++ /dev/null @@ -1,354 +0,0 @@ -namespace IFoxCAD.Cad; - -/// -/// 符号表记录扩展类 -/// -public static class SymbolTableRecordEx -{ - #region 块表记录 - - #region 克隆实体id - /// - /// 深度克隆id到块表记录 - /// - /// 0x01 此方法不允许是未添加数据库的图元,因此它是id
- /// 0x02 若为未添加数据库图元,则利用entity.Clone();同时不需要考虑动态块属性,可以使用entity.GetTransformedCopy - ///
- ///
- /// 块表记录 - /// - /// 克隆到当前块表记录,相当于原地克隆
- /// 克隆到目标块表记录内,相当于制作新块 - ///
- /// - /// 图元id集合,注意所有成员都要在同一个空间中 - /// 返回克隆后的id词典 - public static void DeepCloneEx(this BlockTableRecord btr, ObjectIdCollection objIds, IdMapping maoOut) - { - if (objIds is null || objIds.Count == 0) - throw new ArgumentNullException(nameof(objIds)); - - var db = objIds[0].Database; - using (btr.ForWrite()) - { - try - { - db.DeepCloneObjects(objIds, btr.ObjectId, maoOut, false); - - // 不在此提取,为了此函数被高频调用 - // 获取克隆键值对(旧块名,新块名) - // foreach (ObjectId item in blockIds) - // result.Add(mapping[item].Value); - } - catch - { - - } - } - } - /// - /// 深度克隆id到块表记录 - /// - /// 块表记录 - /// 图元id集合 - /// id词典 - public static IdMapping DeepCloneEx(this BlockTableRecord btr, ObjectIdCollection objIds) - { - if (objIds is null || objIds.Count == 0) - throw new ArgumentNullException(nameof(objIds)); - - var db = objIds[0].Database; - IdMapping mapOut = new(); - using (btr.ForWrite()) - { - try - { - db.DeepCloneObjects(objIds, btr.ObjectId, mapOut, false); - - // 不在此提取,为了此函数被高频调用 - // 获取克隆键值对(旧块名,新块名) - // foreach (ObjectId item in blockIds) - // result.Add(mapping[item].Value); - } - catch - { - - } - } - return mapOut; - } - - #endregion - - #region 添加实体 - /// - /// 添加实体对象 - /// - /// 块表记录 - /// 实体 - /// 对象 id - public static ObjectId AddEntity(this BlockTableRecord btr, Entity entity) - { - - ObjectId id; - var tr = DBTrans.GetTopTransaction(btr.Database); - using (btr.ForWrite()) - { - id = btr.AppendEntity(entity); - tr.AddNewlyCreatedDBObject(entity, true); - } - - return id; - } - - /// - /// 添加实体集合 - /// - /// 块表记录 - /// 实体集合 - /// 对象 id 列表 - public static IEnumerable AddEntity(this BlockTableRecord btr, IEnumerable ents) - { - - var tr = DBTrans.GetTopTransaction(btr.Database); - using (btr.ForWrite()) - { - return ents.Select(ent => - { - ObjectId id = btr.AppendEntity(ent); - tr.AddNewlyCreatedDBObject(ent, true); - return id; - }).ToList(); - } - } - - /// - /// 添加多个实体 - /// - /// 块表记录 - /// 实体集合 - /// 对象 id 列表 - public static IEnumerable AddEntity(this BlockTableRecord btr, params Entity[] ents) - { - return btr.AddEntity(ents.ToList()); - } - #endregion - - #region 获取实体/实体id - /// - /// 获取块表记录内的指定类型的实体 - /// (此处不会检查id.IsOk()) - /// - /// 实体类型 - /// 块表记录 - /// 打开模式 - /// 是否打开已删除对象,默认为不打开 - /// 是否打开锁定图层对象,默认为不打开 - /// 实体集合 - public static IEnumerable GetEntities(this BlockTableRecord btr, - OpenMode openMode = OpenMode.ForRead, - bool openErased = false, - bool openLockedLayer = false) where T : Entity - { - var rxc = RXObject.GetClass(typeof(T)); - return - btr - .Cast() - .Where(id => id.ObjectClass.IsDerivedFrom(rxc)) - .Select(id => id.GetObject(openMode, openErased, openLockedLayer)) - .OfType(); - } - - /// - /// 按类型获取实体Id - /// - /// 实体类型 - /// 块表记录 - /// 实体Id集合 - public static IEnumerable GetObjectIds(this BlockTableRecord btr) where T : Entity - { - string dxfName = RXClass.GetClass(typeof(T)).DxfName; - return btr.Cast() - .Where(id => id.ObjectClass.DxfName == dxfName); - } - - /// - /// 按类型获取实体Id的分组 - /// - /// 块表记录 - /// 实体Id分组 - public static IEnumerable> GetObjectIds(this BlockTableRecord btr) - { - return btr.Cast() - .GroupBy(id => id.ObjectClass.DxfName); - } - - - /// - /// 获取绘制顺序表 - /// - /// 块表 - /// 开启方式 - /// 是否打开已删除对象,默认为不打开 - /// 是否打开锁定图层对象,默认为不打开 - /// 绘制顺序表 - public static DrawOrderTable GetDrawOrderTable(this BlockTableRecord btr, - OpenMode openMode = OpenMode.ForRead, - bool openErased = false, - bool openLockedLayer = false) - { - var tr = DBTrans.GetTopTransaction(btr.Database); - return (DrawOrderTable)tr.GetObject(btr.DrawOrderTableId, openMode, openErased, openLockedLayer); - } - #endregion - - #region 插入块参照 - /// - /// 插入块参照 - /// - /// 块表记录 - /// 插入点 - /// 块名 - /// 块插入比例,默认为1 - /// 块插入旋转角(弧度),默认为0 - /// 属性字典{Tag,Value},默认为null - /// 块参照对象id - public static ObjectId InsertBlock(this BlockTableRecord blockTableRecord, Point3d position, - string blockName, - Scale3d scale = default, - double rotation = default, - Dictionary? atts = null) - { - var tr = DBTrans.GetTop(blockTableRecord.Database); - if (!tr.BlockTable.Has(blockName)) - { - tr.Editor?.WriteMessage($"\n不存在名字为{blockName}的块定义。"); - return ObjectId.Null; - } - return blockTableRecord.InsertBlock(position, tr.BlockTable[blockName], scale, rotation, atts); - } - /// - /// 插入块参照 - /// - /// 块表记录 - /// 插入点 - /// 块定义id - /// 块插入比例,默认为1 - /// 块插入旋转角(弧度),默认为0 - /// 属性字典{Tag,Value},默认为null - /// 块参照对象id - public static ObjectId InsertBlock(this BlockTableRecord blockTableRecord, - Point3d position, - ObjectId blockId, - Scale3d scale = default, - double rotation = default, - Dictionary? atts = null) - { - //trans ??= DBTrans.Top.Transaction; - var tr = DBTrans.GetTop(blockTableRecord.Database); - - if (!tr.BlockTable.Has(blockId)) - { - tr.Editor?.WriteMessage($"\n不存在块定义。"); - return ObjectId.Null; - } - - - using var blockref = new BlockReference(position, blockId) - { - ScaleFactors = scale, - Rotation = rotation - }; - var objid = blockTableRecord.AddEntity(blockref); - // 检查块的注释性 - using var ocm = blockTableRecord.Database.ObjectContextManager; - using var occ = ocm.GetContextCollection("ACDB_ANNOTATIONSCALES"); - if (blockref.Annotative == AnnotativeStates.True) - blockref.AddContext(occ.CurrentContext); - - var btr = tr.GetObject(blockref.BlockTableRecord)!; - - if (!btr.HasAttributeDefinitions) return objid; - - var attdefs = btr.GetEntities(); - foreach (var attdef in attdefs) - { - using AttributeReference attref = new(); - attref.SetDatabaseDefaults(); - attref.SetAttributeFromBlock(attdef, blockref.BlockTransform); - attref.Position = attdef.Position.TransformBy(blockref.BlockTransform); - attref.AdjustAlignment(tr.Database); - if (atts is not null && atts.TryGetValue(attdef.Tag, out string str)) - { - attref.TextString = str; - } - - if (blockref.Annotative == AnnotativeStates.True) - attref.AddContext(occ.CurrentContext); - - blockref.AttributeCollection.AppendAttribute(attref); - tr.Transaction.AddNewlyCreatedDBObject(attref, true); - } - - return objid; - } - #endregion - - #endregion - - #region 遍历 -#line hidden // 调试的时候跳过它 - /// - /// 遍历符号表记录,执行委托 - /// - /// 符号表记录 - /// 要运行的委托 - public static void ForEach(this TRecord record, Action task) - where TRecord : SymbolTableRecord, IEnumerable - { - foreach (ObjectId id in record) - task.Invoke(id); - } - - /// - /// 遍历符号表记录,执行委托(允许循环中断) - /// - /// 符号表记录 - /// 要执行的委托 - public static void ForEach(this TRecord record, Action task) - where TRecord : SymbolTableRecord, IEnumerable - { - LoopState state = new();/*这种方式比Action改Func更友好*/ - foreach (ObjectId id in record) - { - task.Invoke(id, state); - if (!state.IsRun) - break; - } - } - - /// - /// 遍历符号表记录,执行委托(允许循环中断,输出索引值) - /// - /// 符号表记录 - /// 要执行的委托 - [System.Diagnostics.DebuggerStepThrough] - public static void ForEach(this TRecord record, Action task) - where TRecord : SymbolTableRecord, IEnumerable - { - //if (task == null) - // throw new ArgumentNullException(nameof(task)); - ArgumentNullEx.ThrowIfNull(task); - int i = 0; - LoopState state = new();/*这种方式比Action改Func更友好*/ - foreach (ObjectId id in record) - { - task.Invoke(id, state, i); - if (!state.IsRun) - break; - i++; - } - } -#line default - #endregion -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Tools.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/Tools.cs deleted file mode 100644 index 17846f6..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/Tools.cs +++ /dev/null @@ -1,164 +0,0 @@ -using static IFoxCAD.Basal.Timer; -namespace IFoxCAD.Cad; -/// -/// 工具类 -/// -public static class Tools -{ - /// - /// 计时器 - /// - [System.Diagnostics.DebuggerStepThrough] - public static void TestTimes2(int count, string message, Action action) - { - System.Diagnostics.Stopwatch watch = new(); - watch.Start(); // 开始监视代码运行时间 - for (var i = 0; i < count; i++) - action.Invoke();// 需要测试的代码 - watch.Stop(); // 停止监视 - var timespan = watch.Elapsed; // 获取当前实例测量得出的总时间 - var time = timespan.TotalMilliseconds; - var name = "毫秒"; - if (timespan.TotalMilliseconds > 1000) - { - time = timespan.TotalSeconds; - name = "秒"; - } - Env.Print($"{message} 代码执行 {count} 次的时间:{time} ({name})"); // 总毫秒数 - } - - /// - /// 计时器 - /// - [System.Diagnostics.DebuggerStepThrough] - public static void TestTimes3(int count, string message, Action action) - { - System.Diagnostics.Stopwatch watch = new(); - watch.Start(); // 开始监视代码运行时间 - for (var i = 0; i < count; i++) - action.Invoke(i);// 需要测试的代码 - watch.Stop(); // 停止监视 - var timespan = watch.Elapsed; // 获取当前实例测量得出的总时间 - var time = timespan.TotalMilliseconds; - var name = "毫秒"; - if (timespan.TotalMilliseconds > 1000) - { - time = timespan.TotalSeconds; - name = "秒"; - } - Env.Print($"{message} 代码执行 {count} 次的时间:{time} ({name})"); // 总毫秒数 - } - - - - /// - /// 纳秒计时器 - /// - [System.Diagnostics.DebuggerStepThrough] - public static void TestTimes(int count, string message, Action action, - TimeEnum timeEnum = TimeEnum.Millisecond) - { - var time = RunTime(() => { - for (var i = 0; i < count; i++) - action.Invoke(); - }, timeEnum); - - var timeNameZn = timeEnum switch - { - TimeEnum.Millisecond => " 毫秒", - TimeEnum.Microsecond => " 微秒", - TimeEnum.Nanosecond => " 纳秒", - _ => " 秒" - }; - - Env.Print($"{message} 代码执行 {count} 次的时间:{time} ({timeNameZn})"); - } - -#if acad - /// - /// 刷新图层状态,在修改图层的锁定或冻结状态后使用 - /// - /// 图层id集合 - public static void RegenLayers(IEnumerable objectIds) - { - var type = Acaop.Version.Major >= 21 - ? Assembly.Load("accoremgd")?.GetType("Autodesk.AutoCAD.Internal.CoreLayerUtilities") - : Assembly.Load("acmgd")?.GetType("Autodesk.AutoCAD.Internal.LayerUtilities"); - var mi = type?.GetMethods().FirstOrDefault(e => e.Name == "RegenLayers"); - var pi = type?.GetProperties().FirstOrDefault(e => e.Name == "RegenPending"); - var regenPending = (int)(pi?.GetValue(null) ?? 0); - mi?.Invoke(null, new object[] { objectIds.ToArray(), regenPending }); - } - - /// - /// 发送气泡通知 - /// - /// 显示的秒数,范围1-10为相应秒数,0为常显 - /// 标题 - /// 内容1 - /// 图标样式 - /// 链接 - /// 链接地址 - /// 内容2 - public static void ShowBubbleWindow(int second, string title, string text, Autodesk.AutoCAD.Windows.IconType iconType = Autodesk.AutoCAD.Windows.IconType.None, string? hyperText = null, string? hyperLink = null, string? text2 = null) - { - Autodesk.AutoCAD.Windows.TrayItem? trayItem = null; - const string name = "IFox"; - var num = Acap.StatusBar.TrayItems.Count; - for (var i = 0; i < num; i++) - { - var ti = Acap.StatusBar.TrayItems[i]; - if (ti.ToolTipText != name) continue; - trayItem = ti; - break; - } - if (trayItem == null) - { - trayItem = new() - { - ToolTipText = name, - Visible = true, - }; - Acap.StatusBar.TrayItems.Add(trayItem); - Acap.StatusBar.Update(); - } - if (second <= 0) second = 0; - else if (second % 10 == 0) second = 10; - else second %= 10; - Acaop.SetSystemVariable("TrayTimeOut", second); - var tibw = new Autodesk.AutoCAD.Windows.TrayItemBubbleWindow - { - IconType = iconType, - Title = title, - Text = text, - HyperText = hyperText, - HyperLink = hyperLink, - Text2 = text2 - }; - Acaop.SetSystemVariable("TRAYICONS", 1); - Acaop.SetSystemVariable("TRAYNOTIFY", 1); - trayItem.Visible = true; - trayItem.ShowBubbleWindow(tibw); - } - - /// - /// 否决双击事件本身的后续操作,在双击事件中使用 - /// - public static void VetoMouseDoubleClickEvent() - { - const string key = "DBLCLKEDIT"; - var value = Acaop.GetSystemVariable(key); - Acaop.SetSystemVariable(key, 0); - IdleAction.Add(() => Acaop.SetSystemVariable(key, value)); - } - /// - /// 获取透明度 - /// - /// cad特性栏透明度值,范围0-100 - /// cad透明度值 - public static Transparency CreateTransparency(int value) - { - return new Transparency(Convert.ToByte(Math.Floor((100 - value) * 2.55))); - } -#endif -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/TransactionEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/TransactionEx.cs deleted file mode 100644 index 698f503..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/TransactionEx.cs +++ /dev/null @@ -1,41 +0,0 @@ -namespace IFoxCAD.Cad; - -/// -/// cad的事务的扩展类 -/// -public static class TransactionEx -{ - /// - /// 根据对象id获取对象 - /// - /// - /// 对象id - /// 打开模式,默认为只读 - /// 是否打开已删除对象,默认为不打开 - /// 是否打开锁定图层对象,默认为不打开 - /// 数据库DBObject对象 - public static DBObject GetObject(this Transaction tr, ObjectId id, - OpenMode openMode = OpenMode.ForRead, - bool openErased = false, - bool openLockedLayer = false) - { - return tr.GetObject(id, openMode, openErased, openLockedLayer); - } - /// - /// 根据对象id获取图元对象 - /// - /// 要获取的图元对象的类型 - /// - /// 对象id - /// 打开模式,默认为只读 - /// 是否打开已删除对象,默认为不打开 - /// 是否打开锁定图层对象,默认为不打开 - /// 图元对象,类型不匹配时抛异常 - public static T? GetObject(this Transaction tr, ObjectId id, - OpenMode openMode = OpenMode.ForRead, - bool openErased = false, - bool openLockedLayer = false) where T : DBObject - { - return tr.GetObject(id, openMode, openErased, openLockedLayer) as T; - } -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ExtensionMethod/XrefEx.cs b/src/CAD/IFox.CAD.Shared/ExtensionMethod/XrefEx.cs deleted file mode 100644 index 09e2104..0000000 --- a/src/CAD/IFox.CAD.Shared/ExtensionMethod/XrefEx.cs +++ /dev/null @@ -1,643 +0,0 @@ -namespace IFoxCAD.Cad; - -#region 参照工厂 -/// -/// 参照绑定模式接口 -/// -public interface IXrefBindModes -{ - /// - /// 卸载 - /// - public void Unload(); - /// - /// 重载 - /// - public void Reload(); - /// - /// 拆离 - /// - public void Detach(); - /// - /// 绑定 - /// - public void Bind(); -} -/// -/// 参照工厂类 -/// -/// -/// 要处理的参照名称,就处理所有 -public class XrefFactory(DBTrans tr, HashSet? xrefNames = null) : IXrefBindModes -{ - #region 私有字段 - readonly DBTrans _tr = tr; - /// - /// 要处理的参照名称,就处理所有 - /// - readonly HashSet? _xrefNames = xrefNames; - #endregion - - #region 公开字段 - /// - /// 解析外部参照:线性引擎
- /// 默认
- /// 时会在cad命令历史打印一些AEC信息,并导致绑定慢一点...具体作用不详
- ///
- public bool UseThreadEngine = false; - /// - /// 解析外部参照:仅处理 Unresolved_未融入(未解析)的参照
- /// 默认 - ///
- public bool DoNewOnly = true; - /// - /// 解析外部参照:包含僵尸参照 - /// - public bool IncludeGhosts = true; - - - /// - /// 绑定模式和双美元符号相关(与cad保持相同的默认)
- /// 为绑定模式,产生双美元; - /// 为插入模式,块重名会以本图覆盖; - ///
- public bool BindOrInsert = false; - /// - /// bind时候是否拆离参照
- /// 默认:学官方的绑定后自动拆离 - ///
- public bool AutoDetach = true; - /// - /// bind时候是否删除被卸载的嵌套参照
- /// 默认 - ///
- public bool EraseNested = true; - /// - /// bind时候控制绑定的符号表:请保持默认
- /// 目前仅推荐用于
- /// 其他项有异常:
- ///
- public SymModes SymModesBind = SymModes.LayerTable; - - #endregion - - - #region 重写 - /// - /// 绑定 - /// - public void Bind() - { - // 此功能有绑定出错的问题 - // db.BindXrefs(xrefIds, true); - - // 绑定后会自动拆离 - // 此功能修补了上面缺失 - DoubleBind(); - } - /// - /// 分离 - /// - public void Detach() - { - using ObjectIdCollection xrefIds = new(); - GetAllXrefNode(xrefIds); - foreach (ObjectId id in xrefIds) - _tr.Database.DetachXref(id); - } - /// - /// 重载 - /// - public void Reload() - { - using ObjectIdCollection xrefIds = new(); - GetAllXrefNode(xrefIds); - if (xrefIds.Count > 0) - _tr.Database.ReloadXrefs(xrefIds); - } - /// - /// 卸载 - /// - public void Unload() - { - using ObjectIdCollection xrefIds = new(); - GetAllXrefNode(xrefIds); - if (xrefIds.Count > 0) - _tr.Database.UnloadXrefs(xrefIds); - } - #endregion - - #region 双重绑定 - /// - /// 获取参照 - /// - /// 返回全部参照id - void GetAllXrefNode(ObjectIdCollection xrefIds) - { - // 储存要处理的参照id - //var xrefIds = new ObjectIdCollection(); - XrefNodeForEach((xNodeName, xNodeId, xNodeStatus, xNodeIsNested) => { - if (XrefNamesContains(xNodeName)) - xrefIds.Add(xNodeId); - }); - } - - bool XrefNamesContains(string xNodeName) - { - // 为空的时候全部加入 || 有内容时候含有目标 - return _xrefNames is null || _xrefNames.Contains(xNodeName); - } - - /// - /// 遍历参照 - /// - /// (参照名,参照块表记录id,参照状态,是否嵌入) - void XrefNodeForEach(Action action) - { - // btRec.IsFromOverlayReference 是覆盖 - // btRec.GetXrefDatabase(true) 外部参照数据库 - - if (action == null) - return; - - // 解析外部参照:此功能不能锁定文档 - _tr.Database.ResolveXrefs(UseThreadEngine, DoNewOnly); - - var xg = _tr.Database.GetHostDwgXrefGraph(IncludeGhosts); - for (int i = 0; i < xg.NumNodes; i++) - { - var xNode = xg.GetXrefNode(i); - if (!xNode.BlockTableRecordId.IsOk()) - continue; - - action.Invoke(xNode.Name, - xNode.BlockTableRecordId, - xNode.XrefStatus, - xNode.IsNested); - } - } - - /// - /// 符号表记录加入容器 - /// - static void AddedxbindIds(ObjectIdCollection xbindXrefsIds, - SymbolTable symbolTable) - where TTable : SymbolTable - where TRecord : SymbolTableRecord, new() - { - symbolTable.ForEach(tabRec => { - if (tabRec.IsResolved) - xbindXrefsIds.Add(tabRec.ObjectId); - }, checkIdOk: true); - } - - - void GetXBindIds(ObjectIdCollection xbindIds) - { - // xbind - // 0x01 它是用来绑其他符号表,绑块表会有异常 - // 0x02 集合若有问题,就会出现eWrongObjectType - //var xbindIds = new ObjectIdCollection(); - - // 起初测试是将九大符号表记录均加入的,但经实测不行...(为什么?存疑) - #region Option1 - if ((SymModesBind & SymModes.LayerTable) == SymModes.LayerTable) - AddedxbindIds(xbindIds, _tr.LayerTable); - - if ((SymModesBind & SymModes.TextStyleTable) == SymModes.TextStyleTable) - AddedxbindIds(xbindIds, _tr.TextStyleTable); - - if ((SymModesBind & SymModes.RegAppTable) == SymModes.RegAppTable) - AddedxbindIds(xbindIds, _tr.RegAppTable); - - if ((SymModesBind & SymModes.DimStyleTable) == SymModes.DimStyleTable) - AddedxbindIds(xbindIds, _tr.DimStyleTable); - - if ((SymModesBind & SymModes.LinetypeTable) == SymModes.LinetypeTable) - AddedxbindIds(xbindIds, _tr.LinetypeTable); - #endregion - - #region Option2 - if ((SymModesBind & SymModes.UcsTable) == SymModes.UcsTable) - AddedxbindIds(xbindIds, _tr.UcsTable); - - if ((SymModesBind & SymModes.ViewTable) == SymModes.ViewTable) - AddedxbindIds(xbindIds, _tr.ViewTable); - - if ((SymModesBind & SymModes.ViewportTable) == SymModes.ViewportTable) - AddedxbindIds(xbindIds, _tr.ViewportTable); - #endregion - } - - void GetBindIds(ObjectIdCollection bindIds) - { - // bind 只绑块表 - //var bindIds = new ObjectIdCollection(); - - _tr.BlockTable.ForEach(btr => { - if (btr.IsLayout) - return; - - // 外部参照 && 已融入 - if (btr.IsFromExternalReference && btr.IsResolved) - bindIds.Add(btr.ObjectId); - }, checkIdOk: true); - } - - /// - /// 获取可以拆离的ids - /// - /// 返回已卸载中含有嵌套的参照,要重载之后才能绑定 - /// 返回未参照中嵌套的参照,直接拆离 - List GetDetachIds(Dictionary nested) - { - // 直接拆离的id - List detachIds = new(); - - // 收集要处理的id - XrefNodeForEach((xNodeName, xNodeId, xNodeStatus, xNodeIsNested) => { - switch (xNodeStatus) - { - case XrefStatus.Unresolved:// 未融入_ResolveXrefs参数2 - break; - case XrefStatus.FileNotFound:// 未融入(未解析)_未找到文件 - break; - case XrefStatus.Unreferenced:// 未参照 - { - // 为空的时候全部加入 || 有内容时候含有目标 - if (XrefNamesContains(xNodeName)) - detachIds.Add(xNodeId); - } - break; - case XrefStatus.Unloaded:// 已卸载 - { - // 为空的时候全部加入 || 有内容时候含有目标 - if (XrefNamesContains(xNodeName)) - { - var btr = _tr.GetObject(xNodeId); - if (btr != null && btr.IsFromExternalReference) - { - if (!xNodeIsNested) - detachIds.Add(xNodeId); - else if (!nested.ContainsKey(xNodeId)) - nested.Add(xNodeId, xNodeName);// 嵌套参照 - } - } - } - break; - case XrefStatus.Resolved:// 已融入_就是可以绑定的 - break; - case XrefStatus.NotAnXref:// 不是外部参照 - break; - default: - break; - } - }); - return detachIds; - } - - /// - /// 双重绑定参照 - /// 参考链接 - /// - void DoubleBind() - { - Dictionary nested = new(); - var detachIds = GetDetachIds(nested); - - // 拆离:未参照的文件 - if (AutoDetach) - { - for (int i = 0; i < detachIds.Count; i++) - _tr.Database.DetachXref(detachIds[i]); - } - // 重载:嵌套参照已卸载了,需要重载之后才能进行绑定 - var keys = nested.Keys; - if (keys.Count > 0) - { - using ObjectIdCollection idc = new(keys.ToArray()); - _tr.Database.ReloadXrefs(idc); - } - - // 绑定:切勿交换,否则会绑定无效 - using ObjectIdCollection bindIds = new(); - using ObjectIdCollection xbindIds = new(); - GetBindIds(bindIds); - GetXBindIds(xbindIds); - if (xbindIds.Count > 0) - _tr.Database.XBindXrefs(xbindIds, BindOrInsert); - if (bindIds.Count > 0) - _tr.Database.BindXrefs(bindIds, BindOrInsert); - - - // 内部删除嵌套参照的块操作 - if (EraseNested) - { - foreach (var item in nested) - { - var name = item.Value; - if (_tr.BlockTable.Has(name)) - _tr.GetObject(_tr.BlockTable[name], OpenMode.ForWrite)? - .Erase(); - } - } - } - #endregion -} - - -/// -/// 参照扩展 -/// -public static class XrefEx -{ - /// - /// 外部参照工厂 - /// - /// - /// 处理参照的枚举 - /// 要处理的参照名称,就处理所有 - public static void XrefFactory(this DBTrans tr, - XrefModes xrefModes, - HashSet? xrefNames = null) - { - var xf = new XrefFactory(tr, xrefNames); - tr.Task(() => { - switch (xrefModes) - { - case XrefModes.Unload: - xf.Unload(); - break; - case XrefModes.Reload: - xf.Reload(); - break; - case XrefModes.Detach: - xf.Detach(); - break; - case XrefModes.Bind: - xf.Bind(); - break; - default: - break; - } - }); - } -} - -#endregion - -#region 参照路径工具类 -/// -/// 获取外部参照的路径 -/// -public class XrefPath -{ - #region 属性 - /// - /// 基础路径 - /// - public string CurrentDatabasePath; - /// - /// 是否外部参照 - /// - public bool IsFromExternalReference { get; private set; } - /// - /// 外部参照保存的路径 - /// - /// 它们会是以下任一路径:
- /// 0x01 相对路径
- /// 0x02 绝对路径
- /// 0x03 共目录优先找到的路径(文件夹整体移动会发生此类情况) - ///
- ///
- public string? PathSave { get; private set; } - /// - /// 找到的路径(参照面板的名称) - /// 路径不存在时,返回是外部参照dwg文件路径 - /// - public string? PathDescribe { get; private set; } - - string? _PathComplete; - /// - /// 绝对路径 - /// - public string? PathComplete => _PathComplete ??= - PathConverter(CurrentDatabasePath, PathDescribe, PathConverterModes.Complete); - - string? _PathRelative; - /// - /// 相对路径 - /// - public string? PathRelative => _PathRelative ??= - PathConverter(CurrentDatabasePath, PathComplete, PathConverterModes.Relative); - #endregion - - #region 构造 - /// - /// 获取外部参照的路径 - /// - /// 外部参照图元 - /// 事务 - /// 是否外部参照 - public XrefPath(BlockReference brf, DBTrans tr) - { - //if (brf == null) - // throw new ArgumentNullException(nameof(brf)); - ArgumentNullEx.ThrowIfNull(brf); - CurrentDatabasePath = Path.GetDirectoryName(tr.Database.Filename); - - var btRec = tr.GetObject(brf.BlockTableRecord);// 块表记录 - if (btRec == null) - return; - - IsFromExternalReference = btRec.IsFromExternalReference; - if (!IsFromExternalReference) - return; - - // 相对路径==".\\AA.dwg" - // 无路径=="AA.dwg" - PathSave = btRec.PathName; - - if ((!string.IsNullOrEmpty(PathSave) && PathSave[0] == '.') || File.Exists(PathSave)) - { - // 相对路径||绝对路径 - PathDescribe = PathSave; - } - else - { - // 无路径 - var db = btRec.GetXrefDatabase(true); - PathDescribe = db.Filename; - } - } - #endregion - - #region 静态函数 - /// - /// 获取相对路径或者绝对路径 - /// 参考链接 - /// - /// 基础目录(末尾无斜杠) - /// 相对路径或者绝对路径 - /// 依照枚举返回对应的字符串 - /// - public static string? PathConverter(string? directory, string? fileRelations, PathConverterModes converterModes) - { - //if (directory == null) - // throw new ArgumentNullException(nameof(directory)); - //if (fileRelations == null) - // throw new ArgumentNullException(nameof(fileRelations)); - - ArgumentNullEx.ThrowIfNull(directory); - ArgumentNullEx.ThrowIfNull(fileRelations); - - string? result = null; - switch (converterModes) - { - case PathConverterModes.Relative: - result = GetRelativePath(directory, fileRelations); - break; - case PathConverterModes.Complete: - result = GetCompletePath(directory, fileRelations); - break; - default: - break; - } - return result; - } - -#if error_demo - /// - /// 绝对路径->相对路径 - /// - /// 绝对路径 - /// 相对关系 - /// - /// StringHelper.GetRelativePath("G:\\A1.项目\\20190920金山谷黄宅\\01.饰施图\\03.平面图", - /// "G:\\A1.项目\\20190920金山谷黄宅\\01.饰施图\\01.辅助文件\\图框\\A3图框.dwg"); - public static string GetRelativePath(string strDbPath, string strXrefPath) - { - Uri uri1 = new(strXrefPath); - Uri uri2 = new(strDbPath); - Uri relativeUri = uri2.MakeRelativeUri(uri1); - // 测试例子变成 01.%E8%BE%85%E5%8A%A9%E6%96%87%E4%BB%B6/%E5%9B%BE%E6%A1%86/A3%E5%9B%BE%E6%A1%86.dwg - string str = relativeUri.ToString(); - - // 因为这里不会实现".\A.dwg"而是"A.dwg",所以加入这个操作,满足同目录文件 - var strs = str.Split('\\'); - if (strs.Length == 1) - str = ".\\" + str; - return str; - } -#else - /// - /// 绝对路径->相对路径 - /// - /// 相对关系:文件夹路径 - /// 完整路径:文件路径 - /// 相对路径 - /// "..\\01.辅助文件\\图框\\A3图框.dwg" - /// ]]> - static string GetRelativePath(string directory, string file) - { - string[] directorys = directory.Split('\\'); - string[] files = file.Split('\\'); - // 获取两条路径中的最短路径 - int getMinLength = directorys.Length < files.Length ? directorys.Length : files.Length; - - // 用于确定我们退出的循环中的位置。 - int lastCommonRoot = -1; - int index; - // 找到共根 - for (index = 0; index < getMinLength; index++) - { - if (directorys[index] != files[index]) - break; - lastCommonRoot = index; - } - // 如果我们没有找到一个共同的前缀,那么抛出 - if (lastCommonRoot == -1) - throw new ArgumentException("路径没有公共相同路径部分"); - - // 建立相对路径 - var result = new StringBuilder(); - for (index = lastCommonRoot + 1; index < directorys.Length; index++) - if (directorys[index].Length > 0) - result.Append("..\\");// 上级目录加入 - - // 添加文件夹 - for (index = lastCommonRoot + 1; index < files.Length - 1; index++) - result.Append(files[index] + "\\"); - - // 本级目录 - if (result.Length == 0) - result.Append(".\\"); - // result.Append(strXrefPaths[^1]);// 下级目录加入 - result.Append(files[^1]);// 下级目录加入 - return result.ToString(); - } -#endif - - /// - /// 相对路径->绝对路径 - /// - /// 文件夹路径 - /// 相对关系:有..的 - /// 完整路径 - /// "G:\\A1.项目\\20190920金山谷黄宅\\01.饰施图\\01.辅助文件\\图框\\A3图框.dwg" - /// ]]> - static string? GetCompletePath(string directory, string relativePath) - { - if (relativePath is null || relativePath.Trim() == string.Empty) - return null; - - var relativeName = Path.GetDirectoryName(relativePath); - if (relativeName is null) - return null; - - if (relativePath[0] != '.') - return relativePath; - - const char slash = '\\'; - - // 判断向上删除几个 - var path_xiangduis = relativeName.Split(slash); - int index = 0; - for (int i = 0; i < path_xiangduis.Length; i++) - { - if (path_xiangduis[i] != "..") - break; - index++; - } - - var result = new StringBuilder(); - // 前段 - var path_dwgs = directory.Split(slash); - path_dwgs = path_dwgs.Where(s => !string.IsNullOrEmpty(s)).ToArray();// 清理空数组 - for (int i = 0; i < path_dwgs.Length - index; i++) - { - result.Append(path_dwgs[i]); - result.Append(slash); - } - // 后段 - for (int i = 0; i < path_xiangduis.Length; i++) - { - var item = path_xiangduis[i]; - if (item != "." && item != "..") - { - result.Append(item); - result.Append(slash); - } - } - result.Append(Path.GetFileName(relativePath)); - return result.ToString(); - } - #endregion -} -#endregion \ No newline at end of file diff --git "a/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchConverter.cs" "b/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchConverter.cs" deleted file mode 100644 index a88b970..0000000 --- "a/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchConverter.cs" +++ /dev/null @@ -1,454 +0,0 @@ -namespace IFoxCAD.Cad; - - -using System.Data; -using PointV = Point2d; - -/// -/// 填充边界转换器 -/// -public class HatchConverter -{ - #region 辅助类 - /// - /// 生成圆形数据 - /// - class CircleData - { - public PointV Center; - public double Radius; - - /// - /// 生成圆形数据 - /// - /// 对称点1 - /// 对称点2 - public CircleData(PointV symmetryAxisPoint1, PointV symmetryAxisPoint2) - { - Center = PointEx.GetMidPointTo(symmetryAxisPoint1, symmetryAxisPoint2); - Radius = symmetryAxisPoint1.GetDistanceTo(symmetryAxisPoint2) * 0.5; - } - } - - /// - /// 填充转换器的数据 - /// - class HatchConverterData - { - public List PolyLineData; - public List CircleData; - public List SplineData; - - /// - /// 填充转换器的数据 - /// - public HatchConverterData() - { - PolyLineData = new(); - CircleData = new(); - SplineData = new(); - } - } - #endregion - - #region 成员 - /// - /// 外部只能调用id,否则跨事务造成错误 - /// - public ObjectId OldHatchId - { - get - { - if (_oldHatch is null) - return ObjectId.Null; - return _oldHatch.ObjectId; - } - } - readonly Hatch? _oldHatch; - - readonly List _hcDatas; - /// - /// 填充边界id(生成的/已存在反应器的直接提取) - /// - public List BoundaryIds; - #endregion - - #region 构造 - /// - /// 填充边界转换器 - /// - HatchConverter() - { - _hcDatas = new(); - BoundaryIds = new(); - } - - /// - /// 填充边界转换器 - /// - /// 需要转化的Hatch对象 - public HatchConverter(Hatch hatch) : this() - { - _oldHatch = hatch; - - if (hatch.Associative) - { - // 填充边界反应器 - var assIds = hatch.GetAssociatedObjectIds(); - if (assIds != null) - { - foreach (ObjectId id in assIds) - if (id.IsOk()) - BoundaryIds.Add(id); - - if (BoundaryIds.Count == 0) - { - throw new ArgumentException("关联的填充边界被删除后没有清理反应器,请调用:" + - "\n hatch.RemoveAssociatedObjectIds()" + - "\n hatch.Associative = false"); - } - } - } - } - - /// - /// 提取边界信息 - /// - public void GetBoundarysData() - { - _oldHatch?.ForEach(loop => - { - HatchConverterData hcData = new(); - - bool isCurve2d = true; - if (loop.IsPolyline) - { - // 边界是多段线 - HatchLoopIsPolyline(loop, hcData); - isCurve2d = false; - } - else - { - if (loop.Curves.Count == 2)// 1是不可能的,大于2的是曲线 - { - // 边界是曲线,过滤可能是圆形的情况 - var cir = TwoArcFormOneCircle(loop); - if (cir is not null) - { - hcData.CircleData.Add(cir); - isCurve2d = false; - } - } - } - - // 边界是曲线 - if (isCurve2d) - HatchLoopIsCurve2d(loop, hcData); - - _hcDatas.Add(hcData); - }); - } - #endregion - - #region 方法 - /// - /// 多段线处理 - /// - /// 填充边界 - /// 收集图元信息 - static void HatchLoopIsPolyline(HatchLoop loop, HatchConverterData hcData) - { - //if (loop is null) - // throw new ArgumentNullException(nameof(loop)); - - //if (hcData is null) - // throw new ArgumentNullException(nameof(hcData)); - - ArgumentNullEx.ThrowIfNull(loop); - ArgumentNullEx.ThrowIfNull(hcData); - - - // 判断为圆形: - // 上下两个圆弧,然后填充,就会生成此种填充 - // 顶点数是3,凸度是半圆,两个半圆就是一个圆形 - if (loop.Polyline.Count == 3 && loop.Polyline[0].Bulge == 1 && loop.Polyline[1].Bulge == 1 || - loop.Polyline.Count == 3 && loop.Polyline[0].Bulge == -1 && loop.Polyline[1].Bulge == -1) - { - hcData.CircleData.Add(new CircleData(loop.Polyline[0].Vertex, loop.Polyline[1].Vertex)); - } - else - { - // 遍历多段线信息 - var bvc = loop.Polyline; - for (int i = 0; i < bvc.Count; i++) - hcData.PolyLineData.Add(new BulgeVertexWidth(bvc[i])); - } - } - - /// - /// 两个圆弧组成圆形 - /// - /// - /// - static CircleData? TwoArcFormOneCircle(HatchLoop loop) - { - //if (loop is null) - // throw new ArgumentNullException(nameof(loop)); - - ArgumentNullEx.ThrowIfNull(loop); - - if (loop.Curves.Count != 2) - throw new ArgumentException( - "边界非多段线,而且点数!=2,点数为:" + nameof(loop.Curves.Count) + ";两个矩形交集的时候会出现此情况."); - - CircleData? circular = null; - - // 判断为圆形: - // 用一条(不是两条)多段线画出两条圆弧为正圆,就会生成此种填充 - // 边界为曲线,数量为2,可能是两个半圆曲线,如果是,就加入圆形数据中 - - // 第一段 - var getCurves1Pts = loop.Curves[0].GetSamplePoints(3); // 曲线取样点分两份(3点) - var mid1Pt = getCurves1Pts[1]; // 腰点 - double bulge1 = loop.Curves[0].StartPoint.GetArcBulge(mid1Pt, loop.Curves[0].EndPoint); - - // 第二段 - var getCurves2Pts = loop.Curves[1].GetSamplePoints(3); - var mid2Pt = getCurves2Pts[1]; - double bulge2 = loop.Curves[1].StartPoint.GetArcBulge(mid2Pt, loop.Curves[1].EndPoint); - - // 第一段上弧&&第二段反弧 || 第一段反弧&&第二段上弧 - if (bulge1 == -1 && bulge2 == -1 || bulge1 == 1 && bulge2 == 1) - circular = new CircleData(loop.Curves[0].StartPoint, loop.Curves[1].StartPoint); // 两个起点就是对称点 - - return circular; - } - - /// - /// 处理边界曲线 - /// - /// 填充边界 - /// 收集图元信息 - static void HatchLoopIsCurve2d(HatchLoop loop, HatchConverterData hcData) - { - // 取每一段曲线,曲线可能是直线来的,但是圆弧会按照顶点来分段 - int curveIsClosed = 0; - - // 遍历边界的多个子段 - foreach (Curve2d curve in loop.Curves) - { - // 计数用于实现闭合 - curveIsClosed++; - if (curve is NurbCurve2d spl) - { - // 判断为样条曲线: - hcData.SplineData.Add(spl); - continue; - } - - var pts = curve.GetSamplePoints(3); - var midPt = pts[1]; - if (curve.StartPoint.IsEqualTo(curve.EndPoint, new Tolerance(1e-6, 1e-6)))// 首尾相同,就是圆形 - { - // 判断为圆形: - // 获取起点,然后采样三点,中间就是对称点(直径点) - hcData.CircleData.Add(new CircleData(curve.StartPoint, midPt)); - continue; - } - - // 判断为多段线,圆弧: - double bulge = curve.StartPoint.GetArcBulge(midPt, curve.EndPoint); - hcData.PolyLineData.Add(new BulgeVertexWidth(curve.StartPoint, bulge)); - - // 末尾点,不闭合的情况下就要获取这个 - if (curveIsClosed == loop.Curves.Count) - hcData.PolyLineData.Add(new BulgeVertexWidth(curve.EndPoint, 0)); - } - } - - /// - /// 创建边界图元 - /// - /// 返回图元 - [Obsolete("使用带返回值的CreateBoundary替代")] - public void CreateBoundary(List outEnts) - { - for (int i = 0; i < _hcDatas.Count; i++) - { - var data = _hcDatas[i]; - - // 生成边界:多段线 - if (data.PolyLineData.Count > 0) - { - Polyline pl = new(); - pl.SetDatabaseDefaults(); - for (int j = 0; j < data.PolyLineData.Count; j++) - { - pl.AddVertexAt(j, - data.PolyLineData[j].Vertex, - data.PolyLineData[j].Bulge, - data.PolyLineData[j].StartWidth, - data.PolyLineData[j].EndWidth); - } - outEnts.Add(pl); - } - - // 生成边界:圆 - data.CircleData.ForEach(item => - { - outEnts.Add(new Circle(item.Center.Point3d(), Vector3d.ZAxis, item.Radius)); - }); - - // 生成边界:样条曲线 - data.SplineData.ForEach(item => - { - outEnts.Add(item.ToCurve()); - }); - } - - if (_oldHatch is not null) - { - outEnts.ForEach(ent => - { - ent.Color = _oldHatch.Color; - ent.Layer = _oldHatch.Layer; - }); - } - } - /// - /// 创建边界 - /// - /// - public List CreateBoundary() - { - List outEnts = new List(); - for (int i = 0; i < _hcDatas.Count; i++) - { - var data = _hcDatas[i]; - - // 生成边界:多段线 - if (data.PolyLineData.Count > 0) - { - Polyline pl = new(); - pl.SetDatabaseDefaults(); - for (int j = 0; j < data.PolyLineData.Count; j++) - { - pl.AddVertexAt(j, - data.PolyLineData[j].Vertex, - data.PolyLineData[j].Bulge, - data.PolyLineData[j].StartWidth, - data.PolyLineData[j].EndWidth); - } - outEnts.Add(pl); - } - - // 生成边界:圆 - data.CircleData.ForEach(item => - { - outEnts.Add(new Circle(item.Center.Point3d(), Vector3d.ZAxis, item.Radius)); - }); - - // 生成边界:样条曲线 - data.SplineData.ForEach(item => - { - outEnts.Add(item.ToCurve()); - }); - } - - if (_oldHatch is not null) - { - outEnts.ForEach(ent => - { - ent.Color = _oldHatch.Color; - ent.Layer = _oldHatch.Layer; - }); - } - return outEnts; - } - - /// - /// 创建边界图元和新填充到当前空间 - /// - /// - /// 边界关联 - /// 是否创建填充,false则只创建边界 - /// 新填充id,边界在获取 - public ObjectId CreateBoundarysAndHatchToMsPs(BlockTableRecord btrOfAddEntitySpace, - bool boundaryAssociative = true, - bool createHatchFlag = true) - { - List boEnts = CreateBoundary(); - boEnts.ForEach(ent => - { - BoundaryIds.Add(btrOfAddEntitySpace.AddEntity(ent)); - }); - - if (!createHatchFlag) - return ObjectId.Null; - /* - * 此处为什么要克隆填充,而不是新建填充? - * 因为填充如果是新建的,那么将会丢失基点,概念如下: - * 两个一样的填充,平移其中一个,那么再提取他们的基点会是一样的! - * 所以生成时候就不等同于画面相同. - * 也因为我不知道什么新建方式可以新建一模一样的填充,因此使用了克隆 - * 那么它的平移后的基点在哪里呢? - */ - - using ObjectIdCollection idc = new(new ObjectId[] { OldHatchId }); - using IdMapping map = new(); - btrOfAddEntitySpace.DeepCloneEx(idc, map); - var newHatchId = map.GetValues()[0]; - var tr = DBTrans.GetTopTransaction(btrOfAddEntitySpace.Database); - - bool openErased = false; - bool openLockedLayer = false; - var hatchEnt = tr.GetObject(newHatchId, OpenMode.ForWrite, openErased, openLockedLayer); - if (hatchEnt != null) - { - ResetBoundary(hatchEnt, boundaryAssociative); - hatchEnt.DowngradeOpen(); - } - return newHatchId; - } - - /// - /// 重设边界 - /// - /// - /// 边界关联 - void ResetBoundary(Hatch hatch, bool boundaryAssociative = true) - { - if (BoundaryIds.Count == 0) - return; - - // todo ------ acad08分离填充报错: Microsoft Visual Studio C 运行库在 acad.exe 中检测到一个错误 - // 0x01 测试命令 CmdTest_CreateHatch 创建是可以分离的, - // 那么可能是 克隆后 修改导致的, - // 我是克隆了之后移除原有边界,为了一些xdata之类的 - // 0x02 测试了 hatch.SetDatabaseDefaults(); 并不是因为这个 - // 0x03 测试了 v1110 不移除原有边界,而是加入了之后再移除旧的边界,也是一样 - // 要处理这个问题,我想:自己实现一个分离填充,不用cad自带的,然后单独填充每个. - // 填充边界的算法是扫描线算法.这样就可以绕过去了...发现过于麻烦,放弃... - - // v1110 删除原有边界 - while (hatch.NumberOfLoops != 0) - hatch.RemoveLoopAt(0); - - hatch.Associative = boundaryAssociative; - - using ObjectIdCollection obIds = new(); - for (int i = 0; i < BoundaryIds.Count; i++) - { - obIds.Clear(); - obIds.Add(BoundaryIds[i]); - // 要先添加最外面的边界 - if (i == 0) - hatch.AppendLoop(HatchLoopTypes.Outermost, obIds); - else - hatch.AppendLoop(HatchLoopTypes.Default, obIds); - } - // 计算填充并显示 - hatch.EvaluateHatch(true); - } - #endregion -} \ No newline at end of file diff --git "a/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchEx.cs" "b/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchEx.cs" deleted file mode 100644 index 51d2c65..0000000 --- "a/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchEx.cs" +++ /dev/null @@ -1,358 +0,0 @@ -namespace IFoxCAD.Cad; - -/// -/// 充填扩展类 -/// -public static class HatchEx -{ - /// - /// 遍历填充每条边 - /// - /// - /// - public static void ForEach(this Hatch hatch, Action action) - { - for (int i = 0; i < hatch.NumberOfLoops; i++) - action.Invoke(hatch.GetLoopAt(i)); - } - - /// - /// 提取已存在的关联边界(一个边界环里所有的对象 id 组成一个 ObjectIdCollection) - /// - /// - /// - /// - public static List? GetAssociatedBoundaryIds(this Hatch hatch) - { - if (!hatch.Id.IsOk()) - throw new ArgumentException("填充未加入或不存在于数据库"); - - if (!hatch.Associative) - return null; - - var listObjIdColl = new List(); - - for (var i = 0; i < hatch.NumberOfLoops; i++) - { - var assIds = hatch.GetAssociatedObjectIdsAt(i); - if (assIds != null) - { - var objIds = new ObjectIdCollection(); - foreach (ObjectId id in assIds) - { - if (id.IsOk()) - objIds.Add(id); - } - - if (objIds.Count == 0) - { - throw new ArgumentException("关联的填充边界被删除后没有清理反应器,请调用:" + - "\n hatch.RemoveAssociatedObjectIds()" + - "\n hatch.Associative = false"); - } - - listObjIdColl.Add(objIds); - } - } - - return listObjIdColl; - } - - /// - /// 创建边界(仅创建于内存中,未加入数据库) - /// - /// - /// 边界环列表(一个边界环里所有的对象组成一个 DBObjectCollection) - public static List CreateBoundarys(this Hatch hatch) - { - if (!hatch.Id.IsOk()) - throw new ArgumentException("填充未加入或不存在于数据库"); - - var listDbObjColl = new List(); - - for (int i = 0; i < hatch.NumberOfLoops; i++) - { - var objColl = new DBObjectCollection(); - var loop = hatch.GetLoopAt(i); - bool isCurve2d = true; - - if (loop.IsPolyline) - { - // 边界是多段线 - HatchLoopIsPolyline(loop, objColl); - isCurve2d = false; - } - else - { - // 1是不可能的,大于2的是曲线; - if (loop.Curves.Count == 2) - { - // 边界是曲线,过滤可能是圆形的情况 - var circle = TwoArcFormOneCircle(loop, objColl); - if (circle is not null) - { - objColl.Add(circle); - isCurve2d = false; - } - } - } - - // 边界是曲线 - if (isCurve2d) - HatchLoopIsCurve2d(loop, objColl); - - listDbObjColl.Add(objColl); - }; - - return listDbObjColl; - } - - /// - /// 对已存在于数据库的填充重新设置边界并计算 - /// - /// - /// 边界对象(一个边界环里所有的对象 id 组成一个 ObjectIdCollection) - ///
边界必需是封闭的环, 可以是一条线围合而成也可以是多条线首尾相连围合而成
- ///
多个外边界的时候, 建议顺序为(外边界,外边界,外边界,普通边界....), 或(外边界, 普通边界.....外边界, 普通边界....)
- /// - /// 关联边界(默认保持原样) - public static void ResetBoundarys(this Hatch hatch, List boundaryIds, bool? associative = null) - { - if (!hatch.Id.IsOk()) - throw new ArgumentException("填充未加入或不存在于数据库"); - - boundaryIds.ForEach(ids => - { - foreach (ObjectId id in ids) - { - if (!id.IsOk()) - throw new ArgumentException("边界未加入或不存在于数据库"); - } - }); - - using (hatch.ForWrite()) - { - while (hatch.NumberOfLoops > 0) - hatch.RemoveLoopAt(0); - - if (associative != null) - hatch.Associative = associative == true; - - var isOutermost = true; - - boundaryIds.ForEach(ids => - { - try - { - // 要先添加最外面的边界 - if (isOutermost) - { - isOutermost = false; - hatch.AppendLoop(HatchLoopTypes.Outermost, ids); - } - else - { - // HatchLoopTypes.External 比 HatchLoopTypes.Default 似乎更不容易出问题 - hatch.AppendLoop(HatchLoopTypes.External, ids); - } - } - catch (Exception ex) - { - Env.Editor.WriteMessage(Environment.NewLine - + "发生错误,传入的边界不符合要求,请核实传入的边界是否为封闭的"); - throw new Exception(ex.Message); - } - }); - - hatch.EvaluateHatch(true); - } - } - - #region 私有方法 - /// - /// 处理边界多段线 - /// - /// 填充边界 - /// 收集边界图元 - private static void HatchLoopIsPolyline(HatchLoop loop, DBObjectCollection objColl) - { - // 判断为圆形: - // 上下两个圆弧,然后填充,就会生成此种填充 - // 顶点数是3,凸度是半圆,两个半圆就是一个圆形 - if (loop.Polyline.Count == 3 && loop.Polyline[0].Bulge == 1 && loop.Polyline[1].Bulge == 1 - || loop.Polyline.Count == 3 && loop.Polyline[0].Bulge == -1 && loop.Polyline[1].Bulge == -1) - { - var center = PointEx.GetMidPointTo(loop.Polyline[0].Vertex, loop.Polyline[1].Vertex); - var radius = loop.Polyline[0].Vertex.GetDistanceTo(loop.Polyline[1].Vertex) * 0.5; - var circle = new Circle(center.Point3d(), Vector3d.ZAxis, radius); - objColl.Add(circle); - } - else - { - // 遍历多段线信息 - var bvc = loop.Polyline; - var pl = new Polyline(); - pl.SetDatabaseDefaults(); - for (int j = 0; j < bvc.Count; j++) - { - var bvw = new BulgeVertexWidth(bvc[j]); - pl.AddVertexAt(j, bvw.Vertex, bvw.Bulge, bvw.StartWidth, bvw.EndWidth); - } - objColl.Add(pl); - } - } - - /// - /// 两个圆弧组成圆形 - /// - /// 填充边界 - /// 收集边界图元 - private static Circle? TwoArcFormOneCircle(HatchLoop loop, DBObjectCollection objColl) - { - if (loop.Curves.Count != 2) - { - throw new ArgumentException( - "边界非多段线,而且点数!=2,点数为:" + nameof(loop.Curves.Count) + ";两个矩形交集的时候会出现此情况."); - } - - Circle? circle = null; - - // 判断为圆形: - // 用一条(不是两条)多段线画出两条圆弧为正圆,就会生成此种填充 - // 边界为曲线,数量为2,可能是两个半圆曲线,如果是,就加入圆形数据中 - - // 第一段 - var getCurves1Pts = loop.Curves[0].GetSamplePoints(3); // 曲线取样点分两份(3点) - var mid1Pt = getCurves1Pts[1]; // 腰点 - double bulge1 = loop.Curves[0].StartPoint.GetArcBulge(mid1Pt, loop.Curves[0].EndPoint); - - // 第二段 - var getCurves2Pts = loop.Curves[1].GetSamplePoints(3); - var mid2Pt = getCurves2Pts[1]; - double bulge2 = loop.Curves[1].StartPoint.GetArcBulge(mid2Pt, loop.Curves[1].EndPoint); - - // 第一段上弧&&第二段反弧 || 第一段反弧&&第二段上弧 - if (bulge1 == -1 && bulge2 == -1 || bulge1 == 1 && bulge2 == 1) - { - var center = PointEx.GetMidPointTo(loop.Curves[0].StartPoint, loop.Curves[1].StartPoint); - var radius = loop.Curves[0].StartPoint.GetDistanceTo(loop.Curves[1].StartPoint) * 0.5; - circle = new Circle(center.Point3d(), Vector3d.ZAxis, radius); - } - - return circle; - } - - /// - /// 处理边界曲线 - /// - /// 填充边界 - /// 收集边界图元 - private static void HatchLoopIsCurve2d(HatchLoop loop, DBObjectCollection objColl) - { - int pLineCount = 0; //记录多段线数量 - int curveIsClosed = 0; // 取每一段曲线,曲线可能是直线来的,但是圆弧会按照顶点来分段 - bool newPline = true; // 是否开始新的多段线(一个边界中可能有多条多段线) - bool firstIsPline = false; //遍历边界的第一个子段为多段线(遍历时不一定从多段线的首段开始) - List? polyLineVertexs = null; - List> polyLineData = new(); - - // 遍历边界的多个子段 - foreach (Curve2d curve in loop.Curves) - { - // 计数用于实现闭合 - curveIsClosed++; - - if (curve is CircularArc2d or LineSegment2d) - { - var pts = curve.GetSamplePoints(3); - var midPt = pts[1]; - - // 判断为多段线圆: - // 首尾相同,就是圆形 - if (curve.StartPoint.IsEqualTo(curve.EndPoint, new Tolerance(1e-6, 1e-6))) - { - // 获取起点,然后采样三点,中间就是对称点(直径点) - var center = PointEx.GetMidPointTo(curve.StartPoint, midPt); - var radius = curve.StartPoint.GetDistanceTo(midPt) * 0.5; - var circle = new Circle(center.Point3d(), Vector3d.ZAxis, radius); - objColl.Add(circle); - // 添加在中部的多段线末尾点 - if (curveIsClosed > 1 && !newPline) - polyLineVertexs?.Add(new BulgeVertexWidth(curve.StartPoint, 0)); - // 开始新的多段线 - newPline = true; - continue; - } - - if (curveIsClosed == 1) - firstIsPline = true; - - if (newPline) - { - polyLineVertexs = new(); - polyLineData.Add(polyLineVertexs); - newPline = false; - pLineCount++; - } - - // 判断为多段线,圆弧或直线: - double bulge = curve.StartPoint.GetArcBulge(midPt, curve.EndPoint); - polyLineVertexs?.Add(new BulgeVertexWidth(curve.StartPoint, bulge)); - - // 末尾点,不闭合的情况下就要获取这个 - if (curveIsClosed == loop.Curves.Count) - { - if (firstIsPline && pLineCount > 1) - { - // 连接首尾多段线 - polyLineData[0].ForEach(bvw => polyLineData[^1].Add(bvw)); - polyLineData.RemoveAt(0); - } - else - polyLineVertexs?.Add(new BulgeVertexWidth(curve.EndPoint, 0)); - } - - continue; - } - - // 判断为样条曲线: - if (curve is NurbCurve2d spl) - objColl.Add(spl.ToCurve()); - - // 判断为椭圆: - if (curve is EllipticalArc2d eArc2d) - { - var startParam = eArc2d.IsClockWise ? -eArc2d.EndAngle : eArc2d.StartAngle; - var endParam = eArc2d.IsClockWise ? -eArc2d.StartAngle : eArc2d.EndAngle; - var ellipse = new Ellipse( - eArc2d.Center.Point3d(), - Vector3d.ZAxis, - eArc2d.MajorAxis.Convert3d() * eArc2d.MajorRadius, - eArc2d.MinorRadius / eArc2d.MajorRadius, - Math.Atan2(Math.Sin(startParam) * eArc2d.MinorRadius, - Math.Cos(startParam) * eArc2d.MajorRadius), - Math.Atan2(Math.Sin(endParam) * eArc2d.MinorRadius, - Math.Cos(endParam) * eArc2d.MajorRadius)); - objColl.Add(ellipse); - } - - // 添加在中部的多段线末尾点 - if (curveIsClosed > 1 && !newPline) - polyLineVertexs?.Add(new BulgeVertexWidth(curve.StartPoint, 0)); - // 开始新的多段线 - newPline = true; - } - - // 生成多段线 - polyLineData.ForEach(bvws => - { - if (bvws.Count == 0) return; - var pl = new Polyline(); - pl.SetDatabaseDefaults(); - for (int j = 0; j < bvws.Count; j++) - pl.AddVertexAt(j, bvws[j].Vertex, bvws[j].Bulge, bvws[j].StartWidth, bvws[j].EndWidth); - objColl.Add(pl); - }); - } - #endregion -} \ No newline at end of file diff --git "a/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchInfo.cs" "b/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchInfo.cs" deleted file mode 100644 index bf1fa8d..0000000 --- "a/src/CAD/IFox.CAD.Shared/ExtensionMethod/\346\226\260\345\273\272\345\241\253\345\205\205/HatchInfo.cs" +++ /dev/null @@ -1,354 +0,0 @@ - - -namespace IFoxCAD.Cad; - -/* - * 添加的第一个边界必须是外边界,即用于定义图案填充最外面的边界。 - * 要添加外部边界,请使用添加环的类型为 HatchLoopTypes.Outermost 常量的 AppendLoop 方法, - * 一旦外边界被定义,就可以继续添加另外的边界。 - * 添加内部边界请使用带 HatchLoopTypes.Default 常量的 AppendLoop 方法。 - * - * 多个外边界的时候,添加的是(外边界,外边界,外边界,普通边界....) - * 多个外边界的时候,添加的是(外边界,普通边界.....外边界,普通边界....) - */ - -/// -/// 图案填充 -/// -public class HatchInfo -{ - #region 成员 - /// - /// 边界id(最外面放第一) - /// - readonly List _boundaryIds; - /// - /// 填充图元 - /// - readonly Hatch _hatch; - /// - /// 边界关联(此处不能直接=>给填充成员,因为它会加入反应器) - /// - readonly bool _boundaryAssociative; - /// - /// 填充的名称:用户定义(固定名称)/渐变/填充依据定义文件 - /// - string? _hatchName; - /// - /// 填充模式类型(预定义/用户定义/自定义) - /// - HatchPatternType _patternTypeHatch; - /// - /// 渐变模式类型 - /// - GradientPatternType _patternTypeGradient; - /// - /// 比例/间距 - /// - double Scale => _hatch.PatternScale; - /// - /// 角度 - /// - double Angle => _hatch.PatternAngle; - - // 延后处理角度 - private double _angle; - #endregion - - #region 构造 - HatchInfo() - { - _hatch = new Hatch(); - _hatch.SetDatabaseDefaults(); - _boundaryIds = new(); - } - - /// - /// 图案填充 - /// - /// 关联边界 - /// 填充原点 - /// 比例 - /// 角度 - public HatchInfo(bool boundaryAssociative = true, - Point2d? hatchOrigin = null, - double hatchScale = 1, - double hatchAngle = 0) : this() - { - if (hatchScale <= 0) - throw new ArgumentException("填充比例不允许小于等于0"); - - _hatch.PatternScale = hatchScale;// 填充比例 - _angle = hatchAngle;// 填充角度 - _boundaryAssociative = boundaryAssociative; - - hatchOrigin ??= Point2d.Origin; - _hatch.Origin = hatchOrigin.Value; // 填充原点 - } - - /// - /// 图案填充 - /// - /// 边界 - /// 关联边界 - /// 填充原点 - /// 比例 - /// 角度 - public HatchInfo(IEnumerable boundaryIds, - bool boundaryAssociative = true, - Point2d? hatchOrigin = null, - double hatchScale = 1, - double hatchAngle = 0) - : this(boundaryAssociative, hatchOrigin, hatchScale, hatchAngle) - { - _boundaryIds.AddRange(boundaryIds); - } - - #endregion - - #region 方法 - /// - /// 模式1:预定义 - /// - public HatchInfo Mode1PreDefined(string name) - { - _hatchName = name; - _hatch.HatchObjectType = HatchObjectType.HatchObject; // 对象类型(填充/渐变) - _patternTypeHatch = HatchPatternType.PreDefined; - return this; - } - - /// - /// 模式2:用户定义 - /// - /// 是否双向 - public HatchInfo Mode2UserDefined(bool patternDouble = true) - { - _hatchName = "_USER"; - _hatch.HatchObjectType = HatchObjectType.HatchObject; // 对象类型(填充/渐变) - _patternTypeHatch = HatchPatternType.UserDefined; - - _hatch.PatternDouble = patternDouble; // 是否双向(必须写在 SetHatchPattern 之前) - _hatch.PatternSpace = Scale; // 间距(必须写在 SetHatchPattern 之前) - return this; - } - - /// - /// 模式3:自定义 - /// - /// - public HatchInfo Mode3UserDefined(string name) - { - _hatchName = name; - _hatch.HatchObjectType = HatchObjectType.HatchObject; // 对象类型(填充/渐变) - _patternTypeHatch = HatchPatternType.CustomDefined; - return this; - } - - /// - /// 模式4:渐变填充 - /// - /// 渐变填充名称 - /// 渐变色起始颜色 - /// 渐变色结束颜色 - /// 渐变移动 - /// 色调值 - /// 单色双色 - public HatchInfo Mode4Gradient(GradientName name, Color colorStart, Color colorEnd, - float gradientShift = 0, - float shadeTintValue = 0, - bool gradientOneColorMode = false) - { - // entget渐变的名字必然是"SOLID",但是这里作为"渐变"名,而不是"填充"名 - _hatchName = name.ToString(); - _hatch.HatchObjectType = HatchObjectType.GradientObject; // 对象类型(填充/渐变) - _patternTypeGradient = GradientPatternType.PreDefinedGradient;// 模式4:渐变 - // _patternTypeGradient = GradientPatternType.UserDefinedGradient;// 模式5:渐变..这种模式干啥用呢 - - // 设置渐变色填充的起始和结束颜色 - var gColor1 = new GradientColor(colorStart, 0); - var gColor2 = new GradientColor(colorEnd, 1); - _hatch.SetGradientColors(new GradientColor[] { gColor1, gColor2 }); - - _hatch.GradientShift = gradientShift; // 梯度位移 - _hatch.ShadeTintValue = shadeTintValue; // 阴影色值 - _hatch.GradientOneColorMode = gradientOneColorMode;// 渐变单色/双色 - _hatch.GradientAngle = Angle; // 渐变角度 - - return this; - } - - /// - /// 构建 - /// - /// 将填充加入此空间 - public ObjectId Build(BlockTableRecord btrOfAddEntitySpace) - { - // 加入数据库 - var hatchId = btrOfAddEntitySpace.AddEntity(_hatch); - - // 设置模式:渐变/填充 - if (_hatch.HatchObjectType == HatchObjectType.GradientObject) - _hatch.SetGradient(_patternTypeGradient, _hatchName); - else - _hatch.SetHatchPattern(_patternTypeHatch, _hatchName); - - // 处理充填角度 - _hatch.PatternAngle = _angle; - - - // 关联边界,如果不先添加数据库空间内就会出错 - // 为 true 会加入反应器,因此比较慢(二维码将会十几秒才生成好),视需求而定. - _hatch.Associative = _boundaryAssociative; - - // 利用 AppendLoop 重载加入,这里就不处理 - if (_boundaryIds.Count > 0) - AppendLoop(_boundaryIds, HatchLoopTypes.Default); - - // 计算填充并显示(若边界出错,这句会异常) - _hatch.EvaluateHatch(true); - - return hatchId; - } - - /// - /// 执行图元的属性修改 - /// - /// 扔出填充实体 - public HatchInfo Action(Action action) - { - action(_hatch); - return this; - } - - /// - /// 清空边界集合 - /// - public HatchInfo ClearBoundary() - { - _boundaryIds.Clear(); - return this; - } - - /// - /// 删除边界图元 - /// - public HatchInfo EraseBoundary() - { - for (int i = 0; i < _boundaryIds.Count; i++) - _boundaryIds[i].Erase(); - return this; - } - - /// - /// 加入边界 - /// - /// 边界id - /// 加入方式 - void AppendLoop(IEnumerable boundaryIds, - HatchLoopTypes hatchLoopTypes = HatchLoopTypes.Default) - { - ObjectIdCollection obIds = new(); - // 边界是闭合的,而且已经加入数据库 - // 填充闭合环类型.最外面 - - // 此段代码会出错的原因在于 如果是直线围成的闭合区域, - // 那么每次添加的其实一条直线,而直线不构成loop,所以不符合预期的数据,出错 - try - { - foreach (var border in boundaryIds) - { - obIds.Clear(); - obIds.Add(border); - _hatch.AppendLoop(hatchLoopTypes, obIds); - } // 此段代码会出错 - } - catch (Exception ex) - { - - Env.Print(ex.Message); - Env.Print("发生错误,传入的边界不符合要求,请核实传入的边界是否为闭合边界列表,而不是组成边界的图元列表"); - throw; - } - - // 下面这行代码出错的原因是: 添加了重复的线条,需要进行剔除 - // _hatch.AppendLoop(hatchLoopTypes, boundaryIds.ToCollection()); - - // 这个函数还需要进行改造: - // 1. 明确传入的 boundaryIds 到底是多个边界,还是一个边界的子图元 - // 2. 根据传入的参数的不同 需要不同的处理措施 - // 3. 临时性措施 try一下抛异常,让用户确保传入的参数是准确的 - - } - - /// - /// 加入边界(仿高版本的填充函数) - /// - /// 点集 - /// 凸度集 - /// 加入此空间 - /// 加入方式 - /// - public HatchInfo AppendLoop(Point2dCollection pts, - DoubleCollection bluges, - BlockTableRecord btrOfAddEntitySpace, - HatchLoopTypes hatchLoopTypes = HatchLoopTypes.Default) - { - //if (pts == null) - // throw new ArgumentNullException(nameof(pts)); - ArgumentNullEx.ThrowIfNull(pts); - pts.End2End(); - // 2011新增API,可以不生成图元的情况下加入边界, - // 通过这里进入的话,边界 _boundaryIds 是空的,那么 Build() 时候就需要过滤空的 - _hatch.AppendLoop(hatchLoopTypes, pts, bluges); - return this; - } - - - #endregion - - #region 枚举 - /// - /// 渐变色填充的图案名称 - /// - public enum GradientName - { - /// - /// 线状渐变 - /// - Linear, - /// - /// 圆柱状渐变 - /// - Cylinder, - /// - /// 反圆柱状渐变 - /// - Invcylinder, - /// - /// 球状渐变 - /// - Spherical, - /// - /// 反球状渐变 - /// - Invspherical, - /// - /// 半球状渐变 - /// - Hemisperical, - /// - /// 反半球状渐变 - /// - InvHemisperical, - /// - /// 抛物面状渐变 - /// - Curved, - /// - /// 反抛物面状渐变 - /// - Incurved - } - #endregion -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems b/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems deleted file mode 100644 index 1f3aa51..0000000 --- a/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.projitems +++ /dev/null @@ -1,100 +0,0 @@ - - - - $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - true - 20f254f7-aee5-42ae-a9b3-149bbdc7397f - - - IFox.CAD.Shared - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.shproj b/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.shproj deleted file mode 100644 index ac52df3..0000000 --- a/src/CAD/IFox.CAD.Shared/IFox.CAD.Shared.shproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - 20f254f7-aee5-42ae-a9b3-149bbdc7397f - 14.0 - - - - - - - - diff --git a/src/CAD/IFox.CAD.Shared/PE/AcadPeInfo.cs b/src/CAD/IFox.CAD.Shared/PE/AcadPeInfo.cs deleted file mode 100644 index df72756..0000000 --- a/src/CAD/IFox.CAD.Shared/PE/AcadPeInfo.cs +++ /dev/null @@ -1,389 +0,0 @@ -using System.Diagnostics; - -namespace IFoxCAD.Cad; - -/// -/// 选择模式 -/// -[Flags] -public enum AcadPeEnum : byte -{ - /// - /// AcadExe - /// - AcadExe = 1, - /// - /// AccoreDll - /// - AccoreDll = 2, - /// - /// Acdb - /// - Acdb = 4, - /// - /// ExeAndCore - /// - ExeAndCore = AcadExe | AccoreDll, -} - -/// -/// 这里的枚举对应 GetMethodException 错误值 -/// -[Flags] -public enum GetMethodErrorNum : byte -{ - /// - /// - /// - Ok = 0, - /// - /// - /// - NoModule = 1, - /// - /// - /// - NoFuncName = 2, -} - -/// -/// 自动获取本工程上面的发送命令的接口 -/// -public class AcadPeInfo -{ - #region 静态单例获取exe/dll信息 - static PeInfo? _PeForAcadExe; - /// - /// - /// - public static PeInfo? PeForAcadExe - { - get - { - if (_PeForAcadExe is null) - { - // 获取此acad.exe获取所有的函数名 - var file = Process.GetCurrentProcess().MainModule.FileName; - _PeForAcadExe = new PeInfo(file); - } - return _PeForAcadExe; - } - } - - static PeInfo? _PeForAccoreDll; - /// - /// - /// - public static PeInfo? PeForAccoreDll - { - get - { - if (_PeForAccoreDll is null) - { - // 获取此dll所有的函数名 - var file = Process.GetCurrentProcess().MainModule.FileName; - var dll = Path.GetDirectoryName(file) + "\\accore.dll"; - if (File.Exists(dll))// 08没有,高版本分离的 - _PeForAccoreDll = new PeInfo(dll); - } - return _PeForAccoreDll; - } - } - - static PeInfo? _PeForAcdbDll; - /// - /// - /// - public static PeInfo? PeForAcdbDll - { - get - { - if (_PeForAcdbDll is null) - { - // 获取此dll所有的函数名 - var file = Process.GetCurrentProcess().MainModule.FileName; - var dll = Path.GetDirectoryName(file) + $"\\acdb{Acap.Version.Major}.dll"; - if (File.Exists(dll)) - _PeForAcdbDll = new PeInfo(dll); - } - return _PeForAcdbDll; - } - } - - List? _Methods; // 这个不是静态的 - /// - /// 同名函数指针们 - /// - public List? Methods - { - get - { - if (_Methods is null) - { - _Methods = new(); - - if ((_acadPeEnum & AcadPeEnum.AcadExe) == AcadPeEnum.AcadExe) - GetPeMethod(PeForAcadExe); - if ((_acadPeEnum & AcadPeEnum.AccoreDll) == AcadPeEnum.AccoreDll) - GetPeMethod(PeForAccoreDll); - if ((_acadPeEnum & AcadPeEnum.Acdb) == AcadPeEnum.Acdb) - GetPeMethod(PeForAcdbDll); - } - return _Methods; - } - } - #endregion - - #region 字段/构造 - /// - /// 用于查找PE不带修饰的函数名 - /// - string _findFuncName; - /// - /// 枚举查找对象 - /// - AcadPeEnum _acadPeEnum; - - /// - /// 通过函数名获取指针,指定类型 - /// - /// 不带修饰的函数名 - /// 读取哪个cad内部文件的枚举(目前只支持两个) - public AcadPeInfo(string methodName, AcadPeEnum acadPeEnum) - { - _findFuncName = methodName; - _acadPeEnum = acadPeEnum; - } - - /// - /// 获取CAD的函数指针 - /// - /// 委托 - /// 不带修饰的函数名 - /// 读取哪个cad内部文件的枚举(目前只支持两个) - /// 委托 - public static TDelegate? GetDelegate(string methodName, AcadPeEnum acadPeEnum) - where TDelegate : class - { - return new AcadPeInfo(methodName, acadPeEnum) - .GetDelegate(); - } - #endregion - - #region 方法 - /// - /// 储存旧值,去除修饰函数名(查找的),带修饰函数名们 - /// - static Dictionary> _Dict = new(); - - /// - /// 返回函数指针 - /// - /// Pe信息:可能来自exe/dll - /// 错误信息 - GetMethodErrorNum GetPeMethod(PeInfo? peInfo) - { - if (peInfo == null) - return GetMethodErrorNum.NoFuncName;// cad08需要检查 AccoreDll 的时候跳过 - - var identifyStr = _findFuncName + ";" + peInfo.FullName; - if (_Dict.ContainsKey(identifyStr))// 如果已经找过,直接返回 - { - _Methods = _Dict[identifyStr]; - } - else - { - _Methods ??= new(); - try - { - PeFunction.Finds(peInfo, _findFuncName, _Methods); - if (_Methods.Count != 0)// 此时从不含有 - _Dict.Add(identifyStr, _Methods); - } - catch (GetPeMethodException ex) - { return (GetMethodErrorNum)ex.ErrorNum; } - } - return GetMethodErrorNum.Ok; - } - - /// - /// 转为委托 - /// - /// 委托对象 - /// - public TDelegate? GetDelegate() where TDelegate : class - { - if (Methods is null || Methods.Count == 0) - return null; - - TDelegate? func = null; - - /* - * 0x01 - * 这里永远不报错,但是不代表不会出错. - * 调用C盘exe/dll时需要权限, - * 所以会出现:[DLLImport]可以,直接运行cad也可以,但是调试不行. - * 此时可以提权vs再调试,有时候会出现:调试不显示东西,但是运行是对的. - * - * 0x02 - * 出错时候用完整的修饰名 - * - * 0x03 - * 这里可能同时存在acad.exe和accore.dll相同指针? - * 所以我是用排序方法找最短的指针,所以它是第First个. - */ - - // 排序,最少长度原则本身就是让完全相同字符串在最前面 - // 这里替换为有序哈希,因为我总是需要不带修饰的返回函数,所以是排序长度的第一个 - _Methods = _Methods.OrderBy(str => str.CName?.Length) - .ThenBy(str => str.MethodName.Length) - .ToList(); - - func = Marshal.GetDelegateForFunctionPointer(Methods.First().GetProcAddress(), typeof(TDelegate)) as TDelegate; - return func; - } - #endregion -} - -/// -/// 通过名字查找exe/dll内所有名字 -/// -public class PeFunction -{ - #region 字段/构造 - string? _CName; - /// - /// 纯c语言名 - /// - public string? CName - { - get - { - if (_CName is null && MethodName is not null) - { - _CName = MethodName.Replace("?", string.Empty); // 剔除cpp前缀 - int num = _CName.IndexOf("@"); - if (num > -1) - _CName = _CName.Substring(0, num); // 剔除参数部分 - } - return _CName; - } - } - - /// - /// 模块文件路径 - /// - public string? ModuleFullName; - /// - /// 模块指针 - /// - public IntPtr ModuleIntPtr; - /// - /// 函数名 - /// - public string MethodName; - /// - /// 通过名字查找exe/dll内所有名字 - /// - /// 没修饰的方法名 - public PeFunction(string methodName) - { - MethodName = methodName; - } - #endregion - - /// - /// 获取函数指针 - /// - public IntPtr GetProcAddress() - { - return WindowsAPI.GetProcAddress(ModuleIntPtr, MethodName); - } - - /// - /// 通过名字查找exe/dll内所有名字 - /// - /// pe结构 - /// 用于查找的方法名 - /// 返回函数集合 - public static void Finds(PeInfo peInfo, - string findFuncName, - List funcAdress_Out) - { - if (findFuncName == null) - throw new GetPeMethodException(2, "没有找到对应的函数:" + findFuncName); - - var peModuleFullName = peInfo.FullName; - if (peModuleFullName == null) - throw new GetPeMethodException(1, "找不到模块:" + peModuleFullName + "当前程序没有加载这个东西?"); - var hModule = WindowsAPI.GetModuleHandle(peModuleFullName); // 执行前必须加载了先,acad.exe/accore.dll - if (hModule == IntPtr.Zero) - throw new GetPeMethodException(1, "找不到模块:" + peModuleFullName + "当前程序没有加载这个东西?"); - - // 遍历函数接口名单 - var names = peInfo.ExportDirectory?.FunctionNames(); - if (names == null) - throw new ArgumentException(nameof(names)); - - foreach (var name in names) - { - if (name.Contains(findFuncName))// 这里是名称含有,不是容器含有 - { - var fn = new PeFunction(name) - { - ModuleFullName = peModuleFullName, - ModuleIntPtr = hModule - }; - funcAdress_Out.Add(fn); - } - } - } -} - - - -/// -/// 错误信息 -/// -public class GetPeMethodException : ApplicationException -{ - /// - /// - /// - public int ErrorNum; - /// - /// - /// - public string? ErrorMsg; - /// - /// - /// - public Exception? InnerException1; - /// - /// - /// - /// - public GetPeMethodException(string msg) : base(msg) - { - ErrorMsg = msg; - } - /// - /// - /// - /// - /// - public GetPeMethodException(int errorNum, string msg) : base(msg) - { - ErrorNum = errorNum; - } - /// - /// - /// - /// - /// - public GetPeMethodException(string msg, Exception innerException) : base(msg, innerException) - { - InnerException1 = innerException; - ErrorMsg = msg; - } -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/PE/DBmod.cs b/src/CAD/IFox.CAD.Shared/PE/DBmod.cs deleted file mode 100644 index b45a033..0000000 --- a/src/CAD/IFox.CAD.Shared/PE/DBmod.cs +++ /dev/null @@ -1,120 +0,0 @@ -namespace IFoxCAD.Cad; - -/// -/// 获取数据库修改状态 -/// -/// 相关链接 -/// -[Flags] -public enum DBmod : short -{ - /// - /// 数据库未修改 - /// - [Description("数据库未修改")] - DatabaseNoModifies = 0, - /// - /// 数据库有修改 - /// - [Description("数据库有修改")] - Database = 1, - /// - /// 变量有修改 - /// - [Description("变量有修改")] - Value = 4, - /// - /// 窗口有修改 - /// - [Description("窗口有修改")] - Window = 8, - /// - /// 视图有修改 - /// - [Description("视图有修改")] - View = 16, - /// - /// 字段有修改 - /// - [Description("字段有修改")] - Field = 32 -} -/// -/// 图形修改状态 -/// -public class DBmodEx -{ - /// - /// 图形修改状态 - /// - public static DBmod DBmod => (DBmod)Env.GetVar("dbmod"); - - delegate long DelegateAcdbSetDbmod(IntPtr db, DBmod newValue); - static DelegateAcdbSetDbmod? acdbSetDbmod;//别改名称 - /// - /// 设置图形修改状态 - /// - /// 数据库的指针 - /// 修改状态 - /// - public static long AcdbSetDbmod(IntPtr db, DBmod newValue) - { - acdbSetDbmod ??= AcadPeInfo.GetDelegate( - nameof(acdbSetDbmod), AcadPeEnum.Acdb); - if (acdbSetDbmod is null) - return -1; - return acdbSetDbmod.Invoke(db, newValue);// 调用方法 - } - - /// - /// Dbmod 不被修改的任务 - /// - /// - public static void DBmodTask(Action action) - { - var dm = Acap.DocumentManager; - if (dm.Count == 0) - return; - var doc = dm.MdiActiveDocument; - if (doc is null) - return; - - var bak = DBmod; - action.Invoke(); - if (bak == DBmod.DatabaseNoModifies && DBmod != DBmod.DatabaseNoModifies) - AcdbSetDbmod(doc.Database.UnmanagedObject, DBmod.DatabaseNoModifies); - } - - static bool _flag = true; - /// - /// 请在无法处理的初始化才使用它 - /// (源泉在初始化的时候进行了修改数据库,所以必须要用一个新线程等待lisp执行完成才可以) - /// - public static void DatabaseNoModifies() - { - if (_flag)// 仅执行一次,在初始化时候 - { - var dm = Acap.DocumentManager; - if (dm.Count == 0) - return; - var doc = dm.MdiActiveDocument; - if (doc is null) - return; - - if (DBmod != DBmod.DatabaseNoModifies) - AcdbSetDbmod(doc.Database.UnmanagedObject, DBmod.DatabaseNoModifies); - _flag = false; - } - } - - - //[CommandMethod(nameof(TestCmd_AcdbSetDbmodChange))] - //public void TestCmd_AcdbSetDbmodChange() - //{ - // DBmodTask(() => { - // using DBTrans tr = new(); - // Line line = new(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); - // tr.CurrentSpace.AddEntity(line); - // }); - //} -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/PE/PostCmd.cs b/src/CAD/IFox.CAD.Shared/PE/PostCmd.cs deleted file mode 100644 index 7e70074..0000000 --- a/src/CAD/IFox.CAD.Shared/PE/PostCmd.cs +++ /dev/null @@ -1,237 +0,0 @@ -namespace IFoxCAD.Cad; -/// -/// 发送命令 -/// -public class PostCmd -{ - /* - * #if NET35 || NET40 - * [DllImport("acad.exe", EntryPoint = "acedCmd", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)] - * #else - * // cad2015的AcedCmd改为AcedCmdS.参数也改了,不过不影响pe读取,accore.dll是2013版本后才开始改 - * [DllImport("accore.dll", EntryPoint = "acedCmdS", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)] - * static extern int AcedCmd(IntPtr rbp, bool forFutureUse = false, IntPtr pForFutureUse = IntPtr.Zero); - * #endif - * static extern int AcedCmd(IntPtr rbp); - * public static int AcedCmd(ResultBuffer args) - * { - * if (Acap.DocumentManager.IsApplicationContext) - * return 0; - * else - * return AcedCmd(args.UnmanagedObject); - * } - */ - delegate int DelegateAcedCmd(IntPtr parameter); - static DelegateAcedCmd? acedCmd;//nameof 别改名称 - /// - /// 发送命令(同步)如果2015.+这里报错,那么表示vs需要提权测试 - /// - static PromptStatus AcedCmd(ResultBuffer args) - { - if (Acap.DocumentManager.IsApplicationContext) - return 0; - if (acedCmd is null) - { - string str = nameof(acedCmd); - if (Acap.Version.Major >= 20)// 2015.+ - str += "S"; - - acedCmd = AcadPeInfo.GetDelegate( - str, AcadPeEnum.ExeAndCore); - } - if (acedCmd is null) - return 0; - - var result = (PromptStatus)acedCmd.Invoke(args.UnmanagedObject); - if (result != PromptStatus.OK) - throw new ArgumentException("发送命令出错,是否vs权限不足?"); - return result; - } - - /* - * [DllImport("accore.dll", EntryPoint = "acedCommand")] - * static extern int AcedCommand(IntPtr vlist); - */ - delegate int DelegateAcedCommand(IntPtr parameter); - static DelegateAcedCommand? acedCommand;//nameof 别改名称 - /// - /// 发送命令(同步) - /// - static PromptStatus AcedCommand(IntPtr args) - { - acedCommand ??= AcadPeInfo.GetDelegate( - nameof(acedCommand), AcadPeEnum.ExeAndCore); - if (acedCommand is null) - return PromptStatus.Error; - return (PromptStatus)acedCommand.Invoke(args);// 调用方法 - } - - /* - * [DllImport("acad.exe", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, - * EntryPoint = "?acedPostCommand@@YAHPB_W@Z")] - * public static extern int AcedPostCommand(string strExpr); - */ - delegate int DelegateAcedPostCommand(byte[] parameter); - static DelegateAcedPostCommand? acedPostCommand;//nameof 别改名称 - /// - /// 发送命令(同步) - /// 这个可以在多线程发送 - /// - static PromptStatus AcedPostCommand(string args) - { - acedPostCommand ??= AcadPeInfo.GetDelegate( - nameof(acedPostCommand), AcadPeEnum.ExeAndCore); - - // 不然到CAD之后会乱码 - byte[] bytes = Encoding.Unicode.GetBytes(args); - if (acedPostCommand is null) - return PromptStatus.Error; - return (PromptStatus)acedPostCommand.Invoke(bytes);// 调用方法 - } - - delegate int DelegateAcedInvoke(byte[] parameter); - static DelegateAcedInvoke? acedInvoke;//nameof 别改名称 - /// - /// 发送命令(同步) - /// - static PromptStatus AcedInvoke(string args) - { - acedInvoke ??= AcadPeInfo.GetDelegate( - nameof(acedInvoke), AcadPeEnum.ExeAndCore); - - // 不然到CAD之后会乱码 - byte[] bytes = Encoding.Unicode.GetBytes(args); - - if (acedInvoke is null) - return PromptStatus.Error; - return (PromptStatus)acedInvoke.Invoke(bytes);// 调用方法 - } - - /// - /// 发送命令(异步)+CommandFlags.Session可以同步发送 - /// - static void AsyncCommand(string args) - { - object[] commandArray = { args + "\n" }; -#if zcad - var com = Acap.ZcadApplication; -#else - var com = Acap.AcadApplication; -#endif - // activeDocument 加载lisp第二个文档有问题,似乎要切换了才能 - var doc = com.GetType() - .InvokeMember("ActiveDocument", BindingFlags.GetProperty, null, com, null); - doc?.GetType() - .InvokeMember("SendCommand", BindingFlags.InvokeMethod, null, doc, commandArray);// 返回值是null - } - /// - /// 命令模式 - /// - public enum RunCmdFlag : byte - { - /// - /// 发送命令(同步)如果2015.+这里报错,那么表示vs需要提权测试 - /// - AcedCmd = 1, - /// - /// 发送命令(同步) - /// - AcedCommand = 2, - /// - /// 发送命令(同步),可以多线程 - /// - AcedPostCommand = 4, - /// - /// 发送命令(同步) - /// - AcedInvoke = 8, - /// - /// 默认的发送命令 - /// - SendStringToExecute = 16, - /// - /// 异步命令 - /// - AsyncCommand = 32, - } - - /* - * 发送命令会记录在命令历史 - * 发送lisp的(command "xx")就不会 - */ - /// - /// 发送命令 - /// - /// - /// - public static PromptStatus SendCommand(ResultBuffer args) - { - return AcedCmd(args); - } - /// - /// 发送命令 - /// - /// - /// - public static PromptStatus SendCommand(IntPtr args) - { - return AcedCommand(args); - } - /// - /// 发送命令 - /// - /// - /// - /// - public static PromptStatus SendCommand(string args, RunCmdFlag flag) - { - PromptStatus ret = PromptStatus.OK; - if (!Acap.DocumentManager.IsApplicationContext) - { - if ((flag & RunCmdFlag.AcedCmd) == RunCmdFlag.AcedCmd) - { - using ResultBuffer rb = new() - { - new((int)LispDataType.Text, args), - }; - ret = SendCommand(rb); - } - if ((flag & RunCmdFlag.AcedCommand) == RunCmdFlag.AcedCommand) - { - // 此处是这样转换吗? - using ResultBuffer rb = new() - { - new((int)LispDataType.Text, args), - }; - ret = SendCommand(rb.UnmanagedObject); - } - if ((flag & RunCmdFlag.AcedPostCommand) == RunCmdFlag.AcedPostCommand) - { - ret = AcedPostCommand(args); - } - if ((flag & RunCmdFlag.AcedInvoke) == RunCmdFlag.AcedInvoke) - { - ret = AcedInvoke(args); - } - } - else - { - var dm = Acap.DocumentManager; - var doc = dm.MdiActiveDocument; - if (doc == null) - return PromptStatus.Error; - - if ((flag & RunCmdFlag.SendStringToExecute) == RunCmdFlag.SendStringToExecute) - { - doc.SendStringToExecute(args, true, false, false); - } - if ((flag & RunCmdFlag.AsyncCommand) == RunCmdFlag.AsyncCommand) - { - // 此处+CommandFlags.Session可以同步发送,bo命令可以,其他是否可以? - // 仿人工输入,像lisp一样可以直接发送关键字 - AsyncCommand(args); - } - } - return ret; - } -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/PE/ProgramPE.cs b/src/CAD/IFox.CAD.Shared/PE/ProgramPE.cs deleted file mode 100644 index 32208fc..0000000 --- a/src/CAD/IFox.CAD.Shared/PE/ProgramPE.cs +++ /dev/null @@ -1,1576 +0,0 @@ -#pragma warning disable CS1591 // 缺少对公共可见类型或成员的 XML 注释 -namespace IFoxCAD.Cad; - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Data; -using System.IO; -using System.Text; - - -/* 来源 https://blog.csdn.net/zgke/article/details/2955560 我在他基础上面增加了X64的处理 - * 调用例子 - static void Main(string[] args) - { - var path = @"C:\Program Files\Autodesk\AutoCAD 2021\acad.exe"; - // path = @"G:\AutoCAD 2008\acad.exe"; - - var pe = new JoinBox.BasalCurrency.PeInfo(path); - - // 输出所有的函数名 - var sb = new StringBuilder(); - foreach (var item in pe.ExportDirectory.NameList) - { - sb.Append(Environment.NewLine); - var str = System.Text.Encoding.Default.GetString(item as byte[]); - sb.Append(str); - } - Debugx.Printl(sb.ToString()); - - // 原作者的封装 - var ss = pe.GetPETable(); - foreach (var item in ss.Tables) - { - } - } -*/ - -/// -/// 微软软件结构PE信息 -/// -public class PeInfo -{ - #region 成员 - /// - /// 获取是否正常打开文件 - /// - public bool OpenFile { get; private set; } = false; - - public DosHeader? DosHeader { get; private set; } - - public DosStub? DosStub { get; private set; } - public PEHeader? PEHeader { get; private set; } - public OptionalHeader? OptionalHeader { get; private set; } - public OptionalDirAttrib? OptionalDirAttrib { get; private set; } - public SectionTable? SectionTable { get; private set; } - /// - /// 函数接口名单 - /// - public ExportDirectory? ExportDirectory { get; private set; } - public ImportDirectory? ImportDirectory { get; private set; } - public ResourceDirectory? ResourceDirectory { get; private set; } - /// - /// PE文件完整路径 - /// - public string? FullName; - - bool _IsX86 = true; - - /// - /// 全部文件数据 - /// - readonly byte[]? _PEFileByte; - /// - /// 文件读取的位置 - /// - long _PEFileIndex = 0; - #endregion - - #region 构造 - /// - /// 构造函数 - /// - /// - /// - public PeInfo(string fullName) - { - if (fullName is null) - throw new ArgumentException(nameof(fullName)); ; - - FullName = fullName; - FileStream? file = null; - OpenFile = false; - try - { - // 文件流 - file = new FileStream(fullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);// FileShare才能进c盘 - _PEFileByte = new byte[file.Length]; - file.Read(_PEFileByte, 0, _PEFileByte.Length); - LoadFile(); - OpenFile = true; - } - catch (Exception) { throw; } - finally - { - file?.Close(); - } - } - #endregion - - #region 读表方法 - /// - /// 开始读取 - /// - private void LoadFile() - { - LoadDosHeader(); // 获取DOS头,为了兼容DOS所以首先处理这个,然后才到PE头 - LoadDosStub(); // 获取DOS的身体 - LoadPEHeader(); // PE头 - LoadOptionalHeader(); // PE头扩展 - LoadOptionalDirAttrib(); // 获取选项目录属性 - LoadSectionTable(); // 获取节表 - LoadExportDirectory(); // 获取输出表 - LoadImportDirectory(); // 获取输入表 - LoadResourceDirectory(); // 获取资源目录 - } - - /// - /// 获得DOS头 - /// - private void LoadDosHeader() - { - DosHeader = new DosHeader - { - FileStarIndex = _PEFileIndex - }; - Loadbyte(ref DosHeader.e_magic); - Loadbyte(ref DosHeader.e_cblp); - Loadbyte(ref DosHeader.e_cp); - Loadbyte(ref DosHeader.e_crlc); - Loadbyte(ref DosHeader.e_cparhdr); - Loadbyte(ref DosHeader.e_minalloc); - Loadbyte(ref DosHeader.e_maxalloc); - Loadbyte(ref DosHeader.e_ss); - Loadbyte(ref DosHeader.e_sp); - Loadbyte(ref DosHeader.e_csum); - Loadbyte(ref DosHeader.e_ip); - Loadbyte(ref DosHeader.e_cs); - Loadbyte(ref DosHeader.e_rva); - Loadbyte(ref DosHeader.e_fg); - Loadbyte(ref DosHeader.e_bl1); - Loadbyte(ref DosHeader.e_oemid); - Loadbyte(ref DosHeader.e_oeminfo); - Loadbyte(ref DosHeader.e_bl2); - Loadbyte(ref DosHeader.e_PESTAR); - - DosHeader.FileEndIndex = _PEFileIndex; - } - - /// - /// 获得DOS SUB字段 - /// - private void LoadDosStub() - { - if (DosHeader is null) - return; - - long Size = GetLong(DosHeader.e_PESTAR) - _PEFileIndex; // 获得SUB的大小 - DosStub = new DosStub(Size) - { - FileStarIndex = _PEFileIndex - }; - Loadbyte(ref DosStub.DosStubData); - DosStub.FileEndIndex = _PEFileIndex; - } - - /// - /// 获得PE的文件头 - /// - /// - private void LoadPEHeader() - { - PEHeader = new PEHeader - { - FileStarIndex = _PEFileIndex - }; - Loadbyte(ref PEHeader.Header); - Loadbyte(ref PEHeader.Machine);// [76 1]==[0x4C 1]是x32, - _IsX86 = PEHeader.Machine[0] == 0x4c && PEHeader.Machine[1] == 0x1; - // (PEHeader.Machine[0] == 0x64 && PEHeader.Machine[1] == 0x86)// x64 - Loadbyte(ref PEHeader.NumberOfSections); - Loadbyte(ref PEHeader.TimeDateStamp); - Loadbyte(ref PEHeader.PointerToSymbolTable); - Loadbyte(ref PEHeader.NumberOfSymbols); - Loadbyte(ref PEHeader.SizeOfOptionalHeader); - Loadbyte(ref PEHeader.Characteristics); - PEHeader.FileEndIndex = _PEFileIndex; - } - - /// - /// 获得OPTIONAL PE扩展属性 - /// - /// - private void LoadOptionalHeader() - { - // 这里必须通过PE文件来判断它是一个什么架构,从而使用x86-x64 - OptionalHeader = new OptionalHeader(_IsX86) - { - FileStarIndex = _PEFileIndex - }; - Loadbyte(ref OptionalHeader.Magic); - Loadbyte(ref OptionalHeader.MajorLinkerVersion); - Loadbyte(ref OptionalHeader.MinorLinkerVersion); - Loadbyte(ref OptionalHeader.SizeOfCode); - Loadbyte(ref OptionalHeader.SizeOfInitializedData); - Loadbyte(ref OptionalHeader.SizeOfUninitializedData); - Loadbyte(ref OptionalHeader.AddressOfEntryPoint); - Loadbyte(ref OptionalHeader.BaseOfCode); - Loadbyte(ref OptionalHeader.ImageBase); - Loadbyte(ref OptionalHeader.BaseOfData); - Loadbyte(ref OptionalHeader.SectionAlignment); - Loadbyte(ref OptionalHeader.FileAlignment); - - Loadbyte(ref OptionalHeader.MajorOperatingSystemVersion); - Loadbyte(ref OptionalHeader.MinorOperatingSystemVersion); - Loadbyte(ref OptionalHeader.MajorImageVersion); - Loadbyte(ref OptionalHeader.MinorImageVersion); - Loadbyte(ref OptionalHeader.MajorSubsystemVersion); - Loadbyte(ref OptionalHeader.MinorSubsystemVersion); - Loadbyte(ref OptionalHeader.Win32VersionValue); - Loadbyte(ref OptionalHeader.SizeOfImage); - Loadbyte(ref OptionalHeader.SizeOfHeards); - Loadbyte(ref OptionalHeader.CheckSum); - Loadbyte(ref OptionalHeader.Subsystem); - Loadbyte(ref OptionalHeader.DLLCharacteristics); - Loadbyte(ref OptionalHeader.SizeOfStackReserve); - Loadbyte(ref OptionalHeader.SizeOfStackCommit); - Loadbyte(ref OptionalHeader.SizeOfHeapReserve); - Loadbyte(ref OptionalHeader.SizeOfHeapCommit); - Loadbyte(ref OptionalHeader.LoaderFlags); - Loadbyte(ref OptionalHeader.NumberOfRvaAndSizes); - - OptionalHeader.FileEndIndex = _PEFileIndex; - } - - /// - /// 获取目录表 - /// - /// - private void LoadOptionalDirAttrib() - { - if (OptionalHeader is null) - return; - - OptionalDirAttrib = new OptionalDirAttrib - { - FileStarIndex = _PEFileIndex - }; - - long DirCount = GetLong(OptionalHeader.NumberOfRvaAndSizes);// 这里导致无法使用64位 - for (int i = 0; i != DirCount; i++) - { - OptionalDirAttrib.DirAttrib? directAttrib = new(); - Loadbyte(ref directAttrib.DirRva); - Loadbyte(ref directAttrib.DirSize); - OptionalDirAttrib.DirByte.Add(directAttrib); - } - OptionalDirAttrib.FileEndIndex = _PEFileIndex; - } - - /// - /// 获取节表 - /// - private void LoadSectionTable() - { - if (PEHeader is null) - return; - - SectionTable = new SectionTable(); - long Count = GetLong(PEHeader.NumberOfSections); - SectionTable.FileStarIndex = _PEFileIndex; - for (long i = 0; i != Count; i++) - { - var Section = new SectionTable.SectionData(); - - Loadbyte(ref Section.SectName); - Loadbyte(ref Section.VirtualAddress); - Loadbyte(ref Section.SizeOfRawDataRVA); - Loadbyte(ref Section.SizeOfRawDataSize); - Loadbyte(ref Section.PointerToRawData); - Loadbyte(ref Section.PointerToRelocations); - Loadbyte(ref Section.PointerToLinenumbers); - Loadbyte(ref Section.NumberOfRelocations); - Loadbyte(ref Section.NumberOfLinenumbers); - Loadbyte(ref Section.Characteristics); - SectionTable.Section.Add(Section); - } - SectionTable.FileEndIndex = _PEFileIndex; - } - - /// - /// 读取输出表 - /// - private void LoadExportDirectory() - { - if (OptionalDirAttrib is null) - return; - if (OptionalDirAttrib.DirByte.Count == 0) - return; - - if (OptionalDirAttrib.DirByte[0] is not OptionalDirAttrib.DirAttrib exporRVA || - GetLong(exporRVA.DirRva) == 0) - return; - - long exporAddress = GetLong(exporRVA.DirRva); // 获取的位置 - ExportDirectory = new ExportDirectory(); - - if (SectionTable is null) - return; - - for (int i = 0; i != SectionTable.Section.Count; i++) // 循环节表 - { - if (SectionTable.Section[i] is not SectionTable.SectionData sect) - continue; - - long starRva = GetLong(sect.SizeOfRawDataRVA); - long endRva = GetLong(sect.SizeOfRawDataSize); - - if (exporAddress >= starRva && exporAddress < starRva + endRva) - { - _PEFileIndex = exporAddress - GetLong(sect.SizeOfRawDataRVA) + GetLong(sect.PointerToRawData); - - ExportDirectory.FileStarIndex = _PEFileIndex; - ExportDirectory.FileEndIndex = _PEFileIndex + GetLong(exporRVA.DirSize); - - Loadbyte(ref ExportDirectory.Characteristics); - Loadbyte(ref ExportDirectory.TimeDateStamp); - Loadbyte(ref ExportDirectory.MajorVersion); - Loadbyte(ref ExportDirectory.MinorVersion); - Loadbyte(ref ExportDirectory.Name); - Loadbyte(ref ExportDirectory.Base); - Loadbyte(ref ExportDirectory.NumberOfFunctions); - Loadbyte(ref ExportDirectory.NumberOfNames); - Loadbyte(ref ExportDirectory.AddressOfFunctions); - Loadbyte(ref ExportDirectory.AddressOfNames); - Loadbyte(ref ExportDirectory.AddressOfNameOrdinals); - - _PEFileIndex = GetLong(ExportDirectory.AddressOfFunctions) - GetLong(sect.SizeOfRawDataRVA) + GetLong(sect.PointerToRawData); - long endIndex = GetLong(ExportDirectory.AddressOfNames) - GetLong(sect.SizeOfRawDataRVA) + GetLong(sect.PointerToRawData); - long numb = (endIndex - _PEFileIndex) / 4; - for (long z = 0; z != numb; z++) - { - byte[] Data = new byte[4]; - Loadbyte(ref Data); - ExportDirectory.AddressOfFunctionsList.Add(Data); - } - - _PEFileIndex = endIndex; - endIndex = GetLong(ExportDirectory.AddressOfNameOrdinals) - GetLong(sect.SizeOfRawDataRVA) + GetLong(sect.PointerToRawData); - numb = (endIndex - _PEFileIndex) / 4; - for (long z = 0; z != numb; z++) - { - byte[] Data = new byte[4]; - Loadbyte(ref Data); - ExportDirectory.AddressOfNamesList.Add(Data); - } - - _PEFileIndex = endIndex; - endIndex = GetLong(ExportDirectory.Name) - GetLong(sect.SizeOfRawDataRVA) + GetLong(sect.PointerToRawData); - numb = (endIndex - _PEFileIndex) / 2; - for (long z = 0; z != numb; z++) - { - byte[] Data = new byte[2]; - Loadbyte(ref Data); - ExportDirectory.AddressOfNameOrdinalsList.Add(Data); - } - - _PEFileIndex = endIndex; - - if (_PEFileByte is not null) - { - long ReadIndex = 0; - while (true) - { - if (_PEFileByte[_PEFileIndex + ReadIndex] == 0) - { - if (_PEFileByte[_PEFileIndex + ReadIndex + 1] == 0) - break; - - var Date = new byte[ReadIndex]; - Loadbyte(ref Date); - ExportDirectory.FunctionNamesByte.Add(Date); - - _PEFileIndex++; - ReadIndex = 0; - } - ReadIndex++; - } - } - break; - } - } - } - - /// - /// 读取输入表 - /// - private void LoadImportDirectory() - { - if (OptionalDirAttrib is null) - return; - if (OptionalDirAttrib.DirByte.Count < 1) - return; - if (OptionalDirAttrib.DirByte[1] is not OptionalDirAttrib.DirAttrib ImporRVA) - return; - - long ImporAddress = GetLong(ImporRVA.DirRva); // 获取的位置 - if (ImporAddress == 0) - return; - long ImporSize = GetLong(ImporRVA.DirSize); // 获取大小 - - ImportDirectory = new ImportDirectory(); - - long SizeRva = 0; - long PointerRva = 0; - - long StarRva = 0; - long EndRva = 0; - - #region 获取位置 - if (SectionTable is null) - return; - for (int i = 0; i != SectionTable.Section.Count; i++) // 循环节表 - { - if (SectionTable.Section[i] is not SectionTable.SectionData Sect) - continue; - - StarRva = GetLong(Sect.SizeOfRawDataRVA); - EndRva = GetLong(Sect.SizeOfRawDataSize); - - if (ImporAddress >= StarRva && ImporAddress < StarRva + EndRva) - { - SizeRva = GetLong(Sect.SizeOfRawDataRVA); - PointerRva = GetLong(Sect.PointerToRawData); - _PEFileIndex = ImporAddress - SizeRva + PointerRva; - - ImportDirectory.FileStarIndex = _PEFileIndex; - ImportDirectory.FileEndIndex = _PEFileIndex + ImporSize; - break; - } - } - - if (SizeRva == 0 && PointerRva == 0) - return; - #endregion - - #region 输入表结构 - while (true) - { - var import = new ImportDirectory.ImportDate(); - Loadbyte(ref import.OriginalFirstThunk); - Loadbyte(ref import.TimeDateStamp); - Loadbyte(ref import.ForwarderChain); - Loadbyte(ref import.Name); - Loadbyte(ref import.FirstThunk); - - if (GetLong(import.Name) == 0) - break; - ImportDirectory.ImportList.Add(import); // 添加 - } - #endregion - - - #region 获取输入DLL名称 - for (int z = 0; z != ImportDirectory.ImportList.Count; z++) // 获取引入DLL名字 - { - if (ImportDirectory.ImportList[z] is not ImportDirectory.ImportDate Import) - continue; - - long ImportDLLName = GetLong(Import.Name) - SizeRva + PointerRva; - _PEFileIndex = ImportDLLName; - long ReadCount = 0; - while (_PEFileByte is not null) // 获取引入名 - { - if (_PEFileByte[_PEFileIndex + ReadCount] == 0) - { - Import.DLLName = new byte[ReadCount]; - Loadbyte(ref Import.DLLName); - break; - } - ReadCount++; - } - } - #endregion - - #region 获取引入方法 先获取地址 然后获取名字和头 - for (int z = 0; z != ImportDirectory.ImportList.Count; z++) // 获取引入方法 - { - if (ImportDirectory.ImportList[z] is not ImportDirectory.ImportDate import) - continue; - - long importDLLName = GetLong(import.OriginalFirstThunk) - SizeRva + PointerRva; - _PEFileIndex = importDLLName; - while (true) - { - var function = new ImportDirectory.ImportDate.FunctionList(); - Loadbyte(ref function.OriginalFirst); - - long loadIndex = GetLong(function.OriginalFirst); - if (loadIndex == 0) - break; - long oldIndex = _PEFileIndex; - - _PEFileIndex = loadIndex - SizeRva + PointerRva; - - if (loadIndex >= StarRva && loadIndex < StarRva + EndRva) // 发现有些数字超级大 - { - int ReadCount = 0; - - while (_PEFileByte is not null) - { - if (ReadCount == 0) - Loadbyte(ref function.FunctionHead); - if (_PEFileByte[_PEFileIndex + ReadCount] == 0) - { - byte[] FunctionName = new byte[ReadCount]; - Loadbyte(ref FunctionName); - function.FunctionName = FunctionName; - - break; - } - ReadCount++; - } - } - else - { - function.FunctionName = new byte[1]; - } - - _PEFileIndex = oldIndex; - import.DLLFunctionList.Add(function); - } - } - #endregion - } - - /// - /// 读取资源表 - /// - private void LoadResourceDirectory() - { - #region 初始化 - if (OptionalDirAttrib is null || OptionalDirAttrib.DirByte.Count < 3) - return; - if (OptionalDirAttrib.DirByte[2] is not OptionalDirAttrib.DirAttrib ImporRVA) - return; - - long ImporAddress = GetLong(ImporRVA.DirRva); // 获取的位置 - if (ImporAddress == 0) - return; - long ImporSize = GetLong(ImporRVA.DirSize); // 获取大小 - - ResourceDirectory = new ResourceDirectory(); - - long SizeRva = 0; - long PointerRva = 0; - long StarRva = 0; - long PEIndex = 0; - #endregion - - #region 获取位置 - if (SectionTable is null) - return; - - for (int i = 0; i != SectionTable.Section.Count; i++) // 循环节表 - { - if (SectionTable.Section[i] is not SectionTable.SectionData sect) - continue; - - StarRva = GetLong(sect.SizeOfRawDataRVA); - var EndRva = GetLong(sect.SizeOfRawDataSize); - if (ImporAddress >= StarRva && ImporAddress < StarRva + EndRva) - { - SizeRva = GetLong(sect.SizeOfRawDataRVA); - PointerRva = GetLong(sect.PointerToRawData); - _PEFileIndex = ImporAddress - SizeRva + PointerRva; - PEIndex = _PEFileIndex; - ResourceDirectory.FileStarIndex = _PEFileIndex; - ResourceDirectory.FileEndIndex = _PEFileIndex + ImporSize; - break; - } - } - - if (SizeRva == 0 && PointerRva == 0) - return; - #endregion - - AddResourceNode(ResourceDirectory, PEIndex, 0, StarRva); - } - - /// - /// 添加资源节点 - /// - /// - /// - /// - /// - private void AddResourceNode(ResourceDirectory node, long PEIndex, long RVA, long resourSectRva) - { - _PEFileIndex = PEIndex + RVA; // 设置位置 - Loadbyte(ref node.Characteristics); - Loadbyte(ref node.TimeDateStamp); - Loadbyte(ref node.MajorVersion); - Loadbyte(ref node.MinorVersion); - Loadbyte(ref node.NumberOfNamedEntries); - Loadbyte(ref node.NumberOfIdEntries); - - long NameRVA = GetLong(node.NumberOfNamedEntries); - for (int i = 0; i != NameRVA; i++) - { - var Entry = new ResourceDirectory.DirectoryEntry(); - Loadbyte(ref Entry.Name); - Loadbyte(ref Entry.Id); - byte[] temp = new byte[2]; - temp[0] = Entry.Name[0]; - temp[1] = Entry.Name[1]; - - if (_PEFileByte is null) - return; - - long NameIndex = GetLong(temp) + PEIndex; - temp[0] = _PEFileByte[NameIndex + 0]; - temp[1] = _PEFileByte[NameIndex + 1]; - - long NameCount = GetLong(temp); - node.Name = new byte[NameCount * 2]; - - for (int z = 0; z != node.Name.Length; z++) - node.Name[z] = _PEFileByte[NameIndex + 2 + z]; - // System.Windows.Forms.MessageBox.Show(GetString(Entry.ID)); - - temp[0] = Entry.Id[2]; - temp[1] = Entry.Id[3]; - - long oldIndex = _PEFileIndex; - - if (GetLong(temp) == 0) - { - temp[0] = Entry.Id[0]; - temp[1] = Entry.Id[1]; - - _PEFileIndex = GetLong(temp) + PEIndex; - - var dataRVA = new ResourceDirectory.DirectoryEntry.DataEntry(); - - Loadbyte(ref dataRVA.ResourRVA); - Loadbyte(ref dataRVA.ResourSize); - Loadbyte(ref dataRVA.ResourTest); - Loadbyte(ref dataRVA.ResourWen); - - _PEFileIndex = oldIndex; - Entry.DataEntryList.Add(dataRVA); - // System.Windows.Forms.MessageBox.Show(GetString(DataRVA.ResourRVA)+"*"+GetString(DataRVA.ResourSize)); - } - else - { - temp[0] = Entry.Id[0]; - temp[1] = Entry.Id[1]; - - var Resource = new ResourceDirectory(); - Entry.NodeDirectoryList.Add(Resource); - AddResourceNode(Resource, PEIndex, GetLong(temp), resourSectRva); - } - _PEFileIndex = oldIndex; - node.EntryList.Add(Entry); - } - - long Count = GetLong(node.NumberOfIdEntries); - for (int i = 0; i != Count; i++) - { - var entry = new ResourceDirectory.DirectoryEntry(); - Loadbyte(ref entry.Name); - Loadbyte(ref entry.Id); - // System.Windows.Forms.MessageBox.Show(GetString(Entry.Name)+"_"+GetString(Entry.Id)); - - byte[] temp = new byte[2]; - temp[0] = entry.Id[2]; - temp[1] = entry.Id[3]; - - long OldIndex = _PEFileIndex; - - if (GetLong(temp) == 0) - { - temp[0] = entry.Id[0]; - temp[1] = entry.Id[1]; - - _PEFileIndex = GetLong(temp) + PEIndex; - - var dataRVA = new ResourceDirectory.DirectoryEntry.DataEntry(); - Loadbyte(ref dataRVA.ResourRVA); - Loadbyte(ref dataRVA.ResourSize); - Loadbyte(ref dataRVA.ResourTest); - Loadbyte(ref dataRVA.ResourWen); - - long FileRva = GetLong(dataRVA.ResourRVA) - resourSectRva + PEIndex; - - dataRVA.FileStarIndex = FileRva; - dataRVA.FileEndIndex = FileRva + GetLong(dataRVA.ResourSize); - - _PEFileIndex = OldIndex; - entry.DataEntryList.Add(dataRVA); - // System.Windows.Forms.MessageBox.Show(GetString(DataRVA.ResourRVA)+"*"+GetString(DataRVA.ResourSize)); - } - else - { - temp[0] = entry.Id[0]; - temp[1] = entry.Id[1]; - var Resource = new ResourceDirectory(); - entry.NodeDirectoryList.Add(Resource); - AddResourceNode(Resource, PEIndex, GetLong(temp), resourSectRva); - } - _PEFileIndex = OldIndex; - node.EntryList.Add(entry); - } - } - - #endregion - - #region 工具方法 - /// - /// 读数据 读byte[]的数量 会改边PEFileIndex的值 - /// - /// - private void Loadbyte(ref byte[] data) - { - if (_PEFileByte is null) - return; - - for (int i = 0; i != data.Length; i++) - { - data[i] = _PEFileByte[_PEFileIndex]; - _PEFileIndex++; - } - } - /// - /// 转换byte为字符串 - /// - /// byte[] - /// AA BB CC DD - private string GetString(byte[] data) - { - string Temp = ""; - for (int i = 0; i != data.Length - 1; i++) - Temp += data[i].ToString("X02") + " "; - - Temp += data[data.Length - 1].ToString("X02"); - // Temp += data[^1].ToString("X02"); - return Temp; - } - /// - /// 转换字符为显示数据 - /// - /// byte[] - /// ASCII DEFAULT UNICODE BYTE - /// - private string GetString(byte[] data, string type) - { - if (type.Trim().ToUpper() == "ASCII") - return System.Text.Encoding.ASCII.GetString(data); - if (type.Trim().ToUpper() == "DEFAULT") - return System.Text.Encoding.Default.GetString(data); - if (type.Trim().ToUpper() == "UNICODE") - return System.Text.Encoding.Unicode.GetString(data); - if (type.Trim().ToUpper() == "BYTE") - { - string Temp = ""; - for (int i = data.Length - 1; i != 0; i--) - Temp += data[i].ToString("X02") + " "; - Temp += data[0].ToString("X02"); - return Temp; - } - return GetInt(data); - } - /// - /// 转换BYTE为INT - /// - /// - /// - static string GetInt(byte[] data) - { - string Temp = ""; - for (int i = 0; i != data.Length - 1; i++) - { - int ByteInt = (int)data[i]; - Temp += ByteInt.ToString() + " "; - } - int EndByteInt = (int)data[data.Length - 1]; - // int EndByteInt = (int)data[^1]; - Temp += EndByteInt.ToString(); - return Temp; - } - /// - /// 转换数据为LONG - /// - /// - /// - private long GetLong(byte[] data) - { - if (data.Length > 4) - return 0; - - string MC = ""; - // if (data.Length <= 4) - for (int i = data.Length - 1; i != -1; i--) - MC += data[i].ToString("X02"); - return Convert.ToInt64(MC, 16); - } - /// - /// 添加一行信息 - /// - /// 表 - /// 数据 - /// 名称 - /// 说明 - private void AddTableRow(DataTable refTable, byte[]? data, string name, string describe) - { - if (data == null) - throw new ArgumentException(nameof(data)); - - refTable.Rows.Add( - new string[] - { - name, - data.Length.ToString(), - GetString(data), - GetLong(data).ToString(), - GetString(data,"ASCII"), - describe - }); - } - #endregion - - #region Table绘制 - /// - /// 获取PE信息 DataSet方式 - /// - /// 多个表 最后资源表 绘制成树结构TABLE - public DataSet? GetPETable() - { - if (OpenFile == false) - return null; - - var ds = new DataSet("PEFile"); - var a1 = TableDosHeader(); - if (a1 is not null) - ds.Tables.Add(a1); - var a2 = TablePEHeader(); - if (a2 is not null) - ds.Tables.Add(a2); - var a3 = TableOptionalHeader(); - if (a3 is not null) - ds.Tables.Add(a3); - var a4 = TableOptionalDirAttrib(); - if (a4 is not null) - ds.Tables.Add(a4); - var a5 = TableSectionData(); - if (a5 is not null) - ds.Tables.Add(a5); - - - var a6 = TableExportDirectory(); - var a7 = TableExportFunction(); - if (a6 is not null) - ds.Tables.Add(a6); - if (a7 is not null) - ds.Tables.Add(a7); - - var a8 = TableImportDirectory(); - var a9 = TableImportFunction(); - if (a8 is not null) - ds.Tables.Add(a8); - if (a9 is not null) - ds.Tables.Add(a9); - - var a10 = TableResourceDirectory(); - if (a10 is not null) - ds.Tables.Add(a10); - - return ds; - } - - private DataTable? TableDosHeader() - { - if (DosHeader is null) - return null; - - var returnTable = new DataTable("DosHeader FileStar{" + DosHeader.FileStarIndex.ToString() + "}FileEnd{" + DosHeader.FileEndIndex.ToString() + "}"); - returnTable.Columns.Add("Name"); - returnTable.Columns.Add("Size"); - returnTable.Columns.Add("Value16"); - returnTable.Columns.Add("Value10"); - returnTable.Columns.Add("ASCII"); - returnTable.Columns.Add("Describe"); - - AddTableRow(returnTable, DosHeader.e_magic, "e_magic", "魔术数字"); - AddTableRow(returnTable, DosHeader.e_cblp, "e_cblp", "文件最后页的字节数"); - AddTableRow(returnTable, DosHeader.e_cp, "e_cp", "文件页数"); - AddTableRow(returnTable, DosHeader.e_crlc, "e_crlc", "重定义元素个数"); - AddTableRow(returnTable, DosHeader.e_cparhdr, "e_cparhdr", "头部尺寸,以段落为单位"); - AddTableRow(returnTable, DosHeader.e_minalloc, "e_minalloc", "所需的最小附加段"); - AddTableRow(returnTable, DosHeader.e_maxalloc, "e_maxalloc", "所需的最大附加段"); - AddTableRow(returnTable, DosHeader.e_ss, "e_ss", "初始的SS值(相对偏移量)"); - AddTableRow(returnTable, DosHeader.e_sp, "e_sp", "初始的SP值"); - AddTableRow(returnTable, DosHeader.e_csum, "e_csum", "校验和"); - AddTableRow(returnTable, DosHeader.e_ip, "e_ip", "初始的IP值"); - AddTableRow(returnTable, DosHeader.e_cs, "e_cs", "初始的CS值(相对偏移量)"); - AddTableRow(returnTable, DosHeader.e_rva, "e_rva", ""); - AddTableRow(returnTable, DosHeader.e_fg, "e_fg", ""); - AddTableRow(returnTable, DosHeader.e_bl1, "e_bl1", ""); - AddTableRow(returnTable, DosHeader.e_oemid, "e_oemid", ""); - AddTableRow(returnTable, DosHeader.e_oeminfo, "e_oeminfo", ""); - AddTableRow(returnTable, DosHeader.e_bl2, "e_bl2", ""); - AddTableRow(returnTable, DosHeader.e_PESTAR, "e_PESTAR", "PE开始 +本结构的位置"); - - return returnTable; - } - - private DataTable? TablePEHeader() - { - if (PEHeader is null) - return null; - - var returnTable = new DataTable("PeHeader FileStar{" + PEHeader.FileStarIndex.ToString() + "}FileEnd{" + PEHeader.FileEndIndex.ToString() + "}"); - returnTable.Columns.Add("Name"); - returnTable.Columns.Add("Size"); - returnTable.Columns.Add("Value16"); - returnTable.Columns.Add("Value10"); - returnTable.Columns.Add("ASCII"); - returnTable.Columns.Add("Describe"); - - - AddTableRow(returnTable, PEHeader.Header, "Header", "PE文件标记"); - AddTableRow(returnTable, PEHeader.Machine, "Machine", "该文件运行所要求的CPU.对于Intel平台,该值是IMAGE_FILE_MACHINE_I386 (14Ch).我们尝试了LUEVELSMEYER的pe.txt声明的14Dh和14Eh,但Windows不能正确执行. "); - AddTableRow(returnTable, PEHeader.NumberOfSections, "NumberOfSections", "文件的节数目.如果我们要在文件中增加或删除一个节,就需要修改这个值."); - AddTableRow(returnTable, PEHeader.TimeDateStamp, "TimeDateStamp", "文件创建日期和时间. "); - AddTableRow(returnTable, PEHeader.PointerToSymbolTable, "PointerToSymbolTable", "用于调试. "); - AddTableRow(returnTable, PEHeader.NumberOfSymbols, "NumberOfSymbols", "用于调试. "); - AddTableRow(returnTable, PEHeader.SizeOfOptionalHeader, "SizeOfOptionalHeader", "指示紧随本结构之后的 OptionalHeader 结构大小,必须为有效值."); - AddTableRow(returnTable, PEHeader.Characteristics, "Characteristics", "关于文件信息的标记,比如文件是exe还是dll."); - - return returnTable; - } - - private DataTable? TableOptionalHeader() - { - if (OptionalHeader is null) - return null; - - var returnTable = new DataTable("OptionalHeader FileStar{" + OptionalHeader.FileStarIndex.ToString() + "}FileEnd{" + OptionalHeader.FileEndIndex.ToString() + "}"); - returnTable.Columns.Add("Name"); - returnTable.Columns.Add("Size"); - returnTable.Columns.Add("Value16"); - returnTable.Columns.Add("Value10"); - returnTable.Columns.Add("ASCII"); - returnTable.Columns.Add("Describe"); - - AddTableRow(returnTable, OptionalHeader.Magic, "Magic", "Magic 010B=普通可以执行,0107=ROM映像"); - AddTableRow(returnTable, OptionalHeader.MajorLinkerVersion, "MajorLinkerVersion", "主版本号"); - AddTableRow(returnTable, OptionalHeader.MinorLinkerVersion, "MinorLinkerVersion", "副版本号"); - AddTableRow(returnTable, OptionalHeader.SizeOfCode, "SizeOfCode", "代码段大小"); - AddTableRow(returnTable, OptionalHeader.SizeOfInitializedData, "SizeOfInitializedData", "已初始化数据大小"); - AddTableRow(returnTable, OptionalHeader.SizeOfUninitializedData, "SizeOfUninitializedData", "未初始化数据大小"); - AddTableRow(returnTable, OptionalHeader.AddressOfEntryPoint, "AddressOfEntryPoint", "执行将从这里开始(RVA)"); - AddTableRow(returnTable, OptionalHeader.BaseOfCode, "BaseOfCode", "代码基址(RVA)"); - AddTableRow(returnTable, OptionalHeader.ImageBase, "ImageBase", "数据基址(RVA)"); - if (_IsX86) - { - AddTableRow(returnTable, OptionalHeader.BaseOfData, "ImageFileCode", "映象文件基址"); - } - AddTableRow(returnTable, OptionalHeader.SectionAlignment, "SectionAlign", "区段列队"); - AddTableRow(returnTable, OptionalHeader.MajorOperatingSystemVersion, "MajorOSV", "文件列队"); - AddTableRow(returnTable, OptionalHeader.MinorOperatingSystemVersion, "MinorOSV", "操作系统主版本号"); - AddTableRow(returnTable, OptionalHeader.MajorImageVersion, "MajorImageVer", "映象文件主版本号"); - AddTableRow(returnTable, OptionalHeader.MinorImageVersion, "MinorImageVer", "映象文件副版本号"); - AddTableRow(returnTable, OptionalHeader.MajorSubsystemVersion, "MajorSV", "子操作系统主版本号"); - AddTableRow(returnTable, OptionalHeader.MinorSubsystemVersion, "MinorSV", "子操作系统副版本号"); - AddTableRow(returnTable, OptionalHeader.Win32VersionValue, "UNKNOW", "Win32版本值"); - AddTableRow(returnTable, OptionalHeader.SizeOfImage, "SizeOfImage", "映象文件大小"); - AddTableRow(returnTable, OptionalHeader.SizeOfHeards, "SizeOfHeards", "标志头大小"); - AddTableRow(returnTable, OptionalHeader.CheckSum, "CheckSum", "文件效验"); - AddTableRow(returnTable, OptionalHeader.Subsystem, "Subsystem", "子系统(映象文件)1本地 2WINDOWS-GUI 3WINDOWS-CUI 4 POSIX-CUI"); - AddTableRow(returnTable, OptionalHeader.DLLCharacteristics, "DLL_Characteristics", "DLL标记"); - AddTableRow(returnTable, OptionalHeader.SizeOfStackReserve, "Bsize", "保留栈的大小"); - AddTableRow(returnTable, OptionalHeader.SizeOfStackCommit, "TimeBsize", "初始时指定栈大小"); - AddTableRow(returnTable, OptionalHeader.SizeOfHeapReserve, "AucBsize", "保留堆的大小"); - AddTableRow(returnTable, OptionalHeader.SizeOfHeapCommit, "SizeOfBsize", "初始时指定堆大小"); - AddTableRow(returnTable, OptionalHeader.LoaderFlags, "FuckBsize", "加载器标志"); - AddTableRow(returnTable, OptionalHeader.NumberOfRvaAndSizes, "DirectCount", "数据目录数"); - - return returnTable; - } - - private DataTable? TableOptionalDirAttrib() - { - if (OptionalDirAttrib is null) - return null; - - var returnTable = new DataTable( - "OptionalDirAttrib FileStar{" - + OptionalDirAttrib.FileStarIndex.ToString() - + "}FileEnd{" - + OptionalDirAttrib.FileEndIndex.ToString() - + "}"); - returnTable.Columns.Add("Name"); - returnTable.Columns.Add("Size"); - returnTable.Columns.Add("Value16"); - returnTable.Columns.Add("Value10"); - returnTable.Columns.Add("ASCII"); - returnTable.Columns.Add("Describe"); - - var tableName = new Hashtable - { - { 0, "输出表" }, - { 1, "输入表" }, - { 2, "资源表" }, - { 3, "异常表" }, - { 4, "安全表" }, - { 5, "基部重定位表" }, - { 6, "调试数据" }, - { 7, "版权数据" }, - { 8, "全局PTR" }, - { 9, "TLS表" }, - { 10, "装入配置表" }, - { 11, "其他表1" }, - { 12, "其他表2" }, - { 13, "其他表3" }, - { 14, "其他表4" }, - { 15, "其他表5" } - }; - - for (int i = 0; i != OptionalDirAttrib.DirByte.Count; i++) - { - if (OptionalDirAttrib.DirByte[i] is not OptionalDirAttrib.DirAttrib MyDirByte) - continue; - - string? Name; - var tn = tableName[i]; - if (tn is not null) - Name = tn.ToString(); - else - Name = $"未知表{i}"; - AddTableRow(returnTable, MyDirByte.DirRva, Name!, "地址"); - AddTableRow(returnTable, MyDirByte.DirSize, "", "大小"); - } - return returnTable; - } - - private DataTable? TableSectionData() - { - if (SectionTable is null) - return null; - - var returnTable = new DataTable( - "SectionData FileStar{" - + SectionTable.FileStarIndex.ToString() - + "}FileEnd{" - + SectionTable.FileEndIndex.ToString() - + "}"); - returnTable.Columns.Add("Name"); - returnTable.Columns.Add("Size"); - returnTable.Columns.Add("Value16"); - returnTable.Columns.Add("Value10"); - returnTable.Columns.Add("ASCII"); - returnTable.Columns.Add("Describe"); - - for (int i = 0; i != SectionTable.Section.Count; i++) - { - if (SectionTable.Section[i] is not SectionTable.SectionData SectionDate) - continue; - - AddTableRow(returnTable, SectionDate.SectName, "SectName", "名字"); - AddTableRow(returnTable, SectionDate.VirtualAddress, "VirtualAddress", "虚拟内存地址"); - AddTableRow(returnTable, SectionDate.SizeOfRawDataRVA, "SizeOfRawDataRVA", "RVA偏移"); - AddTableRow(returnTable, SectionDate.SizeOfRawDataSize, "SizeOfRawDataSize", "RVA大小"); - AddTableRow(returnTable, SectionDate.PointerToRawData, "PointerToRawData", "指向RAW数据"); - AddTableRow(returnTable, SectionDate.PointerToRelocations, "PointerToRelocations", "指向定位号"); - AddTableRow(returnTable, SectionDate.PointerToLinenumbers, "PointerToLinenumbers", "指向行数"); - AddTableRow(returnTable, SectionDate.NumberOfRelocations, "NumberOfRelocations", "定位号"); - AddTableRow(returnTable, SectionDate.NumberOfLinenumbers, "NumberOfLinenumbers", "行数号"); - AddTableRow(returnTable, SectionDate.Characteristics, "Characteristics", "区段标记"); - } - return returnTable; - } - - private DataTable? TableExportDirectory() - { - if (ExportDirectory is null) - return null; - - var returnTable = new DataTable( - "ExportDirectory FileStar{" - + ExportDirectory.FileStarIndex.ToString() - + "}FileEnd{" - + ExportDirectory.FileEndIndex.ToString() - + "}"); - returnTable.Columns.Add("Name"); - returnTable.Columns.Add("Size"); - returnTable.Columns.Add("Value16"); - returnTable.Columns.Add("Value10"); - returnTable.Columns.Add("ASCII"); - returnTable.Columns.Add("Describe"); - - AddTableRow(returnTable, ExportDirectory.Characteristics, "Characteristics", "一个保留字段,目前为止值为0."); - AddTableRow(returnTable, ExportDirectory.TimeDateStamp, "TimeDateStamp", "产生的时间."); - AddTableRow(returnTable, ExportDirectory.MajorVersion, "MajorVersion", "主版本号"); - AddTableRow(returnTable, ExportDirectory.MinorVersion, "MinorVersion", "副版本号"); - AddTableRow(returnTable, ExportDirectory.Name, "Name", "一个RVA,指向一个dll的名称的ascii字符串."); - AddTableRow(returnTable, ExportDirectory.Base, "Base", "输出函数的起始序号.一般为1."); - AddTableRow(returnTable, ExportDirectory.NumberOfFunctions, "NumberOfFunctions", "输出函数入口地址的数组 中的元素个数."); - AddTableRow(returnTable, ExportDirectory.NumberOfNames, "NumberOfNames", "输出函数名的指针的数组 中的元素个数,也是输出函数名对应的序号的数组 中的元素个数."); - AddTableRow(returnTable, ExportDirectory.AddressOfFunctions, "AddressOfFunctions", "一个RVA,指向输出函数入口地址的数组."); - AddTableRow(returnTable, ExportDirectory.AddressOfNames, "AddressOfNames", "一个RVA,指向输出函数名的指针的数组."); - AddTableRow(returnTable, ExportDirectory.AddressOfNameOrdinals, "AddressOfNameOrdinals", "一个RVA,指向输出函数名对应的序号的数组."); - - return returnTable; - } - private DataTable? TableExportFunction() - { - if (ExportDirectory is null) - return null; - - var returnTable = new DataTable("ExportFunctionList"); - returnTable.Columns.Add("Name"); - returnTable.Columns.Add("Size"); - returnTable.Columns.Add("Value16"); - returnTable.Columns.Add("Value10"); - returnTable.Columns.Add("ASCII"); - returnTable.Columns.Add("Describe"); - - for (int i = 0; i != ExportDirectory.FunctionNamesByte.Count; i++) - { - AddTableRow(returnTable, - ExportDirectory.FunctionNamesByte[i], - "Name", - "_ExportDirectory.Name-Sect.SizeOfRawDataRVA+Sect.PointerToRawData"); - } - - for (int i = 0; i != ExportDirectory.AddressOfNamesList.Count; i++) - { - if (ExportDirectory.AddressOfNamesList[i] is not byte[] a) - continue; - AddTableRow(returnTable, a, "NamesList", ""); - } - - for (int i = 0; i != ExportDirectory.AddressOfFunctionsList.Count; i++) - { - if (ExportDirectory.AddressOfFunctionsList[i] is not byte[] a) - continue; - AddTableRow(returnTable, a, "Functions", ""); - } - - for (int i = 0; i != ExportDirectory.AddressOfNameOrdinalsList.Count; i++) - { - if (ExportDirectory.AddressOfNameOrdinalsList[i] is not byte[] a) - continue; - AddTableRow(returnTable, a, "NameOrdinals", ""); - } - return returnTable; - } - private DataTable? TableImportDirectory() - { - if (ImportDirectory is null) - return null; - - var returnTable = new DataTable("ImportDirectory FileStar{" + ImportDirectory.FileStarIndex.ToString() + "}FileEnd{" + ImportDirectory.FileEndIndex.ToString() + "}"); - returnTable.Columns.Add("Name"); - returnTable.Columns.Add("Size"); - returnTable.Columns.Add("Value16"); - returnTable.Columns.Add("Value10"); - returnTable.Columns.Add("ASCII"); - returnTable.Columns.Add("Describe"); - - for (int i = 0; i != ImportDirectory.ImportList.Count; i++) - { - if (ImportDirectory.ImportList[i] is not ImportDirectory.ImportDate ImportByte) - continue; - - AddTableRow(returnTable, ImportByte.DLLName, "输入DLL名称", "**********"); - AddTableRow(returnTable, ImportByte.OriginalFirstThunk, "OriginalFirstThunk", "这里实际上保存着一个RVA,这个RVA指向一个DWORD数组,这个数组可以叫做输入查询表.每个数组元素,或者叫一个表项,保存着一个指向函数名的RVA或者保存着一个函数的序号."); - AddTableRow(returnTable, ImportByte.TimeDateStamp, "TimeDateStamp", "当这个值为0的时候,表明还没有bind.不为0的话,表示已经bind过了.有关bind的内容后面介绍."); - AddTableRow(returnTable, ImportByte.ForwarderChain, "ForwarderChain", ""); - AddTableRow(returnTable, ImportByte.Name, "Name", "一个RVA,这个RVA指向一个ascii以空字符结束的字符串,这个字符串就是本结构对应的dll文件的名字."); - AddTableRow(returnTable, ImportByte.FirstThunk, "FirstThunk", "一个RVA,这个RVA指向一个DWORD数组,这个数组可以叫输入地址表.如果bind了的话,这个数组的每个元素,就是一个输入函数的入口地址."); - } - - return returnTable; - } - private DataTable? TableImportFunction() - { - if (ImportDirectory is null) - return null; - - var returnTable = new DataTable("ImportFunctionList"); - returnTable.Columns.Add("Name"); - returnTable.Columns.Add("Size"); - returnTable.Columns.Add("Value16"); - returnTable.Columns.Add("Value10"); - returnTable.Columns.Add("ASCII"); - returnTable.Columns.Add("Describe"); - - for (int i = 0; i != ImportDirectory.ImportList.Count; i++) - { - if (ImportDirectory.ImportList[i] is not ImportDirectory.ImportDate ImportByte) - continue; - - AddTableRow(returnTable, ImportByte.DLLName, "DLL-Name", "**********"); - - for (int z = 0; z != ImportByte.DLLFunctionList.Count; z++) - { - if (ImportByte.DLLFunctionList[z] is not ImportDirectory.ImportDate.FunctionList Function) - continue; - - AddTableRow(returnTable, Function.FunctionName, "FunctionName", ""); - AddTableRow(returnTable, Function.FunctionHead, "FunctionHead", ""); - AddTableRow(returnTable, Function.OriginalFirst, "OriginalFirstThunk", ""); - } - } - return returnTable; - } - private DataTable? TableResourceDirectory() - { - if (ResourceDirectory is null) - return null; - var returnTable = new DataTable("ResourceDirectory FileStar{" + ResourceDirectory.FileStarIndex.ToString() + "}FileEnd{" + ResourceDirectory.FileEndIndex.ToString() + "}"); - returnTable.Columns.Add("GUID"); - returnTable.Columns.Add("Text"); - returnTable.Columns.Add("ParentID"); - AddResourceDirectoryRow(returnTable, ResourceDirectory, ""); - return returnTable; - } - private void AddResourceDirectoryRow(DataTable myTable, ResourceDirectory Node, string parentID) - { - string Name = ""; - if (Node.Name is not null) - Name = GetString(Node.Name, "UNICODE"); - - for (int i = 0; i != Node.EntryList.Count; i++) - { - if (Node.EntryList[i] is not ResourceDirectory.DirectoryEntry Entry) - continue; - - long ID = GetLong(Entry.Name); - - string GUID = Guid.NewGuid().ToString(); - - string IDNAME = "ID{" + ID + "}"; - if (Name.Length != 0) - IDNAME += "Name{" + Name + "}"; - - if (parentID.Length == 0) - { - IDNAME += ID switch - { - 1 => "Type{Cursor}", - 2 => "Type{Bitmap}", - 3 => "Type{Icon}", - 4 => "Type{Cursor}", - 5 => "Type{Menu}", - 6 => "Type{Dialog}", - 7 => "Type{String Table}", - 8 => "Type{Font Directory}", - 9 => "Type{Font}", - 10 => "Type{Accelerators}", - 11 => "Type{Unformatted}", - 12 => "Type{Message Table}", - 13 => "Type{Group Cursor}", - 14 => "Type{Group Icon}", - 15 => "Type{Information}", - 16 => "Type{Version}", - _ => "Type{未定义}", - }; - } - - myTable.Rows.Add(new string[] { GUID, IDNAME, parentID }); - - for (int z = 0; z != Entry.DataEntryList.Count; z++) - { - if (Entry.DataEntryList[z] is not ResourceDirectory.DirectoryEntry.DataEntry Data) - continue; - - string Text = "Address{" + GetString(Data.ResourRVA) + "} Size{" + GetString(Data.ResourSize) + "} FileBegin{" + Data.FileStarIndex.ToString() + "-" + Data.FileEndIndex.ToString() + "}"; - - myTable.Rows.Add(new string[] { Guid.NewGuid().ToString(), Text, GUID }); - } - - for (int z = 0; z != Entry.NodeDirectoryList.Count; z++) - { - if (Entry.NodeDirectoryList[z] is not ResourceDirectory a) - continue; - AddResourceDirectoryRow(myTable, a, GUID); - } - } - } - #endregion -} - -#region 类 -/// -/// DOS文件都MS开始 -/// -public class DosHeader // IMAGE_DOS_HEADER -{ - public byte[] e_magic = new byte[2]; // 魔术数字 - public byte[] e_cblp = new byte[2]; // 文件最后页的字节数 - public byte[] e_cp = new byte[2]; // 文件页数 - public byte[] e_crlc = new byte[2]; // 重定义元素个数 - public byte[] e_cparhdr = new byte[2]; // 头部尺寸,以段落为单位 - public byte[] e_minalloc = new byte[2]; // 所需的最小附加段 - public byte[] e_maxalloc = new byte[2]; // 所需的最大附加段 - public byte[] e_ss = new byte[2]; // 初始的SS值(相对偏移量) - public byte[] e_sp = new byte[2]; // 初始的SP值 - public byte[] e_csum = new byte[2]; // 校验和 - public byte[] e_ip = new byte[2]; // 初始的IP值 - public byte[] e_cs = new byte[2]; // 初始的CS值(相对偏移量) - public byte[] e_rva = new byte[2]; - public byte[] e_fg = new byte[2]; - public byte[] e_bl1 = new byte[8]; - public byte[] e_oemid = new byte[2]; - public byte[] e_oeminfo = new byte[2]; - public byte[] e_bl2 = new byte[20]; - public byte[] e_PESTAR = new byte[2]; // PE开始 +自己的位置........重点 - - public long FileStarIndex = 0; - public long FileEndIndex = 0; -} - -/// -/// DOS程序 提示 -/// -public class DosStub -{ - public byte[] DosStubData; - public DosStub(long Size) - { - DosStubData = new byte[Size]; - } - public long FileStarIndex = 0; - public long FileEndIndex = 0; -} - -/// -/// PE文件头 -/// -public class PEHeader // IMAGE_FILE_HEADER -{ - public byte[] Header = new byte[4];// PE文件标记 - public byte[] Machine = new byte[2];// 该文件运行所要求的CPU.对于Intel平台,该值是IMAGE_FILE_MACHINE_I386 (14Ch).我们尝试了LUEVELSMEYER的pe.txt声明的14Dh和14Eh,但Windows不能正确执行.看起来,除了禁止程序执行之外,本域对我们来说用处不大. - public byte[] NumberOfSections = new byte[2];// 文件的节数目.如果我们要在文件中增加或删除一个节,就需要修改这个值. - public byte[] TimeDateStamp = new byte[4];// 文件创建日期和时间.我们不感兴趣. - public byte[] PointerToSymbolTable = new byte[4];// 用于调试. - public byte[] NumberOfSymbols = new byte[4];// 用于调试. - public byte[] SizeOfOptionalHeader = new byte[2];// 指示紧随本结构之后的 OptionalHeader 结构大小,必须为有效值. IMAGE_OPTIONAL_HEADER32 结构大小 - public byte[] Characteristics = new byte[2];// 关于文件信息的标记,比如文件是exe还是dll. - - public long FileStarIndex = 0; - public long FileEndIndex = 0; -} - -/// -/// PE头扩展 -/// -// https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_optional_header32 // IMAGE_OPTIONAL_HEADER32 -// https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_optional_header64 // IMAGE_OPTIONAL_HEADER64 -public class OptionalHeader -{ - public byte[] Magic = new byte[2]; // Magic 010B=普通可以执行,0107=ROM映像 - public byte[] MajorLinkerVersion = new byte[1]; // 主版本号 - public byte[] MinorLinkerVersion = new byte[1]; // 副版本号 - public byte[] SizeOfCode = new byte[4]; // 代码段大小 - public byte[] SizeOfInitializedData = new byte[4]; // 已初始化数据大小 - public byte[] SizeOfUninitializedData = new byte[4]; // 未初始化数据大小 - public byte[] AddressOfEntryPoint = new byte[4]; // 执行将从这里开始(RVA).........入口点指向,dll填充0 - public byte[] BaseOfCode = new byte[4]; // 代码基址(RVA) - - public byte[] BaseOfData = new byte[4]; // 映象文件基址 - - public byte[] ImageBase = new byte[4]; // 数据基址(RVA) - - public byte[] SectionAlignment = new byte[4]; // 区段列队..... - public byte[] FileAlignment = new byte[4]; // 文件列队 - - public byte[] MajorOperatingSystemVersion = new byte[2]; // 操作系统主版本号 - public byte[] MinorOperatingSystemVersion = new byte[2]; // 操作系统副版本号 - public byte[] MajorImageVersion = new byte[2]; // 映象文件主版本号 - public byte[] MinorImageVersion = new byte[2]; // 映象文件副版本号 - public byte[] MajorSubsystemVersion = new byte[2]; // 子操作系统主版本号 - public byte[] MinorSubsystemVersion = new byte[2]; // 子操作系统副版本号 - public byte[] Win32VersionValue = new byte[4]; // Win32版本值 - public byte[] SizeOfImage = new byte[4]; // 映象文件大小 - public byte[] SizeOfHeards = new byte[4]; // 标志头大小 - public byte[] CheckSum = new byte[4]; // 文件效验 - public byte[] Subsystem = new byte[2]; // 子系统(映象文件)1本地 2WINDOWS-GUI 3WINDOWS-CUI 4 POSIX-CUI - public byte[] DLLCharacteristics = new byte[2]; // DLL标记 - - public byte[] SizeOfStackReserve = new byte[4]; // 保留栈的大小 - public byte[] SizeOfStackCommit = new byte[4]; // 初始时指定栈大小 - public byte[] SizeOfHeapReserve = new byte[4]; // 保留堆的大小 - public byte[] SizeOfHeapCommit = new byte[4]; // 初始时指定堆大小 - public byte[] LoaderFlags = new byte[4]; // 加载器标志 - public byte[] NumberOfRvaAndSizes = new byte[4]; // 数据目录数 - - public long FileStarIndex = 0; - public long FileEndIndex = 0; - - public OptionalHeader(bool is32) - { - if (!is32) - { - // X64没有了,但是为了代码保留修改幅度不大,所以置0 - BaseOfData = new byte[0];// x64必须置于0 - // x64长度增加的 - int ulonglong = 8; - ImageBase = new byte[ulonglong]; // 数据基址(RVA) - SizeOfStackReserve = new byte[ulonglong]; // 保留栈的大小 - SizeOfStackCommit = new byte[ulonglong]; // 初始时指定栈大小 - SizeOfHeapReserve = new byte[ulonglong]; // 保留堆的大小 - SizeOfHeapCommit = new byte[ulonglong]; // 初始时指定堆大小 - } - } -} - -/// -/// 目录结构 -/// -public class OptionalDirAttrib -{ - public ArrayList DirByte = new(); - public class DirAttrib - { - public byte[] DirRva = new byte[4]; // 地址 - public byte[] DirSize = new byte[4]; // 大小 - } - public long FileStarIndex = 0; - public long FileEndIndex = 0; -} - -/// -/// 节表 -/// -public class SectionTable -{ - public ArrayList Section = new(); - public class SectionData - { - public byte[] SectName = new byte[8]; // 名字 - public byte[] VirtualAddress = new byte[4]; // 虚拟内存地址 - public byte[] SizeOfRawDataRVA = new byte[4]; // RVA偏移 - public byte[] SizeOfRawDataSize = new byte[4]; // RVA大小 - public byte[] PointerToRawData = new byte[4]; // 指向RAW数据 - public byte[] PointerToRelocations = new byte[4]; // 指向定位号 - public byte[] PointerToLinenumbers = new byte[4]; // 指向行数 - public byte[] NumberOfRelocations = new byte[2]; // 定位号 - public byte[] NumberOfLinenumbers = new byte[2]; // 行数号 - public byte[] Characteristics = new byte[4]; // 区段标记 - } - - public long FileStarIndex = 0; - public long FileEndIndex = 0; -} - -/// -/// 输出表 -/// -public class ExportDirectory -{ - public byte[] Characteristics = new byte[4]; // 一个保留字段,目前为止值为0. - public byte[] TimeDateStamp = new byte[4]; // 产生的时间 - public byte[] MajorVersion = new byte[2]; // 主版本号 - public byte[] MinorVersion = new byte[2]; // 副版本号 - public byte[] Name = new byte[4]; // 一个RVA,指向一个dll的名称的ascii字符串 - public byte[] Base = new byte[4]; // 输出函数的起始序号.一般为1 - public byte[] NumberOfFunctions = new byte[4]; // 输出函数入口地址的数组中的元素个数 - public byte[] NumberOfNames = new byte[4]; // 输出函数名的指针的数组中的元素个数,也是输出函数名对应的序号的数组中的元素个数 - public byte[] AddressOfFunctions = new byte[4]; // 一个RVA,指向输出函数入口地址的数组 - public byte[] AddressOfNames = new byte[4]; // 一个RVA,指向输出函数名的指针的数组 - public byte[] AddressOfNameOrdinals = new byte[4]; // 一个RVA,指向输出函数名对应的序号的数组 - - public ArrayList AddressOfFunctionsList = new(); - public ArrayList AddressOfNamesList = new(); - public ArrayList AddressOfNameOrdinalsList = new(); - /// - /// 函数指针名称集合 - /// - public List FunctionNamesByte = new(); - public long FileStarIndex = 0; - public long FileEndIndex = 0; - - /// - /// 获取函数名 - /// - public HashSet FunctionNames() - { - HashSet names = new(); - for (int i = 0; i < FunctionNamesByte.Count; i++) - names.Add(Encoding.Default.GetString(FunctionNamesByte[i])); - return names; - } -} - - -/// -/// 输入表 -/// -public class ImportDirectory -{ - public ArrayList ImportList = new(); - - public class ImportDate - { - public byte[] OriginalFirstThunk = new byte[4]; // 这里实际上保存着一个RVA,这个RVA指向一个DWORD数组,这个数组可以叫做输入查询表.每个数组元素,或者叫一个表项,保存着一个指向函数名的RVA或者保存着一个函数的序号. - public byte[] TimeDateStamp = new byte[4]; // 当这个值为0的时候,表明还没有bind.不为0的话,表示已经bind过了.有关bind的内容后面介绍. - public byte[] ForwarderChain = new byte[4]; - public byte[] Name = new byte[4]; // 一个RVA,这个RVA指向一个ascii以空字符结束的字符串,这个字符串就是本结构对应的dll文件的名字. - public byte[] FirstThunk = new byte[4]; // 一个RVA,这个RVA指向一个DWORD数组,这个数组可以叫输入地址表.如果bind了的话,这个数组的每个元素,就是一个输入函数的入口地址. - - public byte[]? DLLName; // DLL名称 - public ArrayList DLLFunctionList = new(); - public class FunctionList - { - public byte[] OriginalFirst = new byte[4]; - public byte[]? FunctionName; - public byte[] FunctionHead = new byte[2]; - } - } - public long FileStarIndex = 0; - public long FileEndIndex = 0; -} - -/// -/// 资源表 -/// -public class ResourceDirectory -{ - public byte[] Characteristics = new byte[4]; - public byte[] TimeDateStamp = new byte[4]; - public byte[] MajorVersion = new byte[2]; - public byte[] MinorVersion = new byte[2]; - public byte[] NumberOfNamedEntries = new byte[2]; - public byte[] NumberOfIdEntries = new byte[2]; - public byte[]? Name; - public ArrayList EntryList = new(); - - public class DirectoryEntry - { - public byte[] Name = new byte[4]; - public byte[] Id = new byte[4]; - public ArrayList DataEntryList = new(); - public ArrayList NodeDirectoryList = new(); - - public class DataEntry - { - public byte[] ResourRVA = new byte[4]; - public byte[] ResourSize = new byte[4]; - public byte[] ResourTest = new byte[4]; - public byte[] ResourWen = new byte[4]; - - public long FileStarIndex = 0; - public long FileEndIndex = 0; - } - } - - public long FileStarIndex = 0; - public long FileEndIndex = 0; -} -#endregion -#pragma warning restore CS1591 // 缺少对公共可见类型或成员的 XML 注释 \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ResultData/LispDottedPair.cs b/src/CAD/IFox.CAD.Shared/ResultData/LispDottedPair.cs deleted file mode 100644 index 009d13e..0000000 --- a/src/CAD/IFox.CAD.Shared/ResultData/LispDottedPair.cs +++ /dev/null @@ -1,68 +0,0 @@ -namespace IFoxCAD.Cad; - -/// -/// lisp点对表的数据封装类 -/// -public class LispDottedPair : LispList -{ - #region 构造函数 - /// - /// 默认无参构造函数 - /// - public LispDottedPair() - { - } - - /// - /// 构造函数 - /// - /// TypedValue 迭代器 - public LispDottedPair(IEnumerable values) : base(values) - { - } - /// - /// 构造函数 - /// - /// 点对表左数 - /// 点对表右数 - public LispDottedPair(TypedValue left, TypedValue right) - { - Add(left); - Add(right); - } - #endregion - - #region 重写 - /// - /// 点对表的值 - /// - public override List Value - { - get - { - var value = new List - { - new TypedValue((int)LispDataType.ListBegin,-1), - new TypedValue((int)LispDataType.DottedPair,-1) - }; - value.InsertRange(1, this); - return value; - } - } - #endregion - - #region 转换器 - - /// - /// LispDottedPair 隐式转换到 TypedValue 数组 - /// - /// TypedValueList 实例 - public static implicit operator TypedValue[](LispDottedPair values) => values.Value.ToArray(); - /// - /// LispDottedPair 隐式转换到 ResultBuffer - /// - /// TypedValueList 实例 - public static implicit operator ResultBuffer(LispDottedPair values) => new(values.Value.ToArray()); - - #endregion -} diff --git a/src/CAD/IFox.CAD.Shared/ResultData/LispList.cs b/src/CAD/IFox.CAD.Shared/ResultData/LispList.cs deleted file mode 100644 index c186e43..0000000 --- a/src/CAD/IFox.CAD.Shared/ResultData/LispList.cs +++ /dev/null @@ -1,194 +0,0 @@ -namespace IFoxCAD.Cad; - -/// -/// lisp数据封装类 -/// -public class LispList : TypedValueList -{ - #region 构造函数 - /// - /// 默认构造函数 - /// - public LispList() { } - - /// - /// 构造函数 - /// - /// TypedValue 迭代器 - public LispList(IEnumerable values) : base(values) { } - #endregion - - #region 重写 - /// - /// lisp 列表的值 - /// - public virtual List Value - { - get - { - var value = new List - { - new TypedValue((int)LispDataType.ListBegin,-1), - new TypedValue((int)LispDataType.ListEnd,-1) - }; - value.InsertRange(1, this); - return value; - } - } - #endregion - - #region 添加数据 - /// - /// 添加数据 - /// - /// 组码 - /// 组码值 - public override void Add(int code, object? obj) - { - if (code < 5000) - throw new System.Exception("传入的组码值不是 lisp数据 有效范围!"); - - Add(new TypedValue(code, obj)); - } - - /// - /// 添加数据 - /// - /// dxfcode枚举值 - /// 组码值 - public void Add(LispDataType code, object? obj) - { - Add((int)code, obj); - } - /// - /// 添加数据,参数为true时添加 lisp 中的 T,false时添加 lisp 中的 nil - /// - /// bool 型的数据 - public void Add(bool value) - { - if (value) - { - Add(LispDataType.T_atom, true); - } - else - { - Add(LispDataType.Nil, null); - } - } - /// - /// 添加字符串 - /// - /// 字符串 - public void Add(string value) - { - Add(LispDataType.Text, value); - } - /// - /// 添加短整型数 - /// - /// 短整型数 - public void Add(short value) - { - Add(LispDataType.Int16, value); - } - /// - /// 添加整型数 - /// - /// 整型数 - public void Add(int value) - { - Add(LispDataType.Int32, value); - } - /// - /// 添加浮点数 - /// - /// 浮点数 - public void Add(double value) - { - Add(LispDataType.Double, value); - } - /// - /// 添加对象id - /// - /// 对象id - public void Add(ObjectId value) - { - Add(LispDataType.ObjectId, value); - } - /// - /// 添加选择集 - /// - /// 选择集 - public void Add(SelectionSet value) - { - Add(LispDataType.SelectionSet, value); - } - /// - /// 添加二维点 - /// - /// 二维点 - public void Add(Point2d value) - { - Add(LispDataType.Point2d, value); - } - /// - /// 添加三维点 - /// - /// 三维点 - public void Add(Point3d value) - { - Add(LispDataType.Point3d, value); - } - /// - /// 添加二维点 - /// - /// X - /// Y - public void Add(double x, double y) - { - Add(LispDataType.Point2d, new Point2d(x, y)); - } - /// - /// 添加三维点 - /// - /// X - /// Y - /// Z - public void Add(double x, double y, double z) - { - Add(LispDataType.Point3d, new Point3d(x, y, z)); - } - /// - /// 添加列表 - /// - /// lisp 列表 - public void Add(LispList value) - { - this.AddRange(value.Value); - } - - #endregion - - #region 转换器 - /// - /// ResultBuffer 隐式转换到 LispList - /// - /// ResultBuffer 实例 - public static implicit operator LispList(ResultBuffer buffer) => new(buffer.AsArray()); - /// - /// LispList 隐式转换到 TypedValue 数组 - /// - /// TypedValueList 实例 - public static implicit operator TypedValue[](LispList values) => values.Value.ToArray(); - /// - /// LispList 隐式转换到 ResultBuffer - /// - /// TypedValueList 实例,要using - public static implicit operator ResultBuffer(LispList values) => new(values.Value.ToArray()); - /// - /// TypedValue 数组隐式转换到 LispList - /// - /// TypedValue 数组 - public static implicit operator LispList(TypedValue[] values) => new(values); - #endregion -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ResultData/TypedValueList.cs b/src/CAD/IFox.CAD.Shared/ResultData/TypedValueList.cs deleted file mode 100644 index 16970d2..0000000 --- a/src/CAD/IFox.CAD.Shared/ResultData/TypedValueList.cs +++ /dev/null @@ -1,64 +0,0 @@ -namespace IFoxCAD.Cad; - -/// -/// 用于集中管理扩展数据/扩展字典/resultbuffer的类 -/// -public class TypedValueList : List -{ - #region 构造函数 - /// - /// 默认无参构造函数 - /// - public TypedValueList() { } - /// - /// 采用 TypedValue 迭代器构造 TypedValueList - /// - /// - public TypedValueList(IEnumerable values) : base(values) { } - #endregion - - #region 添加数据 - /// - /// 添加数据 - /// - /// 组码 - /// 组码值 - public virtual void Add(int code, object obj) - { - Add(new TypedValue(code, obj)); - } - - #endregion - - #region 转换器 - /// - /// ResultBuffer 隐式转换到 TypedValueList - /// - /// ResultBuffer 实例 - public static implicit operator TypedValueList(ResultBuffer buffer) => new(buffer.AsArray()); - /// - /// TypedValueList 隐式转换到 TypedValue 数组 - /// - /// TypedValueList 实例 - public static implicit operator TypedValue[](TypedValueList values) => values.ToArray(); - /// - /// TypedValueList 隐式转换到 ResultBuffer - /// - /// TypedValueList 实例 - public static implicit operator ResultBuffer(TypedValueList values) => new(values); - /// - /// TypedValue 数组隐式转换到 TypedValueList - /// - /// TypedValue 数组 - public static implicit operator TypedValueList(TypedValue[] values) => new(values); - /// - /// 转换为字符串 - /// - /// ResultBuffer 字符串 - public override string ToString() - { - using ResultBuffer a = new(this); - return a.ToString(); - } - #endregion -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ResultData/XRecordDataList.cs b/src/CAD/IFox.CAD.Shared/ResultData/XRecordDataList.cs deleted file mode 100644 index 708e155..0000000 --- a/src/CAD/IFox.CAD.Shared/ResultData/XRecordDataList.cs +++ /dev/null @@ -1,67 +0,0 @@ -namespace IFoxCAD.Cad; - -/// -/// 扩展字典数据封装类 -/// -public class XRecordDataList : TypedValueList -{ - #region 构造函数 - /// - /// 扩展字典数据封装类 - /// - public XRecordDataList() { } - - /// - /// 扩展字典数据封装类 - /// - public XRecordDataList(IEnumerable values) : base(values) { } - #endregion - - #region 添加数据 - /// - /// 添加数据 - /// - /// 组码 - /// 组码值 - public override void Add(int code, object obj) - { - if (code >= 1000) - throw new System.Exception("传入的组码值不是 XRecordData 有效范围!"); - - Add(new TypedValue(code, obj)); - } - - /// - /// 添加数据 - /// - /// dxfcode枚举值 - /// 组码值 - public void Add(DxfCode code, object obj) - { - Add((int)code, obj); - } - #endregion - - #region 转换器 - /// - /// ResultBuffer 隐式转换到 XRecordDataList - /// - /// ResultBuffer 实例 - public static implicit operator XRecordDataList(ResultBuffer buffer) => new(buffer.AsArray()); - /// - /// XRecordDataList 隐式转换到 TypedValue 数组 - /// - /// TypedValueList 实例 - public static implicit operator TypedValue[](XRecordDataList values) => values.ToArray(); - /// - /// XRecordDataList 隐式转换到 ResultBuffer - /// - /// TypedValueList 实例s - public static implicit operator ResultBuffer(XRecordDataList values) => new(values); - /// - /// TypedValue 数组隐式转换到 XRecordDataList - /// - /// TypedValue 数组 - public static implicit operator XRecordDataList(TypedValue[] values) => new(values); - #endregion -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/ResultData/XdataList.cs b/src/CAD/IFox.CAD.Shared/ResultData/XdataList.cs deleted file mode 100644 index 157571b..0000000 --- a/src/CAD/IFox.CAD.Shared/ResultData/XdataList.cs +++ /dev/null @@ -1,146 +0,0 @@ -namespace IFoxCAD.Cad; - -/// -/// 扩展数据封装类 -/// -public class XDataList : TypedValueList -{ - #region 构造函数 - /// - /// 扩展数据封装类 - /// - public XDataList() { } - - /// - /// 扩展数据封装类 - /// - public XDataList(IEnumerable values) : base(values) { } - #endregion - - #region 添加数据 - /// - /// 添加数据 - /// - /// 组码 - /// 组码值 - public override void Add(int code, object obj) - { - if (code is < 1000 or > 1071) - throw new Exception("传入的组码值不是 XData 有效范围!"); - - Add(new TypedValue(code, obj)); - } - - /// - /// 添加数据 - /// - /// dxfcode枚举值 - /// 组码值 - public void Add(DxfCode code, object obj) - { - Add((int)code, obj); - } - - /// - /// 是否含有注册名 - /// - /// 注册名 - public bool Contains(string appName) - { - bool result = false; - RangeTask(appName, (tv, state, i) => { - result = true; - state.Break(); - }); - return result; - } - - /// - /// 注册名下含有指定成员 - /// - /// 注册名 - /// 内容 - public bool Contains(string appName, object value) - { - bool result = false; - RangeTask(appName, (tv, state, _) => { - if (tv.Value.Equals(value)) - { - result = true; - state.Break(); - } - }); - return result; - } - - /// - /// 获取appName的索引区间 - /// - /// 注册名称 - /// 任务组码对象 - /// 返回任务组码的索引 - public List GetXdataAppIndex(string appName, DxfCode[] dxfCodes) - { - List indexs = new(); - RangeTask(appName, (tv, state, i) => { - if (dxfCodes.Contains((DxfCode)tv.TypeCode)) - indexs.Add(i); - }); - return indexs; - } - - /// - /// 区间任务 - /// - /// - /// - private void RangeTask(string appName, Action action) - { - LoopState state = new(); - // 在名称和名称之间找 - int appNameIndex = -1; - for (int i = 0; i < this.Count; i++) - { - if (this[i].TypeCode == (short)DxfCode.ExtendedDataRegAppName) - { - if (this[i].Value.ToString() == appName) - { - appNameIndex = i; - continue; - } - if (appNameIndex != -1)//找到了下一个名称 - break; - } - - if (appNameIndex == -1) continue; // 找下一个的时候,获取任务(移除)的对象 - action(this[i], state, i); - if (!state.IsRun) - break; - } - } - - #endregion - - #region 转换器 - /// - /// ResultBuffer 隐式转换到 XDataList - /// - /// ResultBuffer 实例 - public static implicit operator XDataList(ResultBuffer buffer) => new(buffer.AsArray()); - /// - /// XDataList 隐式转换到 TypedValue 数组 - /// - /// TypedValueList 实例 - public static implicit operator TypedValue[](XDataList values) => values.ToArray(); - /// - /// XDataList 隐式转换到 ResultBuffer - /// - /// TypedValueList 实例 - public static implicit operator ResultBuffer(XDataList values) => new(values); - /// - /// TypedValue 数组隐式转换到 XDataList - /// - /// TypedValue 数组 - public static implicit operator XDataList(TypedValue[] values) => new(values); - #endregion -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs b/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs deleted file mode 100644 index b7617b5..0000000 --- a/src/CAD/IFox.CAD.Shared/Runtime/DBTrans.cs +++ /dev/null @@ -1,620 +0,0 @@ -namespace IFoxCAD.Cad; - - -using System.Diagnostics; -using System.IO; - -/// -/// 事务栈 -/// 隐匿事务在数据库其中担任的角色 -/// -[DebuggerDisplay("{DebuggerDisplay,nq}")] -[DebuggerTypeProxy(typeof(DBTrans))] -public sealed class DBTrans : IDisposable -{ - [DebuggerBrowsable(DebuggerBrowsableState.Never)] - private string DebuggerDisplay => ToString(); - - #region 静态函数 - /// - /// 获取顶层事务 - /// - /// 数据库 - /// 事务对象 - public static Transaction GetTopTransaction(Database database) - { - ArgumentNullEx.ThrowIfNull(database); - return database.TransactionManager.TopTransaction switch - { - { } tr => tr, - _ => throw new Exception("没有顶层事务!") - }; - } - - /// - /// 获取给定数据库的顶层 DBTrans 事务 - /// - /// 数据库 - /// DBTrans 事务 - /// - public static DBTrans GetTop(Database database) - { - ArgumentNullEx.ThrowIfNull(database); - var trans = database.TransactionManager.TopTransaction; - ArgumentNullEx.ThrowIfNull(trans); - - foreach (var item in _dBTrans) - { - if (item.Transaction.UnmanagedObject == trans.UnmanagedObject) - { - return item; - } - } // 匹配事务栈内dbtrans的transaction的指针与数据库的顶层事务的指针 - - - return Top; - - } -#endregion - - #region 私有字段 - /// - /// 事务栈 - /// - private static readonly Stack _dBTrans = new(); - /// - /// 文档锁 - /// - private readonly DocumentLock? _documentLock; - /// - /// 是否提交事务 - /// - private bool _commit; - /// - /// 文件名 - /// - private readonly string? _fileName; - #endregion - - #region 公开属性 - /// - /// 返回当前事务 - /// - public static DBTrans Top - { - get - { - /* - * 0x01 - * 事务栈上面有事务,这个事务属于当前文档, - * 那么直接提交原本事务然后再开一个(一直把栈前面的同数据库提交清空) - * 那不就发生跨事务读取图元了吗?....否决 - * - * 0x02 - * 跨文档事务出错 Autodesk.AutoCAD.Runtime.Exception:“eNotFromThisDocument” - * Curves.GetEntities()会从Top获取事务(Top会new一个),此时会是当前文档; - * 然后命令文中发生了 using DBTrans tr = new(); - * 当退出命令此事务释放,但是从来不释放Top, - * 然后我新建了一个文档,再进行命令=>又进入Top,Top返回了前一个文档的事务 - * 因此所以无法清理栈,所以Dispose不触发,导致无法刷新图元和Ctrl+Z出错 - * 所以用AOP方式修复 - * - * 0x03 - * 经过艰苦卓绝的测试,aop模式由于不能断点调试,所以暂时放弃。 - */ - - // 由于大量的函数依赖本属性,强迫用户先开启事务 - if (_dBTrans.Count == 0) - throw new ArgumentNullException("事务栈没有任何事务,请在调用前创建:" + nameof(DBTrans)); - var trans = _dBTrans.Peek(); - return trans; - } - } - - - - /// - /// 文档 - /// - public Document? Document { get; private set; } - /// - /// 命令行 - /// - public Editor? Editor { get; private set; } - /// - /// 事务管理器 - /// - public Transaction Transaction { get; private set; } - /// - /// 数据库 - /// - public Database Database { get; private set; } - #endregion - - #region 构造函数 - /// - /// 事务栈 - /// 默认构造函数,默认为打开当前文档,默认提交事务 - /// - /// 要打开的文档 - /// 事务是否提交 - /// 是否锁文档 - public DBTrans(Document? doc = null, bool commit = true, bool doclock = false) - { - Document = doc ?? Acaop.DocumentManager.MdiActiveDocument; - Database = Document.Database; - Editor = Document.Editor; - Transaction = Database.TransactionManager.StartTransaction(); - _commit = commit; - if (doclock) - _documentLock = Document.LockDocument(); - - _dBTrans.Push(this); - } - - /// - /// 事务栈 - /// 打开数据库,默认提交事务 - /// - /// 要打开的数据库 - /// 事务是否提交 - public DBTrans(Database database, bool commit = true) - { - Database = database; - Transaction = Database.TransactionManager.StartTransaction(); - _commit = commit; - _dBTrans.Push(this); - } - - /// - /// 事务栈 - /// 打开文件,默认提交事务 - /// - /// 要打开的文件名 - /// 事务是否提交 - /// 开图模式 - /// 密码 - /// 后台打开false;前台打开true(必须设置CommandFlags.Session) - public DBTrans(string fileName, - bool commit = true, - FileOpenMode fileOpenMode = FileOpenMode.OpenForReadAndWriteNoShare, - string? password = null, - bool activeOpen = false) - { - if (string.IsNullOrWhiteSpace(fileName)) - throw new ArgumentNullException(nameof(fileName)); - - _fileName = fileName.Replace("/", "\\");// doc.Name总是"D:\\JX.dwg" - - // 此处若为失败的文件名,那么保存的时候就会丢失名称, - // 因此用 _fileName 储存 - if (!File.Exists(_fileName)) - { - if (activeOpen) - { - throw new IOException("错误:事务栈明确为前台开图时,文件不存在"); - } - else - { - // cad08测试: - // 第2个参数使用false,将导致关闭cad的时候出现致命错误: - // Unhandled Access Violation Reading Ox113697a0 Exception at 4b4154h - Database = new Database(true, true); - } - } - else - { - var doc = Acaop.DocumentManager - .Cast() - .FirstOrDefault(doc => !doc.IsDisposed && doc.Name == _fileName); - - if (activeOpen) - { - if (doc is null) - { - try - { - // 设置命令标记: CommandFlags.Session - // 若没有设置: Open()之后的会进入中断状态(不会执行,直到切换文档ctrl+tab或者关闭文档) - doc = Acaop.DocumentManager.Open(fileName, fileOpenMode == FileOpenMode.OpenForReadAndReadShare, password); - } - catch (Exception e) - { - throw new IOException($"错误:此文件打开错误:{fileName}\n错误信息:{e.Message}"); - } - } - // 设置命令标记: CommandFlags.Session - // 若没有设置: doc.IsActive 会异常 - if (!doc.IsActive) - Acaop.DocumentManager.MdiActiveDocument = doc; - - // Open()是跨文档,所以必须要锁文档 - // 否则 Editor?.Redraw() 的 tm.QueueForGraphicsFlush() 将报错提示文档锁 - _documentLock = doc.LockDocument(); - - Database = doc.Database; - Document = doc; - Editor = doc.Editor; - } - else - { - if (doc is null) - { - Database = new Database(false, true); - if (Path.GetExtension(_fileName).ToLower().Contains("dxf")) - { - Database.DxfIn(_fileName, null); - } - else - { - Database.ReadDwgFile(_fileName, fileOpenMode, true, password); - } - Database.CloseInput(true); - } - else - { - Database = doc.Database; - Document = doc; - Editor = doc.Editor; - } - } - } - - Transaction = Database.TransactionManager.StartTransaction(); - _commit = commit; - _dBTrans.Push(this); - } - #endregion - - #region 类型转换 - /// - /// 隐式转换为Transaction - /// - /// 事务管理器 - /// 事务管理器 - public static implicit operator Transaction(DBTrans tr) - { - return tr.Transaction; - } - #endregion - - #region 符号表 - - /// - /// 块表 - /// - public SymbolTable BlockTable => _blockTable ??= new(this, Database.BlockTableId); - - private SymbolTable? _blockTable; - /// - /// 当前绘图空间 - /// - public BlockTableRecord CurrentSpace => BlockTable.GetRecord(Database.CurrentSpaceId)!; - /// - /// 模型空间 - /// - public BlockTableRecord ModelSpace => BlockTable.GetRecord(BlockTable.CurrentSymbolTable[BlockTableRecord.ModelSpace])!; - /// - /// 图纸空间 - /// - public BlockTableRecord PaperSpace => BlockTable.GetRecord(BlockTable.CurrentSymbolTable[BlockTableRecord.PaperSpace])!; - /// - /// 层表 - /// - public SymbolTable LayerTable => _layerTable ??= new(this, Database.LayerTableId); - - private SymbolTable? _layerTable; - /// - /// 文字样式表 - /// - public SymbolTable TextStyleTable => _textStyleTable ??= new(this, Database.TextStyleTableId); - - private SymbolTable? _textStyleTable; - /// - /// 注册应用程序表 - /// - public SymbolTable RegAppTable => _regAppTable ??= new(this, Database.RegAppTableId); - - private SymbolTable? _regAppTable; - /// - /// 标注样式表 - /// - public SymbolTable DimStyleTable => _dimStyleTable ??= new(this, Database.DimStyleTableId); - - private SymbolTable? _dimStyleTable; - /// - /// 线型表 - /// - public SymbolTable LinetypeTable => _linetypeTable ??= new(this, Database.LinetypeTableId); - - private SymbolTable? _linetypeTable; - /// - /// 用户坐标系表 - /// - public SymbolTable UcsTable => _ucsTable ??= new(this, Database.UcsTableId); - - private SymbolTable? _ucsTable; - /// - /// 视图表 - /// - public SymbolTable ViewTable => _viewTable ??= new(this, Database.ViewTableId); - - private SymbolTable? _viewTable; - /// - /// 视口表 - /// - public SymbolTable ViewportTable => _viewportTable ??= new(this, Database.ViewportTableId); - - private SymbolTable? _viewportTable; - #endregion - - #region 字典 - /// - /// 命名对象字典 - /// - public DBDictionary NamedObjectsDict => GetObject(Database.NamedObjectsDictionaryId)!; - /// - /// 组字典 - /// - public DBDictionary GroupDict => GetObject(Database.GroupDictionaryId)!; - /// - /// 多重引线样式字典 - /// - public DBDictionary MLeaderStyleDict => GetObject(Database.MLeaderStyleDictionaryId)!; - /// - /// 多线样式字典 - /// - // ReSharper disable once InconsistentNaming - public DBDictionary MLStyleDict => GetObject(Database.MLStyleDictionaryId)!; - /// - /// 材质字典 - /// - public DBDictionary MaterialDict => GetObject(Database.MaterialDictionaryId)!; - /// - /// 表格样式字典 - /// - public DBDictionary TableStyleDict => GetObject(Database.TableStyleDictionaryId)!; - /// - /// 视觉样式字典 - /// - public DBDictionary VisualStyleDict => GetObject(Database.VisualStyleDictionaryId)!; - /// - /// 颜色字典 - /// - public DBDictionary ColorDict => GetObject(Database.ColorDictionaryId)!; - /// - /// 打印设置字典 - /// - public DBDictionary PlotSettingsDict => GetObject(Database.PlotSettingsDictionaryId)!; - /// - /// 打印样式表名字典 - /// - public DBDictionary PlotStyleNameDict => GetObject(Database.PlotStyleNameDictionaryId)!; - /// - /// 布局字典 - /// - public DBDictionary LayoutDict => GetObject(Database.LayoutDictionaryId)!; - -#if !zcad // 中望官方的问题 - /// - /// 数据链接字典 - /// - public DBDictionary DataLinkDict => GetObject(Database.DataLinkDictionaryId)!; - - - /// - /// 详细视图样式字典 - /// - public DBDictionary DetailViewStyleDict => GetObject(Database.DetailViewStyleDictionaryId)!; - /// - /// 剖面视图样式字典 - /// - public DBDictionary SectionViewStyleDict => GetObject(Database.SectionViewStyleDictionaryId)!; - -#endif -#endregion - - #region 获取对象 - /// - /// 根据对象id获取对象 - /// - /// 对象id - /// 打开模式,默认为只读 - /// 是否打开已删除对象,默认为不打开 - /// 是否打开锁定图层对象,默认为不打开 - /// 数据库DBObject对象 - public DBObject GetObject(ObjectId id, - OpenMode openMode = OpenMode.ForRead, - bool openErased = false, - bool openLockedLayer = false) - { - return Transaction.GetObject(id, openMode, openErased, openLockedLayer); - } - /// - /// 根据对象id获取图元对象 - /// - /// 要获取的图元对象的类型 - /// 对象id - /// 打开模式,默认为只读 - /// 是否打开已删除对象,默认为不打开 - /// 是否打开锁定图层对象,默认为不打开 - /// 图元对象 - public T? GetObject(ObjectId id, - OpenMode openMode = OpenMode.ForRead, - bool openErased = false, - bool openLockedLayer = false) where T : DBObject - { - return Transaction.GetObject(id, openMode, openErased, openLockedLayer) as T; - } - - /// - /// 根据对象句柄字符串获取对象Id - /// - /// 句柄字符串 - /// 对象id - public ObjectId GetObjectId(string handleString) - { - var hanle = new Handle(Convert.ToInt64(handleString, 16)); - // return Database.GetObjectId(false, hanle, 0); - return Database.TryGetObjectId(hanle, out ObjectId id) ? id : ObjectId.Null; - } - #endregion - - #region 前台后台任务 - /// - /// 前台后台任务分别处理 - /// - /// - /// 备注:
- /// 0x01 文字偏移问题主要出现线性引擎函数上面,
- /// 在 参照绑定/深度克隆 的底层共用此函数导致
- /// 0x02 后台是利用前台当前数据库进行处理的
- /// 0x03 跨进程通讯暂无测试(可能存在bug)
- ///
- /// 委托 - /// 开启单行文字偏移处理 - // ReSharper disable once InconsistentNaming - public void Task(Action action, bool handlingDBTextDeviation = true) - { - //if (action == null) - // throw new ArgumentNullException(nameof(action)); - ArgumentNullEx.ThrowIfNull(action); - // 前台开图 || 后台直接处理 - if (Document != null || !handlingDBTextDeviation) - { - action.Invoke(); - return; - } - - // 后台 - // 这种情况发生在关闭了所有文档之后,进行跨进程通讯 - // 此处要先获取激活的文档,不能直接获取当前数据库否则异常 - var dm = Acaop.DocumentManager; - var doc = dm.MdiActiveDocument; - if (doc == null) - { - action.Invoke(); - return; - } - // 处理单行文字偏移 - // 前台绑定参照的时候不能用它,否则抛出异常:eWasErased - // 所以本函数自动识别前后台做处理 - var dbBak = doc.Database; - HostApplicationServices.WorkingDatabase = Database; - action.Invoke(); - HostApplicationServices.WorkingDatabase = dbBak; - } - #endregion - - #region IDisposable接口相关函数 - /// - /// 取消事务 - /// - public void Abort() - { - _commit = false; - Dispose(); - } - - /// - /// 提交事务 - /// - public void Commit() - { - _commit = true; - Dispose(); - } - /// - /// 是否释放事务 - /// - public bool IsDisposed { get; private set; } - - /// - /// 手动调用释放 - /// - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - /// - /// 析构函数调用释放 - /// - ~DBTrans() - { - Dispose(false); - } - /// - /// 释放函数 - /// - /// - private void Dispose(bool disposing) - { - /* 事务dispose流程: - * 1. 根据传入的参数确定是否提交,true为提交,false为不提交 - * 2. 如果锁文档就将文档锁dispose - * 3. 不管是否提交,既然进入dispose,就要将事务栈的当前事务弹出 - * 注意这里的事务栈不是cad的事务管理器,而是dbtrans的事务 - * 4. 清理非托管的字段 - */ - - // 不重复释放,并设置已经释放 - if (IsDisposed) return; - - if (disposing) - { - // 致命错误时候此处是空,直接跳过 - if (Transaction != null) - { - if (_commit) - { - // 刷新队列(后台不刷新) - //Editor?.Redraw(); - // 调用cad的事务进行提交,释放托管状态(托管对象) - Transaction.Commit(); - } - else - { - // 否则取消所有的修改 - Transaction.Abort(); - } - - // 将cad事务进行销毁 - if (!Transaction.IsDisposed) - Transaction.Dispose(); - } - // 将文档锁销毁 - _documentLock?.Dispose(); - } - - // 将当前事务栈弹栈 - _dBTrans.Pop(); - IsDisposed = true; - } - - #endregion - - #region ToString - - /// - public override string ToString() - - { - List lines = - [ - $"StackCount = {_dBTrans.Count}", - $"_fileName = \"{_fileName}\"", - $"_commit = {_commit}", - $"_documentLock = {_documentLock != null}", - - $"Document = {Document != null}", - $"Editor = {Editor != null}", - $"Transaction = {Transaction.UnmanagedObject}", - $"Database = {Database.Filename}" - ]; - - return string.Join("\n", lines.ToArray()); - } - #endregion -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/Runtime/Env.cs b/src/CAD/IFox.CAD.Shared/Runtime/Env.cs deleted file mode 100644 index 9ec9a77..0000000 --- a/src/CAD/IFox.CAD.Shared/Runtime/Env.cs +++ /dev/null @@ -1,887 +0,0 @@ -using System.Security; - -namespace IFoxCAD.Cad; - -/// -/// 系统管理类 -/// -/// 封装了一些系统 osmode;cmdecho;dimblk 系统变量
-/// 封装了常用的 文档 编辑器 数据库等对象为静态变量
-/// 封装了配置页面的注册表信息获取函数 -///
-///
-public static class Env -{ - #region Goal - - /// - /// 当前的数据库 - /// - public static Database Database => HostApplicationServices.WorkingDatabase; - - /// - /// 当前文档 - /// - public static Document Document => Acaop.DocumentManager.MdiActiveDocument; - - /// - /// 编辑器对象 - /// - public static Editor Editor => Document.Editor; - - /// - /// 图形管理器 - /// - public static Manager GsManager => Document.GraphicsManager; - - #endregion Goal - - #region Preferences - -#if !zcad // 中望官方的问题 - /// - /// 获取当前配置的数据 - /// - /// 小节名 - /// 数据名 - /// 对象 - public static object GetCurrentProfileProperty(string subSectionName, string propertyName) - { - var ucm = Acaop.UserConfigurationManager; - var cpf = ucm.OpenCurrentProfile(); - var ss = cpf.OpenSubsection(subSectionName); - return ss.ReadProperty(propertyName, ""); - } - - - /// - /// 获取对话框配置的数据 - /// - /// 对话框对象 - /// 配置项 - public static IConfigurationSection GetDialogSection(object dialog) - { - var ucm = Acaop.UserConfigurationManager; - var ds = ucm.OpenDialogSection(dialog); - return ds; - } - - /// - /// 获取公共配置的数据 - /// - /// 数据名 - /// 配置项 - public static IConfigurationSection GetGlobalSection(string propertyName) - { - var ucm = Acaop.UserConfigurationManager; - var gs = ucm.OpenGlobalSection(); - var ss = gs.OpenSubsection(propertyName); - return ss; - } -#endif - - #endregion Preferences - - #region Enum - - /// - /// 控制在AutoLISP的command函数运行时AutoCAD是否回显提示和输入, 为显示, 为不显示 - /// - public static bool CmdEcho - { - get => Convert.ToInt16(Acaop.GetSystemVariable("cmdecho")) == 1; - set => Acaop.SetSystemVariable("cmdecho", Convert.ToInt16(value)); - } - - /// - /// 获取Cad当前是否有活动命令 - /// - public static bool CmdActive => Convert.ToBoolean(Acaop.GetSystemVariable("CMDACTIVE")); - - /// - /// 控制在光标是否为正交模式, 为打开正交, 为关闭正交 - /// - public static bool OrthoMode - { - get => Convert.ToInt16(Acaop.GetSystemVariable("ORTHOMODE")) == 1; - set => Acaop.SetSystemVariable("ORTHOMODE", Convert.ToInt16(value)); - } - - /// - /// 读写系统变量LastPoint的坐标(UCS) - /// - public static Point3d LastPoint - { - get => (Point3d)Acaop.GetSystemVariable("LASTPOINT"); - set => Acaop.SetSystemVariable("LASTPOINT", value); - } - - #region Dimblk - - /// - /// 标注箭头类型 - /// - public enum DimblkType - { - /// - /// 实心闭合 - /// - Defult, - - /// - /// 点 - /// - Dot, - - /// - /// 小点 - /// - DotSmall, - - /// - /// 空心点 - /// - DotBlank, - - /// - /// 原点标记 - /// - Origin, - - /// - /// 原点标记2 - /// - Origin2, - - /// - /// 打开 - /// - Open, - - /// - /// 直角 - /// - Open90, - - /// - /// 30度角 - /// - Open30, - - /// - /// 闭合 - /// - Closed, - - /// - /// 空心小点 - /// - Small, - - /// - /// 无 - /// - None, - - /// - /// 倾斜 - /// - Oblique, - - /// - /// 实心框 - /// - BoxFilled, - - /// - /// 方框 - /// - BoxBlank, - - /// - /// 空心闭合 - /// - ClosedBlank, - - /// - /// 实心基准三角形 - /// - DatumFilled, - - /// - /// 基准三角形 - /// - DatumBlank, - - /// - /// 完整标记 - /// - Integral, - - /// - /// 建筑标记 - /// - ArchTick - } - - private static readonly Dictionary Dimdescdict = new() - { - { "实心闭合", DimblkType.Defult }, - { "点", DimblkType.Dot }, - { "小点", DimblkType.DotSmall }, - { "空心点", DimblkType.DotBlank }, - { "原点标记", DimblkType.Origin }, - { "原点标记 2", DimblkType.Origin2 }, - { "打开", DimblkType.Open }, - { "直角", DimblkType.Open90 }, - { "30 度角", DimblkType.Open30 }, - { "闭合", DimblkType.Closed }, - { "空心小点", DimblkType.Small }, - { "无", DimblkType.None }, - { "倾斜", DimblkType.Oblique }, - { "实心框", DimblkType.BoxFilled }, - { "方框", DimblkType.BoxBlank }, - { "空心闭合", DimblkType.ClosedBlank }, - { "实心基准三角形", DimblkType.DatumFilled }, - { "基准三角形", DimblkType.DatumBlank }, - { "完整标记", DimblkType.Integral }, - { "建筑标记", DimblkType.ArchTick }, - - { "", DimblkType.Defult }, - { "_DOT", DimblkType.Dot }, - { "_DOTSMALL", DimblkType.DotSmall }, - { "_DOTBLANK", DimblkType.DotBlank }, - { "_ORIGIN", DimblkType.Origin }, - { "_ORIGIN2", DimblkType.Origin2 }, - { "_OPEN", DimblkType.Open }, - { "_OPEN90", DimblkType.Open90 }, - { "_OPEN30", DimblkType.Open30 }, - { "_CLOSED", DimblkType.Closed }, - { "_SMALL", DimblkType.Small }, - { "_NONE", DimblkType.None }, - { "_OBLIQUE", DimblkType.Oblique }, - { "_BOXFILLED", DimblkType.BoxFilled }, - { "_BOXBLANK", DimblkType.BoxBlank }, - { "_CLOSEDBLANK", DimblkType.ClosedBlank }, - { "_DATUMFILLED", DimblkType.DatumFilled }, - { "_DATUMBLANK", DimblkType.DatumBlank }, - { "_INTEGRAL", DimblkType.Integral }, - { "_ARCHTICK", DimblkType.ArchTick } - }; - - - /// - /// 标注箭头属性 - /// - public static DimblkType Dimblk - { - get - { - var s = ((string)Acaop.GetSystemVariable("dimblk")).ToUpper(); - // if (string.IsNullOrEmpty(s)) - // { - // return DimblkType.Defult; - // } - // else - // { - // if (dimdescdict.TryGetValue(s, out DimblkType value)) - // { - // return value; - // } - // return s.ToEnum(); - // // return s.FromDescName(); - // } - return Dimdescdict[s]; - } - set - { - var s = GetDimblkName(value); - Acaop.SetSystemVariable("dimblk", s); - } - } - - /// - /// 获取标注箭头名 - /// - /// 标注箭头类型 - /// 箭头名 - public static string GetDimblkName(DimblkType dimblk) - { - return - dimblk == DimblkType.Defult - ? "." - : "_" + dimblk.GetName(); - } - - /// - /// 获取标注箭头ID - /// - /// 标注箭头类型 - /// 箭头ID - public static ObjectId GetDimblkId(DimblkType dimblk) - { - var oldDimblk = Dimblk; - Dimblk = dimblk; - var id = HostApplicationServices.WorkingDatabase.Dimblk; - Dimblk = oldDimblk; - return id; - } - - #endregion Dimblk - - #region OsMode - - /// - /// 捕捉模式系统变量类型 - /// - [Flags] - public enum OSModeType - { - /// - /// 无 - /// - None = 0, - - /// - /// 端点 - /// - End = 1, - - /// - /// 中点 - /// - Middle = 2, - - /// - /// 圆心 - /// - Center = 4, - - /// - /// 节点 - /// - Node = 8, - - /// - /// 象限点 - /// - Quadrant = 16, - - /// - /// 交点 - /// - Intersection = 32, - - /// - /// 插入点 - /// - Insert = 64, - - /// - /// 垂足 - /// - Pedal = 128, - - /// - /// 切点 - /// - Tangent = 256, - - /// - /// 最近点 - /// - Nearest = 512, - - /// - /// 几何中心 - /// - Quick = 1024, - - /// - /// 外观交点 - /// - Appearance = 2048, - - /// - /// 延伸 - /// - Extension = 4096, - - /// - /// 平行 - /// - Parallel = 8192 - } - - /// - /// 捕捉模式系统变量 - /// - public static OSModeType OSMode - { - get => (OSModeType)Convert.ToInt16(Acaop.GetSystemVariable("osmode")); - set => Acaop.SetSystemVariable("osmode", (int)value); - } - - /// - /// 捕捉模式osm1是否包含osm2 - /// - /// 原模式 - /// 要比较的模式 - /// 包含时返回 ,不包含时返回 - public static bool Include(this OSModeType osm1, OSModeType osm2) - { - return (osm1 & osm2) == osm2; - } - - #endregion OsMode - - - private static string? GetName(this T value) - { - return Enum.GetName(typeof(T), value!); - } - - #endregion Enum - - #region 系统变量 - - /// - /// 获取cad系统变量 - /// - /// 变量名 - /// 变量值 - public static object GetVar(string varName) - { - return Acaop.GetSystemVariable(varName); - } - - /// - /// 设置cad系统变量
- /// 0x01 建议先获取现有变量值和设置的是否相同,否则直接设置会发生异常
- /// 0x02 建议锁文档,否则 Psltscale 设置发生异常
- /// 发生异常的时候vs输出窗口会打印一下,但是如果不介意也没啥问题 - ///
- /// 变量名 - /// 变量值 - /// 输出异常,默认true;此设置仅为打印到命令栏,无法控制vs输出 - public static void SetVar(string varName, object value, bool echo = true) - { - try - { - Acaop.SetSystemVariable(varName, value); - } - catch (Exception) - { - if (echo) - Print($"{varName} 是不存在的变量!"); - } - } - - #endregion - - #region 环境变量 - -#if acad - [SuppressUnmanagedCodeSecurity] - [DllImport("accore.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, - EntryPoint = "acedGetEnv")] - private static extern int AcedGetEnv(string? envName, StringBuilder ReturnValue); - - [SuppressUnmanagedCodeSecurity] - [DllImport("accore.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, - EntryPoint = "acedSetEnv")] - private static extern int AcedSetEnv(string? envName, StringBuilder NewValue); -#endif - -#if gcad - [System.Security.SuppressUnmanagedCodeSecurity] - [DllImport("gced.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, EntryPoint = - "gcedGetEnv")] - static extern int AcedGetEnv(string? envName, StringBuilder ReturnValue); - - [System.Security.SuppressUnmanagedCodeSecurity] - [DllImport("gced.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, EntryPoint = - "gcedSetEnv")] - static extern int AcedSetEnv(string? envName, StringBuilder NewValue); -#endif - - // TODO: 中望没有测试,此处仅为不报错;本工程所有含有"中望"均存在问题 -#if zcad - [System.Security.SuppressUnmanagedCodeSecurity] - [DllImport("zced.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, EntryPoint = - "zcedGetEnv")] - static extern int AcedGetEnv(string? envName, StringBuilder ReturnValue); - - [System.Security.SuppressUnmanagedCodeSecurity] - [DllImport("zced.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, EntryPoint = - "zcedSetEnv")] - static extern int AcedSetEnv(string? envName, StringBuilder NewValue); -#endif - - /// - /// 读取acad环境变量
- /// 也能获取win环境变量 - ///
- /// 变量名 - /// 返回值从不为null,需判断 - public static string GetEnv(string name) - { - // 它将混合查询以下路径: - // acad2008注册表路径: 计算机\HKEY_CURRENT_USER\SOFTWARE\Autodesk\AutoCAD\R17.1\ACAD-6001:804\FixedProfile\General - // 用户: 计算机\HKEY_CURRENT_USER\Environment - // 系统: 计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment - - // GetEnv("Path")长度很长: - // 可用内存 (最新格式) 1 MB (标准格式) - // https://docs.microsoft.com/zh-cn/windows/win32/sysinfo/registry-element-size-limits - - var sbRes = new StringBuilder(1 << 23); - _ = AcedGetEnv(name, sbRes); - return sbRes.ToString(); - } - - /// - /// 设置acad环境变量
- /// 它是不会报错的,但是直接设置会写入注册表的,
- /// 如果是设置高低版本cad不同的变量,建议先读取判断再设置
- ///
- /// 变量名 - /// 变量值 - /// - public static int SetEnv(string name, string var) - { - return AcedSetEnv(name, new StringBuilder(var)); - } - - #endregion - - #region win环境变量/由于 Aced的 能够同时获取此变量与cad内的,所以废弃 - - // /// - // /// 获取系统环境变量 - // /// - // /// 变量名 - // /// 指定的环境变量的值;或者如果找不到环境变量,则返回 null - // public static string? GetEnv(string? var) - // { - // // 从当前进程或者从当前用户或本地计算机的 Windows 操作系统注册表项检索环境变量的值 - // // 用户: 计算机\HKEY_CURRENT_USER\Environment - // // 系统: 计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment - // return Environment.GetEnvironmentVariable(var); - // } - // /// - // /// 设置系统环境变量 - // /// - // /// 变量名 - // /// 变量值 - // public static void SetEnv(string? var, string? value) - // { - // // 创建、修改或删除当前进程中或者为当前用户或本地计算机保留的 Windows 操作系统注册表项中存储的环境变量 - // Environment.SetEnvironmentVariable(var, value); - // } - - #endregion - - #region 支持文件目录 - - /// - /// 添加目录至CAD支持搜索的路径 - /// - /// 目录 - public static void AppendSupportPath(params string[] folders) - { - if (!folders.Any()) return; - var acadPath = GetEnv("ACAD"); - var acadPathLowerArr = - acadPath - .ToLower() - .Split(';') - .Where(item => item != "") - .Select(item => - item[^1] == '\\' ? item.Remove(item.Length - 1) : item) - .ToHashSet(); - foreach (var folder in folders) - { - if (!Directory.Exists(folder)) continue; - var folderLower = - folder[^1] == '\\' ? folder.Remove(folder.Length - 1).ToLower() : folder.ToLower(); - if (!acadPathLowerArr.Contains(folderLower)) - acadPath = folder + ";" + acadPath; //加到前面方便检查 - } - - SetEnv("ACAD", acadPath); - } - - /// - /// 删除支持搜索文件目录 - /// - /// 目录 - public static void RemoveSupportPath(params string[] folders) - { - if (!folders.Any()) return; - var acadPathArr = GetEnv("ACAD").Split(';').ToList(); - foreach (var folder in folders) - { - var folderLower = - folder[^1] == '\\' ? folder.Remove(folder.Length - 1).ToLower() : folder.ToLower(); - acadPathArr.RemoveAll(item => - (item[^1] == '\\' ? item.Remove(item.Length - 1).ToLower() : item.ToLower()) == folderLower); - } - - SetEnv("ACAD", string.Join(";", acadPathArr)); - } - - /// - /// 添加目录至CAD受信任的位置 - /// - /// 目录 - public static void AppendTrustedPath(params string[] folders) - { - if (!folders.Any()) return; - var trustedPath = GetVar("TRUSTEDPATHS").ToString(); - var trustedPathLowerArr = - trustedPath - .ToLower() - .Split(';') - .Where(item => item != "") - .Select(item => - item[^1] == '\\' ? item.Remove(item.Length - 1) : item) - .ToHashSet(); - foreach (var folder in folders) - { - if (!Directory.Exists(folder)) continue; - var folderLower = - folder[^1] == '\\' ? folder.Remove(folder.Length - 1).ToLower() : folder.ToLower(); - if (!trustedPathLowerArr.Contains(folderLower)) - trustedPath = folder + ";" + trustedPath; //加到前面方便检查 - } - - SetVar("TRUSTEDPATHS", trustedPath); - } - - /// - /// 移除信任目录 - /// - /// 目录 - public static void RemoveTrustedPath(params string[] folders) - { - if (!folders.Any()) return; - var trustedPathArr = GetVar("TRUSTEDPATHS").ToString().Split(';').ToList(); - foreach (var folder in folders) - { - var folderLower = - folder[^1] == '\\' ? folder.Remove(folder.Length - 1).ToLower() : folder.ToLower(); - trustedPathArr.RemoveAll(item => - (item[^1] == '\\' ? item.Remove(item.Length - 1).ToLower() : item.ToLower()) == folderLower); - } - - SetVar("TRUSTEDPATHS", string.Join(";", trustedPathArr)); - } - - #endregion - - /// - /// 命令行打印,会自动调用对象的toString函数 - /// - /// 要打印的对象 - public static void Print(object message) - { - Editor.WriteMessage($"{message}\n"); - } - - /// - /// 命令行打印,会自动调用对象的toString函数,在打印内容前添加换行 - /// - /// 要打印的对象 - public static void Printl(object message) - { - Editor.WriteMessage($"{Environment.NewLine}{message}\n"); - } - - /// - /// 判断当前是否在UCS坐标下 - /// - /// Bool - public static bool IsUcs() - { - return (short)GetVar("WORLDUCS") == 0; - } - - - #region dwg版本号/cad版本号/年份 - - /// - /// 获取当前配置文件的保存版本 - /// - /// - public static DwgVersion GetDefaultDwgVersion() - { - var ffs = GetEnv("DefaultFormatForSave"); - var version = ffs switch - { - "1" => DwgVersion.AC1009, // R12/LT12 dxf - "8" => DwgVersion.AC1014, // R14/LT98/LT97 dwg - "12" => DwgVersion.AC1015, // 2000 dwg - "13" => DwgVersion.AC1800a, // 2000 dxf - "24" => DwgVersion.AC1800, // 2004 dwg - "25" => (DwgVersion)26, // 2004 dxf - "36" => (DwgVersion)27, // 2007 dwg DwgVersion.AC1021 - "37" => (DwgVersion)28, // 2007 dxf - - // "38" => (DwgVersion),// dwt 样板文件...啊惊没找到这个是什么 - "48" => (DwgVersion)29, // 2010 dwg DwgVersion.AC1024 - "49" => (DwgVersion)30, // 2010 dxf - "60" => (DwgVersion)31, // 2013 dwg DwgVersion.AC1027 - "61" => (DwgVersion)32, // 2013 dxf - "64" => (DwgVersion)33, // 2018 dwg DwgVersion.AC1032 - "65" => (DwgVersion)34, // 2018 dxf - _ => throw new NotImplementedException() // 提醒维护 - }; - return version; - } - - /// - /// 是否为dxf版本号 - /// - /// - /// - public static bool IsDxfVersion(this DwgVersion dwgVersion) - { - var result = (int)dwgVersion switch - { - 16 => true, // R12/LT12 dxf - 24 => true, // 2000 dxf - 26 => true, // 2004 dxf - 28 => true, // 2007 dxf - 30 => true, // 2010 dxf - 32 => true, // 2013 dxf - 34 => true, // 2018 dxf - _ => false - }; - return result; - } - - /// - /// 获取cad年份 - /// - /// 超出年份就报错 - public static int GetAcadVersion() - { - var ver = Acaop.Version.Major + "." + Acaop.Version.Minor; - var acarVarNum = ver switch - { - "16.2" => 2006, - "17.0" => 2007, - "17.1" => 2008, - "17.2" => 2009, - "18.0" => 2010, - "18.1" => 2011, - "18.2" => 2012, - "19.0" => 2013, - "19.1" => 2014, - "20.0" => 2015, - "20.1" => 2016, - "21.0" => 2017, - "22.0" => 2018, - "23.0" => 2019, - "23.1" => 2020, - "24.0" => 2021, - "24.1" => 2022, - "24.2" => 2023, - _ => throw new NotImplementedException() - }; - return acarVarNum; - } - - /// - /// 获取带cad版本号的dll - /// - /// dll名字 - /// dll的前面 - public static string GetAcapVersionDll(string str = "acdb") - { - return str + Acaop.Version.Major + ".dll"; - } - - #endregion - - - #region cad变量功能延伸 - - /// - /// 设置cad系统变量
- /// 提供一个反序列化后,无cad异常输出的功能
- /// 注意,您需要再此执行时候设置文档锁
- /// 否则也将导致修改数据库异常
- ///
- /// - /// - /// 成功返回当前值,失败null - /// - public static object SetVarEx(string key, string value) - { - var currentVar = GetVar(key); - - object valueType = currentVar.GetType().Name switch - { - "String" => value.Replace("\"", string.Empty), - "Double" => double.Parse(value), - "Int16" => short.Parse(value), - "Int32" => int.Parse(value), - _ => throw new NotImplementedException() - }; - - // 相同的参数进行设置会发生一次异常 - if (!string.Equals(currentVar.ToString(), valueType.ToString(), StringComparison.CurrentCultureIgnoreCase)) - SetVar(key, valueType); - - return currentVar; - } - - /// - /// 设置新系统变量,返回现有系统变量 - /// - /// 设置的变量词典 - /// 返回现有变量词典,然后下次就可以利用它进行设置回来了 - public static Dictionary SaveCadVar(Dictionary args) - { - //if (args is null) - // throw new ArgumentNullException(nameof(args)); - ArgumentNullEx.ThrowIfNull(args); - var dict = new Dictionary(); - foreach (var item in args) - { - // 判断是否为系统变量 - var ok = SetVarEx(item.Key, item.Value); - if (ok != null) - { - dict.Add(item.Key, ok.ToString()); - continue; - } - - // 判断是否为系统变量 - var envstr = GetEnv(item.Key); - if (!string.IsNullOrEmpty(envstr)) - { - SetEnv(item.Key, item.Value); - dict.Add(item.Key, envstr); - } - } - - return dict; - } - - /// - /// 延迟更新图层锁定淡显状态 - /// 在有锁定或解锁图层的命令的末尾使用 - /// - public static void DelayUpdateLayLockFade() - { - const string lfName = "LAYLOCKFADECTL"; - var lf = Convert.ToInt32(Acaop.GetSystemVariable(lfName).ToString()); - Acaop.SetSystemVariable(lfName, -lf); - IdleAction.Add(() => Acaop.SetSystemVariable(lfName, lf)); - } - - #endregion -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/Runtime/SymbolTable.cs b/src/CAD/IFox.CAD.Shared/Runtime/SymbolTable.cs deleted file mode 100644 index 7a54e7b..0000000 --- a/src/CAD/IFox.CAD.Shared/Runtime/SymbolTable.cs +++ /dev/null @@ -1,408 +0,0 @@ -namespace IFoxCAD.Cad; -/// -/// 符号表管理类 -/// -/// 符号表 -/// 符号表记录 -public class SymbolTable : IEnumerable - where TTable : SymbolTable - where TRecord : SymbolTableRecord, new() -{ - #region 程序集内部属性 - /// - /// 事务管理器 - /// - private DBTrans DTrans { get; set; } - /// - /// 数据库 - /// - internal Database Database { get; private set; } - - #endregion - - #region 公开属性 - /// - /// 当前符号表 - /// - public TTable CurrentSymbolTable { get; private set; } - #endregion - - #region 构造函数 - /// - /// 构造函数,初始化Trans和CurrentSymbolTable属性 - /// - /// 事务管理器 - /// 符号表id - /// 默认行为:例如打开隐藏图层 - internal SymbolTable(DBTrans tr, ObjectId tableId, bool defaultBehavior = true) - { - DTrans = tr; - Database = tr.Database; - CurrentSymbolTable = DTrans.GetObject(tableId)!; - - if (!defaultBehavior) - return; - - if (CurrentSymbolTable is LayerTable layer) - { - // 层表包含隐藏的,全部显示出来 - layer = layer.IncludingHidden; - if (layer is TTable tt) - CurrentSymbolTable = tt; - } - } - - #endregion - - #region 索引器 - /// - /// 索引器 - /// - /// 对象名称 - /// 对象的id - public ObjectId this[string key] - { - get - { - if (Has(key)) - return CurrentSymbolTable[key]; - return ObjectId.Null; - } - } - #endregion - - #region Has - /// - /// 判断是否存在符号表记录 - /// - /// 记录名 - /// 存在返回 , 不存在返回 - public bool Has(string key) - { - return CurrentSymbolTable.Has(key); - } - /// - /// 判断是否存在符号表记录 - /// - /// 记录id - /// 存在返回 , 不存在返回 - public bool Has(ObjectId objectId) - { - return CurrentSymbolTable.Has(objectId); - } - #endregion - - #region 添加符号表记录 - /// - /// 添加符号表记录 - /// - /// 符号表记录 - /// 对象id - public ObjectId Add(TRecord record) - { - ObjectId id; - using (CurrentSymbolTable.ForWrite()) - { - id = CurrentSymbolTable.Add(record); - DTrans.Transaction.AddNewlyCreatedDBObject(record, true); - } - return id; - } - /// - /// 添加符号表记录 - /// - /// 符号表记录名 - /// 符号表记录处理函数的无返回值委托 - /// 对象id - public ObjectId Add(string name, Action? action = null) - { - var id = this[name]; - if (!id.IsNull) return id; - var record = new TRecord() - { - Name = name - }; - id = Add(record); - using (record.ForWrite()) - action?.Invoke(record); - return id; - } - #endregion - - #region 删除符号表记录 - /// - /// 删除符号表记录 - /// - /// 符号表记录对象 - private static void Remove(TRecord record) - { - using (record.ForWrite()) - record.Erase(); - } - - /// - /// 删除符号表记录 - /// - /// 符号表记录名 - public void Remove(string name) - { - var record = GetRecord(name); - if (record is not null) - Remove(record); - } - - /// - /// 删除符号表记录 - /// - /// 符号表记录对象id - public void Remove(ObjectId id) - { - var record = GetRecord(id); - if (record is not null) - Remove(record); - } - #endregion - - #region 修改符号表记录 - /// - /// 修改符号表 - /// - /// 符号表记录名 - /// 修改委托 - [System.Diagnostics.DebuggerStepThrough] - public void Change(string name, Action action) - { - var record = GetRecord(name); - if (record is not null) - { - using (record.ForWrite()) - action.Invoke(record); - } - } - - /// - /// 修改符号表 - /// - /// 符号表记录id - /// 修改委托 - [System.Diagnostics.DebuggerStepThrough] - public void Change(ObjectId id, Action action) - { - var record = GetRecord(id); - if (record is not null) - { - using (record.ForWrite()) - action.Invoke(record); - } - } - #endregion - - #region 获取符号表记录 - /// - /// 获取符号表记录 - /// - /// 符号表记录的id - /// 打开模式 - /// 是否打开已删除对象,默认为不打开 - /// 是否打开锁定图层对象,默认为不打开 - /// 符号表记录 - [System.Diagnostics.DebuggerStepThrough] - public TRecord? GetRecord(ObjectId id, - OpenMode openMode = OpenMode.ForRead, - bool openErased = false, - bool openLockedLayer = false) - { - return DTrans.GetObject(id, openMode, openErased, openLockedLayer); - } - - /// - /// 获取符号表记录 - /// - /// 符号表记录名 - /// 打开模式 - /// 是否打开已删除对象,默认为不打开 - /// 是否打开锁定图层对象,默认为不打开 - /// 符号表记录 - [System.Diagnostics.DebuggerStepThrough] - public TRecord? GetRecord(string name, - OpenMode openMode = OpenMode.ForRead, - bool openErased = false, - bool openLockedLayer = false) - { - return GetRecord(this[name], openMode, openErased, openLockedLayer); - } - - /// - /// 获取符号表记录 - /// - /// 符号表记录集合 - public IEnumerable GetRecords() - { - foreach (var item in this) - { - var record = GetRecord(item); - if (record is not null) - yield return record; - } - } - - /// - /// 获取符号表记录的名字集合 - /// - /// 记录的名字集合 - public IEnumerable GetRecordNames() => GetRecords().Select(record => record.Name); - - /// - /// 获取符合过滤条件的符号表记录名字集合 - /// - /// 过滤器委托 - /// 记录的名字集合 - public IEnumerable GetRecordNames(Func filter) - { - foreach (var item in this) - { - var record = GetRecord(item); - if (record is not null && filter.Invoke(record)) - yield return record.Name; - } - } - - /// - /// 从源数据库拷贝符号表记录 - /// - /// 符号表 - /// 符号表记录名 - /// 是否覆盖, 为覆盖, 为不覆盖 - /// 对象id - private ObjectId GetRecordFrom(SymbolTable table, string name, bool over) - { - //if (table is null) - // throw new ArgumentNullException(nameof(table), "对象为null"); - ArgumentNullEx.ThrowIfNull(table); - - ObjectId rid = this[name]; - bool has = rid != ObjectId.Null; - if ((!has || !over) && has) return rid; - ObjectId id = table[name]; - using IdMapping map = new(); - using ObjectIdCollection ids = new() { id }; - table.Database.WblockCloneObjects( - ids, - CurrentSymbolTable.Id, - map, - DuplicateRecordCloning.Replace, - false); - rid = map[id].Value; - return rid; - } - - /// - /// 从文件拷贝符号表记录 - /// - /// 符号表过滤器 - /// 文件名 - /// 符号表记录名 - /// 是否覆盖, 为覆盖, 为不覆盖 - /// 对象id - internal ObjectId GetRecordFrom(Func> tableSelector, - string fileName, - string name, - bool over) - { - using DBTrans tr = new(fileName); - return GetRecordFrom(tableSelector(tr), name, over); - } - #endregion - - #region 遍历 -#line hidden // 调试的时候跳过它 - /// - /// 遍历符号表,执行委托 - /// - /// 要运行的委托 - /// 打开模式,默认为只读 - /// 检查id是否删除,默认true - /// 是否打开已删除对象,默认为不打开 - /// 是否打开锁定图层对象,默认为不打开 - public void ForEach(Action task, - OpenMode openMode = OpenMode.ForRead, - bool checkIdOk = true, - bool openErased = false, - bool openLockedLayer = false) - { - ForEach((a, _, _) => { - task.Invoke(a);//由于此处是委托,所以 DebuggerStepThrough 特性会进入,改用预处理方式避免 - }, openMode, checkIdOk, openErased, openLockedLayer); - } - - /// - /// 遍历符号表,执行委托(允许循环中断) - /// - /// 要执行的委托 - /// 打开模式,默认为只读 - /// 检查id是否删除,默认true - /// 是否打开已删除对象,默认为不打开 - /// 是否打开锁定图层对象,默认为不打开 - public void ForEach(Action task, - OpenMode openMode = OpenMode.ForRead, - bool checkIdOk = true, - bool openErased = false, - bool openLockedLayer = false) - { - ForEach((a, b, _) => { - task.Invoke(a, b); - }, openMode, checkIdOk, openErased, openLockedLayer); - } - - /// - /// 遍历符号表,执行委托(允许循环中断,输出索引值) - /// - /// 要执行的委托 - /// 打开模式,默认为只读 - /// 检查id是否删除,默认true - /// 是否打开已删除对象,默认为不打开 - /// 是否打开锁定图层对象,默认为不打开 - [System.Diagnostics.DebuggerStepThrough] - public void ForEach(Action task, - OpenMode openMode = OpenMode.ForRead, - bool checkIdOk = true, - bool openErased = false, - bool openLockedLayer = false) - { - //if (task == null) - // throw new ArgumentNullException(nameof(task)); - ArgumentNullEx.ThrowIfNull(task); - LoopState state = new();/*这种方式比Action改Func更友好*/ - int i = 0; - foreach (var id in this) - { - if (checkIdOk && !id.IsOk()) - continue; - var record = GetRecord(id, openMode, openErased, openLockedLayer); - if (record is not null) - task.Invoke(record, state, i); - if (!state.IsRun) - break; - i++; - } - } -/// -#line default - - #endregion - - #region IEnumerable 成员 - [System.Diagnostics.DebuggerStepThrough] - public IEnumerator GetEnumerator() - { - foreach (var id in CurrentSymbolTable) - yield return id; - } - - [System.Diagnostics.DebuggerStepThrough] - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - #endregion -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/SelectionFilter/OpComp.cs b/src/CAD/IFox.CAD.Shared/SelectionFilter/OpComp.cs deleted file mode 100644 index 040090a..0000000 --- a/src/CAD/IFox.CAD.Shared/SelectionFilter/OpComp.cs +++ /dev/null @@ -1,79 +0,0 @@ -namespace IFoxCAD.Cad; - -/// -/// 比较运算符类 -/// -public class OpComp : OpEqual -{ - /// - /// 比较运算符,如: - /// "<=" - /// 以及合并比较运算符: - /// "<=,<=,=" - /// - public string Content { get; } - - /// - /// 符号名 - /// - public override string Name - { - get { return "Comp"; } - } - - /// - /// 比较运算符类构造函数 - /// - /// 运算符 - /// 数据 - public OpComp(string content, TypedValue value) - : base(value) - { - Content = content; - } - - /// - /// 比较运算符类构造函数 - /// - /// 运算符 - /// 组码 - public OpComp(string content, int code) - : base(code) - { - Content = content; - } - - /// - /// 比较运算符类构造函数 - /// - /// 运算符 - /// 组码 - /// 组码值 - public OpComp(string content, int code, object value) - : base(code, value) - { - Content = content; - } - - /// - /// 比较运算符类构造函数 - /// - /// 运算符 - /// 组码 - /// 组码值 - public OpComp(string content, DxfCode code, object value) - : base(code, value) - { - Content = content; - } - - /// - /// 获取过滤器数据迭代器 - /// - /// TypedValue迭代器 - public override IEnumerable GetValues() - { - yield return new TypedValue(-4, Content); - yield return Value; - } -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/SelectionFilter/OpEqual.cs b/src/CAD/IFox.CAD.Shared/SelectionFilter/OpEqual.cs deleted file mode 100644 index 370a0c1..0000000 --- a/src/CAD/IFox.CAD.Shared/SelectionFilter/OpEqual.cs +++ /dev/null @@ -1,86 +0,0 @@ -namespace IFoxCAD.Cad; - -/// -/// 相等运算符类 -/// -public class OpEqual : OpFilter -{ - /// - /// 组码与匹配值的TypedValue类型值 - /// - public TypedValue Value { get; private set; } - - /// - /// 符号名 - /// - public override string Name - { - get { return "Equal"; } - } - - /// - /// 相等运算符类构造函数 - /// - /// 组码 - public OpEqual(int code) - { - Value = new TypedValue(code); - } - - /// - /// 相等运算符类构造函数 - /// - /// 组码 - /// 组码值 - public OpEqual(int code, object value) - { - Value = new TypedValue(code, value); - } - - /// - /// 相等运算符类构造函数 - /// - /// 组码 - /// 组码值 - public OpEqual(DxfCode code, object value) - { - Value = new TypedValue((int)code, value); - } - - /// - /// 相等运算符类构造函数 - /// - /// 组码与组码值的TypedValue类型值 - internal OpEqual(TypedValue value) - { - Value = value; - } - - /// - /// 过滤器数据迭代器 - /// - /// TypedValue迭代器 - public override IEnumerable GetValues() - { - yield return Value; - } - - /// - /// 设置数据 - /// - /// 组码值 - public void SetValue(object value) - { - Value = new TypedValue(Value.TypeCode, value); - } - - /// - /// 设置数据 - /// - /// 组码 - /// 组码值 - public void SetValue(int code, object value) - { - Value = new TypedValue(code, value); - } -} diff --git a/src/CAD/IFox.CAD.Shared/SelectionFilter/OpFilter.cs b/src/CAD/IFox.CAD.Shared/SelectionFilter/OpFilter.cs deleted file mode 100644 index 48843f4..0000000 --- a/src/CAD/IFox.CAD.Shared/SelectionFilter/OpFilter.cs +++ /dev/null @@ -1,341 +0,0 @@ -namespace IFoxCAD.Cad; - -/// -/// 选择集过滤器抽象类 -/// -public abstract class OpFilter -{ - /// - /// 过滤器的名字 - /// - public abstract string Name { get; } - - /// - /// 只读属性,表示这个过滤器取反 - /// - public OpFilter Not => new OpNot(this); - - /// - /// 获取TypedValue类型的值的迭代器的抽象方法,子类必须重写 - /// - /// TypedValue迭代器 - public abstract IEnumerable GetValues(); - - /// - /// 非操作符,返回的是OpFilter类型变量的 属性 - /// - /// OpFilter类型变量 - /// OpFilter对象 - public static OpFilter operator !(OpFilter item) - { - return item.Not; - } - - /// - /// 过滤器值转换为 TypedValue 类型数组 - /// - /// TypedValue数组 - public TypedValue[] ToArray() - { - return GetValues().ToArray(); - } - - /// - /// 隐式类型转换,将自定义的过滤器转换为 Autocad 认识的选择集过滤器 - /// - /// 过滤器对象 - /// - /// 选择集过滤器. - /// - public static implicit operator SelectionFilter(OpFilter item) - { - return new SelectionFilter(item.ToArray()); - } - - /// - /// 转换为字符串 - /// - /// 字符串 - public override string ToString() - { - var sb = new StringBuilder(); - foreach (var value in GetValues()) - sb.Append(value); - return sb.ToString(); - } - - /// - /// 构建过滤器 - /// - /// - /// 举两个利用构建函数创建选择集过滤的例子 - /// - /// !(e.Dxf(0) == "line" & e.Dxf(8) == "0") - /// | e.Dxf(0) != "circle" & e.Dxf(8) == "2" & e.Dxf(10) >= p); - /// - /// 例子2: - /// var f2 = OpFilter.Build( - /// e => e.Or( - /// !e.And(e.Dxf(0) == "line", e.Dxf(8) == "0"), - /// e.And(e.Dxf(0) != "circle", e.Dxf(8) == "2", - /// e.Dxf(10) <= new Point3d(10, 10, 0)))); - /// ]]> - /// - /// 构建过滤器的函数委托 - /// 过滤器 - public static OpFilter Build(Func func) - { - return func(new Op()).Filter!; - } - - #region Operator - - /// - /// 过滤器操作符类 - /// - public class Op - { - /// - /// 过滤器属性 - /// - internal OpFilter? Filter { get; private set; } - - internal Op() { } - - private Op(OpFilter filter) - { - Filter = filter; - } - - /// - /// AND 操作符 - /// - /// 操作符类型的可变参数 - /// Op对象 -#pragma warning disable CA1822 // 将成员标记为 static - public Op And(params Op[] args) -#pragma warning restore CA1822 // 将成员标记为 static - { - var filter = new OpAnd(); - foreach (var op in args) - filter.Add(op.Filter!); - return new Op(filter); - } - - /// - /// or 操作符 - /// - /// 操作符类型的可变参数 - /// Op对象 -#pragma warning disable CA1822 // 将成员标记为 static - public Op Or(params Op[] args) -#pragma warning restore CA1822 // 将成员标记为 static - { - var filter = new OpOr(); - foreach (var op in args) - filter.Add(op.Filter!); - return new Op(filter); - } - - /// - /// dxf 操作符,此函数只能用于过滤器中,不是组码操作函数 - /// - /// 组码 - /// Op对象 -#pragma warning disable CA1822 // 将成员标记为 static - public Op Dxf(int code) -#pragma warning restore CA1822 // 将成员标记为 static - { - return new Op(new OpEqual(code)); - } - - /// - /// dxf 操作符,此函数只能用于过滤器中,不是组码操作函数 - /// - /// 组码 - /// 关系运算符的值,比如">,>,=" - /// Op对象 -#pragma warning disable CA1822 // 将成员标记为 static - public Op Dxf(int code, string content) -#pragma warning restore CA1822 // 将成员标记为 static - { - return new Op(new OpComp(content, code)); - } - - /// - /// 非操作符 - /// - /// 过滤器操作符对象 - /// Op对象 - public static Op operator !(Op right) - { - right.Filter = !right.Filter!; - return right; - } - - /// - /// 相等操作符 - /// - /// 过滤器操作符对象 - /// 数据 - /// Op对象 - public static Op operator ==(Op left, object right) - { - var eq = (OpEqual)left.Filter!; - eq.SetValue(right); - return left; - } - - /// - /// 不等操作符 - /// - /// 过滤器操作符对象 - /// 数据 - /// Op对象 - public static Op operator !=(Op left, object right) - { - var eq = (OpEqual)left.Filter!; - eq.SetValue(right); - left.Filter = eq.Not; - return left; - } - - private static Op GetCompOp(string content, Op left, object right) - { - var eq = (OpEqual)left.Filter!; - var comp = new OpComp(content, eq.Value.TypeCode, right); - return new Op(comp); - } - - /// - /// 大于操作符 - /// - /// 过滤器操作符对象 - /// 数据 - /// Op对象 - public static Op operator >(Op left, object right) - { - return GetCompOp(">", left, right); - } - - /// - /// 小于操作符 - /// - /// 过滤器操作符对象 - /// 数据 - /// Op对象 - public static Op operator <(Op left, object right) - { - return GetCompOp("<", left, right); - } - - /// - /// 大于等于操作符 - /// - /// 过滤器操作符对象 - /// 数据 - /// Op对象 - public static Op operator >=(Op left, object right) - { - return GetCompOp(">=", left, right); - } - - /// - /// 小于等于操作符 - /// - /// 过滤器操作符对象 - /// 数据 - /// Op对象 - public static Op operator <=(Op left, object right) - { - return GetCompOp("<=", left, right); - } - - /// - /// 大于等于操作符 - /// - /// 过滤器操作符对象 - /// 点 - /// Op对象 - public static Op operator >=(Op left, Point3d right) - { - return GetCompOp(">,>,*", left, right); - } - - /// - /// 小于等于操作符 - /// - /// 过滤器操作符对象 - /// 点 - /// Op对象 - public static Op operator <=(Op left, Point3d right) - { - return GetCompOp("<,<,*", left, right); - } - - /// - /// 并操作符 - /// - /// 过滤器操作符对象 - /// 过滤器操作符对象 - /// Op对象 - public static Op operator &(Op left, Op right) - { - var filter = new OpAnd - { - left.Filter!, - right.Filter! - }; - return new Op(filter); - } - - /// - /// 或操作符 - /// - /// 过滤器操作符对象 - /// 过滤器操作符对象 - /// Op对象 - public static Op operator |(Op left, Op right) - { - var filter = new OpOr - { - left.Filter!, - right.Filter! - }; - return new Op(filter); - } - - /// - /// 异或操作符 - /// - /// 过滤器操作符对象 - /// 过滤器操作符对象 - /// Op对象 - public static Op operator ^(Op left, Op right) - { - var filter = new OpXor(left.Filter!, right.Filter!); - return new Op(filter); - } - - /// - /// 比较函数 - /// - /// 对象 - /// - /// 是否相等 - /// - public override bool Equals(object obj) => base.Equals(obj); - - /// - /// 获取HashCode - /// - /// HashCode - public override int GetHashCode() => base.GetHashCode(); - } - - #endregion Operator -} diff --git a/src/CAD/IFox.CAD.Shared/SelectionFilter/OpList.cs b/src/CAD/IFox.CAD.Shared/SelectionFilter/OpList.cs deleted file mode 100644 index 0eb2350..0000000 --- a/src/CAD/IFox.CAD.Shared/SelectionFilter/OpList.cs +++ /dev/null @@ -1,162 +0,0 @@ -namespace IFoxCAD.Cad; - -/// -/// 逻辑操作符的列表抽象类 -/// -public abstract class OpList : OpLogi -{ - /// - /// 过滤器列表 - /// - protected readonly List Lst = []; - - /// - /// 添加过滤器条件的虚函数,子类可以重写 - /// - /// 举个利用这个类及其子类创建选择集过滤的例子 - /// - /// ,>,*" } - /// }, - /// }; - /// ]]> - /// - /// 过滤器对象 - public virtual void Add(OpFilter value) - { - Lst.Add(value); - } - - /// - /// 添加过滤条件 - /// - /// 逻辑非~ - /// 组码 - /// 组码值 - public void Add(string speccode, int code, object value) - { - if (speccode == "~") - Lst.Add(new OpEqual(code, value).Not); - } - - /// - /// 添加过滤条件 - /// - /// 组码 - /// 组码值 - public void Add(int code, object value) - { - Lst.Add(new OpEqual(code, value)); - } - - /// - /// 添加过滤条件 - /// - /// 组码 - /// 组码值 - public void Add(DxfCode code, object value) - { - Lst.Add(new OpEqual(code, value)); - } - - /// - /// 添加过滤条件 - /// - /// 组码 - /// 组码值 - /// 比较运算符 - public void Add(int code, object value, string comp) - { - Lst.Add(new OpComp(comp, code, value)); - } - - /// - /// 添加过滤条件 - /// - /// 组码 - /// 组码值 - /// 比较运算符 - public void Add(DxfCode code, object value, string comp) - { - Lst.Add(new OpComp(comp, code, value)); - } - - /// - /// 过滤器迭代器 - /// - /// OpFilter迭代器 - [System.Diagnostics.DebuggerStepThrough] - public override IEnumerator GetEnumerator() - { - // foreach (var value in Lst) - // yield return value; - return Lst.GetEnumerator(); - } -} - -/// -/// 逻辑与类 -/// -public class OpAnd : OpList -{ - /// - /// 符号名 - /// - public override string Name => "And"; - - /// - /// 添加过滤条件 - /// - /// 过滤器对象 - public override void Add(OpFilter value) - { - if (value is OpAnd opand) - { - foreach (var item in opand) - Lst.Add(item); - } - else - { - Lst.Add(value); - } - } -} - -/// -/// 逻辑或类 -/// -public class OpOr : OpList -{ - /// - /// 符号名 - /// - public override string Name => "Or"; - - /// - /// 添加过滤条件 - /// - /// 过滤器对象 - public override void Add(OpFilter value) - { - if (value is OpOr opor) - { - foreach (var item in opor) - Lst.Add(item); - } - else - { - Lst.Add(value); - } - } -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Shared/SelectionFilter/OpLogi.cs b/src/CAD/IFox.CAD.Shared/SelectionFilter/OpLogi.cs deleted file mode 100644 index bdacb86..0000000 --- a/src/CAD/IFox.CAD.Shared/SelectionFilter/OpLogi.cs +++ /dev/null @@ -1,133 +0,0 @@ -namespace IFoxCAD.Cad; - -/// -/// 过滤器逻辑运算符抽象类 -/// -public abstract class OpLogi : OpFilter, IEnumerable -{ - /// - /// 返回-4组码的开始内容 - /// - public TypedValue First - { - get { return new TypedValue(-4, $"<{Name}"); } - } - - /// - /// 返回-4组码的结束内容 - /// - public TypedValue Last - { - get { return new TypedValue(-4, $"{Name}>"); } - } - - /// - /// 获取过滤条件 - /// - /// TypedValue迭代器 - //[System.Diagnostics.DebuggerStepThrough] - public override IEnumerable GetValues() - { - yield return First; - foreach (var item in this) - { - foreach (var value in item.GetValues()) - yield return value; - } - yield return Last; - } - - /// - /// 获取迭代器 - /// - /// OpFilter迭代器 - [System.Diagnostics.DebuggerStepThrough] - public abstract IEnumerator GetEnumerator(); - - [System.Diagnostics.DebuggerStepThrough] - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } -} - -/// -/// 逻辑非类 -/// -public class OpNot : OpLogi -{ - private OpFilter Value { get; } - - /// - /// 逻辑非类构造函数 - /// - /// OpFilter数据 - public OpNot(OpFilter value) - { - Value = value; - } - - /// - /// 符号名 - /// - public override string Name - { - get { return "Not"; } - } - - /// - /// 获取迭代器 - /// - /// OpFilter迭代器 - [System.Diagnostics.DebuggerStepThrough] - public override IEnumerator GetEnumerator() - { - yield return Value; - } -} - -/// -/// 逻辑异或类 -/// -public class OpXor : OpLogi -{ - /// - /// 左操作数 - /// - public OpFilter Left { get; } - - /// - /// 右操作数 - /// - public OpFilter Right { get; } - - /// - /// 逻辑异或类构造函数 - /// - /// 左操作数 - /// 右操作数 - public OpXor(OpFilter left, OpFilter right) - { - Left = left; - Right = right; - } - - /// - /// 符号名 - /// - public override string Name - { - get { return "Xor"; } - } - - /// - /// 获取迭代器 - /// - /// 选择集过滤器类型迭代器 - [System.Diagnostics.DebuggerStepThrough] - public override IEnumerator GetEnumerator() - { - yield return Left; - yield return Right; - } -} \ No newline at end of file diff --git a/src/CAD/IFox.CAD.Source/IFox.CAD.Source.csproj b/src/CAD/IFox.CAD.Source/IFox.CAD.Source.csproj deleted file mode 100644 index 262b591..0000000 --- a/src/CAD/IFox.CAD.Source/IFox.CAD.Source.csproj +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - netstandard1.0 - true - $(AssemblyName) - $(Version) - true - - - - CS8021 - true - false - contentFiles - true - false - false - true - - - - - true - $(ContentTargetFolders)\cs\any\$(PackageId)\ - false - - - - true - - - - true - - - - - - - - - - - - - diff --git a/src/CAD/IFox.CAD.ZCAD/GlobalUsings.cs b/src/CAD/IFox.CAD.ZCAD/GlobalUsings.cs deleted file mode 100644 index 2b57555..0000000 --- a/src/CAD/IFox.CAD.ZCAD/GlobalUsings.cs +++ /dev/null @@ -1,42 +0,0 @@ -// 系统引用 -global using System; -global using System.Collections; -global using System.Collections.Generic; -global using System.IO; -global using System.Linq; -global using System.Text; -global using System.Reflection; -global using System.Text.RegularExpressions; -global using Microsoft.Win32; -global using System.ComponentModel; -global using System.Runtime.InteropServices; -global using System.Web.Script.Serialization; -global using Exception = System.Exception; - -global using Registry = Microsoft.Win32.Registry; -global using RegistryKey = Microsoft.Win32.RegistryKey; - -// cad 引用 -global using ZwSoft.ZwCAD.ApplicationServices; -global using ZwSoft.ZwCAD.EditorInput; -global using ZwSoft.ZwCAD.Colors; -global using ZwSoft.ZwCAD.DatabaseServices; -global using ZwSoft.ZwCAD.Geometry; -global using ZwSoft.ZwCAD.Runtime; -global using Acap = ZwSoft.ZwCAD.ApplicationServices.Application; -global using Acaop = ZwSoft.ZwCAD.ApplicationServices.Application; -global using AcException = ZwSoft.ZwCAD.Runtime.Exception; -global using ZwSoft.ZwCAD.DatabaseServices.Filters; - -// jig命名空间会引起Viewport/Polyline等等重义,最好逐个引入 using ZwSoft.ZwCAD.GraphicsInterface -global using ZwSoft.ZwCAD.GraphicsInterface; -global using WorldDraw = ZwSoft.ZwCAD.GraphicsInterface.WorldDraw; -global using Manager = ZwSoft.ZwCAD.GraphicsSystem.Manager; -global using Group = ZwSoft.ZwCAD.DatabaseServices.Group; -global using Viewport = ZwSoft.ZwCAD.DatabaseServices.Viewport; -global using Polyline = ZwSoft.ZwCAD.DatabaseServices.Polyline; - -// ifoxcad.basal 引用 -global using IFoxCAD.Basal; - - diff --git a/src/CAD/IFox.CAD.ZCAD/IFox.CAD.ZCAD.csproj b/src/CAD/IFox.CAD.ZCAD/IFox.CAD.ZCAD.csproj deleted file mode 100644 index 926c3fb..0000000 --- a/src/CAD/IFox.CAD.ZCAD/IFox.CAD.ZCAD.csproj +++ /dev/null @@ -1,44 +0,0 @@ - - - - NET48 - - true - true - false - MSB3270 - - - - DEBUG - - - $(Configuration);zcad - - - - runtime - - - - - - True - - - - - - - - - - - - - - - - - - diff --git a/src/Event/EVENT/.keep b/src/Event/EVENT/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/src/Event/IFox.Event.Shared/EventEx/BeginDoubleClickEvent.cs b/src/Event/IFox.Event.Shared/EventEx/BeginDoubleClickEvent.cs deleted file mode 100644 index d800baf..0000000 --- a/src/Event/IFox.Event.Shared/EventEx/BeginDoubleClickEvent.cs +++ /dev/null @@ -1,108 +0,0 @@ -namespace IFoxCAD.Event; -internal static class BeginDoubleClickEvent -{ - private static readonly Type returnType = typeof(void); - private static readonly Type firstType = typeof(object); - private static readonly Type secondType = typeof(BeginDoubleClickEventArgs); - private static readonly HashSet dic = new(); - internal static void Initlize(Assembly assembly) - { - var types = assembly.GetTypes(); - foreach (var type in types) - { - if (!type.IsClass) - continue; - foreach (var methodInfo in type.GetMethods()) - { - foreach (Attribute att in methodInfo.GetCustomAttributes(typeof(BeginDoubleClickAttribute), false)) - { - if (att is not BeginDoubleClickAttribute targetAtt) - continue; - if (!methodInfo.IsStatic) - throw new ArgumentException($"标记{nameof(BeginDoubleClickAttribute)}特性的方法{type.Name}.{methodInfo.Name},应为静态方法"); - if (methodInfo.ReturnType != returnType) - throw new ArgumentException($"标记{nameof(BeginDoubleClickAttribute)}特性的方法{type.Name}.{methodInfo.Name},返回值应为void"); - var args = methodInfo.GetParameters(); - if (args.Length > 2) - throw new ArgumentException($"标记{nameof(BeginDoubleClickAttribute)}特性的方法{type.Name}.{methodInfo.Name},参数类型错误"); - - - EventParameterType? ept = null; - if (args.Length == 0) - ept = EventParameterType.None; - else if (args.Length == 1) - { - if (args[0].ParameterType == firstType) - ept = EventParameterType.Object; - else if (args[0].ParameterType == secondType) - ept = EventParameterType.EventArgs; - } - else if (args.Length == 2 && args[0].ParameterType == firstType && args[1].ParameterType == secondType) - { - ept = EventParameterType.Complete; - } - if (ept is null) - throw new ArgumentException($"标记{nameof(BeginDoubleClickAttribute)}特性的方法{type.Name}.{methodInfo.Name},参数类型错误"); - dic.Add(new(methodInfo, ept.Value, targetAtt.Level)); - break; - } - } - } - AddEvent(); - } - - internal static void AddEvent() - { - Acap.BeginDoubleClick -= Acap_BeginDoubleClick; - Acap.BeginDoubleClick += Acap_BeginDoubleClick; - } - - internal static void RemoveEvent() - { - Acap.BeginDoubleClick -= Acap_BeginDoubleClick; - } - private static void Acap_BeginDoubleClick(object sender, BeginDoubleClickEventArgs e) - { -#if Debug - if (!EventFactory.closeCheck.Invoke()) - { - EventFactory.RemoveEvent(CadEvent.All); - return; - } -#endif - foreach (var eventMethodInfo in dic.OrderByDescending(a => a.Level)) - { - switch (eventMethodInfo.ParameterType) - { - case EventParameterType.None: - eventMethodInfo.Method.Invoke(null, new object[0]); - break; - case EventParameterType.Object: - eventMethodInfo.Method.Invoke(null, new[] { sender }); - break; - case EventParameterType.EventArgs: - eventMethodInfo.Method.Invoke(null, new[] { e }); - break; - case EventParameterType.Complete: - eventMethodInfo.Method.Invoke(null, new[] { sender, e }); - break; - } - } - } - -} -[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)] -public class BeginDoubleClickAttribute : Attribute -{ - /// s - /// 系统变量修改时触发被标记的函数 - /// 返回值应为void - /// 参数不大于2个且只能为object和BeginDoubleClickEventArgs - /// - /// 级别(越高越先触发) - public BeginDoubleClickAttribute( int level = -1) - { - Level = level; - } - public int Level { get; } -} \ No newline at end of file diff --git a/src/Event/IFox.Event.Shared/EventEx/DocumentActivatedEvent.cs b/src/Event/IFox.Event.Shared/EventEx/DocumentActivatedEvent.cs deleted file mode 100644 index 884fe73..0000000 --- a/src/Event/IFox.Event.Shared/EventEx/DocumentActivatedEvent.cs +++ /dev/null @@ -1,108 +0,0 @@ -namespace IFoxCAD.Event; -internal static class DocumentActivatedEvent -{ - private static readonly Type returnType = typeof(void); - private static readonly Type firstType = typeof(object); - private static readonly Type secondType = typeof(DocumentCollectionEventArgs); - private static readonly HashSet dic = new(); - internal static void Initlize(Assembly assembly) - { - var types = assembly.GetTypes(); - foreach (var type in types) - { - if (!type.IsClass) - continue; - foreach (var methodInfo in type.GetMethods()) - { - foreach (Attribute att in methodInfo.GetCustomAttributes(typeof(DocumentActivatedAttribute), false)) - { - if (att is not DocumentActivatedAttribute targetAtt) - continue; - if (!methodInfo.IsStatic) - throw new ArgumentException($"标记{nameof(DocumentActivatedAttribute)}特性的方法{type.Name}.{methodInfo.Name},应为静态方法"); - if (methodInfo.ReturnType != returnType) - throw new ArgumentException($"标记{nameof(DocumentActivatedAttribute)}特性的方法{type.Name}.{methodInfo.Name},返回值应为void"); - var args = methodInfo.GetParameters(); - if (args.Length > 2) - throw new ArgumentException($"标记{nameof(DocumentActivatedAttribute)}特性的方法{type.Name}.{methodInfo.Name},参数类型错误"); - - - EventParameterType? ept = null; - if (args.Length == 0) - ept = EventParameterType.None; - else if (args.Length == 1) - { - if (args[0].ParameterType == firstType) - ept = EventParameterType.Object; - else if (args[0].ParameterType == secondType) - ept = EventParameterType.EventArgs; - } - else if (args.Length == 2 && args[0].ParameterType == firstType && args[1].ParameterType == secondType) - { - ept = EventParameterType.Complete; - } - if (ept is null) - throw new ArgumentException($"标记{nameof(DocumentActivatedAttribute)}特性的方法{type.Name}.{methodInfo.Name},参数类型错误"); - dic.Add(new(methodInfo, ept.Value, targetAtt.Level)); - break; - } - } - } - AddEvent(); - } - - internal static void AddEvent() - { - Acap.DocumentManager.DocumentActivated -= DocumentManager_DocumentActivated; - Acap.DocumentManager.DocumentActivated += DocumentManager_DocumentActivated; - } - - internal static void RemoveEvent() - { - Acap.DocumentManager.DocumentActivated -= DocumentManager_DocumentActivated; - } - private static void DocumentManager_DocumentActivated(object sender, DocumentCollectionEventArgs e) - { -#if Debug - if (!EventFactory.closeCheck.Invoke()) - { - EventFactory.RemoveEvent(CadEvent.All); - return; - } -#endif - foreach (var eventMethodInfo in dic.OrderByDescending(a => a.Level)) - { - switch (eventMethodInfo.ParameterType) - { - case EventParameterType.None: - eventMethodInfo.Method.Invoke(null, new object[0]); - break; - case EventParameterType.Object: - eventMethodInfo.Method.Invoke(null, new[] { sender }); - break; - case EventParameterType.EventArgs: - eventMethodInfo.Method.Invoke(null, new[] { e }); - break; - case EventParameterType.Complete: - eventMethodInfo.Method.Invoke(null, new[] { sender, e }); - break; - } - } - } - -} -[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)] -public class DocumentActivatedAttribute : Attribute -{ - /// s - /// 系统变量修改时触发被标记的函数 - /// 返回值应为void - /// 参数不大于2个且只能为object和DocumentCollectionEventArgs - /// - /// 级别(越高越先触发) - public DocumentActivatedAttribute(int level = -1) - { - Level = level; - } - public int Level { get; } -} \ No newline at end of file diff --git a/src/Event/IFox.Event.Shared/EventEx/DocumentLockModeChangedEvent.cs b/src/Event/IFox.Event.Shared/EventEx/DocumentLockModeChangedEvent.cs deleted file mode 100644 index e5acb16..0000000 --- a/src/Event/IFox.Event.Shared/EventEx/DocumentLockModeChangedEvent.cs +++ /dev/null @@ -1,122 +0,0 @@ -namespace IFoxCAD.Event; -internal static class DocumentLockModeChangedEvent -{ - private static readonly Type returnType = typeof(void); - private static readonly Type firstType = typeof(object); - private static readonly Type secondType = typeof(DocumentLockModeChangedEventArgs); - private static readonly Dictionary> dic = new(); - internal static void Initlize(Assembly assembly) - { - var types = assembly.GetTypes(); - foreach (var type in types) - { - if (!type.IsClass) - continue; - foreach (var methodInfo in type.GetMethods()) - { - foreach (Attribute att in methodInfo.GetCustomAttributes(typeof(DocumentLockModeChangedAttribute), false)) - { - if (att is not DocumentLockModeChangedAttribute targetAtt) - continue; - if (!methodInfo.IsStatic) - throw new ArgumentException($"{nameof(DocumentLockModeChangedAttribute)}Եķ{type.Name}.{methodInfo.Name},ӦΪ̬"); - if (methodInfo.ReturnType != returnType) - throw new ArgumentException($"{nameof(DocumentLockModeChangedAttribute)}Եķ{type.Name}.{methodInfo.Name}ֵӦΪvoid"); - var args = methodInfo.GetParameters(); - var key = targetAtt.CommandName.ToUpper(); - if (!dic.ContainsKey(key)) - { - dic.Add(key, new()); - } - if (args.Length > 2) - throw new ArgumentException($"{nameof(DocumentLockModeChangedAttribute)}Եķ{type.Name}.{methodInfo.Name}ʹ"); - - - EventParameterType? ept = null; - if (args.Length == 0) - ept = EventParameterType.None; - else if (args.Length == 1) - { - if (args[0].ParameterType == firstType) - ept = EventParameterType.Object; - else if (args[0].ParameterType == secondType) - ept = EventParameterType.EventArgs; - } - else if (args.Length == 2 && args[0].ParameterType == firstType && args[1].ParameterType == secondType) - { - ept = EventParameterType.Complete; - } - if (ept is null) - throw new ArgumentException($"{nameof(DocumentLockModeChangedAttribute)}Եķ{type.Name}.{methodInfo.Name}ʹ"); - dic[key].Add(new(methodInfo, ept.Value, targetAtt.Level)); - } - } - } - AddEvent(); - } - internal static void AddEvent() - { - Acap.DocumentManager.DocumentLockModeChanged -= DocumentManager_DocumentLockModeChanged; - Acap.DocumentManager.DocumentLockModeChanged += DocumentManager_DocumentLockModeChanged; - } - - internal static void RemoveEvent() - { - Acap.DocumentManager.DocumentLockModeChanged -= DocumentManager_DocumentLockModeChanged; - } - private static void DocumentManager_DocumentLockModeChanged(object sender, DocumentLockModeChangedEventArgs e) - { - var key = e.GlobalCommandName.ToUpper(); - if (!dic.ContainsKey(key)) - return; - -#if Debug - if (!EventFactory.closeCheck.Invoke()) - { - EventFactory.RemoveEvent(CadEvent.All); - return; - } -#endif - foreach (var eventMethodInfo in dic[key].OrderByDescending(a => a.Level)) - { - switch (eventMethodInfo.ParameterType) - { - case EventParameterType.None: - eventMethodInfo.Method.Invoke(null, new object[0]); - break; - case EventParameterType.Object: - eventMethodInfo.Method.Invoke(null, new[] { sender }); - break; - case EventParameterType.EventArgs: - eventMethodInfo.Method.Invoke(null, new[] { e }); - break; - case EventParameterType.Complete: - eventMethodInfo.Method.Invoke(null, new[] { sender, e }); - break; - } - } - } - -} -[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = true)] -public class DocumentLockModeChangedAttribute : Attribute -{ - /// - /// ϵͳ޸ʱǵĺ - /// ֵӦΪvoid - /// 2ֻΪobjectDocumentLockModeChangedEventArgs - /// - /// - /// (ԽԽȴ) - public DocumentLockModeChangedAttribute(string commandName, int level = -1) - { - CommandName = commandName; - Level = level; - } - - /// - /// ϵͳ - /// - public string CommandName { get; } - public int Level { get; } -} \ No newline at end of file diff --git a/src/Event/IFox.Event.Shared/EventEx/SystemVariableChangedEvent.cs b/src/Event/IFox.Event.Shared/EventEx/SystemVariableChangedEvent.cs deleted file mode 100644 index f65f7a5..0000000 --- a/src/Event/IFox.Event.Shared/EventEx/SystemVariableChangedEvent.cs +++ /dev/null @@ -1,122 +0,0 @@ -namespace IFoxCAD.Event; -internal static class SystemVariableChangedEvent -{ - private static readonly Type returnType = typeof(void); - private static readonly Type firstType = typeof(object); - private static readonly Type secondType = typeof(SystemVariableChangedEventArgs); - private static readonly Dictionary> dic = new(); - internal static void Initlize(Assembly assembly) - { - var types = assembly.GetTypes(); - foreach (var type in types) - { - if (!type.IsClass) - continue; - foreach (var methodInfo in type.GetMethods()) - { - foreach (Attribute att in methodInfo.GetCustomAttributes(typeof(SystemVariableChangedAttribute), false)) - { - if (att is not SystemVariableChangedAttribute targetAtt) - continue; - if (!methodInfo.IsStatic) - throw new ArgumentException($"{nameof(SystemVariableChangedAttribute)}Եķ{type.Name}.{methodInfo.Name},ӦΪ̬"); - if (methodInfo.ReturnType != returnType) - throw new ArgumentException($"{nameof(SystemVariableChangedAttribute)}Եķ{type.Name}.{methodInfo.Name}ֵӦΪvoid"); - var args = methodInfo.GetParameters(); - var key = targetAtt.Name.ToUpper(); - if (!dic.ContainsKey(key)) - { - dic.Add(key, new()); - } - if (args.Length > 2) - throw new ArgumentException($"{nameof(SystemVariableChangedAttribute)}Եķ{type.Name}.{methodInfo.Name}ʹ"); - - - EventParameterType? ept = null; - if (args.Length == 0) - ept = EventParameterType.None; - else if (args.Length == 1) - { - if (args[0].ParameterType == firstType) - ept = EventParameterType.Object; - else if (args[0].ParameterType == secondType) - ept = EventParameterType.EventArgs; - } - else if (args.Length == 2 && args[0].ParameterType == firstType && args[1].ParameterType == secondType) - { - ept = EventParameterType.Complete; - } - if (ept is null) - throw new ArgumentException($"{nameof(SystemVariableChangedAttribute)}Եķ{type.Name}.{methodInfo.Name}ʹ"); - dic[key].Add(new(methodInfo, ept.Value, targetAtt.Level)); - } - } - } - AddEvent(); - } - internal static void AddEvent() - { - Acap.SystemVariableChanged -= Acap_SystemVariableChanged; - Acap.SystemVariableChanged += Acap_SystemVariableChanged; - } - internal static void RemoveEvent() - { - Acap.SystemVariableChanged -= Acap_SystemVariableChanged; - } - private static void Acap_SystemVariableChanged(object sender, SystemVariableChangedEventArgs e) - { - var key = e.Name.ToUpper(); - if (!dic.ContainsKey(key)) - return; - -#if Debug - if (!EventFactory.closeCheck.Invoke()) - { - EventFactory.RemoveEvent(CadEvent.All); - return; - } -#endif - - foreach (var eventMethodInfo in dic[key].OrderByDescending(a => a.Level)) - { - switch (eventMethodInfo.ParameterType) - { - case EventParameterType.None: - eventMethodInfo.Method.Invoke(null, new object[0]); - break; - case EventParameterType.Object: - eventMethodInfo.Method.Invoke(null, new[] { sender }); - break; - case EventParameterType.EventArgs: - eventMethodInfo.Method.Invoke(null, new[] { e }); - break; - case EventParameterType.Complete: - eventMethodInfo.Method.Invoke(null, new[] { sender, e }); - break; - } - } - } - -} -[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)] -public class SystemVariableChangedAttribute : Attribute -{ - /// s - /// ϵͳ޸ʱǵĺ - /// ֵӦΪvoid - /// 2ֻΪobjectSystemVariableChangedEventArgs - /// - /// ϵͳ - /// (ԽԽȴ) - public SystemVariableChangedAttribute(string name, int level = -1) - { - Name = name; - Level = level; - } - - /// - /// ϵͳ - /// - public string Name { get; } - public int Level { get; } -} \ No newline at end of file diff --git a/src/Event/IFox.Event.Shared/EventFactory/CadEvent.cs b/src/Event/IFox.Event.Shared/EventFactory/CadEvent.cs deleted file mode 100644 index 3b91cdc..0000000 --- a/src/Event/IFox.Event.Shared/EventFactory/CadEvent.cs +++ /dev/null @@ -1,30 +0,0 @@ -namespace IFoxCAD.Event; - -[Flags] -public enum CadEvent -{ - /// - /// 无 - /// - None = 0, - /// - /// 全选 - /// - All = -1, - /// - /// 系统变量修改 - /// - SystemVariableChanged = 1 << 1, - /// - /// 文档锁定事件 - /// - DocumentLockModeChanged = 1 << 2, - /// - /// 开始双击 - /// - BeginDoubleClick = 1 << 3, - /// - /// 文档激活 - /// - DocumentActivated = 1 << 4, -} \ No newline at end of file diff --git a/src/Event/IFox.Event.Shared/EventFactory/EventFactory.cs b/src/Event/IFox.Event.Shared/EventFactory/EventFactory.cs deleted file mode 100644 index bb43eff..0000000 --- a/src/Event/IFox.Event.Shared/EventFactory/EventFactory.cs +++ /dev/null @@ -1,100 +0,0 @@ -namespace IFoxCAD.Event; -public static class EventFactory -{ - /// - /// ʹCad¼ - /// - /// ¼ö - /// - public static void UseCadEvent(CadEvent cadEvent, Assembly? assembly = null) - { - assembly ??= Assembly.GetCallingAssembly(); - IdleAction.Add(() => - { - if ((cadEvent & CadEvent.SystemVariableChanged) != 0) - { - SystemVariableChangedEvent.Initlize(assembly); - } - if ((cadEvent & CadEvent.DocumentLockModeChanged) != 0) - { - DocumentLockModeChangedEvent.Initlize(assembly); - } - if ((cadEvent & CadEvent.BeginDoubleClick) != 0) - { - BeginDoubleClickEvent.Initlize(assembly); - } - if ((cadEvent & CadEvent.DocumentActivated) != 0) - { - DocumentActivatedEvent.Initlize(assembly); - } - }); - } - /// - /// ʱر¼(Ҫö) - /// - /// - /// - public static EventTemporaryShutdownManager TemporaryShutdown(CadEvent cadEvent = CadEvent.All) - { - return new EventTemporaryShutdownManager(cadEvent); - } - /// - /// ¼ - /// - /// ¼ö - public static void AddEvent(CadEvent cadEvent) - { - if ((cadEvent & CadEvent.SystemVariableChanged) != 0) - { - SystemVariableChangedEvent.AddEvent(); - } - if ((cadEvent & CadEvent.DocumentLockModeChanged) != 0) - { - DocumentLockModeChangedEvent.AddEvent(); - } - if ((cadEvent & CadEvent.BeginDoubleClick) != 0) - { - BeginDoubleClickEvent.AddEvent(); - } - if ((cadEvent & CadEvent.DocumentActivated) != 0) - { - DocumentActivatedEvent.AddEvent(); - } - } - /// - /// Ƴ¼ - /// - /// ¼ö - public static void RemoveEvent(CadEvent cadEvent) - { - if ((cadEvent & CadEvent.SystemVariableChanged) != 0) - { - SystemVariableChangedEvent.RemoveEvent(); - } - if ((cadEvent & CadEvent.DocumentLockModeChanged) != 0) - { - DocumentLockModeChangedEvent.RemoveEvent(); - } - if ((cadEvent & CadEvent.BeginDoubleClick) != 0) - { - BeginDoubleClickEvent.RemoveEvent(); - } - if ((cadEvent & CadEvent.DocumentActivated) != 0) - { - DocumentActivatedEvent.RemoveEvent(); - } - } - - internal static Func closeCheck = () => true; -#if Debug - /// - /// жȫ¼Debugʹã - /// 㶯̬ضθʱжص֮ǰdllжҪû - /// - /// - public static void SetCloseCondition(this Func condition) - { - closeCheck = condition; - } -#endif -} \ No newline at end of file diff --git a/src/Event/IFox.Event.Shared/EventFactory/EventMethodInfo.cs b/src/Event/IFox.Event.Shared/EventFactory/EventMethodInfo.cs deleted file mode 100644 index 1f71246..0000000 --- a/src/Event/IFox.Event.Shared/EventFactory/EventMethodInfo.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace IFoxCAD.Event; - -internal class EventMethodInfo -{ - public EventMethodInfo(MethodInfo method, EventParameterType parameterType, int level) - { - Method = method; - ParameterType = parameterType; - Level = level; - } - - public MethodInfo Method { get; } - public EventParameterType ParameterType { get; } - public int Level { get; } -} -internal enum EventParameterType -{ - None = 0, - Object = 1, - EventArgs = 2, - Complete = 3, -} \ No newline at end of file diff --git a/src/Event/IFox.Event.Shared/EventFactory/EventTemporaryShutdownManager.cs b/src/Event/IFox.Event.Shared/EventFactory/EventTemporaryShutdownManager.cs deleted file mode 100644 index b67d814..0000000 --- a/src/Event/IFox.Event.Shared/EventFactory/EventTemporaryShutdownManager.cs +++ /dev/null @@ -1,40 +0,0 @@ -namespace IFoxCAD.Event; - -public class EventTemporaryShutdownManager : IDisposable -{ - private readonly CadEvent _cadEvent; - /// - /// 临时关闭事件,dispose的时候重开,防止事件嵌套时使用 - /// - /// 事件枚举 - internal EventTemporaryShutdownManager(CadEvent cadEvent) - { - _cadEvent = cadEvent; - EventFactory.RemoveEvent(_cadEvent); - } - #region Dispose - - private bool _isDisposed = false; - public bool IsDisposed => _isDisposed; - - protected virtual void Dispose(bool disposing) - { - if (disposing) - { - if (!_isDisposed) - { - EventFactory.AddEvent(_cadEvent); - _isDisposed = true; - } - } - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - #endregion -} - diff --git a/src/Event/IFox.Event.Shared/IFox.Event.Shared.projitems b/src/Event/IFox.Event.Shared/IFox.Event.Shared.projitems deleted file mode 100644 index 53ffa13..0000000 --- a/src/Event/IFox.Event.Shared/IFox.Event.Shared.projitems +++ /dev/null @@ -1,21 +0,0 @@ - - - - $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - true - c4f9a0cf-920e-41d0-bf51-0a59df660ad9 - - - IFox.Event.Shared - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Event/IFox.Event.Shared/IFox.Event.Shared.shproj b/src/Event/IFox.Event.Shared/IFox.Event.Shared.shproj deleted file mode 100644 index 8932f2e..0000000 --- a/src/Event/IFox.Event.Shared/IFox.Event.Shared.shproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - c4f9a0cf-920e-41d0-bf51-0a59df660ad9 - 14.0 - - - - - - - - diff --git a/src/WPF/BindingErrorTraceListener.cs b/src/WPF/BindingErrorTraceListener.cs deleted file mode 100644 index 9ba3a4b..0000000 --- a/src/WPF/BindingErrorTraceListener.cs +++ /dev/null @@ -1,84 +0,0 @@ -namespace IFoxCAD.WPF; -using System.Text.RegularExpressions; - -/* - xaml 需要绑定失败时候报错(vs默认是不报错的): - https://cloud.tencent.com/developer/article/1342661 - 所有的绑定输出,重写方法就可以转发,构造函数上加入: - public MainWindow() - { - PresentationTraceSources.DataBindingSource.Switch.Level = SourceLevels.Error; - PresentationTraceSources.DataBindingSource.Listeners.Add(new BindingErrorTraceListener()); - App.Current.DispatcherUnhandledException += DispatcherUnhandledException; - // InitializeComponent(); - // DataContext = new ViewModel(); - } - private void DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e) - { - if (e.Exception is BindingErrorException bindingErrorException) - { - MessageBox.Show($"Binding error. {bindingErrorException.SourceObject}.{bindingErrorException.SourceProperty} {bindingErrorException.TargetElement}.{bindingErrorException.TargetProperty}"); - } - } -*/ - -/// -/// 属性绑定错误异常 -/// -public class BindingErrorException : Exception -{ - /// - /// 来源对象 - /// - public string? SourceObject { get; set; } - /// - /// 来源属性 - /// - public string? SourceProperty { get; set; } - /// - /// 目标元素 - /// - public string? TargetElement { get; set; } - /// - /// 目标属性 - /// - public string? TargetProperty { get; set; } - - public BindingErrorException() : base() - { - } - - public BindingErrorException(string message) : base(message) - { - } -} - -/// -/// 属性绑定错误侦听器 -/// -public class BindingErrorTraceListener : TraceListener -{ - const string BindingErrorPattern = - @"^BindingExpression path error(?:.+)'(.+)' property not found(?:.+)object[\s']+(.+?)'(?:.+)target element is '(.+?)'(?:.+)target property is '(.+?)'(?:.+)$"; - - public override void Write(string message) - { - Trace.WriteLine(string.Format("[Write]{0}", message)); - Debug.WriteLine(string.Format("[Write]{0}", message)); - } - - public override void WriteLine(string message) - { - var match = Regex.Match(message, BindingErrorPattern); - if (match.Success) - { - throw new BindingErrorException(message) - { - SourceObject = match.Groups[2].ToString(), - SourceProperty = match.Groups[1].ToString(), - TargetElement = match.Groups[3].ToString(), - TargetProperty = match.Groups[4].ToString() - }; - } - } -} \ No newline at end of file diff --git a/src/WPF/Converter.cs b/src/WPF/Converter.cs deleted file mode 100644 index 828ece9..0000000 --- a/src/WPF/Converter.cs +++ /dev/null @@ -1,98 +0,0 @@ -namespace IFoxCAD.WPF; - -/// -/// 字符串到整数的转换器 -/// -public class StringToIntConverter : IValueConverter -{ - /// - /// 字符串转换到整数 - /// - /// 绑定源生成的值 - /// 绑定目标属性的类型 - /// 要使用的转换器参数 - /// 要用在转换器中的区域性 - /// 转换后的值。 如果该方法返回 null,则使用有效的 null 值。 - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) - { - string? a = value as string; - _ = int.TryParse(a, out int b); - return b; - } - /// - /// 整数转换到字符串 - /// - /// 绑定目标生成的值 - /// 要转换为的类型 - /// 要使用的转换器参数 - /// 要用在转换器中的区域性 - /// 转换后的值。 如果该方法返回 null,则使用有效的 null 值。 - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) - { - return value.ToString(); - } -} -/// -/// 字符串到实数的转换器 -/// -public class StringToDoubleConverter : IValueConverter -{ - /// - /// 字符串转换到实数 - /// - /// 绑定源生成的值 - /// 绑定目标属性的类型 - /// 要使用的转换器参数 - /// 要用在转换器中的区域性 - /// 转换后的值。 如果该方法返回 null,则使用有效的 null 值。 - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) - { - string? a = value as string; - _ = double.TryParse(a, out double b); - return b; - } - /// - /// 实数转换到字符串 - /// - /// 绑定目标生成的值 - /// 要转换为的类型 - /// 要使用的转换器参数 - /// 要用在转换器中的区域性 - /// 转换后的值。 如果该方法返回 null,则使用有效的 null 值。 - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) - { - return value.ToString(); - } -} -/// -/// 整数到字符串的转换器 -/// -public class IntToStringConverter : IValueConverter -{ - /// - /// 整数转换到字符串 - /// - /// 绑定源生成的值 - /// 绑定目标属性的类型 - /// 要使用的转换器参数 - /// 要用在转换器中的区域性 - /// 转换后的值。 如果该方法返回 null,则使用有效的 null 值。 - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) - { - return value.ToString(); - } - /// - /// 字符串转换到整数 - /// - /// 绑定目标生成的值 - /// 要转换为的类型 - /// 要使用的转换器参数 - /// 要用在转换器中的区域性 - /// 转换后的值。 如果该方法返回 null,则使用有效的 null 值。 - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) - { - string? a = value as string; - _ = int.TryParse(a, out int b); - return b; - } -} diff --git a/src/WPF/DependencyObjectExtensions.cs b/src/WPF/DependencyObjectExtensions.cs deleted file mode 100644 index 0852858..0000000 --- a/src/WPF/DependencyObjectExtensions.cs +++ /dev/null @@ -1,36 +0,0 @@ -namespace IFoxCAD.WPF; - -/// -/// 依赖属性扩展类 -/// -public static class DependencyObjectExtensions -{ - /// - /// 获取父对象依赖属性 - /// - /// 子对象 - /// 依赖属性 - public static DependencyObject? GetParentObject(this DependencyObject child) - { - if (child is null) return null; - - if (child is ContentElement ce) - { - var parent = ContentOperations.GetParent(ce); - if (parent is not null) - return parent; - - var fce = ce as FrameworkContentElement; - return fce?.Parent; - } - - if (child is FrameworkElement fe) - { - var parent = fe.Parent; - if (parent is not null) - return parent; - } - - return VisualTreeHelper.GetParent(child); - } -} \ No newline at end of file diff --git a/src/WPF/EnumSelection.cs b/src/WPF/EnumSelection.cs deleted file mode 100644 index 96630e4..0000000 --- a/src/WPF/EnumSelection.cs +++ /dev/null @@ -1,80 +0,0 @@ -namespace IFoxCAD.WPF; -public class EnumSelection : INotifyPropertyChanged where T : struct, IComparable, IFormattable, IConvertible -{ - private T value; // stored value of the Enum - private readonly bool isFlagged; // Enum uses flags? - private readonly bool canDeselect; // Can be deselected? (Radio buttons cannot deselect, checkboxes can) - private readonly T blankValue; // what is considered the "blank" value if it can be deselected? - - public EnumSelection(T value) : this(value, false, default) - { - } - public EnumSelection(T value, bool canDeselect) : this(value, canDeselect, default) - { - } - public EnumSelection(T value, T blankValue) : this(value, true, blankValue) - { - } - public EnumSelection(T value, bool canDeselect, T blankValue) - { - if (!typeof(T).IsEnum) - throw new ArgumentException($"{nameof(T)} must be an enum type"); // I really wish there was a way to constrain generic types to enums... - isFlagged = typeof(T).IsDefined(typeof(FlagsAttribute), false); - - this.value = value; - this.canDeselect = canDeselect; - this.blankValue = blankValue; - } - - public T Value - { - get { return value; } - set - { - if (this.value.Equals(value)) return; - this.value = value; - OnPropertyChanged(); - OnPropertyChanged("Item[]"); // Notify that the indexer property has changed - } - } - - [IndexerName("Item")] - public bool this[T key] - { - get - { - int iKey = (int)(object)key; - return isFlagged ? ((int)(object)value & iKey) == iKey : value.Equals(key); - } - set - { - if (isFlagged) - { - int iValue = (int)(object)this.value; - int iKey = (int)(object)key; - - if ((iValue & iKey) == iKey == value) - return; - - if (value) - Value = (T)(object)(iValue | iKey); - else - Value = (T)(object)(iValue & ~iKey); - } - else - { - if (this.value.Equals(key) == value) return; - if (!value && !canDeselect) return; - - Value = value ? key : blankValue; - } - } - } - - public event PropertyChangedEventHandler? PropertyChanged; - - private void OnPropertyChanged([CallerMemberName] string propertyName = "") - { - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); - } -} \ No newline at end of file diff --git a/src/WPF/EventBindingExtension.cs b/src/WPF/EventBindingExtension.cs deleted file mode 100644 index ab46a12..0000000 --- a/src/WPF/EventBindingExtension.cs +++ /dev/null @@ -1,190 +0,0 @@ -namespace IFoxCAD.WPF; - -/// -/// 事件绑定标签类 -/// -/// -public class EventBindingExtension : MarkupExtension -{ - /// - /// 命令属性 - /// - public string? Command { get; set; } - /// - /// 命令参数属性 - /// - public string? CommandParameter { get; set; } - /// - /// 当在派生类中实现时,返回用作此标记扩展的目标属性值的对象。 - /// - /// 可为标记扩展提供服务的服务提供程序帮助程序。 - /// - /// 要在应用了扩展的属性上设置的对象值。 - /// - /// - /// - public override object? ProvideValue(IServiceProvider serviceProvider) - { - if (serviceProvider is null) - throw new ArgumentNullException(nameof(serviceProvider)); - if (serviceProvider.GetService(typeof(IProvideValueTarget)) is not IProvideValueTarget targetProvider) - throw new InvalidOperationException(message: $"{nameof(ProvideValue)}:{nameof(IProvideValueTarget)}"); - - if (targetProvider.TargetObject is not FrameworkElement targetObject) - throw new InvalidOperationException(message: $"{nameof(ProvideValue)}:{nameof(FrameworkElement)}"); - - if (targetProvider.TargetProperty is not MemberInfo memberInfo) - throw new InvalidOperationException(message: $"{nameof(ProvideValue)}:{nameof(MemberInfo)}"); - - if (string.IsNullOrWhiteSpace(Command)) - { - Command = memberInfo.Name.Replace("Add", ""); - if (Command.Contains("Handler")) - Command = Command.Replace("Handler", "Command"); - else - Command += "Command"; - } - - return CreateHandler(memberInfo, Command!, targetObject.GetType()); - } - - private Type? GetEventHandlerType(MemberInfo memberInfo) - { - Type? eventHandlerType = null; - if (memberInfo is EventInfo eventInfo) - { - // var info = memberInfo as EventInfo; - // var eventInfo = info; - eventHandlerType = eventInfo.EventHandlerType; - } - else if (memberInfo is MethodInfo methodInfo) - { - // var info = memberInfo as MethodInfo; - // var methodInfo = info; - var pars = methodInfo.GetParameters(); - eventHandlerType = pars[1].ParameterType; - } - - return eventHandlerType; - } - -#pragma warning disable IDE0060 // 删除未使用的参数 - private object? CreateHandler(MemberInfo memberInfo, string cmdName, Type targetType) -#pragma warning restore IDE0060 // 删除未使用的参数 - { - var eventHandlerType = GetEventHandlerType(memberInfo); - if (eventHandlerType is null) - return null; - - var handlerInfo = eventHandlerType.GetMethod("Invoke"); - var method = new DynamicMethod("", handlerInfo.ReturnType, - new Type[] - { - handlerInfo.GetParameters()[0].ParameterType, - handlerInfo.GetParameters()[1].ParameterType, - }); - - var gen = method.GetILGenerator(); - gen.Emit(OpCodes.Ldarg, 0); - gen.Emit(OpCodes.Ldarg, 1); - gen.Emit(OpCodes.Ldstr, cmdName); - - if (CommandParameter is null) - gen.Emit(OpCodes.Ldnull); - else - gen.Emit(OpCodes.Ldstr, CommandParameter); - - gen.Emit(OpCodes.Call, getMethod); - gen.Emit(OpCodes.Ret); - - return method.CreateDelegate(eventHandlerType); - } - - static readonly MethodInfo getMethod = typeof(EventBindingExtension) - .GetMethod("HandlerIntern", new Type[] { typeof(object), typeof(object), typeof(string), typeof(string) }); - -#pragma warning disable IDE0051 // 删除未使用的私有成员 - static void Handler(object sender, object args) -#pragma warning restore IDE0051 // 删除未使用的私有成员 - { - HandlerIntern(sender, args, "cmd", null); - } - /// - /// Handlers the intern. - /// - /// The sender. - /// The arguments. - /// Name of the command. - /// The command parameter. - public static void HandlerIntern(object sender, object args, string cmdName, string? commandParameter) - { - if (sender is FrameworkElement fe) - { - var cmd = GetCommand(fe, cmdName); - object? commandParam = null; - if (!string.IsNullOrWhiteSpace(commandParameter)) - commandParam = GetCommandParameter(fe, args, commandParameter!); - if ((cmd is not null) && cmd.CanExecute(commandParam)) - cmd.Execute(commandParam); - } - } - - internal static ICommand? GetCommand(FrameworkElement target, string cmdName) - { - var vm = FindViewModel(target); - if (vm is null) - return null; - - var vmType = vm.GetType(); - var cmdProp = vmType.GetProperty(cmdName); - if (cmdProp is not null) - return cmdProp.GetValue(vm) as ICommand; -#if DEBUG - throw new Exception("EventBinding path error: '" + cmdName + "' property not found on '" + vmType + "' 'DelegateCommand'"); -#else - return null; -#endif - } - - internal static object GetCommandParameter(FrameworkElement target, object args, string commandParameter) - { - var classify = commandParameter.Split('.'); - object ret = classify[0] switch - { - "$e" => args, - "$this" => classify.Length > 1 ? FollowPropertyPath(target, commandParameter.Replace("$this.", ""), target.GetType()) : target, - _ => commandParameter, - }; - return ret; - } - - internal static ViewModelBase? FindViewModel(FrameworkElement? target) - { - if (target is null) - return null; - if (target.DataContext is ViewModelBase vm) - return vm; - return FindViewModel(target.GetParentObject() as FrameworkElement); - } - - internal static object FollowPropertyPath(object target, string path, Type? valueType = null) - { - if (target is null) - throw new ArgumentNullException(nameof(target)); - if (path is null) - throw new ArgumentNullException(nameof(path)); - - valueType ??= target.GetType(); - var spls = path.Split('.'); - for (int i = 0; i < spls.Length; i++) - { - var property = valueType.GetProperty(spls[i]); - if (property is null) - throw new NullReferenceException("property"); - - target = property.GetValue(target); - valueType = property.PropertyType; - } - return target; - } -} \ No newline at end of file diff --git a/src/WPF/GlobalUsings.cs b/src/WPF/GlobalUsings.cs deleted file mode 100644 index 8ab21a7..0000000 --- a/src/WPF/GlobalUsings.cs +++ /dev/null @@ -1,18 +0,0 @@ -/// 系统引用 -global using System; -global using System.Collections; -global using System.Collections.Generic; -global using System.IO; -global using System.Linq; -global using System.ComponentModel; -global using System.Runtime.CompilerServices; -global using System.Diagnostics; -global using System.Windows; -global using System.Windows.Input; -global using System.Reflection.Emit; -global using System.Windows.Markup; -global using System.Reflection; -global using System.Windows.Media; -global using System.Globalization; -global using System.Windows.Data; - diff --git a/src/WPF/IFox.WPF.csproj b/src/WPF/IFox.WPF.csproj deleted file mode 100644 index 4f84d57..0000000 --- a/src/WPF/IFox.WPF.csproj +++ /dev/null @@ -1,44 +0,0 @@ - - - - 0.4 - 开启可空类型. - - - preview - enable - NET45 - true - true - true - ..\..\bin\$(Configuration)\ - true - xsfhlzh;vicwjb - xsfhlzh;vicwjb;liuqihong - InspireFunction - WPF的简单MVVM模式开发类库 - InspireFunction - LICENSE - https://gitee.com/inspirefunction/ifoxcad - https://gitee.com/inspirefunction/ifoxcad.git - IFoxCAD;C#;NET;WPF;MVVM - git - True - - - - DEBUG;TRACE - - - - - - - - - True - - - - - diff --git a/src/WPF/RelayCommand.cs b/src/WPF/RelayCommand.cs deleted file mode 100644 index 5d35777..0000000 --- a/src/WPF/RelayCommand.cs +++ /dev/null @@ -1,181 +0,0 @@ -using Microsoft.Xaml.Behaviors; - -namespace IFoxCAD.WPF; - -/// -/// 命令基类 -/// -/// -public class RelayCommand : ICommand -{ - readonly Func? _canExecute; - readonly Action _execute; - /// - /// 初始化 类. - /// - /// 执行函数 - public RelayCommand(Action execute) : this(execute, null) - { - } - /// - /// 初始化 类. - /// - /// 执行函数委托 - /// 是否可执行函数委托 - /// execute - public RelayCommand(Action execute, Func? canExecute) - { - _execute = execute ?? throw new ArgumentNullException(nameof(execute)); - _canExecute = canExecute; - } - - /// - /// 当出现影响是否应执行该命令的更改时发生。 - /// - public event EventHandler CanExecuteChanged - { - add - { - if (_canExecute is not null) - CommandManager.RequerySuggested += value; - } - remove - { - if (_canExecute is not null) - CommandManager.RequerySuggested -= value; - } - } - /// - /// 定义确定此命令是否可在其当前状态下执行的方法。 - /// - /// 此命令使用的数据。 如果此命令不需要传递数据,则该对象可以设置为 。 - /// - /// 如果可执行此命令,则为 ;否则为 。 - /// - [DebuggerStepThrough] - public bool CanExecute(object parameter) - { - return _canExecute is null || _canExecute(parameter); - } - /// - /// 定义在调用此命令时要调用的方法。 - /// - /// 此命令使用的数据。 如果此命令不需要传递数据,则该对象可以设置为 。 - public void Execute(object parameter) - { - _execute(parameter); - } -} - -/// -/// 命令泛型基类 -/// -/// 事件类型 -/// -public class RelayCommand : ICommand -{ - readonly Func _canExecute; - readonly Action _execute; - /// - /// 初始化 类。 - /// - /// 执行函数 - public RelayCommand(Action execute) : this(execute, (o) => true) - { - } - - /// - /// 初始化 类。 - /// - /// 执行函数委托 - /// 是否可执行函数委托 - /// execute - public RelayCommand(Action execute, Func canExecute) - { - _execute = execute ?? throw new ArgumentNullException(nameof(execute)); - _canExecute = canExecute; - } - /// - /// 当出现影响是否应执行该命令的更改时发生。 - /// - public event EventHandler CanExecuteChanged - { - add - { - if (_canExecute is not null) - CommandManager.RequerySuggested += value; - } - remove - { - if (_canExecute is not null) - CommandManager.RequerySuggested -= value; - } - } - /// - /// 定义确定此命令是否可在其当前状态下执行的方法。 - /// - /// 此命令使用的数据。 如果此命令不需要传递数据,则该对象可以设置为 。 - /// - /// 如果可执行此命令,则为 ;否则为 。 - /// - public bool CanExecute(object parameter) - { - if (_canExecute is null) - return true; - return _canExecute((T)parameter); - } - /// - /// 定义在调用此命令时要调用的方法。 - /// - /// 此命令使用的数据。 如果此命令不需要传递数据,则该对象可以设置为 。 - public void Execute(object parameter) - { - if (_execute is not null && CanExecute(parameter)) - _execute((T)parameter); - } -} - -/// -/// 事件命令 -/// -public class EventCommand : TriggerAction -{ - /// - /// 执行动作 - /// - /// 要执行的动作参数, 如果动作为提供参数,就设置为null - protected override void Invoke(object parameter) - { - if (CommandParameter is not null) - parameter = CommandParameter; - if (Command is not null) - Command.Execute(parameter); - } - /// - /// 事件 - /// - public ICommand Command - { - get { return (ICommand)GetValue(CommandProperty); } - set { SetValue(CommandProperty, value); } - } - /// - /// 事件属性 - /// - public static readonly DependencyProperty CommandProperty = - DependencyProperty.Register("Command", typeof(ICommand), typeof(EventCommand), new PropertyMetadata(null)); - - /// - /// 事件参数,如果为空,将自动传入事件的真实参数 - /// - public object CommandParameter - { - get { return (object)GetValue(CommandParameterProperty); } - set { SetValue(CommandParameterProperty, value); } - } - /// - /// 事件参数属性 - /// - public static readonly DependencyProperty CommandParameterProperty = - DependencyProperty.Register("CommandParameter", typeof(object), typeof(EventCommand), new PropertyMetadata(null)); -} \ No newline at end of file diff --git a/src/WPF/ViewModelBase.cs b/src/WPF/ViewModelBase.cs deleted file mode 100644 index 6d8908a..0000000 --- a/src/WPF/ViewModelBase.cs +++ /dev/null @@ -1,58 +0,0 @@ -namespace IFoxCAD.WPF; - -/// -/// ViewModel基类 -/// -/// -public class ViewModelBase : INotifyPropertyChanged -{ - /// - /// 属性值更改事件。 - /// - public event PropertyChangedEventHandler? PropertyChanged; - /// - /// 属性改变时调用 - /// - /// 属性名 - public void OnPropertyChanged([CallerMemberName] string propertyName = "") - { - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); - } - /// - /// 设置属性函数,自动通知属性改变事件 - /// - /// 属性类型 - /// 属性 - /// 属性值 - /// 属性名 - /// 成功返回 ,反之 - protected virtual bool Set(ref T storage, T value, [CallerMemberName] string propertyName = "") - { - if (object.Equals(storage, value)) - return false; - - storage = value; - this.OnPropertyChanged(propertyName); - - return true; - } - /// - /// 创建命令 - /// - /// 要调用的命令函数委托 - /// WPF命令 - protected RelayCommand CreateCommand(Action executeMethod) - { - return CreateCommand(executeMethod, (o) => true); - } - /// - /// 创建命令 - /// - /// 要调用的命令函数委托 - /// 命令是否可以执行的委托 - /// WPF命令 - protected RelayCommand CreateCommand(Action executeMethod, Func canExecuteMethod) - { - return new(executeMethod, canExecuteMethod); - } -} \ No newline at end of file diff --git a/tests/TestAcad09plus/GlobalUsings.cs b/tests/TestAcad09plus/GlobalUsings.cs deleted file mode 100644 index d32580b..0000000 --- a/tests/TestAcad09plus/GlobalUsings.cs +++ /dev/null @@ -1,50 +0,0 @@ -/// 系统引用 -global using System; -global using System.Collections; -global using System.Collections.Generic; -global using System.IO; -global using System.Linq; -global using System.Text; -global using System.Reflection; -global using System.Text.RegularExpressions; -global using Microsoft.Win32; -global using System.ComponentModel; -global using System.Runtime.InteropServices; -global using System.Collections.Specialized; - -global using Exception = System.Exception; - -global using Registry = Microsoft.Win32.Registry; -global using RegistryKey = Microsoft.Win32.RegistryKey; - -/// autocad 引用 -global using Autodesk.AutoCAD.ApplicationServices; -global using Autodesk.AutoCAD.EditorInput; -global using Autodesk.AutoCAD.Colors; -global using Autodesk.AutoCAD.DatabaseServices; -global using Autodesk.AutoCAD.Geometry; -global using Autodesk.AutoCAD.Runtime; -global using Acap = Autodesk.AutoCAD.ApplicationServices.Application; -global using Acaop = Autodesk.AutoCAD.ApplicationServices.Core.Application; -global using Acgi = Autodesk.AutoCAD.GraphicsInterface; - -global using Autodesk.AutoCAD.DatabaseServices.Filters; -global using Autodesk.AutoCAD; - -// jig命名空间会引起Viewport/Polyline等等重义,最好逐个引入 using Autodesk.AutoCAD.GraphicsInterface -global using WorldDraw = Autodesk.AutoCAD.GraphicsInterface.WorldDraw; -global using Manager = Autodesk.AutoCAD.GraphicsSystem.Manager; -global using Group = Autodesk.AutoCAD.DatabaseServices.Group; -global using Viewport = Autodesk.AutoCAD.DatabaseServices.Viewport; -global using Autodesk.AutoCAD.GraphicsInterface; -global using Polyline = Autodesk.AutoCAD.DatabaseServices.Polyline; -global using Cad_DwgFiler = Autodesk.AutoCAD.DatabaseServices.DwgFiler; -global using Cad_DxfFiler = Autodesk.AutoCAD.DatabaseServices.DxfFiler; -global using Cad_ErrorStatus = Autodesk.AutoCAD.Runtime.ErrorStatus; - - -/// ifoxcad -global using IFoxCAD.Cad; -global using IFoxCAD.Basal; - -global using IFoxCAD.WPF; diff --git a/tests/TestAcad09plus/TestAcad09plus.csproj b/tests/TestAcad09plus/TestAcad09plus.csproj deleted file mode 100644 index 3fe2240..0000000 --- a/tests/TestAcad09plus/TestAcad09plus.csproj +++ /dev/null @@ -1,43 +0,0 @@ - - - preview - enable - - NET48 - true - true - x64 - True - 1.0.0.* - 1.0.0.0 - false - - - - $(Configuration);acad - - - - - - - - - - TestView.xaml - - - - - - Designer - - - - - - - - - - \ No newline at end of file diff --git a/tests/TestAcad09plus/wpf/Cmd.cs b/tests/TestAcad09plus/wpf/Cmd.cs deleted file mode 100644 index 9f81401..0000000 --- a/tests/TestAcad09plus/wpf/Cmd.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Test.wpf; - -public class Cmd -{ - [CommandMethod(nameof(Test_WPf))] - public void Test_WPf() - { - var test = new TestView(); - Acap.ShowModalWindow(test); - } -} \ No newline at end of file diff --git a/tests/TestAcad09plus/wpf/TestView.xaml b/tests/TestAcad09plus/wpf/TestView.xaml deleted file mode 100644 index e51e2ac..0000000 --- a/tests/TestAcad09plus/wpf/TestView.xaml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - diff --git a/tests/TestAcad09plus/wpf/TestView.xaml.cs b/tests/TestAcad09plus/wpf/TestView.xaml.cs deleted file mode 100644 index 4eb001e..0000000 --- a/tests/TestAcad09plus/wpf/TestView.xaml.cs +++ /dev/null @@ -1,28 +0,0 @@ -namespace Test.wpf; - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Shapes; - - -/// -/// TestView.xaml 的交互逻辑 -/// -public partial class TestView : Window -{ - public TestView() - { - InitializeComponent(); - DataContext = new TestViewModel(); - } -} diff --git a/tests/TestAcad09plus/wpf/TestViewModel.cs b/tests/TestAcad09plus/wpf/TestViewModel.cs deleted file mode 100644 index e726029..0000000 --- a/tests/TestAcad09plus/wpf/TestViewModel.cs +++ /dev/null @@ -1,82 +0,0 @@ -namespace Test.wpf; - -using System.Windows; -using System.Windows.Input; - - -class TestViewModel : ViewModelBase -{ - string? name; - public string? Name - { - get { return name; } - set { Set(ref name, value); } - } - - private RelayCommand? clickCommand; - - public RelayCommand? ClickCommand - { - get - { - clickCommand ??= - new(execute => Name = "hello " + Name, - can => !string.IsNullOrEmpty(Name)); - return clickCommand; - } - } - - private bool receiveMouseMove; - public bool ReceiveMouseMove - { - get { return receiveMouseMove; } - set { Set(ref receiveMouseMove, value); } - } - - private string? tipText; - public string? TipText - { - get { return tipText; } - set { Set(ref tipText, value); } - } - - private RelayCommand? loadedCommand; - public RelayCommand? LoadCommand - { - get - { - loadedCommand ??= new(execute => MessageBox.Show("程序加载完毕")); - return loadedCommand; - } - } - - private RelayCommand? mouseMoveCommand; - public RelayCommand? MouseMoveCommand - { - get - { - mouseMoveCommand ??= new( - execute => { - var pt = execute.GetPosition(execute.Device.Target); - var left = "左键放开"; - var mid = "中键放开"; - var right = "右键放开"; - - if (execute.LeftButton == MouseButtonState.Pressed) - left = "左键放下"; - if (execute.MiddleButton == MouseButtonState.Pressed) - mid = "中键放下"; - if (execute.RightButton == MouseButtonState.Pressed) - right = "右键放下"; - TipText = $"当前鼠标位置:X={pt.X},Y={pt.Y}。当前鼠标状态:{left}、{mid}、{right}"; - }, - can => ReceiveMouseMove); - return mouseMoveCommand; - } - } - - public TestViewModel() - { - Name = "world"; - } -} diff --git "a/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/01.\346\213\211\344\274\270\345\241\253\345\205\205\345\217\263\351\224\256\350\217\234\345\215\225.cs" "b/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/01.\346\213\211\344\274\270\345\241\253\345\205\205\345\217\263\351\224\256\350\217\234\345\215\225.cs" deleted file mode 100644 index 6afeef7..0000000 --- "a/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/01.\346\213\211\344\274\270\345\241\253\345\205\205\345\217\263\351\224\256\350\217\234\345\215\225.cs" +++ /dev/null @@ -1,184 +0,0 @@ -using Autodesk.AutoCAD.Windows; -using System.Diagnostics; -using static IFoxCAD.Cad.PostCmd; -using MenuItem = Autodesk.AutoCAD.Windows.MenuItem; - -namespace JoinBoxAcad; -public class HatchPick -{ - [IFoxInitialize] - [CommandMethod(nameof(HatchPickInit))] - public void HatchPickInit() - { - Env.Printl($"※拉伸填充控制※\n{nameof(HatchPickSwitch)} - 切换开关\n"); - - if (Debugger.IsAttached) - Env.SetVar("hpscale", 22); - // 设定高版本双击填充启动修改面板 - // JoinBoxAcad.Menu.Cui.CuiInit(); - LoadHelper(true); - } - - // 只能命令卸载哦,因为关闭cad是不需要卸载的 - [CommandMethod(nameof(UnLoadHatchPick))] - public void UnLoadHatchPick() - { - LoadHelper(false); - } - - [CommandMethod(nameof(HatchPickSwitch))] - public void HatchPickSwitch() - { - if (HatchPickEvent.State.IsStop) - { - Env.Printl("已经 卸载 拉伸填充控制+ 用: " + nameof(HatchPickInit) + " 加载"); - return; - } - - if (HatchPickEvent.State.IsRun) - HatchPickEvent.State.Break(); - else - HatchPickEvent.State.Start(); - Env.Printl("已经 " + (HatchPickEvent.State.IsRun ? "开启" : "禁用") + " 拉伸填充控制+"); - } - - - internal static Dictionary MapDocHatchPickEvent = new(); - void LoadHelper(bool isLoad) - { - var dm = Acap.DocumentManager; - if (dm is null || dm.Count == 0) - return; - if (isLoad) - { - dm.DocumentCreated += Dm_DocumentCreated; - Dm_DocumentCreated(); // 自执行一次 - AddRightClickMenu(); - HatchPickEvent.AddInit(); - } - else - { - HatchPickEvent.RemoveInit(); - dm.DocumentCreated -= Dm_DocumentCreated; - UnDocumentCreated(); - HatchPick.RemoveRightClickMenu(); - } - } - - /// - /// 文档创建反应器 - /// - void Dm_DocumentCreated(object? sender = null, DocumentCollectionEventArgs? e = null) - { - var dm = Acap.DocumentManager; - if (dm is null || dm.Count == 0) - return; - var doc = dm.MdiActiveDocument; - if (doc is null) - return; - if (!MapDocHatchPickEvent.ContainsKey(doc)) - MapDocHatchPickEvent.Add(doc, new HatchPickEvent(doc)); - } - - /// - /// 卸载文档创建反应器 - /// - static void UnDocumentCreated() - { - var dm = Acap.DocumentManager; - if (dm is null || dm.Count == 0) - return; - var doc = dm.MdiActiveDocument; - if (doc is null) - return; - if (MapDocHatchPickEvent.ContainsKey(doc)) - { - MapDocHatchPickEvent[doc].Dispose(); - MapDocHatchPickEvent.Remove(doc); - } - } - - - - private const string V0 = "拉伸填充-开"; - private const string V1 = "拉伸填充-关";// (面板的独立填充必须关,否则致命错误) - private const string V2 = "独立填充";//(快捷,不需要关...目前还是会崩溃) - static readonly HashSet _menuItems = new() { V0, V1, V2 }; - static readonly ContextMenuExtension _contextMenu = new() { Title = "惊惊盒子" }; - /// - /// 添加右键菜单 - /// - void AddRightClickMenu() - { - // 右键菜单 - foreach (var item in _menuItems) - { - MenuItem mi = new(item); // 添加菜单项 - mi.Click += MenuItemClick; // 添加单击事件 - - //mi.MenuItems.Add(new MenuItem("改颜色1")); // 二级菜单 - _contextMenu.MenuItems.Add(mi); // 提交 - } - Acap.AddDefaultContextMenuExtension(_contextMenu);// 添加默认上下文菜单扩展,带标题的 - - //加入到某一种对象的右键菜单中 - //RXClass rxClass = Entity.GetClass(typeof(BlockReference)); - //Acap.AddObjectContextMenuExtension(rxClass, contextMenu); - //// 选择实体右键菜单才有用. 获得实体所属的RXClass类型 - // RXClass rx = RXObject.GetClass(typeof(Entity)); - // Acap.AddObjectContextMenuExtension(rx, contextMenu); // 这里为什么又可以不带标题 - } - - /// - /// 卸载右键菜单 - /// - static void RemoveRightClickMenu() - { - if (_contextMenu is null) - return; - Acap.RemoveDefaultContextMenuExtension(_contextMenu); - } - - /// - /// 右键点击触发 - /// - /// - /// - void MenuItemClick(object sender, EventArgs e) - { - // 获取发出命令的快捷菜单项 - if (sender is not MenuItem mi) - return; - - // 根据快捷菜单项的名字,分别调用对应的命令 - if (!_menuItems.Contains(mi.Text)) - return; - - switch (mi.Text) - { - case V0: - HatchPickEvent.State.Start(); - break; - case V1: - HatchPickEvent.State.Break(); - break; - case V2: - { - HatchPickEvent.State.Break(); - PromptSelectionOptions pso = new() - { - AllowDuplicates = true, // 不允许重复选择 - SingleOnly = true, // 隐含窗口选择(不需要空格确认) - }; - var ssPsr = Env.Editor.GetSelection(pso, HatchPickEvent.FilterForHatch); - if (ssPsr.Status != PromptStatus.OK) - return; - - Env.Editor.SetImpliedSelection(ssPsr.Value.GetObjectIds()); - SendCommand("-hatchedit H ", RunCmdFlag.AcedPostCommand); - HatchPickEvent.State.Start(); - } - break; - } - } -} \ No newline at end of file diff --git "a/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/02.\346\213\211\344\274\270\345\241\253\345\205\205\344\272\213\344\273\266.cs" "b/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/02.\346\213\211\344\274\270\345\241\253\345\205\205\344\272\213\344\273\266.cs" deleted file mode 100644 index 8fed9c2..0000000 --- "a/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/02.\346\213\211\344\274\270\345\241\253\345\205\205\344\272\213\344\273\266.cs" +++ /dev/null @@ -1,1030 +0,0 @@ -using System.Drawing; -using System.Runtime.CompilerServices; -using System.Windows.Forms; -using static IFoxCAD.Cad.PostCmd; - -namespace JoinBoxAcad; - -public class HatchPickEvent : IDisposable -{ - #region 静态成员 - public static ProState State = new(); - // 选择集过滤器 - public static readonly SelectionFilter FilterForHatch = new(new TypedValue[] { new TypedValue((int)DxfCode.Start, "HATCH") }); - // 临时标记(重设选择集会触发一次选择集反应器) - static bool _selectChangedStop = false; - // 临时选择集用 - static readonly List _hatchIds = new(); - // 获取夹点在哪个图元边界上面,是为true - static bool _pickInBo = false; - static bool _vetoProperties = false; - private Tolerance _tol = new(1e-6, 1e-6); - - public static void AddInit() - { - HatchHook.SetHook(); - // 全局事件重复+=是不需要担心的 - Acap.DocumentManager.DocumentLockModeChanged += Dm_VetoCommand; - State.Start(); - } - - public static void RemoveInit() - { - State.Stop(); - Acap.DocumentManager.DocumentLockModeChanged -= Dm_VetoCommand; - HatchHook.RemoveHook(); - } - - /// - /// 反应器->命令否决触发命令前(不可锁文档) - /// - /// - /// - public static void Dm_VetoCommand(object sender, DocumentLockModeChangedEventArgs e) - { - if (!State.IsRun) - return; - if (string.IsNullOrEmpty(e.GlobalCommandName) || e.GlobalCommandName == "#") - return; - switch (e.GlobalCommandName.ToUpper()) - { - case "PROPERTIES": // 特性面板 - { - // 事件顺序问题: - // 开cad之后第一次双击必弹出特性面板 - // 所以这里直接删除填充边界 - HatchPick.MapDocHatchPickEvent[e.Document].SetPropertiesInfoTask(); - if (_vetoProperties) - { - DebugEx.Printl("Dm_VetoCommand 否决了"); - e.Veto(); - _vetoProperties = false; - // 发送编辑填充命令 - SendCommand("_hatchedit ", RunCmdFlag.AcedPostCommand); - return; - } - DebugEx.Printl("Dm_VetoCommand 没否决"); - } - break; - } - } - - - #endregion - - #region 动态成员 - /// - /// 在位编辑器 记录全图选择集的填充 - /// - readonly HashSet _refeditSsgeting = new(); - /// - /// 在位编辑器 获取当前选择集做差集=>内部填充 - /// - readonly HashSet _refeditSsgeted = new(); - // map<填充id,边界转换器> - readonly Dictionary _mapHatchConv = new(); - readonly Document _doc; - public HatchPickEvent(Document doc) - { - _doc = doc; - LoadHelper(true); - } - - void LoadHelper(bool isLoad) - { - if (isLoad) - { - _doc.ImpliedSelectionChanged += Md_ImpliedSelectionChanged; - _doc.CommandWillStart += Md_CommandWillStart; - _doc.LispWillStart += Md_LispWillStart; - _doc.CommandEnded += Md_CommandEnded; - _doc.Database.ObjectErased += DB_ObjectErased; - _doc.Database.ObjectModified += DB_ObjectModified; - } - else - { - _doc.ImpliedSelectionChanged -= Md_ImpliedSelectionChanged; - _doc.CommandWillStart -= Md_CommandWillStart; - _doc.LispWillStart -= Md_LispWillStart; - _doc.CommandEnded -= Md_CommandEnded; - _doc.Database.ObjectErased -= DB_ObjectErased; - _doc.Database.ObjectModified -= DB_ObjectModified; - } - } - #endregion - - #region 事件 - /// - /// 反应器->command命令完成前 - /// - /// - /// - void Md_CommandWillStart(object sender, CommandEventArgs e) - { - if (!State.IsRun) - return; - - // 此处无法使用文档锁,否则将导致文档锁无法释放,然后ctrl+z失败 - var cmdup = e.GlobalCommandName.ToUpper(); - DebugEx.Printl("Md_CommandWillStart::" + cmdup); - - switch (cmdup) - { - case "REFEDIT": - { - // 在位编辑命令,执行前,获取当前空间所有填充 - var prompt = Env.Editor.SelectAll(FilterForHatch); - if (prompt.Status != PromptStatus.OK) - return; - using DBTrans tr = new(); - GetHatchIds(prompt); - if (_hatchIds.Count == 0) - return; - for (int i = 0; i < _hatchIds.Count; i++) - _refeditSsgeting.Add(_hatchIds[i]); - } - break; - } - - // 拉伸夹点命令前触发 - if (cmdup != "GRIP_STRETCH") - { - EraseAllHatchBorders(); - } - else - { - var mp = HatchHook.MouseStartPoint; - var mouseStart = Screen.ScreenToCad(mp); - DebugEx.Printl("mouseStart,屏幕点::" + mp); - DebugEx.Printl("mouseStart,cad点::" + mouseStart); - - // 获取当前选择的对象,然后提取所有的夹点 - var prompt = Env.Editor.SelectImplied(); - if (prompt.Status != PromptStatus.OK) - return; - using DBTrans tr = new(); - GetHatchIds(prompt); - if (_hatchIds.Count == 0) - return; - - // TODO 屏幕像素点转cad点的误差,要随着视口高度而动态计算....这里的计算可能不太正确 - var tol = (double)Env.GetVar("viewsize") / 10; - DebugEx.Printl("tol::" + tol); - - // 0x01 移动了矩形填充中间的夹点,删除边界,并且重新生成填充和边界 - // 0x02 移动了填充边界上的夹点,不处理,然后它会通过关联进行自己修改 - _pickInBo = false; - for (int i = 0; i < _hatchIds.Count; i++) - { - var hatId = _hatchIds[i]; - if (!_mapHatchConv.ContainsKey(hatId)) - continue; - - _mapHatchConv[hatId].BoundaryIds.ForEach((id, idState) => { - var boEnt = tr.GetObject(id); - if (boEnt == null) - return; - - // 获取夹点在哪个图元边界上 - HashSet boPts = new(); - if (boEnt is Circle circle) - { - // 圆形的边界夹点是: 圆心+半径 - var x = circle.Center.X; - var y = circle.Center.Y; - var z = circle.Center.Z; - var r = circle.Radius; - boPts.Add(new(x + r, y, z));//上 - boPts.Add(new(x - r, y, z));//下 - boPts.Add(new(x, y - r, z));//左 - boPts.Add(new(x, y + r, z));//右 - } - else - { - // 获取所有的边点 - // 这里圆形会获取圆心,所以剔除圆形 - var tmp = GetEntityPoint3ds(boEnt); - for (int j = 0; j < tmp.Count; j++) - boPts.Add(tmp[j]); - } - - if (boEnt is Arc arc) - { - if (!arc.StartPoint.IsEqualTo(arc.EndPoint, _tol)) - { - // 圆弧的腰点 - var arc2 = arc.GetPointAtDist(arc.GetDistAtPoint(arc.EndPoint) * 0.5); - boPts.Add(arc2); - } - } - else if (boEnt is Polyline pl) - { - for (int j = 0; j < pl.NumberOfVertices; j++) - { - var bulge = pl.GetBulgeAt(j); - if (bulge == 0.0) - continue; - // 有凸度就是有每段的中点 - var pta = pl.GetPoint2dAt(j); - Point2d ptb; - if (j + 1 < pl.NumberOfVertices) - ptb = pl.GetPoint2dAt(j + 1); - else - ptb = pl.GetPoint2dAt(0); - - var p = MathHelper.GetArcMidPoint(pta, ptb, bulge); - boPts.Add(p.Point3d()); - } - } - - boPts.ForEach((pt, ptState) => { - var dist = pt.DistanceTo(mouseStart); - //Debugx.Printl("pt::" + pt + " dist::" + dist); - if (dist < tol) - { - ptState.Break(); - _pickInBo = true; - } - }); - }); - - // 点在边界上:就不处理了,它会通过cad的关联填充反应器自动修改 - if (_pickInBo) - DebugEx.Printl("夹点在边界上"); - else - DebugEx.Printl("夹点不在边界上"); - } - } - } - - /// - /// 图元拉伸点 - /// - /// - /// - static List GetEntityPoint3ds(Entity ent) - { - var pts3d = new Point3dCollection(); - ent.GetStretchPoints(pts3d); - return pts3d.Cast().ToList(); - } - - - - - /// - /// 反应器->command命令完成后 - /// - /// - /// - void Md_CommandEnded(object sender, CommandEventArgs e) - { - if (!State.IsRun) - return; - - var cmdup = e.GlobalCommandName.ToUpper(); - switch (cmdup) - { - case "REFEDIT": - { - DebugEx.Printl("Md_CommandEnded:: REFEDIT"); - - // 在位编辑命令,执行后,获取当前空间所有填充 - var prompt = Env.Editor.SelectAll(FilterForHatch); - if (prompt.Status != PromptStatus.OK) - return; - - using DBTrans tr = new(); - GetHatchIds(prompt); - if (_hatchIds.Count == 0) - return; - - for (int i = 0; i < _hatchIds.Count; i++) - if (!_refeditSsgeting.Contains(_hatchIds[i]))//Except - _refeditSsgeted.Add(_hatchIds[i]); - - var sb = new StringBuilder(); - foreach (var id in _refeditSsgeted) - sb.AppendLine(id.ToString()); - Env.Printl("块内填充id:" + sb.ToString()); - } - break; - case "REFSET": // 加减在位编辑图元 - { - DebugEx.Printl("Md_CommandEnded:: REFSET"); - - // 命令历史的最后一行是:添加/删除 - var last = Env.GetVar("lastprompt").ToString(); - if (last is null) - return; - - // 完成后必然有上次选择集 - var prompt = Env.Editor.SelectPrevious(); - if (prompt.Status != PromptStatus.OK) - return; - using DBTrans tr = new(); - GetHatchIds(prompt); - if (_hatchIds.Count == 0) - return; - - // 就是因为无法遍历到在位编辑的块内图元,只能进行布尔运算 - if (last.Contains("添加") || last.Contains("Added"))// 中英文cad - { - for (int i = 0; i < _hatchIds.Count; i++) - { - _refeditSsgeting.Remove(_hatchIds[i]); - _refeditSsgeted.Add(_hatchIds[i]); - } - return; - } - if (last.Contains("删除") || last.Contains("Removed"))// 中英文cad - { - for (int i = 0; i < _hatchIds.Count; i++) - { - _refeditSsgeted.Remove(_hatchIds[i]); - _refeditSsgeting.Add(_hatchIds[i]); - } - return; - } - } - break; - case "REFCLOSE":// 保存块,清空集合 - { - DebugEx.Printl("Md_CommandEnded:: REFCLOSE"); - _refeditSsgeted.Clear(); - _refeditSsgeting.Clear(); - } - break; - case "GRIP_STRETCH":// 拉伸夹点命令后触发 - { - // 夹点在边界上,退出 - if (_pickInBo) - return; - - // 夹点不在边界上: - // cad会平移填充,在这之后,我们删除填充边界,重建填充边界 - var prompt = Env.Editor.SelectImplied(); - if (prompt.Status != PromptStatus.OK) - return; - using DBTrans tr = new(); - GetHatchIds(prompt); - if (_hatchIds.Count == 0) - return; - - // 删除指定填充的边界,并清理关联反应器 - HashSet idsOfSsget = new(); - foreach (var hatId in _hatchIds) - { - idsOfSsget.Add(hatId); - - if (!_mapHatchConv.ContainsKey(hatId)) - continue; - bool clearFlag = false; - _mapHatchConv[hatId].BoundaryIds.ForEach(boId => { - if (!boId.IsOk()) - return; - var boEnt = tr.GetObject(boId); - if (boEnt == null) - return; - if (!HatchPickEnv.IsMeCreate(boEnt)) - return; - boId.Erase(); - clearFlag = true; - }); - - if (!clearFlag) - return; - - _mapHatchConv[hatId].BoundaryIds.Clear(); - - // 清理填充反应器 - var hatch = tr.GetObject(hatId); - if (hatch == null) - return; - using (hatch.ForWrite()) - RemoveAssociative(hatch); - CreatHatchConverter(hatch, idsOfSsget); - } - SetImpliedSelection(idsOfSsget); - } - break; - } - } - - /// - /// 获取选择集上的填充,在缓存内提取 - /// - /// - /// - static void GetHatchIds(PromptSelectionResult psr, DBTrans? tr = null) - { - tr ??= DBTrans.Top; - _hatchIds.Clear(); - var ids = psr.Value.GetObjectIds(); - for (int i = 0; i < ids.Length; i++) - { - var hatch = tr.GetObject(ids[i]); - if (hatch is not null) - _hatchIds.Add(ids[i]); - } - } - - /// - /// 反应器->lisp命令 - /// - void Md_LispWillStart(object sender, LispWillStartEventArgs e) - { - if (!State.IsRun) - return; - - using DBTrans tr = new(doclock: true); - EraseAllHatchBorders(); - } - - /// - /// 反应器->选择集 - /// - /// - /// - void Md_ImpliedSelectionChanged(object sender, EventArgs e) - { - if (!State.IsRun) - return; - - // 此处必须要文档锁 - if (_selectChangedStop) - { - _selectChangedStop = false; - return; - } - DebugEx.Printl("Md_ImpliedSelectionChanged"); - - using DBTrans tr = new(doclock: true); - var prompt = Env.Editor.SelectImplied(); - if (prompt.Status != PromptStatus.OK) - { - EraseAllHatchBorders(); - return; - } - - // 获取图层锁定的记录,用于跳过 - Dictionary islocks = new(); - foreach (var layerRecord in tr.LayerTable.GetRecords()) - if (!layerRecord.IsErased)// 08符号表记录保留了这个 - islocks.Add(layerRecord.Name, layerRecord.IsLocked); - - // 遍历选择,创建边界转换器 - // 重设选择集 - HashSet idsOfSsget = new(); - foreach (var entId in prompt.Value.GetObjectIds()) - { - idsOfSsget.Add(entId); - var hatch = tr.GetObject(entId, openLockedLayer: true); - if (hatch is null) - continue; - if (islocks[hatch.Layer]) - continue; - // 重复选择 || 在位编辑外 - if (_mapHatchConv.ContainsKey(entId) || _refeditSsgeting.Contains(entId)) - continue; - CreatHatchConverter(hatch, idsOfSsget); - } - SetImpliedSelection(idsOfSsget); - } - - /// - /// 创建填充和填充边界转换器 - /// - /// - /// - /// - void CreatHatchConverter(Hatch hatch, HashSet outSsgetIds) - { - //tr ??= DBTrans.Top; - var tr = DBTrans.GetTop(hatch.Database); - var hc = new HatchConverter(hatch); - ObjectId newid; - - // 如果边界在图纸上没有删除(删除就不是关联的), - // 那就不创建新的,然后选中它们 - if (hc.BoundaryIds.Count != 0) - { - DebugEx.Printl("CreatHatchConverter:: 加入了现有边界到选择集"); - - // 加入选择集 - foreach (var item in hc.BoundaryIds) - outSsgetIds.Add(item); - outSsgetIds.Add(hatch.ObjectId); - newid = hatch.ObjectId; - } - else - { - DebugEx.Printl("CreatHatchConverter:: 创建新填充和边界"); - - // 创建新填充和边界 - hc.GetBoundarysData(); - - newid = hc.CreateBoundarysAndHatchToMsPs(tr.CurrentSpace); - HatchPickEnv.SetMeXData(newid, hc.BoundaryIds); - - // 清理上次,删除边界和填充 - if (_mapHatchConv.ContainsKey(hatch.ObjectId)) - { - var boIds = _mapHatchConv[hatch.ObjectId].BoundaryIds; - for (int i = 0; i < boIds.Count; i++) - boIds[i].Erase(); - _mapHatchConv.Remove(hatch.ObjectId); - } - // 删除选中的 - hatch.ObjectId.Erase(); - } - - if (!_mapHatchConv.ContainsKey(newid)) - _mapHatchConv.Add(newid, hc); - else - _mapHatchConv[newid] = hc; - - if (newid == hatch.ObjectId) - return; - - // 优先: 块内含有旧的,就加入新的 - if (_refeditSsgeted.Contains(hatch.ObjectId)) - { - _refeditSsgeted.Remove(hatch.ObjectId); - _refeditSsgeted.Add(newid); - } - else if (_refeditSsgeting.Contains(hatch.ObjectId)) - { - _refeditSsgeting.Remove(hatch.ObjectId); - _refeditSsgeting.Add(newid); - } - } - - /// - /// 重设选择集 - /// - /// 加入选择集的成员 - void SetImpliedSelection(HashSet setImpSelect) - { - // 获取填充 - foreach (var id in _mapHatchConv.Keys) - setImpSelect.Add(id); - - // 获取填充边界 - foreach (var item in _mapHatchConv.Values) - foreach (var id in item.BoundaryIds) - setImpSelect.Add(id); - - // 设置选择集,没有标记的话会死循环 - _selectChangedStop = true; - Env.Editor.SetImpliedSelection(setImpSelect.ToArray()); - } - - /// - /// 删除全部填充边界 - /// - void EraseAllHatchBorders() - { - if (_mapHatchConv.Count == 0) - return; - foreach (var dict in _mapHatchConv) - { - dict.Value.BoundaryIds.ForEach(boId => { - if (!boId.IsOk()) - return; - using DBTrans tr = new(database: boId.Database); - var boEnt = tr.GetObject(boId, OpenMode.ForWrite); - if (boEnt == null) - return; - // 删除填充边界并清理关联反应器 - if (!HatchPickEnv.IsMeCreate(boEnt)) - return; - boEnt.Erase(); - if (dict.Key.IsOk()) - { - var hatch = tr.GetObject(dict.Key, OpenMode.ForWrite); - if (hatch == null) - return; - RemoveAssociative(hatch); - } - }); - } - _mapHatchConv.Clear(); - } - - /// - /// 移除关联反应器 - /// - /// - static void RemoveAssociative(Hatch hatch) - { - // 撤回填充,没有边界就移除关联反应器 - if (!hatch.Associative) - return; - - // 填充边界反应器 - var assIds = hatch.GetAssociatedObjectIds(); - if (assIds == null) - return; - bool isok = true; - foreach (ObjectId id in assIds) - { - if (!id.IsOk()) - { - isok = false; - break; - } - } - // 这里边界id已经删除了,所以移除会导致异常 - if (isok) - hatch.RemoveAssociatedObjectIds(); - // 取消关联反应器才能生成的正确 - hatch.Associative = false; - } - - /// - /// 撤回事件(获取删除对象) - /// - /// - /// - static void DB_ObjectErased(object sender, ObjectErasedEventArgs e) - { - if (!State.IsRun) - return; - - // object erased. - if (e.Erased) - { - return; - } - - // UNDO - if (e.DBObject is Hatch hatch) - { - if (HatchPickEnv.IsMeCreate(hatch)) - RemoveAssociative(hatch); - } - else if (e.DBObject is Entity boEnt) - { - // 撤回边界 - if (HatchPickEnv.IsMeCreate(boEnt)) - { - boEnt.Erase(); - // 通过xdata回溯填充,清理关联反应器 - if (boEnt.XData != null) - { - using DBTrans tr = new(); - var hatchId = HatchPickEnv.GetXdataHatch(boEnt); - if (hatchId.IsOk()) - { - var hatchEnt = tr.GetObject(hatchId, OpenMode.ForWrite); - if (hatchEnt != null) - RemoveAssociative(hatchEnt); - } - } - } - } - } - - /// - /// 撤回事件(更改时触发) - /// 它会获取有修改步骤的图元id - /// - /// - /// - static void DB_ObjectModified(object sender, ObjectEventArgs e) - { - if (!State.IsRun) - return; - - // 然后删除我制造的拉伸填充上面的关联反应器 - if (!e.DBObject.IsUndoing) - return; - if (e.DBObject.IsErased) - return; - // 是我生成的填充才删除关联 - if (e.DBObject is Hatch hatch) - { - if (HatchPickEnv.IsMeCreate(hatch)) - RemoveAssociative(hatch); - } - } - - void SetPropertiesInfoTask() - { - // 原有选择集 - var prompt = Env.Editor.SelectImplied(); - if (prompt.Status != PromptStatus.OK) - return; - - using DBTrans tr = new(); - - // 获取记录的边界 - HashSet boAll = new(); - foreach (var hc in _mapHatchConv.Values) - foreach (var boid in hc.BoundaryIds) - boAll.Add(boid); - - // 获取选择集上面所有的填充,如果没有填充就结束(不屏蔽特性面板) - bool hasHatch = false; - HashSet idsOfSsget = new(); - foreach (var id in prompt.Value.GetObjectIds()) - { - // 含有填充 - if (_mapHatchConv.ContainsKey(id)) - hasHatch = true; - // 排除边界的加入 - if (!boAll.Contains(id)) - idsOfSsget.Add(id); - } - if (!hasHatch) - return; - - // 删除填充边界,并清理关联反应器 - EraseAllHatchBorders(); - - // 重设选择集 提供给后续命令判断 - SetImpliedSelection(idsOfSsget); - - // 如果有填充才否决 - _vetoProperties = idsOfSsget.Count != 0; - } - #endregion - - #region IDisposable接口相关函数 - public bool IsDisposed { get; private set; } = false; - - /// - /// 手动调用释放 - /// - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - /// - /// 析构函数调用释放 - /// - ~HatchPickEvent() - { - Dispose(false); - } - - protected virtual void Dispose(bool disposing) - { - // 不重复释放 - if (IsDisposed) return; - IsDisposed = true; - - if (_doc.IsDisposed) - return; - LoadHelper(false); - } - #endregion -} - -/// -/// 填充的鼠标钩子 -/// -public static class HatchHook -{ - static readonly MouseHook MouseHook; - // 夹点拉伸前的点,拉伸后利用命令后反应器去处理"GRIP_STRETCH" - static volatile int _X; - static volatile int _Y; - public static Point MouseStartPoint { get => new(_X, _Y); } - - /// - /// 鼠标双击事件 - /// - public static event EventHandler? DoubleClick; - - static HatchHook() - { - MouseHook = new(); - } - - /// - /// 查找主线程
- /// 代替
- /// 托管线程和他们不一样: - ///
- /// 主窗口 - /// 进程ID - /// 线程ID - [DllImport("user32.dll", SetLastError = true)] - static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId); - - [DllImport("user32.dll")] - static extern bool IsWindowEnabled(IntPtr hWnd); - /// - /// 获取当前窗口 - /// - /// 当前窗口标识符 - [DllImport("user32.dll")] - static extern IntPtr GetForegroundWindow(); - - public static void SetHook() - { - // 如果是全局钩子会发生偶尔失效的情况,改用进程钩子反而好多了 - MouseHook.SetHook(true); - MouseHook.MouseDown += (sender, e) => { - // 此处断点时候就会使得钩子失效 - if (!IsWindowEnabled(Acap.MainWindow.Handle)) - return; - // 进程号拦截 - GetWindowThreadProcessId(GetForegroundWindow(), out uint winId); - if (MouseHook.Process.Id != winId) - return; - if (e.Button == MouseButtons.Left) - { - _X = e.X; - _Y = e.Y; - } - }; - - MouseHook.DoubleClick += (sender, e) => { - // 此处断点时候就会使得钩子失效 - if (!IsWindowEnabled(Acap.MainWindow.Handle)) - return; - // 进程号拦截 - GetWindowThreadProcessId(GetForegroundWindow(), out uint winId); - if (MouseHook.Process.Id != winId) - return; - DoubleClick?.Invoke(sender, e); - }; - } - - public static void RemoveHook() - { - MouseHook?.Dispose(); - } -} - -public static class HatchPickEnv -{ - //static readonly string _appName = nameof(JoinBox); - //static readonly string _data = nameof(CreateBoundary); - - static readonly string _appName = "JoinBox"; - static readonly string _data = "CreateBoundary"; - - /// - /// 判断图元是否由 我的转换器 创建(相对的是直接提取现有图元边界) - /// - /// 任何图元 - /// - public static bool IsMeCreate(Entity entity) - { - if (entity.XData == null) - return false; - var xl = (XDataList)entity.XData; - return xl.Contains(_appName, _data); - } - - /// - /// 我的转换器 xdata数据模板 - /// - /// - /// - /// - public static ResultBuffer GetMeBuffer(Handle hatchHandle, DBTrans? trans = null) - { - trans ??= DBTrans.Top; - trans.RegAppTable.Add(_appName); // add函数会默认的在存在这个名字的时候返回这个名字的regapp的id,不存在就新建 - ResultBuffer resBuf = new() - { - new((int)DxfCode.ExtendedDataRegAppName, _appName), - new((int)DxfCode.ExtendedDataAsciiString,_data), - new((int)DxfCode.ExtendedDataHandle, hatchHandle),//边界回溯这个填充的句柄,如果创建新填充,就需要再去改 - }; - return resBuf; - } - - /// - /// 填充和边界上面增加xdata,实现区分原生和我的数据 - /// - /// - /// - /// - public static void SetMeXData(ObjectId newHatchId, List boIds, DBTrans? trans = null) - { - trans ??= DBTrans.Top; - var hatchEnt = trans.GetObject(newHatchId); - if (hatchEnt != null) - using (hatchEnt.ForWrite()) - hatchEnt.XData = GetMeBuffer(hatchEnt.Handle, trans); // 设置xdata仅仅为debug可以通过鼠标悬停看见它数据,因此设置为自己 - - // 修改边界的xdata为新填充的 - boIds.ForEach(id => { - var boEnt = trans.GetObject(id); - if (boEnt is null) - return; - using (boEnt.ForWrite()) - { - boEnt.RemoveXData(_appName); - boEnt.XData = GetMeBuffer(newHatchId.Handle, trans); - } - }); - } - - /// - /// 通过边界ent获取填充id - /// - /// 边界图元 - /// - /// - public static ObjectId GetXdataHatch(Entity boEntity, DBTrans? trans = null) - { - if (boEntity.XData == null) - return ObjectId.Null; - XDataList data = boEntity.XData; - - if (!data.Contains(_appName, _data)) - return ObjectId.Null; - - var indexs = data.GetXdataAppIndex(_appName, new DxfCode[] { DxfCode.ExtendedDataHandle }); - if (indexs.Count == 0) - return ObjectId.Null; - - trans ??= DBTrans.Top; - return trans.GetObjectId(data[indexs[0]].Value.ToString()); - } -} - -public static class MathHelper -{ - /// - /// 圆弧的腰点 - /// - /// 圆弧点1 - /// 圆弧点3 - /// 凸度 - /// 返回腰点 - /// - [MethodImpl] - public static Point2d GetArcMidPoint(Point2d arc1, Point2d arc3, double bulge) - { - if (bulge == 0) - throw new ArgumentException("凸度为0,此线是平的"); - - var center = GetArcBulgeCenter(arc1, arc3, bulge); - var angle1 = center.GetVectorTo(arc1).GetAngle2XAxis(); - var angle3 = center.GetVectorTo(arc3).GetAngle2XAxis(); - // 利用边点进行旋转,就得到腰点,旋转角/2 - // 需要注意镜像的多段线 - double angle = angle3 - angle1; - if (bulge > 0) - { - if (angle < 0) - angle += Math.PI * 2; - } - else - { - if (angle > 0) - angle += Math.PI * 2; - } - return arc1.RotateBy(angle / 2, center); - } - /// http://bbs.xdcad.net/thread-722387-1-1.html - /// https://blog.csdn.net/jiangyb999/article/details/89366912 - /// - /// 凸度求圆心 - /// - /// 圆弧头点 - /// 圆弧尾点 - /// 凸度 - /// 圆心 - [MethodImpl] - public static Point2d GetArcBulgeCenter(Point2d arc1, Point2d arc3, double bulge) - { - if (bulge == 0) - throw new ArgumentException("凸度为0,此线是平的"); - - var x1 = arc1.X; - var y1 = arc1.Y; - var x2 = arc3.X; - var y2 = arc3.Y; - - var b = (1 / bulge - bulge) / 2; - var x = (x1 + x2 - b * (y2 - y1)) / 2; - var y = (y1 + y2 + b * (x2 - x1)) / 2; - return new Point2d(x, y); - } - - /// - /// X轴到向量的弧度,cad的获取的弧度是1PI,所以转换为2PI(上小,下大) - /// - /// 向量 - /// X轴到向量的弧度 - public static double GetAngle2XAxis(this Vector2d ve, double tolerance = 1e-6) - { - const double Tau = Math.PI + Math.PI; - // 世界重合到用户 Vector3d.XAxis->两点向量 - double al = Vector2d.XAxis.GetAngleTo(ve); - al = ve.Y > 0 ? al : Tau - al; // 逆时针为正,大于0是上半圆,小于则是下半圆,如果-负值控制正反 - al = Math.Abs(Tau - al) <= tolerance ? 0 : al; - return al; - } -} \ No newline at end of file diff --git "a/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/HatchHelper.cs" "b/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/HatchHelper.cs" deleted file mode 100644 index 6d6c243..0000000 --- "a/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/HatchHelper.cs" +++ /dev/null @@ -1,124 +0,0 @@ -namespace JoinBoxAcad; - -public static class HatchHelper -{ - /// - /// 遍历填充每条边 - /// - /// - /// - public static void ForEach(this Hatch hatch, Action action) - { - for (int i = 0; i < hatch.NumberOfLoops; i++) - action.Invoke(hatch.GetLoopAt(i)); - } - - -#if false - /// - /// 分离填充边界 - /// 将外边界和包含的边界成为一个集 - /// - /// 填充的边界(只有多段线和圆) - /// 多个id集,id中第一个是外边界 - public static IEnumerable[] SeparationBorder(this IEnumerable bianjie) - { - IEnumerable[] objectIds = null; - if (bianjie.Length < 1) return null; - - Database db = bianjie[0].Database; - - // 首先获取一个图元,这个图元默认成边界,看它是否包含第二个,如果是,加入a集 - // 如果不是,它是否把自己包含了, - // 如果是,把它加入a集,并下次使用它来成为外边界 - // 如果不是,则为新边界,把它加入b集 - List alist = new List(); // 边界包含 - List blist = new List(); // 有另外的边界 - List> clist = new List>();// 边界集 - - using (Transaction tr = db.TransactionManager.StartTransaction()) - { - while (true) - { - for (int i = 0; i < bianjie.Length; i++) - { - Entity ent = bianjie[i].ObjectIdToEntity(false); - ent.UpgradeOpen(); - for (int j = i + 1; j < bianjie.Length; j++) - { - if (ent is Polyline polyline)// 多段线 - { - } - else if (ent is Circle circle) // 圆 - { - } - } - ent.DowngradeOpen(); - } - - if (blist.Count == 0)// 没有其他边界就结束循环 - { - break; - } - // 把blist的第一个用来作为新的外边界 - } - } - return objectIds; - } - - /// - /// 判断边界是否包含图元 布尔算法... - /// - /// 边界 - /// 包含的图元 - /// 是true,否false - public static bool BorderIntoCollect(this ObjectId border, ObjectId include) - { - bool flag = false; - Database db = border.Database; - using (Transaction tr = db.TransactionManager.StartTransaction()) - { - Entity ent = border.ObjectIdToEntity(false); - Entity ent2 = include.ObjectIdToEntity(false); - - if (ent is Polyline polyline)// 多段线边界 - { - if (ent2 is Polyline polyline2)// 多段线 - { - } - else if (ent2 is Circle circle2) // 圆 - { - // 判断圆心在多段线内 - if (circle2.Center.RayCasting(polyline.GetPolylinePoints()) != 3) - { - if (true)// 半径若大于多段线最长那段,表示包含不到,是圆包含了多段线(含有弧度就错了) - { - flag = true; - } - } - else // 圆心不在边界内,判断边界是否有交点 - { - } - } - } - else if (ent is Circle circle) // 圆边界 - { - if (ent2 is Polyline polyline2)// 多段线 - { - } - else if (ent2 is Circle circle2) // 圆 - { - // 填充边界不存在交集 - // 两个圆心的距离>两个圆的半径和=两圆分离 - double length = circle.Center.GetDistanceBetweenTwoPoint(circle2.Center); - if (length < circle.Radius + circle2.Radius) - { - flag = true; - } - } - } - return flag; - } - } -#endif -} \ No newline at end of file diff --git "a/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/\345\261\217\345\271\225\345\235\220\346\240\207\350\275\254cad\345\235\220\346\240\207.cs" "b/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/\345\261\217\345\271\225\345\235\220\346\240\207\350\275\254cad\345\235\220\346\240\207.cs" deleted file mode 100644 index 6c3d29d..0000000 --- "a/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/\345\261\217\345\271\225\345\235\220\346\240\207\350\275\254cad\345\235\220\346\240\207.cs" +++ /dev/null @@ -1,120 +0,0 @@ -//#define cpp -namespace JoinBoxAcad; - -using System.Drawing; -using static IFoxCAD.Basal.WindowsAPI; - -public partial class Screen -{ - [CommandMethod(nameof(GetScreenToCadxx))] - public static void GetScreenToCadxx() - { - var dm = Acap.DocumentManager; - var doc = dm.MdiActiveDocument; - var ed = doc.Editor; - var ucsPoint = GetScreenToCad(); - ed.WriteMessage(ucsPoint.ToString() + "\n"); - } - - /// - /// 屏幕坐标转cad坐标 - /// - public static Point3d GetScreenToCad() - { - // 两种获取方式都可以 - var cursorPos = System.Windows.Forms.Control.MousePosition; - // GetCursorPos(out Point cursorPos); - return ScreenToCad(cursorPos); - } - - /// - /// 屏幕像素点转cad图纸坐标点 - /// - /// 屏幕像素点 - /// 返回ucs的点 - public static Point3d ScreenToCad(Point cursorPos) - { - var dm = Acap.DocumentManager; - var doc = dm.MdiActiveDocument; - var ed = doc.Editor; - var mid = WindowsAPI.GetParent(doc.Window.Handle); - - ScreenToClient(mid, ref cursorPos); - var vn = ed.GetViewportNumber(cursorPos);// System.Windows.Forms.Control.MousePosition - var wcsPoint = ed.PointToWorld(cursorPos, vn); - var ucsPoint = wcsPoint.TransformBy(doc.Editor.CurrentUserCoordinateSystem.Inverse()); - return ucsPoint; - } - - /// - /// 屏幕坐标到客户区坐标转换 - /// - /// 窗口句柄 - /// 点结构,返回屏幕坐标 - /// - [DllImport("user32.dll")] - public static extern bool ScreenToClient(IntPtr hWnd, ref Point lpPoint); - [DllImport("user32.dll")] - static extern bool ClientToScreen(IntPtr hWnd, ref Point lpPoint); - - public static Point CadToScreen(Point3d pt3d, Point mousePosition) - { - var dm = Acap.DocumentManager; - var doc = dm.MdiActiveDocument; - var ed = doc.Editor; - var mid = WindowsAPI.GetParent(doc.Window.Handle); - - var vn = ed.GetViewportNumber(mousePosition);//System.Windows.Forms.Control.MousePosition - var ptScr = Env.Editor.PointToScreen(pt3d, vn);// 高版本这个不一样,转为客户区 - var ptScrWin = new Point((int)ptScr.X, (int)ptScr.Y); - ClientToScreen(mid, ref ptScrWin); - return ptScrWin; - } - - - - delegate IntPtr DelegateAcedGetAcadDwgview(); - static DelegateAcedGetAcadDwgview? acedGetAcadDwgView; - /// - /// 获取视口指针 - /// - public static IntPtr AcedGetAcadDwgview() - { - if (acedGetAcadDwgView is null) - { - acedGetAcadDwgView = AcadPeInfo - .GetDelegate( - nameof(acedGetAcadDwgView), AcadPeEnum.AcadExe); - } - if (acedGetAcadDwgView is not null) - return acedGetAcadDwgView.Invoke();// 调用方法 - return IntPtr.Zero; - } - - delegate int DelegateAcedGetWinNum(int x, int y); - static DelegateAcedGetWinNum? acedGetWinNum; - /// - /// 获取窗口数字 - /// - public static int AcedGetWinNum(int x, int y) - { - if (acedGetWinNum is null) - acedGetWinNum = AcadPeInfo - .GetDelegate( - nameof(acedGetWinNum), AcadPeEnum.ExeAndCore); - if (acedGetWinNum is not null) - return acedGetWinNum.Invoke(x, y);// 调用方法 - return 0; - } - - /// - /// 将坐标从绘图窗口转换为活动视口坐标系 - /// - /// - /// - /// - /// - - [DllImport("accore.dll", EntryPoint = "?acedCoordFromPixelToWorld@@YAHHVCPoint@@QEAN@Z")] - static extern int AcedCoordFromPixelToWorld(int windnum, Point pt, out Point3D ptOut); -} \ No newline at end of file diff --git "a/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/\350\277\207\347\250\213\346\226\207\344\273\266/\344\270\200\344\270\252\346\227\240\346\263\225\347\247\273\345\212\250\347\272\242\350\211\262\345\234\206\347\232\204\344\276\213\345\255\220.cs" "b/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/\350\277\207\347\250\213\346\226\207\344\273\266/\344\270\200\344\270\252\346\227\240\346\263\225\347\247\273\345\212\250\347\272\242\350\211\262\345\234\206\347\232\204\344\276\213\345\255\220.cs" deleted file mode 100644 index 4e45d21..0000000 --- "a/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/\350\277\207\347\250\213\346\226\207\344\273\266/\344\270\200\344\270\252\346\227\240\346\263\225\347\247\273\345\212\250\347\272\242\350\211\262\345\234\206\347\232\204\344\276\213\345\255\220.cs" +++ /dev/null @@ -1,94 +0,0 @@ -// 一个无法移动红色圆的例子 https://www.keanw.com/2008/08/rolling-back-th.html -#if true2 -namespace JoinBoxAcad; - -public class CmdReactor -{ - Document? _doc; - ObjectIdCollection _ids = new(); - Point3dCollection _pts = new(); - - [CommandMethod(nameof(Test_REACTOR))] - public void Test_REACTOR() - { - _doc = Acap.DocumentManager.MdiActiveDocument; - _doc.CommandWillStart += Doc_CommandWillStart; - } - - /// - /// 挂载一个命令反应器,如果出现了move就挂载一个 - /// - /// - /// - void Doc_CommandWillStart(object sender, CommandEventArgs e) - { - if (e.GlobalCommandName == "MOVE") - { - _ids.Clear(); - _pts.Clear(); - - if (_doc is null) - return; - _doc.Database.ObjectOpenedForModify += Db_ObjectOpenedForModify; - _doc.CommandCancelled += Doc_CommandEnded; - _doc.CommandEnded += Doc_CommandEnded; - _doc.CommandFailed += Doc_CommandEnded; - } - } - - /// - /// 卸载一堆反应器 - /// - void RemoveEventHandlers() - { - if (_doc is null) - return; - _doc.CommandCancelled -= Doc_CommandEnded; - _doc.CommandEnded -= Doc_CommandEnded; - _doc.CommandFailed -= Doc_CommandEnded; - _doc.Database.ObjectOpenedForModify -= Db_ObjectOpenedForModify; - } - - void Doc_CommandEnded(object sender, CommandEventArgs e) - { - // 在恢复位置之前删除数据库reactor - RemoveEventHandlers(); - RollbackLocations(); - } - - /// - /// 颜色是1的圆加入集合 - /// - /// - /// - void Db_ObjectOpenedForModify(object sender, ObjectEventArgs e) - { - if (e.DBObject is Circle circle && circle.ColorIndex == 1)// 如果颜色是1 - { - // 不含有就加入集合 - if (!_ids.Collection.Contains(circle.ObjectId)) - { - _ids.Add(circle.ObjectId); - _pts.Add(circle.Center); - } - } - } - - /// - /// 修改圆心 - /// - void RollbackLocations() - { - Debug.Assert(_ids.Count == _pts.Count, "预计相同数量的ID和位置"); - _doc?.Database.Action(tr => { - int i = 0; - foreach (ObjectId id in _ids.Collection) - { - var circle = tr.GetObject(id, OpenMode.ForWrite) as Circle; - if (circle is not null) - circle.Center = _pts[i++]; - } - }); - } -} -#endif \ No newline at end of file diff --git "a/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/\350\277\207\347\250\213\346\226\207\344\273\266/\350\207\252\345\256\232\344\271\211\345\233\276\345\205\203\345\241\253\345\205\205\350\276\271\347\225\214.txt" "b/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/\350\277\207\347\250\213\346\226\207\344\273\266/\350\207\252\345\256\232\344\271\211\345\233\276\345\205\203\345\241\253\345\205\205\350\276\271\347\225\214.txt" deleted file mode 100644 index 50ccab0..0000000 --- "a/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/\350\277\207\347\250\213\346\226\207\344\273\266/\350\207\252\345\256\232\344\271\211\345\233\276\345\205\203\345\241\253\345\205\205\350\276\271\347\225\214.txt" +++ /dev/null @@ -1,104 +0,0 @@ -拉伸填充bug: -1号: 不闭合的多段线,新建边界会丢失一个不和头点重叠的倒数第二个点. -与头点重叠是ok的 -闭合是ok的 -解决:因为倒数第二个点要从 curve.EndPoint 获取. - -2号: -如果画了一个矩形,然后填充,再删除边界,再点选填充,那么通过生成出来关联标注, -移动第一个点的时候,是没有响应的,移动第二次的时候才会响应. - -两种想法解决这个问题, -a:生成之后,用移动矩阵影响一下关联反应器. - 答:不会触发的,即使我分成两个事务分别提交. -b:先克隆一个填充,再创建关联边界. - 答:可行的,但是会导致3号问题的发生. - -3号: -由于我是生成填充的,所以在在位编辑的时候会在长事务内部: - -【贵妃】惊惊 2019/7/13 17:52:02 -我遇到了一个问题,如果是在位编辑的时候,当前空间是模型空间,那么我用函数克隆一个块外的东西到模型空间,实际上会克隆到在位编辑的内部... -我都不知道怎么处理这个情况了..莫非要关闭用户的在位编辑状态么.. - -【才人】edata 2019/7/13 17:57:15 -在位编辑是这样的. - -【贵妃】惊惊 2019/7/13 17:58:08 -那桌子是怎么控制在位编辑-减出去块外的? - -【才人】edata 2019/7/13 17:58:20 -在位编辑实际上是对当前空间的修改,然后移动回块定义.. - -【才人】edata 2019/7/13 17:58:44 -这个就不是很清楚了... - -【贵妃】惊惊 2019/7/13 17:58:47 -也就是长事务上面记录了要移动回去的id? -如果减选了就是剔除了id? - -【才人】edata 2019/7/13 17:59:27 -你能卡到这个长事务吗? - -【贵妃】惊惊 2019/7/13 17:59:39 -net貌似无法控制长事务呀 -应该桌子有考虑到的,只是我还没有挖出来具体怎么处理的.. - -【才人】edata 2019/7/13 18:08:59 -用命令去移除当前在位编辑. - -我用了命令去移除块外的填充和边界,这样操作是可行的, -然后又产生了一个问题,如果是块内的填充,我并不想减去. -想法: 用命令反应器在在位编辑前获取当前空间所有的图元,然后在位编辑时候就知道两个集合的交叉部分了 -答:证明是可以分类出来的,但是会引起一个问题,在位编辑复制的填充id不在任何一个表上. - -判断执行的时候不是选择前的填充均执行产生边界(这样就不用复制反应器了 -再检测命令 _refset 加减三个集合的填充 -但是命令反应器无法检测二级命令,只能通过 lastprompt 获取最后一行命令,判断添加或者删除 - -命令完成后,执行选择上次选择,便是_refset命令的选择 -然后把id改成加减到判断的两个集合中 - - - - - -U 大写命令,用户回滚的时会导致集合信息不符: -之前koz找到的方法,先选择在位编辑命令触发时的所有图元,再选择触发后的所有图元,分别建立两个集合储存,然后进行差集运算, -得出那些是块内图元,这个方法是可行的,然后我发现在使用+加入块内和-减出块内这也都可以判断, -问题就是....如果是使用了U回滚,那么我将不知道如何修改这两个集合.... - -检测在位编辑命令启动之后,而无结束命令的时候, -期间如果用户使用了u就提示用户是否禁止拉伸填充. - -挂载一个图元的反应器,如果使用了命令U,那么判断填充是否被更改了-> ObjectOpenedForModify 反应器 -如果更改了,更改方式无法知道?? 可能是改颜色,也可能是会在块内外加减操作更改. -无解决方案! - - - -拉伸非圆的时候,如果中心移动,那么边界不会跟随 -发生了拉伸命令的时候, -答: 选择的对象有填充,就克隆填充,并且删除原有的边界,及填充 - - - - -频闪控制 -grips=0 - - - - -编辑填充 -样条曲线边界生成 - -在cad2008设计一条填充边界 -填充边界的自定义图元名称叫做: HatchBoundary -设定HatchBoundary变量,0为使用,1为不使用边界 -想法破产:不会自定义图元. - - - -在位编辑的锁定图元的方法,该不是一个隐藏图层导致的吧. -不是,但是在位编辑的时候出现了一个图层 0-RefEdit0 \ No newline at end of file diff --git "a/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/\350\277\207\347\250\213\346\226\207\344\273\266/\350\216\267\345\217\226\345\244\271\347\202\271\344\276\213\345\255\220.cs" "b/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/\350\277\207\347\250\213\346\226\207\344\273\266/\350\216\267\345\217\226\345\244\271\347\202\271\344\276\213\345\255\220.cs" deleted file mode 100644 index 7aad795..0000000 --- "a/tests/TestAcad09plus/\346\213\211\344\274\270\345\241\253\345\205\205/\350\277\207\347\250\213\346\226\207\344\273\266/\350\216\267\345\217\226\345\244\271\347\202\271\344\276\213\345\255\220.cs" +++ /dev/null @@ -1,99 +0,0 @@ - -namespace GripOverruleTest; - -// https://through-the-interface.typepad.com/through_the_interface/2009/08/knowing-when-an-autocad-object-is-grip-edited-using-overrules-in-net.html -public class GripVectorOverrule : GripOverrule -{ - // A static pointer to our overrule instance - static public GripVectorOverrule theOverrule = new(); - // A flag to indicate whether we're overruling - static bool overruling = false; - // A single set of grips would not have worked in - // the case where multiple objects were selected. - static Dictionary _gripDict = new(); - - private string GetKey(Entity e) - { - // Generate a key based on the name of the object's type - // and its geometric extents - // (We cannot use the ObjectId, as this is null during - // grip-stretch operations.) - return e.GetType().Name + ":" + e.GeometricExtents.ToString(); - } - // Save the locations of the grips for a particular entity - private void StoreGripInfo(Entity e, Point3dCollection grips) - { - string key = GetKey(e); - if (_gripDict.ContainsKey(key)) - { - // Clear the grips if any already associated - Point3dCollection grps = _gripDict[key]; - using (grps) - grps.Clear(); - _gripDict.Remove(key); - } - // Now we add our grips - Point3d[] pts = new Point3d[grips.Count]; - grips.CopyTo(pts, 0); - Point3dCollection gps = new(pts); - _gripDict.Add(key, gps); - } - // Get the locations of the grips for an entity - private Point3dCollection? RetrieveGripInfo(Entity e) - { - Point3dCollection? grips = null; - string key = GetKey(e); - if (_gripDict.ContainsKey(key)) - grips = _gripDict[key]; - return grips; - } - public override void GetGripPoints(Entity e, Point3dCollection grips, IntegerCollection snaps, IntegerCollection geomIds) - { - base.GetGripPoints(e, grips, snaps, geomIds); - StoreGripInfo(e, grips); - } - public override void MoveGripPointsAt(Entity e, IntegerCollection indices, Vector3d offset) - { - var dm = Acap.DocumentManager; - var doc = dm.MdiActiveDocument; - var ed = doc.Editor; - - var grips = RetrieveGripInfo(e); - if (grips != null) - { - // Could get multiple points moved at once, - // hence the integer collection - foreach (int i in indices) - { - // Get the grip point from our internal state - Point3d pt = grips[i]; - // Draw a vector from the grip point to the newly - // offset location, using the index into the - // grip array as the color (excluding colours 0 and 7). - // These vectors don't getting cleared, which makes - // for a fun effect. - ed.DrawVector( - pt, - pt + offset, - (i >= 6 ? i + 2 : i + 1), // exclude colours 0 and 7 - false - ); - } - } - base.MoveGripPointsAt(e, indices, offset); - } - [CommandMethod(nameof(GripOverruleOnOff))] - public static void GripOverruleOnOff() - { - var dm = Acap.DocumentManager; - var doc = dm.MdiActiveDocument; - var ed = doc.Editor; - if (overruling) - RemoveOverrule(GetClass(typeof(Entity)), theOverrule); - else - AddOverrule(GetClass(typeof(Entity)), theOverrule, true); - overruling = !overruling; - Overruling = overruling; - ed.WriteMessage("\nGrip overruling turned {0}.", overruling ? "on" : "off"); - } -} \ No newline at end of file diff --git a/tests/TestConsole/GlobalUsings.cs b/tests/TestConsole/GlobalUsings.cs deleted file mode 100644 index 87d3183..0000000 --- a/tests/TestConsole/GlobalUsings.cs +++ /dev/null @@ -1,15 +0,0 @@ -/// 系统引用 -global using System; -global using System.Collections; -global using System.Collections.Generic; -global using System.Linq; -global using System.Text; -global using Microsoft.Win32; -global using System.ComponentModel; -global using System.Runtime.CompilerServices; -global using System.Runtime.InteropServices; -global using System.Diagnostics; -global using System.Threading; -global using System.Linq.Expressions; -global using System.Collections.ObjectModel; -global using System.Diagnostics.CodeAnalysis; diff --git a/tests/TestConsole/Info.cs b/tests/TestConsole/Info.cs deleted file mode 100644 index 7c41b71..0000000 --- a/tests/TestConsole/Info.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System.Runtime.InteropServices; - -namespace TestConsole; - -[Flags] -public enum PlugIn -{ - [Description("惊惊")] - JoinBox = 1, - [Description("源泉")] - YuanQuan = 2, - [Description("迷你")] - IMinCad = 4, - - Lisp = JoinBox | YuanQuan | IMinCad, - - DOCBAR = 8, - DUOTAB = 16, - - All = Lisp | DOCBAR | DUOTAB -} - - -[Flags] -public enum PlugIn2 -{ - [Description("惊惊")] - JoinBox = 1, - [Description("源泉")] - YuanQuan = 2, - [Description("迷你")] - IMinCad = 4, - - [Description("*Lisp*")] - Lisp = JoinBox | YuanQuan | IMinCad, - - DOCBAR = 8, - DUOTAB = 16, - - // all == *Lisp*|DOCBAR|DUOTAB - // 采取的行为是:注释的行为是特殊的,就按照注释的,否则,遍历子元素提取注释 - All = Lisp | DOCBAR | DUOTAB -} \ No newline at end of file diff --git a/tests/TestConsole/Program.cs b/tests/TestConsole/Program.cs deleted file mode 100644 index 74ce9d7..0000000 --- a/tests/TestConsole/Program.cs +++ /dev/null @@ -1,218 +0,0 @@ -// See https://aka.ms/new-console-template for more information -using System; -using System.Runtime.InteropServices; -using System.Runtime.Serialization.Formatters.Binary; -using System.Text; -using TestConsole; -using System; -using System.Collections.Generic; -using System.Text; -using System.Diagnostics; -using CalculatorDemo; - -Console.WriteLine("release"); - -var a = new PointA(); -var b = new PointB(); - -CalculatorDemo.Program.TestTimes2(1000000, "PointA:", (i) => -{ - a.X = i * 0.1; - a.Y = i * 0.1; -}); -CalculatorDemo.Program.TestTimes2(1000000, "PointB:", (i) => -{ - b.X = i * 0.1; - b.Y = i * 0.1; -}); - -#if true -namespace CalculatorDemo -{ - public class PointA - { - public double X; - public double Y; - } - public class PointB - { - public double X { set; get; } - public double Y { set; get; } - } - - class Program - { - static void Main(string[] args) - { -#if false - int nResult = AddTwoNumbers(10, 20); - Console.WriteLine(nResult); - - AddTwoNumbers22((a, b) => { - Console.WriteLine(a + b); - }); - - var a = new int[] { 1, 2, 3, 4, 5, 6, 78, 9, 92, }; - a.ForEach(a => { - Console.WriteLine(a); - }); -#endif - - var aa = new int[] { 1, 2, 3, 4, 5, 6, 78, 9, 92, }; - Console.WriteLine(aa[1..^2]); - - - - } - - private static int addtuple((int ,int ) b) - { - return b.Item1 + b.Item2; - } - - - [DebuggerHidden] - private static int AddTwoNumbers(int nNum1, int nNum2) - { - return Add(nNum1, nNum2); - } - private static int Add(int op1, int op2) - { - return op1 + op2; - } - - [DebuggerHidden] - private static void AddTwoNumbers22(Action action) - { - action(10, 20); - } - - public static void TestTimes2(int count, string message, Action action) - { - System.Diagnostics.Stopwatch watch = new(); - watch.Start(); // 开始监视代码运行时间 - for (int i = 0; i < count; i++) - action.Invoke(i);// 需要测试的代码 - watch.Stop(); // 停止监视 - TimeSpan timespan = watch.Elapsed; // 获取当前实例测量得出的总时间 - double time = timespan.TotalMilliseconds; - string name = "毫秒"; - if (timespan.TotalMilliseconds > 1000) - { - time = timespan.TotalSeconds; - name = "秒"; - } - Console.WriteLine($"{message} 代码执行 {count} 次的时间:{time} ({name})"); // 总毫秒数 - } - } - - public static class Fors - { - /// - /// 遍历集合,执行委托 - /// - /// 集合值的类型 - /// 集合 - /// 委托 - [DebuggerHidden] - public static void ForEach(this IEnumerable source, Action action) - { - foreach (var element in source) - { - action.Invoke(element); - } - } - } -} -#endif - -#if true2 - -Console.WriteLine("***************************************************"); - - -List list = new List(); -list.Add(1); -list.Add(2); -list.Add(3); -list.Add(4); -list.Add(5); -list.ForEach((x, loop) => { - if (x == 3) - loop.Break(); - Console.WriteLine(x); -}); - - - -// 乱序 -Console.WriteLine(PlugIn.JoinBox.PrintNote()); -Console.WriteLine(PlugIn.Lisp.PrintNote());// 这里先交换顺序来试试能不能成功 -Console.WriteLine(PlugIn.IMinCad.PrintNote()); -Console.WriteLine(PlugIn.YuanQuan.PrintNote()); -Console.WriteLine(PlugIn.All.PrintNote()); -Console.WriteLine(PlugIn.DOCBAR.PrintNote()); -Console.WriteLine(PlugIn.DUOTAB.PrintNote()); -Console.WriteLine("***************************************************"); -// 乱序2 -Console.WriteLine(PlugIn2.JoinBox.PrintNote()); -Console.WriteLine(PlugIn2.Lisp.PrintNote());// 这里先交换顺序来试试能不能成功 -Console.WriteLine(PlugIn2.IMinCad.PrintNote()); -Console.WriteLine(PlugIn2.YuanQuan.PrintNote()); -Console.WriteLine(PlugIn2.All.PrintNote()); -Console.WriteLine(PlugIn2.DOCBAR.PrintNote()); -Console.WriteLine(PlugIn2.DUOTAB.PrintNote()); - -EnumEx.CleanCache(); - -// 表达式树例子 -TestConsole.Test_Expression.Demo3(); -// TestConsole.Test_Expression.Demo1(); - -#region 元组测试 -var valuetuple = (1, 2); - -Console.WriteLine(valuetuple.ToString()); - -int[] someArray = new int[5] { 1, 2, 3, 4, 5 }; -int lastElement = someArray[^1]; // lastElement = 5 -Console.WriteLine(lastElement); -int midElement = someArray[^3]; -Console.WriteLine(midElement); -var range = someArray[1..3]; -foreach (var item in range) - Console.WriteLine(item); -#endregion - -Console.ReadLine(); - - -#region 测试遍历枚举 -// Season a = Season.Autumn; -// Console.WriteLine($"Integral value of {a} is {(int)a}"); // output: Integral value of Autumn is 2 -// foreach (var enumItem in Enum.GetValues(typeof(Season))) -// Console.WriteLine((byte)enumItem); - -var sb = new StringBuilder(); -/*因为 net framework 没写好的原因,导致直接使用迭代器反而更慢,到了NET60就迭代器比foreach更快*/ -var enums = Enum.GetValues(typeof(Season)).GetEnumerator(); -while (enums.MoveNext()) -{ - sb.Append(((byte)enums.Current).ToString()); - sb.Append(","); -} -Console.WriteLine(sb); - -sb.Remove(sb.Length - 1, 1);// 剔除末尾, -// 因为有返回值所以容易理解成 sb = sb.Remove(sb.Length - 1, 1); -Console.WriteLine(sb); - -public enum Season : byte -{ - Spring, - Summer, - Autumn, - Winter -} -#endregion -#endif \ No newline at end of file diff --git a/tests/TestConsole/RuntimeHelpers.cs b/tests/TestConsole/RuntimeHelpers.cs deleted file mode 100644 index fb91a15..0000000 --- a/tests/TestConsole/RuntimeHelpers.cs +++ /dev/null @@ -1,47 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -// 如果要用range的语法比如 a[1..3],那么需要将本文件复制到你的项目里 -#if true -namespace System.Runtime.CompilerServices -{ - internal static class RuntimeHelpers - { - /// - /// Slices the specified array using the specified range. - /// - public static T[] GetSubArray(T[] array, Range range) - { - if (array == null) - { - throw new ArgumentNullException(); - } - - (int offset, int length) = range.GetOffsetAndLength(array.Length); - - if (default(T)! != null || typeof(T[]) == array.GetType()) // NULLABLE: default(T) == null warning (https://github.com/dotnet/roslyn/issues/34757) - { - // We know the type of the array to be exactly T[]. - - if (length == 0) - { - // return Array.Empty(); - return new T[0]; - } - - var dest = new T[length]; - Array.Copy(array, offset, dest, 0, length); - return dest; - } - else - { - // The array is actually a U[] where U:T. - T[] dest = (T[])Array.CreateInstance(array.GetType().GetElementType()!, length); - Array.Copy(array, offset, dest, 0, length); - return dest; - } - } - } -} -#endif \ No newline at end of file diff --git a/tests/TestConsole/TestConsole.csproj b/tests/TestConsole/TestConsole.csproj deleted file mode 100644 index c1b52da..0000000 --- a/tests/TestConsole/TestConsole.csproj +++ /dev/null @@ -1,22 +0,0 @@ - - - - preview - enable - - Exe - NET48 - enable - preview - - - - - - - - - - - - diff --git a/tests/TestConsole/TestSerialize.cs b/tests/TestConsole/TestSerialize.cs deleted file mode 100644 index 413764d..0000000 --- a/tests/TestConsole/TestSerialize.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System.Runtime.Serialization; - -namespace TestConsole; - -[Serializable] -public struct StructDemo -{ - public char[] Chars1; - public char[] Chars2; -} - -[Serializable] -public struct StructDemo2 : ISerializable -{ - public char[] Chars1; - public char[] Chars2; - - public void GetObjectData(SerializationInfo info, StreamingContext context) - { - info.AddValue("i", Chars1); - info.AddValue("j", Chars2); - } -} - -// 二进制序列化,存在元数据 -//{ -// StructDemo structDemo = new(); -// structDemo.Chars1 = "aaa".ToCharArray(); -// structDemo.Chars2 = "bbb".ToCharArray(); - -// using MemoryStream stream = new(); -// BinaryFormatter formatter = new(); -// formatter.Serialize(stream, structDemo); -// var str = Encoding.ASCII.GetString(stream.ToArray()); -// Console.WriteLine(str); -//} - -//{ -// StructDemo2 structDemo = new(); -// structDemo.Chars1 = "aaa".ToCharArray(); -// structDemo.Chars2 = "bbb".ToCharArray(); - -// using MemoryStream stream = new(); -// BinaryFormatter formatter = new(); -// formatter.Serialize(stream, structDemo); -// var str = Encoding.ASCII.GetString(stream.ToArray()); -// Console.WriteLine(str); -//} \ No newline at end of file diff --git "a/tests/TestConsole/\350\241\250\350\276\276\345\274\217\346\240\221.cs" "b/tests/TestConsole/\350\241\250\350\276\276\345\274\217\346\240\221.cs" deleted file mode 100644 index 4c706dd..0000000 --- "a/tests/TestConsole/\350\241\250\350\276\276\345\274\217\346\240\221.cs" +++ /dev/null @@ -1,142 +0,0 @@ -namespace TestConsole; - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Linq.Expressions; - -/// -/// 表达式树 -/// MSDN链接 -/// -public class Test_Expression -{ - public static void Demo1() - { - // 官方例子:表达式体内只有一个式子 - // 创建表达式树 - Expression> exprTree = num => num < 5; - - // 分解表达式树 - ParameterExpression param = exprTree.Parameters[0];// num - BinaryExpression operation = (BinaryExpression)exprTree.Body;// 函数体 {(num < 5)} - ParameterExpression left = (ParameterExpression)operation.Left;// 左节点 num - ConstantExpression right = (ConstantExpression)operation.Right;// 右表达式 5 - - Console.WriteLine("表达式树例子: {0} => {1} {2} {3}", - param.Name, left.Name, operation.NodeType, right.Value); - Console.Read(); - } - - - public static void Demo2() - { - // 这里是会报错的!! 原因就是体内有多个例子需要分解!! - // Expression> exprTree = x => x > 5 && x < 50; - // - // // 分解表达式树 - // ParameterExpression param = exprTree.Parameters[0];// x - // BinaryExpression operation = (BinaryExpression)exprTree.Body;// 函数体 {((x > 5) AndAlso (x < 50))} - // - // ParameterExpression left = (ParameterExpression)operation.Left;// 左节点.......这里报错 - // ConstantExpression right = (ConstantExpression)operation.Right;// 右表达式.....这里报错 - // - // Console.WriteLine("表达式树例子: {0} => {1} {2} {3}", - // param.Name, left.Name, operation.NodeType, right.Value); - } - - - // 博客园例子,表达式体内有多个式子 - public static void Demo3() - { - List names = new() { "Cai", "Edward", "Beauty" }; - - Console.WriteLine("******************一个表达式"); - Expression> lambda2 = name => name.Length > 2 && name.Length < 4; - var method2 = ReBuildExpression(lambda2); - var query2 = names.Where(method2); - foreach (string n in query2) - Console.WriteLine(n); - - Console.WriteLine("******************二个表达式"); - Expression> lambda0 = item => item.Length > 2; - Expression> lambda1 = item => item.Length < 4; - var method = ReBuildExpression(lambda0, lambda1); - var query = names.Where(method); - foreach (string n in query) - Console.WriteLine(n); - Console.WriteLine("******************表达式结束"); - Console.Read(); - } - - - static Func ReBuildExpression(Expression> lambda) - { - MyExpressionVisitor my = new() - { - Parameter = Expression.Parameter(typeof(string), "name") - }; - - Expression left = my.Modify(lambda.Body); - // 构造一个新的表达式 - var newLambda = Expression.Lambda>(left, my.Parameter); - return newLambda.Compile(); - } - - - - /// - /// 重构表达式_合并 - /// - /// 匿名函数表达式1 - /// 匿名函数表达式2 - /// - static Func ReBuildExpression(Expression> lambda0, - Expression> lambda1) - { - MyExpressionVisitor my = new() - { - Parameter = Expression.Parameter(typeof(string), "name") - }; - - Expression left = my.Modify(lambda0.Body); - Expression right = my.Modify(lambda1.Body); - var expression = Expression.AndAlso(left, right);// 就是 && 合并两个匿名函数 - - // 构造一个新的表达式 - var newLambda = Expression.Lambda>(expression, my.Parameter); - return newLambda.Compile(); - } -} - - -/// -/// 表达式参数分解 -/// 博客园链接 -/// -public class MyExpressionVisitor : ExpressionVisitor -{ - /// - /// 公共参数 - /// - public ParameterExpression? Parameter; - /// - /// 返回替换后的参数表达式 - /// - /// - /// - public Expression Modify(Expression exp) - { - return Visit(exp); - } - /// - /// 重写参数 - /// - /// - /// - protected override Expression? VisitParameter(ParameterExpression p) - { - return Parameter; - } -} diff --git a/tests/TestGcad2024/GlobalUsings.cs b/tests/TestGcad2024/GlobalUsings.cs deleted file mode 100644 index a4bf204..0000000 --- a/tests/TestGcad2024/GlobalUsings.cs +++ /dev/null @@ -1,49 +0,0 @@ -/// 系统引用 -global using System; -global using System.Collections; -global using System.Collections.Generic; -global using System.IO; -global using System.Linq; -global using System.Text; -global using System.Reflection; -global using System.Text.RegularExpressions; -global using Microsoft.Win32; -global using System.ComponentModel; -global using System.Runtime.InteropServices; -global using System.Collections.Specialized; - -global using Exception = System.Exception; - -global using Registry = Microsoft.Win32.Registry; -global using RegistryKey = Microsoft.Win32.RegistryKey; - -/// autocad 引用 -global using Gssoft.Gscad.ApplicationServices; -global using Gssoft.Gscad.EditorInput; -global using Gssoft.Gscad.Colors; -global using Gssoft.Gscad.DatabaseServices; -global using Gssoft.Gscad.Geometry; -global using Gssoft.Gscad.Runtime; -global using Acap = Gssoft.Gscad.ApplicationServices.Application; -global using Acaop = Gssoft.Gscad.ApplicationServices.Core.Application; -global using Acgi = Gssoft.Gscad.GraphicsInterface; - -global using Gssoft.Gscad.DatabaseServices.Filters; -global using Gssoft.Gscad; - -// jig命名空间会引起Viewport/Polyline等等重义,最好逐个引入 using Gssoft.Gscad.GraphicsInterface -global using WorldDraw = Gssoft.Gscad.GraphicsInterface.WorldDraw; -global using Manager = Gssoft.Gscad.GraphicsSystem.Manager; -global using Group = Gssoft.Gscad.DatabaseServices.Group; -global using Viewport = Gssoft.Gscad.DatabaseServices.Viewport; -global using Gssoft.Gscad.GraphicsInterface; -global using Polyline = Gssoft.Gscad.DatabaseServices.Polyline; -global using Cad_DwgFiler = Gssoft.Gscad.DatabaseServices.DwgFiler; -global using Cad_DxfFiler = Gssoft.Gscad.DatabaseServices.DxfFiler; -global using Cad_ErrorStatus = Gssoft.Gscad.Runtime.ErrorStatus; - - -/// ifoxcad -global using IFoxCAD.Cad; -global using IFoxCAD.Basal; - diff --git a/tests/TestGcad2024/TestGcad2024.csproj b/tests/TestGcad2024/TestGcad2024.csproj deleted file mode 100644 index 5336ff6..0000000 --- a/tests/TestGcad2024/TestGcad2024.csproj +++ /dev/null @@ -1,29 +0,0 @@ - - - preview - enable - - NET48 - true - true - x64 - True - - - - $(Configuration);gcad - - - - - - - - - - - - - - - diff --git a/tests/TestShared/CmdINI.cs b/tests/TestShared/CmdINI.cs deleted file mode 100644 index c296a56..0000000 --- a/tests/TestShared/CmdINI.cs +++ /dev/null @@ -1,189 +0,0 @@ -//#define givePeopleTest -#if false -using System.Diagnostics; - -namespace Test; - -/// -/// 注册中心(自动执行接口): -/// -/// 继承虚函数后才能使用
-/// 0x01 netload加载之后自动执行,写入启动注册表,下次就不需要netload了
-/// 0x02 反射调用特性和接口
-/// 启动cad后的执行顺序为:
-/// 1:构造函数
-/// 2:特性..多个
-/// 3:接口..多个
-/// 4:本类的构造函数
-/// -/// **** 警告 **** -/// 如果不写一个 储存这个对象, -/// 而是直接写卸载命令在此, -/// 第一次加载的时候会初始化完成,然后这个类生命就结束了, -/// 第二次通过命令进入,会引发构造函数再次执行,留意构造函数的打印信息即可发现 -/// -///
-///
-public class AutoRegAssemEx : AutoRegAssem -{ - public AutoRegAssemEx() : base(AutoRegConfig.All) - { - CmdInit.AutoRegAssemEx = this; -#if givePeopleTest -#if Debug - // 此处用来反射本程序集,检查是否存在重复命令 - AutoReflection.DebugCheckCmdRecurrence(); -#endif - Env.Printl($"{nameof(AutoRegAssemEx)}构造函数,开始自动执行\r\n"); -#endif - } -} - - -public class CmdInit -{ - public static AutoRegAssemEx? AutoRegAssemEx; - - /// 如果netload之后用 删除注册表, - /// 由于不是也不能卸载dll,再netload是无法执行自动接口的, - /// 所以此时会产生无法再注册的问题...因此需要暴露此注册函数(硬来) - [CommandMethod(nameof(IFoxAddReg))] - public void IFoxAddReg() - { - Env.Printl($"加入注册表"); - - AutoRegAssemEx ??= new(); - AutoRegAssemEx.RegApp(); - } - - /// - /// 卸载注册表信息 - /// - [CommandMethod(nameof(IFoxRemoveReg))] - public void IFoxRemoveReg() - { - Env.Printl($"卸载注册表"); - - // 防止卸载两次,不然会报错的 - AutoRegAssemEx?.UnRegApp(); - AutoRegAssemEx = null; - } - - [CommandMethod(nameof(Debugx))] - public void Debugx() - { - var flag = Environment.GetEnvironmentVariable("debugx", EnvironmentVariableTarget.User); - if (flag == null || flag == "0") - { - Environment.SetEnvironmentVariable("debugx", "1", EnvironmentVariableTarget.User); - Env.Printl($"vs输出 -- 已启用"); - } - else - { - Environment.SetEnvironmentVariable("debugx", "0", EnvironmentVariableTarget.User); - Env.Printl($"vs输出 -- 已禁用"); - } - } -} - -#if givePeopleTest -/* - * 自动执行:特性 - */ -public class Cmd_IFoxInitialize -{ - int TestInt = 0; - - [IFoxInitialize] - public void Initialize() - { - Env.Printl($"开始自动执行,可以分开多个类和多个函数:{nameof(Cmd_IFoxInitialize)}.{nameof(Initialize)}+{TestInt}"); - } - - [IFoxInitialize] - public void Initialize2() - { - Env.Printl($"开始自动执行,可以分开多个类和多个函数,又一次测试:{nameof(Cmd_IFoxInitialize)}.{nameof(Initialize2)}"); - } - - //[IFoxInitialize(isInitialize: false)] - //public void Terminate() - //{ - // try - // { - // // 注意此时编辑器已经回收,所以此句引发错误 - // // 您可以写一些其他的释放动作,例如资源回收之类的 - // Env.Printl($"\n 结束自动执行 Terminate \r\n"); - // // 改用 - // Debugx.Printl($"\n 结束自动执行 Terminate \r\n"); - // } - // catch (System.Exception e) - // { - // System.Windows.Forms.MessageBox.Show(e.Message); - // } - //} - - [IFoxInitialize] - public static void StaticInitialize() - { - Env.Printl($"开始自动执行,静态调用:{nameof(Cmd_IFoxInitialize)}.{nameof(StaticInitialize)}"); - } -} - - -/* - * 自动执行:接口 - */ -public class Cmd_IFoxInitializeInterface : IFoxAutoGo -{ - int TestInt = 0; - public Cmd_IFoxInitializeInterface() - { - Env.Printl($"开始自动执行,{nameof(IFoxAutoGo)}接口调用:{nameof(Cmd_IFoxInitializeInterface)}::{TestInt}"); - } - - public Sequence SequenceId() - { - return Sequence.Last; - } - - public void Initialize() - { - Env.Printl($"开始自动执行,{nameof(IFoxAutoGo)}接口调用:{nameof(Initialize)}::{TestInt}"); - } - - public void Terminate() - { - Debugx.Printl($"开始自动执行,{nameof(IFoxAutoGo)}接口调用:{nameof(Terminate)}::{TestInt}"); - // try - // { - // // 注意此时编辑器已经回收,所以此句没用,并引发错误 - // Env.Printl($"结束自动执行 {nameof(Cmd_IFoxInitializeInterface)}.Terminate \r\n"); - // } - // catch (System.Exception e) - // { - // System.Windows.Forms.MessageBox.Show(e.Message); - // } - } -} -#endif - - -public class Init : AutoLoad -{ - public override void Initialize() - { - - Env.Print("loading..."); - // 将程序的目录加入信任路径 - // Env.AppendSupportPath(CurrentDirectory.FullName); - } - - public override void Terminate() - { - // 这里不能调用输出函数,因为这个函数执行的时候,已经没有editor对象了。 - // 所以如果不是想要在cad关闭的时候清理某些东西,这里不用写任何的代码。 - - } -} -#endif \ No newline at end of file diff --git a/tests/TestShared/Copyclip.cs b/tests/TestShared/Copyclip.cs deleted file mode 100644 index 96aaf81..0000000 --- a/tests/TestShared/Copyclip.cs +++ /dev/null @@ -1,879 +0,0 @@ -#define test -#define COPYCLIP -#define PASTECLIP - -namespace Test; -using System; -using System.Diagnostics; -using System.Drawing.Imaging; -using System.Threading; -using System.Windows; - -/* - * 0x01 (已完成) - * 跨cad复制,由于高版本会保存为当前dwg格式,所以我们将所有都保存为07格式(有动态块), - * 就可以多个版本cad相互复制粘贴了 - * - * 0x02 - * 设置一个粘贴板栈,用tmp.config储存(路径和粘贴基点), - * ctrl+shfit+v v v 就是三次前的剪贴板内容;也可以制作一个剪贴板窗口更好给用户交互 - * - * 0x03 - * 天正图元的复制粘贴出错原因 - * - * 引用技术贴: - * https://forums.autodesk.com/t5/net/paste-list-of-objects-from-clipboard-on-dwg-file-using-c-net/td-p/6797606 - */ -public class Copyclip -{ - #region 命令 -#if test - static bool _IsRunIFoxCopyClip = false; - [IFoxInitialize] // 惊惊: 遇到了高版本无法导出WMF,放弃此功能,等待有缘人 - public void Init() - { - Acap.DocumentManager.DocumentLockModeChanged += Dm_VetoCommand; - Env.Printl($"※剪贴板控制※\n{nameof(Copyclip_Switch)} - 切换开关\n"); - } - - [CommandMethod(nameof(Copyclip_Switch))] - public void Copyclip_Switch() - { - _IsRunIFoxCopyClip = !_IsRunIFoxCopyClip; - Env.Printl("已经 " + (_IsRunIFoxCopyClip ? "开启" : "禁用") + " 剪贴板+"); - } - - /// - /// 反应器->命令否决触发命令前(不可锁文档) - /// - /// - /// - void Dm_VetoCommand(object sender, DocumentLockModeChangedEventArgs e) - { - if (string.IsNullOrEmpty(e.GlobalCommandName) || e.GlobalCommandName == "#") - return; - if (!_IsRunIFoxCopyClip) - return; - - var up = e.GlobalCommandName.ToUpper(); - - string? cmd = null; -#if COPYCLIP - if (up == "COPYCLIP")// 复制 - { - e.Veto(); - cmd = nameof(IFoxCopyClip); - } - else if (up == "COPYBASE") //ctrl+shift+c 带基点复制 - { - e.Veto(); - cmd = nameof(IFoxCopyBase); - } - else if (up == "CUTCLIP") // 剪切 - { - e.Veto(); - cmd = nameof(IFoxCutclip); - } -#endif -#if PASTECLIP - if (up == "PASTECLIP")// 粘贴 - { - // === 完成之后此处将会移除 - // 粘贴文本的生成单行文字/多行文字,这些还需要自己去实现 - var getClip = ClipTool.GetClipboard(ClipboardEnv.CadVer, out TagClipboardInfo tag); - if (!getClip) - return; - //=== 完成之后此处将会移除 - - e.Veto(); - cmd = nameof(IFoxPasteClip); - } - else if (up == "PASTEBLOCK") //ctrl+shift+v 粘贴为块 - { - // === 完成之后此处将会移除 - var getClip = ClipTool.GetClipboard(ClipboardEnv.CadVer, out TagClipboardInfo tag); - if (!getClip) - return; - //=== 完成之后此处将会移除 - - e.Veto(); - cmd = nameof(IFoxPasteBlock); - } -#endif - if (cmd != null) - { - var dm = Acap.DocumentManager; - if (dm.Count == 0) - return; - var doc = dm.MdiActiveDocument; - // 发送命令是因为com导出WMF需要命令形式,否则将报错 - // 但是发送命令会导致选择集被取消了,那么就需要设置 CommandFlags.Redraw - doc.SendStringToExecute(cmd + "\n", true, false, false); - } - } - - - /// - /// 复制 - /// - [CommandMethod(nameof(IFoxCopyClip), CommandFlags.UsePickSet | CommandFlags.Redraw)] - public void IFoxCopyClip() - { - Copy(false); - } - /// - /// 带基点复制 - /// - [CommandMethod(nameof(IFoxCopyBase), CommandFlags.UsePickSet | CommandFlags.Redraw)] - public void IFoxCopyBase() - { - Copy(true); - } - /// - /// 剪切 - /// - [CommandMethod(nameof(IFoxCutclip), CommandFlags.UsePickSet | CommandFlags.Redraw)] - public void IFoxCutclip() - { - Copy(false, true); - } - - - /// - /// 粘贴 - /// - [CommandMethod(nameof(IFoxPasteClip))] - public void IFoxPasteClip() - { - Paste(false); - } - /// - /// 粘贴为块 - /// - [CommandMethod(nameof(IFoxPasteBlock))] - public void IFoxPasteBlock() - { - Paste(true); - } -#endif - #endregion - - // 想要重启cad之后还可以继续用剪贴板,那么就不要这个: - // [IFoxInitialize(isInitialize: false)] - // 会出现永远存在临时文件夹的情况: - // 0x01 复制的时候,无法删除占用中的, - // 0x02 调试期间直接退出 acad.exe - public void Terminate() - { - // 此处要先去删除tmp文件夹的上次剪贴板产生的dwg文件 - for (int i = _delFile.Count - 1; i >= 0; i--) - { - try - { - if (File.Exists(_delFile[i])) - File.Delete(_delFile[i]); - _delFile.RemoveAt(i); - } - catch { Env.Printl("无法删除(是否占用):" + _delFile[i]); } - } - } - - - /// - /// 读写锁,当资源处于写入模式时,
- /// 其他线程写入需要等待本次写入结束之后才能继续写入 - /// 参考链接 - ///
- static readonly ReaderWriterLockSlim _rwLock = new(); - - /// - /// 储存准备删除的文件 - /// 也可以用txt代替 - /// 如果删除出错(占用),将一直在这个集合中,直到cad关闭 - /// - readonly List _delFile = new(); - - /// - /// 复制 - /// - /// - void Copy(bool getPoint, bool isEraseSsget = false) - { - try - { - if (!_rwLock.IsWriteLockHeld) - _rwLock.EnterWriteLock(); // 进入写入锁 - - var dm = Acap.DocumentManager; - if (dm.Count == 0) - return; - var doc = dm.MdiActiveDocument; - if (doc == null) - return; - - ObjectId[] idArray; -#if true - var psr = doc.Editor.SelectImplied();// 预选 - if (psr.Status != PromptStatus.OK) - psr = doc.Editor.GetSelection();// 手选 - if (psr.Status != PromptStatus.OK) - return; - idArray = psr.Value.GetObjectIds(); -#endif - - // 设置基点 - Point3d pt = Point3d.Origin; - var tempFile = CreateTempFileName(); - while (File.Exists(tempFile) || - File.Exists(Path.ChangeExtension(tempFile, "wmf"))) - { - tempFile = CreateTempFileName(); - Thread.Sleep(1); - } - - using DBTrans tr = new(); - - - #region 写入 WMF 数据 - /* - * 通过cadCom导出wmf(免得自己转换每种图元), - * 再将wmf转为emf,然后才能写入剪贴板 - * wmf生成(win32api): https://www.cnblogs.com/5iedu/p/4706324.html - */ - IntPtr hMetaFile = IntPtr.Zero; - { - var wmf = Path.ChangeExtension(tempFile, "wmf"); - Env.Editor.ComExportWMF(wmf, idArray); - if (File.Exists(wmf)) - { - hMetaFile = PlaceableMetaHeader.Wmf2Emf(wmf);//emf文件句柄 - try { File.Delete(wmf); } - catch (Exception e) { Env.Printl(e); } - } - else - { - Env.Printl("没有创建wmf,失败"); - } - } - if (hMetaFile != IntPtr.Zero) - { - // 克隆一个,并写入描述...此处尚未完成 - // EmfTool.SetEnhMetaFileDescriptionEx(ref hMetaFile, "这是阿惊的emf"); - } - - // 保存文件 - //var emfsave = Path.ChangeExtension(cadClipType.File, ".emf"); - //EmfTool.Save(emf, emfsave); - #endregion - - #region 写入 AutoCAD.R17 数据 - if (getPoint) - { - var pr = doc.Editor.GetPoint("\n选择基点"); - if (pr.Status != PromptStatus.OK) - return; - pt = pr.Value; - } - else - { - // 遍历块内 - // 获取左下角点作为基点 - double minx = double.MaxValue; - double miny = double.MaxValue; - double minz = double.MaxValue; - foreach (var id in idArray) - { - var ent = tr.GetObject(id); - if (ent == null) - continue; - var info = ent.GetBoundingBoxEx(); - if (info != null) - { - if (ent is BlockReference brf) - info.Value.Move(brf.Position, Point3d.Origin); - minx = minx > info.Value.MinX ? info.Value.MinX : minx; - miny = miny > info.Value.MinY ? info.Value.MinY : miny; - minz = minz > info.Value.MinZ ? info.Value.MinZ : minz; - } - } - pt = new(minx, miny, minz); - } - - var cadClipType = new TagClipboardInfo(tempFile, pt); - - // 克隆到目标块表内 - using (DBTrans fileTr = new(cadClipType.File)) - { - fileTr.Task(() => { - using IdMapping map = new(); - using ObjectIdCollection ids = new(idArray); - tr.Database.WblockCloneObjects( - ids, - fileTr.ModelSpace.ObjectId, - map, - DuplicateRecordCloning.Replace, - false); - }); - - // 大于dwg07格式的,保存为07,以实现高低版本通用剪贴板 - // 小于dwg07格式的,本工程没有支持cad06dll - if ((int)DwgVersion.Current >= 27) - fileTr.Database.SaveFile((DwgVersion)27, false); - else - throw new ArgumentException($"版本过低,无法保存,版本号:{DwgVersion.Current}"); - } - #endregion - - // 必须一次性写入剪贴板,详见 OpenClipboardTask - var cadClipFormat = ClipTool.RegisterClipboardFormat(ClipboardEnv.CadVer); - - // 剪贴板需要的指针: 克隆一个新的,不释放内存,不锁定内存(否则高频触发时候卡死) - var cadClipData = cadClipType.CloneToPtr(); - - bool getFlag = ClipTool.OpenClipboardTask(true, () => { - // 写入剪贴板: cad图元 - ClipTool.SetClipboardData(cadClipFormat, cadClipData); - - // 写入剪贴板: wmf,使得在粘贴链接的时候可以用 - if (hMetaFile != IntPtr.Zero) - ClipTool.SetClipboardData((uint)ClipboardFormat.CF_ENHMETAFILE, hMetaFile); - }); - if (hMetaFile != IntPtr.Zero) - EmfTool.DeleteEnhMetaFile(hMetaFile); - - // 成功拷贝就删除上一次的临时文件 - if (getFlag) - Terminate(); - - // 加入删除队列,下次删除 - if (!_delFile.Contains(cadClipType.File)) - _delFile.Add(cadClipType.File); - - // 剪切时候删除 - if (isEraseSsget) - { - idArray.ForEach(id => { - id.Erase(); - }); - } - } - catch (Exception e) - { - Debugger.Break(); - throw e; - } - finally - { - if (_rwLock.IsWriteLockHeld) - _rwLock.ExitWriteLock(); // 退出写入锁 - } - } - - - /// - /// 粘贴 - /// - /// - void Paste(bool isBlock) - { - try - { - if (!_rwLock.IsWriteLockHeld) - _rwLock.EnterWriteLock(); // 进入写入锁 - - var dm = Acap.DocumentManager; - if (dm.Count == 0) - return; - - var getClip = ClipTool.GetClipboard(ClipboardEnv.CadVer, out TagClipboardInfo tag); - if (!getClip) - { - // 在没有安装插件的高版本cad中复制,此时剪贴板是当前版本的, - // 那么在安装了插件的cad中需要识别这个同版本的剪贴板内容 - // 例如天正只在某个启动的cad中加载插件,而不是全部 - getClip = ClipTool.GetClipboard(ClipboardEnv.CadCurrentVer, out tag); - if (!getClip) - return; - } - - var cadClipType = tag; - Env.Print("粘贴来源: " + cadClipType.File); - - if (!File.Exists(cadClipType.File)) - { - Env.Print("文件不存在"); - return; - } - - // 获取临时文件的图元id - List fileEntityIds = []; - using (DBTrans fileTr = new(cadClipType.File, commit: false, - fileOpenMode: FileOpenMode.OpenForReadAndAllShare)) - { - fileTr.ModelSpace.ForEach(id => { - if (id.IsOk()) - fileEntityIds.Add(id); - }); - } - if (fileEntityIds.Count == 0) - return; - - using DBTrans tr = new(); - tr.Editor?.SetImpliedSelection(new ObjectId[0]); // 清空选择集 - - // 新建块表记录 - var btr = CreateBlockTableRecord(tr, cadClipType.File); - if (btr == null) - return; - - /// 克隆进块表记录 - /// 动态块粘贴之后,用ctrl+z导致动态块特性无法恢复, - /// 是因为它: - using IdMapping map = new(); - using ObjectIdCollection idc = new(fileEntityIds.ToArray()); - tr.Task(() => { - tr.Database.WblockCloneObjects( - idc, - btr.ObjectId, // tr.Database.BlockTableId, // 粘贴目标 - map, - DuplicateRecordCloning.Ignore, - false); - }); - - // 移动块内,从基点到原点 - foreach (var id in btr) - { - if (!id.IsOk()) - { - Env.Printl("jig预览块内有克隆失败的脏东西,是否天正克隆期间导致?"); - continue; - } - var ent = tr.GetObject(id); - if (ent == null) - continue; - using (ent.ForWrite()) - ent.Move(cadClipType.Point, Point3d.Origin); - } - - // 预览并获取交互点 - // 天正此处可能存在失败:天正图元不给你jig接口调用之类的 - using var moveJig = new JigEx((mousePoint, drawEntitys) => { - var brf = new BlockReference(Point3d.Origin, btr.ObjectId); - brf.Move(Point3d.Origin, mousePoint); - drawEntitys.Enqueue(brf); - }); - var jppo = moveJig.SetOptions(cadClipType.Point); - jppo.Keywords.Add(" ", " ", "<空格取消>"); - jppo.Keywords.Add("A", "A", "引线点粘贴(A)"); - - var dr = moveJig.Drag(); - Point3d moveTo = Point3d.Origin; - if (dr.Status == PromptStatus.Keyword) - moveTo = cadClipType.Point; - else if (dr.Status == PromptStatus.OK) - moveTo = moveJig.MousePointWcsLast; - else - { - // 删除jig预览的块表记录 - using (btr.ForWrite()) - btr.Erase(); - return; - } - - if (isBlock) - { - PasteIsBlock(tr, moveJig.Entitys, moveJig.MousePointWcsLast, moveTo); - } - else - { - PasteNotBlock(tr, btr, Point3d.Origin, moveTo); - // 删除jig预览的块表记录 - using (btr.ForWrite()) - btr.Erase(); - } - - try - { - #region 读取剪贴板WMF - var msg = new StringBuilder(); - - int a3 = 0; - a3 = 2 | 4; - if ((a3 & 1) == 1) - { - // win32api 不成功 - ClipTool.OpenClipboardTask(false, () => { - // 剪贴板数据保存目标数据列表 - List _bytes = new(); - var cf = (uint)ClipboardFormat.CF_ENHMETAFILE; - var clipTypeData = ClipTool.GetClipboardData(cf); - if (clipTypeData == IntPtr.Zero) - { - Env.Printl("失败:粘贴剪贴板emf1"); - return; - } - - // 无法锁定剪贴板emf内存,也无法获取GlobalSize - bool locked = WindowsAPI.GlobalLockTask(clipTypeData, prt => { - uint size = WindowsAPI.GlobalSize(prt); - if (size > 0) - { - var buffer = new byte[size]; - Marshal.Copy(prt, buffer, 0, buffer.Length); - _bytes.Add(buffer); - } - }); - if (!locked) - Env.Printl("锁定内存失败"); - }); - } - if ((a3 & 2) == 2) - { - ClipTool.OpenClipboardTask(false, () => { - // 无法锁定剪贴板emf内存,也无法获取GlobalSize - // 需要直接通过指针跳转到指定emf结构位置 - var cf = (uint)ClipboardFormat.CF_ENHMETAFILE; - var clipTypeData = ClipTool.GetClipboardData(cf); - if (clipTypeData == IntPtr.Zero) - { - Env.Printl("失败:粘贴剪贴板emf2"); - return; - } - - int a4 = 1; - //int a4 = 1 | 2 | 4; - if ((a4 & 1) == 1) - { - // 获取描述 - var desc = EmfTool.GetEnhMetaFileDescriptionEx(clipTypeData); - if (!string.IsNullOrEmpty(desc)) - msg.AppendLine("DescriptionEx::" + desc); - } - if ((a4 & 2) == 2) - { - // 获取文件信息 - var obj = EnhMetaHeader.Create(clipTypeData); - msg.AppendLine("EnhMetaHeader::" + obj.ToString()); - } - if ((a4 & 4) == 4) - { - // 保存文件 - //var emfsave = Path.ChangeExtension(cadClipType.File, ".emf"); - //EmfTool.Save(clipTypeData, emfsave); - } - }); - } - if ((a3 & 4) == 4) - { - // c# 读取成功,win32直接读取剪贴板的话是不成功的 - if (Clipboard.ContainsData(DataFormats.EnhancedMetafile)) - { - var iData = Clipboard.GetDataObject();//从剪切板获取数据 - if (!iData.GetDataPresent(DataFormats.EnhancedMetafile)) - return; - var metafile = (Metafile)iData.GetData(DataFormats.EnhancedMetafile); - /* - // 为什么序列化失败了呢 - var formatter = new BinaryFormatter(); - //using MemoryStream stream = new(); - Stream stream = new FileStream("MyFile.bin", FileMode.Create, FileAccess.Write, FileShare.None); - formatter.Serialize(stream, metafile); - stream.Close(); - //Metafile obj = (Metafile)formatter.Deserialize(stream); - */ - msg.AppendLine($"c# Metafile::{metafile.Size}"); - } - } - - if (msg.Length != 0) - Env.Printl(msg); - #endregion - } - catch (Exception e) - { - Debugger.Break(); - DebugEx.Printl(e); - } - } - catch (Exception e)//{"剪贴板上的数据无效 (异常来自 HRESULT:0x800401D3 (CLIPBRD_E_BAD_DATA))"} - { - Debugger.Break(); - DebugEx.Printl(e); - } - finally - { - if (_rwLock.IsWriteLockHeld) - _rwLock.ExitWriteLock(); // 退出写入锁 - } - } - - /// - /// 粘贴为块 - /// - /// - /// - /// - /// - static void PasteIsBlock(DBTrans tr, Entity[] entitys, Point3d move, Point3d moveTo) - { - if (!move.IsEqualTo(moveTo, new Tolerance(1e-6, 1e-6))) - { - entitys.ForEach(ent => { - ent.Move(move, moveTo); - }); - } - tr.CurrentSpace.AddEntity(entitys); - } - - /// - /// 直接粘贴(不为块参照) - /// - /// - /// - /// 它总是为 - /// 目标点 - static void PasteNotBlock(DBTrans tr, BlockTableRecord btr, Point3d move, Point3d moveTo) - { - using ObjectIdCollection ids = new(); - foreach (var id in btr) - { - if (!id.IsOk()) - continue; - ids.Add(id); - } - - // 深度克隆,然后平移到当前目标点位置 - using IdMapping map = new(); - tr.CurrentSpace.DeepCloneEx(ids, map); - - map.GetValues().ForEach(id => { - if (!id.IsOk()) - return; - var ent = tr.GetObject(id); - if (ent == null) - return; - using (ent.ForWrite()) - ent.Move(move, moveTo); - }); - } - - /// - /// 创建块表记录 - /// - /// - /// 此名称若已在块表存在,就会自动用时间名称代替 - /// - BlockTableRecord? CreateBlockTableRecord(DBTrans tr, string tempFile) - { - var blockNameNew = Path.GetFileNameWithoutExtension(tempFile); - while (tr.BlockTable.Has(blockNameNew)) - { - tempFile = CreateTempFileName(); - blockNameNew = Path.GetFileNameWithoutExtension(tempFile); - Thread.Sleep(1); - } - var btrIdNew = tr.BlockTable.Add(blockNameNew); - return tr.GetObject(btrIdNew); - } - - /// - /// 创建临时路径的时间文件名 - /// - /// 格式,X是16进制 - /// - static string CreateTempFileName(string format = "X") - { - var t1 = DateTime.Now.ToString("yyyyMMddHHmmssfffffff"); - t1 = Convert.ToInt32(t1.GetHashCode()).ToString(format); - var t2 = Convert.ToInt32(t1.GetHashCode()).ToString(format);// 这里是为了满足长度而做的 - return Path.GetTempPath() + "A$" + t1 + t2[0] + ".DWG"; - } -} - - -public class TestImageFormat -{ - public ImageFormat GetFormat(string filename) - { - string ext = Path.GetExtension(filename).ToLower(); - var imf = ext switch - { - ".bmp" => ImageFormat.Bmp, - ".gif" => ImageFormat.Gif, - ".jpg" => ImageFormat.Jpeg, - ".tif" => ImageFormat.Tiff, - ".wmf" => ImageFormat.Wmf, - ".png" => ImageFormat.Png, - _ => throw new NotImplementedException(), - }; - return imf; - } - - // 此处相当于截图,后台没有doc不可用 - // https://www.cnblogs.com/shangdishijiao/p/15166499.html - [CommandMethod(nameof(CreatePreviewImage))] - public void CreatePreviewImage() - { - using DBTrans tr = new(); - if (tr.Document == null) - return; - - var doc = tr.Document; - - var size = doc.Window.DeviceIndependentSize; - using var bmp = doc.CapturePreviewImage( - Convert.ToUInt32(size.Width), - Convert.ToUInt32(size.Height)); - - //保存wmf会变png,看二进制签名 - var outFile = Path.ChangeExtension(tr.Database.Filename, ".bmp"); - bmp.Save(outFile, GetFormat(outFile)); - Env.Printl($"保存文件:{outFile}"); - Env.Printl($"保存后缀:{GetFormat(outFile)}"); - - // 利用winAPI截图 - bool getFlag = ClipTool.OpenClipboardTask(true, () => { - BitmapTool.CaptureWndImage(doc.Window.Handle, bitmapHandle => { - // 写入剪贴板: BMP位图,这是截图,不是WMF转BMP,不对 - ClipTool.SetClipboardData((uint)ClipboardFormat.CF_BITMAP, bitmapHandle); - }); - }); - } -} - - -public class OleTestClass -{ - // https://adndevblog.typepad.com/autocad/2012/04/update-linked-ole-object-from-net.html - - /// - /// 更新ole链接 - /// 如果 OLE 对象在另一个应用程序中打开,则上面的代码似乎不会更新该对象 - /// 例如,位图在 Microsoft 画图中打开 - /// - /// - /// - [DllImport("mfc90u.dll", CallingConvention = CallingConvention.ThisCall, - EntryPoint = "#6766")] - public static extern int COleClientItem_UpdateLink(IntPtr thisClientItem); - - [DllImport("acdb18.dll", CallingConvention = CallingConvention.ThisCall, - EntryPoint = "?getOleClientItem@AcDbOle2Frame@@QBEPAVCOleClientItem@@XZ")] - public static extern IntPtr AcDbOle2Frame_getOleClientItem(IntPtr thisOle2Frame); - - [CommandMethod(nameof(UpdateOleClient))] - public void UpdateOleClient() - { - var per = Env.Editor.GetEntity("\n选择OLE更新链接"); - if (per.Status != PromptStatus.OK) - return; - - using DBTrans tr = new(); - var ole2frame = tr.GetObject(per.ObjectId); - if (ole2frame == null) - return; - using (ole2frame.ForWrite()) - { - IntPtr ptrClientItem = AcDbOle2Frame_getOleClientItem(ole2frame.UnmanagedObject); - COleClientItem_UpdateLink(ptrClientItem); - } - } - - - // https://adndevblog.typepad.com/autocad/2012/06/iterating-ole-linked-entities.html - // 获取OLE路径 - [CommandMethod(nameof(GetOlePath))] - public void GetOlePath() - { - using DBTrans tr = new(); - foreach (ObjectId id in tr.CurrentSpace) - { - if (!id.IsOk()) - continue; - - var ole2frame = tr.GetObject(id); - if (ole2frame == null) - continue; - switch (ole2frame.Type) - { - case Ole2Frame.ItemType.Static: - Env.Editor.WriteMessage("\n" + "Static"); - break; - case Ole2Frame.ItemType.Embedded: - Env.Editor.WriteMessage("\n" + "Embedded"); - break; - case Ole2Frame.ItemType.Link: - Env.Editor.WriteMessage("\n" + "Link"); - Env.Editor.WriteMessage("\n" + ole2frame.LinkPath); - break; - } - } - } - - [CommandMethod(nameof(SetOle))] - public void SetOle() - { - //var pr = Env.Editor.GetPoint("\n选择基点"); - //if (pr.Status != PromptStatus.OK) - // return; - //var pt = pr.Value; - - using DBTrans tr = new(); - - // https://forums.autodesk.com/t5/net/how-to-create-an-ole-object-with-ole2frame/td-p/3203222 - var oo = new Ole2Frame(); - oo.SetDatabaseDefaults(); - //oo.CopyFrom() - oo.Position2d = new(0, 0, 100, 100); - - // 打印质量? https://learn.microsoft.com/zh-cn/dotnet/api/system.printing.outputquality?view=windowsdesktop-6.0 - //oo.OutputQuality = - //oo.AutoOutputQuality = - oo.Rotation = 0.0; - //oo.WcsWidth = ; - //oo.WcsHeight = ; - //oo.ScaleWidth = ; - //oo.ScaleHeight = ; - - //宽高比锁定 - oo.LockAspect = true; - } - -#if true2 - // https://forums.autodesk.com/t5/net/how-can-i-read-data-from-ole2frame-object-excel-through-api/td-p/7944241 - public void GetOleForOffice() - { - using DBTrans tr = new(); - foreach (ObjectId id in tr.CurrentSpace) - { - if (!id.IsOk()) - continue; - - var ole2frame = tr.GetObject(id); - if (ole2frame == null) - continue; - - var wb = (Microsoft.Office.Interop.Excel.Workbook)ole2frame.OleObject; - var ws = (Microsoft.Office.Interop.Excel.Worksheet)wb.ActiveSheet; - var range = (Microsoft.Office.Interop.Excel.Range)ws.UsedRange; - - tb.SetSize(range.Rows.Count, range.Columns.Count); - tb.SetRowHeight(range.RowHeight); - tb.SetColumnWidth(range.ColumnWidth); - tb.Position = new Point3d(ole2frame.Location.X, ole2frame.Location.Y, ole2frame.Location.Z); - for (int row = 0; row < range.Rows.Count; row++) - { - for (int col = 0; col < range.Columns.Count; col++) - { - tb.Cells[row, col].TextHeight = 1; - var aa = (Microsoft.Office.Interop.Excel.Range)range.Cells[row + 1, col + 1]; - var bb = Convert.ToString(aa.Value2); - tb.SetTextString(row, col, bb ?? ""); - tb.Cells[row, col].Alignment = CellAlignment.MiddleCenter; - } - } - tb.GenerateLayout(); - } - } -#endif -} \ No newline at end of file diff --git a/tests/TestShared/TestAddEntity.cs b/tests/TestShared/TestAddEntity.cs deleted file mode 100644 index 123ba77..0000000 --- a/tests/TestShared/TestAddEntity.cs +++ /dev/null @@ -1,109 +0,0 @@ -namespace Test; - -public partial class Test -{ - - - - - - - - - - - - - [CommandMethod(nameof(Test_Rec))] - public void Test_Rec() - { - Point2d p1 = new(10000.2, 100000.5); - Point2d p2 = new(15000.9, 100000.5); - Point2d p3 = new(15000.9, 105000.7); - Point2d p4 = new(10000.2, 105000.7); - - var p12 = p2 - p1; - var p23 = p3 - p2; - var p34 = p4 - p3; - var p41 = p1 - p4; - var p13 = p3 - p1; - var p24 = p4 - p2; - - - const double pi90 = Math.PI / 2; - pi90.Print(); - - Tools.TestTimes(1000000, "对角线", () => { - var result = false; - if (Math.Abs(p13.Length - p24.Length) <= 1e8) - { - result = p41.IsParallelTo(p12); - } - }); - -#pragma warning disable CS0219 // 变量已被赋值,但从未使用过它的值 - Tools.TestTimes(1000000, "三次点乘", () => { - bool result = Math.Abs(p12.DotProduct(p23)) < 1e8 && - Math.Abs(p23.DotProduct(p34)) < 1e8 && - Math.Abs(p34.DotProduct(p41)) < 1e8; - }); - - Tools.TestTimes(1000000, "三次垂直", () => { - bool result = p12.IsParallelTo(p23) && - p23.IsParallelTo(p34) && - p34.IsParallelTo(p41); - }); -#pragma warning restore CS0219 // 变量已被赋值,但从未使用过它的值 - } - - - - - [CommandMethod(nameof(Test_EntRoration))] - public void Test_EntRoration() - { - var line = new Line(new(0, 0, 0), new(100, 0, 0)); - - using DBTrans tr = new(); - tr.CurrentSpace.AddEntity(line); - var line2 = (Line)line.Clone(); - tr.CurrentSpace.AddEntity(line2); - line2.Rotation(new(100, 0, 0), Math.PI / 2); - } - - [CommandMethod(nameof(Test_TypeSpeed))] - public void Test_TypeSpeed() - { - var line = new Line(); - var line1 = line as Entity; - Tools.TestTimes(100000, "is 匹配:", () => { - var t = line1 is Line; - }); - Tools.TestTimes(100000, "name 匹配:", () => { - // var t = line.GetType().Name; - var tt = line1.GetType().Name == nameof(Line); - }); - Tools.TestTimes(100000, "dxfname 匹配:", () => { - // var t = line.GetType().Name; - var tt = line1.GetRXClass().DxfName == nameof(Line); - }); - } - - [CommandMethod(nameof(Test_sleeptrans))] - public static void Test_sleeptrans() - { - using var tr = new DBTrans(); - for (int i = 0; i < 100; i++) - { - var cir = CircleEx.CreateCircle(new Point3d(i, i, 0), 0.5); - if (cir is null) - { - return; - } - cir.ColorIndex = i; - tr.CurrentSpace.AddEntity(cir); - tr.Editor?.Redraw(cir); - System.Threading.Thread.Sleep(10); - } - } -} \ No newline at end of file diff --git a/tests/TestShared/TestBlock.cs b/tests/TestShared/TestBlock.cs deleted file mode 100644 index fc2fdb2..0000000 --- a/tests/TestShared/TestBlock.cs +++ /dev/null @@ -1,864 +0,0 @@ - -namespace Test; - -public class TestBlock -{ - // 一个命令就把块编辑搞定,减少用户记忆命令 - [CommandMethod(nameof(Test_Refedit), CommandFlags.Redraw | CommandFlags.Session)] - public void Test_Refedit() - { - Env.Printl($"{nameof(Test_Refedit)}-在位编辑块/在位保存块"); - - // 全部用lisp发送命令是为了空格还是本命令 - // 打开了块编辑器,就关闭掉,保存提示 - if ((short)Env.GetVar("BlockEditor") == 1) - { - Env.Editor.RunLisp("(command \"_.bclose\")"); - return; - } - // 0x01 非在位编辑状态: 先选择块参照,然后在位编辑 - // 0x02 在位编辑状态: 关闭并保存 - if (Env.GetVar("RefEditName").ToString() == "")//显示正在编辑的参照名称 - Env.Editor.RunLisp("(command \"_.refedit\")");//直接点选可以有嵌套层次 - else - Env.Editor.RunLisp("(command \"_.refclose\" \"s\")"); - } - - [CommandMethod(nameof(Test_GetBoundingBoxEx))] - public void Test_GetBoundingBoxEx() - { - using DBTrans tr = new(); - var ents = Env.Editor.SSGet().Value?.GetEntities(); - if (ents == null) - return; - foreach (var item in ents) - { - var box = item?.GetBoundingBoxEx(); - Env.Print("min:" + box?.BottomLeft + ";max" + box?.TopRight); - if (box != null) - tr.CurrentSpace.AddEntity(new Line(box.Value.BottomLeft, box.Value.TopRight)); - } - } - - // 前台块定义 - [CommandMethod(nameof(Test_BlockDef))] - public void Test_BlockDef() - { - using DBTrans tr = new(); - // var line = new Line(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); - tr.BlockTable.Add("test", - btr => - { - btr.Origin = new Point3d(0, 0, 0); - }, - () => // 图元 - new List { new Line(new Point3d(0, 0, 0), new Point3d(1, 1, 0)) }, - () => // 属性定义 - { - var id1 = new AttributeDefinition() { Position = new Point3d(0, 0, 0), Tag = "start", Height = 0.2 }; - var id2 = new AttributeDefinition() { Position = new Point3d(1, 1, 0), Tag = "end", Height = 0.2 }; - return new List { id1, id2 }; - } - ); - // ObjectId objectId = tr.BlockTable.Add("a");// 新建块 - // objectId.GetObject().AddEntity();// 测试添加空实体 - tr.BlockTable.Add("test1", - btr => - { - btr.Origin = new Point3d(0, 0, 0); - }, - () => - { - var line = new Line(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); - var acText = DBTextEx.CreateDBText(Point3d.Origin, "123", 2.5); - return new List { line, acText }; - }); - } - - // 后台块定义 - [CommandMethod(nameof(Test_BlockDefbehind))] - public void Test_BlockDefbehind() - { - using DBTrans tr = new(@"C:\Users\vic\Desktop\test.dwg"); - // var line = new Line(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); - tr.BlockTable.Add("test", - btr => - { - btr.Origin = new Point3d(0, 0, 0); - }, - () => // 图元 - { - return new List { new Line(new Point3d(0, 0, 0), new Point3d(1, 1, 0)) }; - }, - () => // 属性定义 - { - var id1 = new AttributeDefinition() { Position = new Point3d(0, 0, 0), Tag = "start", Height = 0.2 }; - var id2 = new AttributeDefinition() { Position = new Point3d(1, 1, 0), Tag = "end", Height = 0.2 }; - return new List { id1, id2 }; - } - ); - // ObjectId objectId = tr.BlockTable.Add("a");// 新建块 - // objectId.GetObject().AddEntity();// 测试添加空实体 - tr.BlockTable.Add("test1", - btr => - { - btr.Origin = new Point3d(0, 0, 0); - }, - () => - { - var line = new Line(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); - var acText = DBTextEx.CreateDBText(Point3d.Origin, "12345", 2.5); - - return new List { line, acText }; - }); - tr.Database.SaveDwgFile(); - } - - - - // 修改块定义 - [CommandMethod(nameof(Test_BlockDefChange))] - public void Test_BlockDefChange() - { - using DBTrans tr = new(); - // var line = new Line(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); - // tr.BlockTable.Change("test", btr => - // { - // btr.Origin = new Point3d(5, 5, 0); - // btr.AddEntity(new Circle(new Point3d(0, 0, 0), Vector3d.ZAxis, 2)); - // btr.GetEntities() - // .ToList() - // .ForEach(e => e.Flush()); // 刷新块显示 - - // }); - - - tr.BlockTable.Change("test", btr => - { - foreach (var id in btr) - { - var ent = tr.GetObject(id); - using (ent!.ForWrite()) - { - switch (ent) - { - case Dimension dBText: - dBText.DimensionText = "234"; - dBText.RecomputeDimensionBlock(true); - break; - case Hatch hatch: - hatch.ColorIndex = 0; - break; - } - } - } - }); - tr.Editor?.Regen(); - } - - [CommandMethod(nameof(Test_InsertBlockDef))] - public void Test_InsertBlockDef() - { - using DBTrans tr = new(); - var line1 = new Line(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); - var line2 = new Line(new Point3d(0, 0, 0), new Point3d(-1, 1, 0)); - var att1 = new AttributeDefinition() { Position = new Point3d(10, 10, 0), Tag = "tagTest1", Height = 1, TextString = "valueTest1" }; - var att2 = new AttributeDefinition() { Position = new Point3d(10, 12, 0), Tag = "tagTest2", Height = 1, TextString = "valueTest2" }; - tr.BlockTable.Add("test1", line1, line2, att1, att2); - - - List ents = []; - var line5 = new Line(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); - var line6 = new Line(new Point3d(0, 0, 0), new Point3d(-1, 1, 0)); - ents.Add(line5); - ents.Add(line6); - tr.BlockTable.Add("test44", ents); - - - var line3 = new Line(new Point3d(5, 5, 0), new Point3d(6, 6, 0)); - var line4 = new Line(new Point3d(5, 5, 0), new Point3d(-6, 6, 0)); - var att3 = new AttributeDefinition() { Position = new Point3d(10, 14, 0), Tag = "tagTest3", Height = 1, TextString = "valueTest3" }; - var att4 = new AttributeDefinition() { Position = new Point3d(10, 16, 0), Tag = "tagTest4", Height = 1, TextString = "valueTest4" }; - tr.BlockTable.Add("test2", new List { line3, line4 }, new List { att3, att4 }); - // tr.CurrentSpace.InsertBlock(new Point3d(4, 4, 0), "test1"); // 测试默认 - // tr.CurrentSpace.InsertBlock(new Point3d(4, 4, 0), "test2"); - // tr.CurrentSpace.InsertBlock(new Point3d(4, 4, 0), "test3"); // 测试插入不存在的块定义 - // tr.CurrentSpace.InsertBlock(new Point3d(0, 0, 0), "test1", new Scale3d(2)); // 测试放大2倍 - // tr.CurrentSpace.InsertBlock(new Point3d(4, 4, 0), "test1", new Scale3d(2), Math.PI / 4); // 测试放大2倍,旋转45度 - - var def1 = new Dictionary - { - { "tagTest1", "1" }, - { "tagTest2", "2" } - }; - tr.CurrentSpace.InsertBlock(new Point3d(0, 0, 0), "test1", atts: def1); - var def2 = new Dictionary - { - { "tagTest3", "1" }, - { "tagTest4", "" } - }; - tr.CurrentSpace.InsertBlock(new Point3d(10, 10, 0), "test2", atts: def2); - tr.CurrentSpace.InsertBlock(new Point3d(20, 20, 0), "test2"); - tr.CurrentSpace.InsertBlock(new Point3d(-10, 0, 0), "test44"); - } - - [CommandMethod(nameof(Test_InsertBlockWithDoubleDatabase))] - public void Test_InsertBlockWithDoubleDatabase() - { - using var tr = new DBTrans(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "test.dwg")); - using var trans = new DBTrans(); - - tr.BlockTable.Add("test456", - btr => - { - btr.Origin = new(0, 0, 0); - }, - () => - { - var line = new Line(new(0, 0, 0), new(1, 1, 0)); - var actext = DBTextEx.CreateDBText(Point3d.Origin, "123", 2.5, database: tr.Database); - - return new List { line, actext }; - - }); - tr.CurrentSpace.InsertBlock(Point3d.Origin, "test456"); - tr.Database.SaveDwgFile(); - } - - - - [CommandMethod(nameof(Test_AddAttsDef))] - public void Test_AddAttsDef() - { - using DBTrans tr = new(); - var blockid = Env.Editor.GetEntity("pick block:").ObjectId; - var btf = tr.GetObject(blockid); - if (btf is null) - return; - var att1 = new AttributeDefinition() { Position = new Point3d(20, 20, 0), Tag = "addtagTest1", Height = 1, TextString = "valueTest1" }; - var att2 = new AttributeDefinition() { Position = new Point3d(10, 12, 0), Tag = "tagTest2", Height = 1, TextString = "valueTest2" }; - tr.BlockTable.AddAttsToBlocks(btf.BlockTableRecord, new() { att1, att2 }); - } - - [CommandMethod(nameof(Test_BlockNullBug))] - public void Test_BlockNullBug() - { - using DBTrans tr = new(); - - List ents = []; - var line5 = new Line(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); - var line6 = new Line(new Point3d(0, 0, 0), new Point3d(-1, 1, 0)); - ents.Add(line5); - ents.Add(line6); - tr.BlockTable.Add("test44", ents); - tr.CurrentSpace.InsertBlock(new Point3d(0, 0, 0), "test44"); - } - - [CommandMethod(nameof(Test_BlockFile))] - public void Test_BlockFile() - { - using DBTrans tr = new(); - var id = tr.BlockTable.GetBlockFrom(@"C:\Users\vic\Desktop\test.dwg", false); - tr.CurrentSpace.InsertBlock(Point3d.Origin, id); - } - - [CommandMethod(nameof(Test_BlockFiledxf))] - public void Test_BlockFiledxf() - { - string [] files; - var folder= new System.Windows.Forms.FolderBrowserDialog(); - if (folder.ShowDialog() == System.Windows.Forms.DialogResult.OK) - { - files = Directory.GetFiles(folder.SelectedPath,"*.dxf",SearchOption.AllDirectories); - using DBTrans tr = new(); - foreach (var item in files) - { - var id = tr.BlockTable.GetBlockFrom(item, false); - var pt = Env.Editor.GetPoint("pick pt"); - if (pt.Status == PromptStatus.OK) - { - tr.CurrentSpace.InsertBlock(pt.Value, id); - Env.Editor.Redraw(); - } - - } - - } - - - } - - [CommandMethod(nameof(Test_ClipBlock))] - public void Test_ClipBlock() - { - using DBTrans tr = new(); - tr.BlockTable.Add("test1", btr => - { - btr.Origin = new Point3d(0, 0, 0); - btr.AddEntity(new Line(new Point3d(0, 0, 0), new Point3d(10, 10, 0)), - new Line(new Point3d(10, 10, 0), new Point3d(10, 0, 0))); - }); - // tr.BlockTable.Add("hah"); - var id = tr.CurrentSpace.InsertBlock(new Point3d(0, 0, 0), "test1"); - var brf1 = tr.GetObject(id)!; - var pts = new List { new Point3d(3, 3, 0), new Point3d(7, 3, 0), new Point3d(7, 7, 0), new Point3d(3, 7, 0) }; - brf1.ClipBlockRef(pts); - - var id1 = tr.CurrentSpace.InsertBlock(new Point3d(20, 20, 0), "test1"); - var brf2 = tr.GetObject(id); - brf2?.ClipBlockRef(new Point3d(13, 13, 0), new Point3d(17, 17, 0)); - } - - - [CommandMethod(nameof(Test_ClipBlock1))] - public void Test_ClipBlock1() - { - using DBTrans tr = new(); - var ent = Env.Editor.GetEntity("pick block"); - if (ent.Status != PromptStatus.OK) return; - - var brf1 = tr.GetObject(ent.ObjectId)!; - var pts = new List { new Point3d(3, 3, 0), new Point3d(7, 3, 0), new Point3d(7, 7, 0), new Point3d(3, 7, 0) }; - brf1.ClipBlockRef(pts); - - } - - - - // 给用户的测试程序,不知道对错 - [CommandMethod(nameof(Test_Block_ej))] - public void Test_Block_ej() - { - using (DBTrans tr = new()) - { - // Point3d.Origin.AddBellowToModelSpace(100, 100, 5, 3, 30);// 画波纹管 - - // Database db2 = new Database(false, true); - // string fullFileName = @".\MyBlockDwgFile\001.dwg"; - // db2.ReadDwgFile(fullFileName, System.IO.FileShare.Read, true, null); - // db2.CloseInput(true); - // string blockName = "test"; - // if (!tr.BlockTable.Has(blockName)) - // { - // // tr.Database.Insert(blockName, db2, false);// 插入块 - // db.Insert(blockName, db2, false); - - // } - - string fullFileName = @"C:\Users\vic\Desktop\001.dwg"; - var blockdef = tr.BlockTable.GetBlockFrom(fullFileName, false); - - tr.Database.Clayer = tr.LayerTable["0"];// 当前图层切换为0图层 - tr.LayerTable.Change(tr.Database.Clayer, ltr => - { - ltr.Color = Color.FromColorIndex(ColorMethod.ByAci, 2); // ColorMethod.ByAci可以让我们使用AutoCAD ACI颜色索引……这里为2(表示黄色) - }); - - var id = tr.ModelSpace.InsertBlock(Point3d.Origin, blockdef);// 插入块参照 - var brf = tr.GetObject(id); - brf?.Draw(); - } - - using DBTrans tr2 = new(); - PromptEntityOptions peo = new("\n请选择一个块"); - peo.SetRejectMessage("\n对象必须是块"); - peo.AddAllowedClass(typeof(BlockReference), true); - - var per = Env.Editor.GetEntity(peo); - if (per.Status != PromptStatus.OK) - return; - - var brf2 = tr2.GetObject(per.ObjectId)!; - // var BTR = tr.GetObject(Bref.BlockTableRecord, OpenMode.ForWrite); - //// 如果知道块名字BTRName - // BlockTableRecord BTR = tr.GetObject(tr.BlockTable[blockName], OpenMode.ForWrite); - - var btr = tr2.BlockTable[brf2.Name]; - - tr2.BlockTable.Change(btr, ltr => - { - foreach (ObjectId oid in ltr) - { - var ent = tr2.GetObject(oid); - if (ent is MText mText) - { - using (ent.ForWrite()) - switch (mText.Text) - { - case "$$A": - mText.Contents = "hahaha"; - break; - case "$$B": - break; - default: - break; - } - } - else if (ent is DBText dBText) - { - using (ent.ForWrite()) - dBText.TextString = "haha"; - } - else if (ent is Dimension dimension) - { - using (ent.ForWrite()) - switch (dimension.DimensionText) - { - case "$$pipeLen": - dimension.DimensionText = "350"; - dimension.RecomputeDimensionBlock(true); - break; - default: - break; - } - } - } - }); - tr2.Editor?.Regen(); - } - - [CommandMethod(nameof(Test_QuickBlockDef2))] - public void Test_QuickBlockDef2() - { - // Database db = HostApplicationServices.WorkingDatabase; - Editor ed = Acap.DocumentManager.MdiActiveDocument.Editor; - PromptSelectionOptions promptOpt = new() - { - MessageForAdding = "请选择需要快速制作块的对象" - }; - string blockName = "W_BLOCK_" + DateTime.Now.ToString("yyyyMMdd_HHmmss"); - // var rss = ed.GetSelection(promptOpt); - var rss = Env.Editor.GetSelection(promptOpt); - using DBTrans tr = new(); - if (rss.Status == PromptStatus.OK) - { - // SelectionSet ss = rss.Value; - // ObjectId[] ids = ss.GetObjectIds(); - // List> ents = []; - // var extents = new Extents3d(); - // foreach (var id in ids) - // { - // Entity ent = tr.GetObject(id); - // if (ent is null) - // continue; - // try - // { - // extents.AddExtents(ent.GeometricExtents); - // var order = id.Handle.Value; - // var newEnt = ent.Clone() as Entity; - // ents.Add(new KeyValuePair(newEnt, order)); - // ent.UpgradeOpen(); - // ent.Erase(); - // ent.DowngradeOpen(); - // } - // catch (System.Exception exc) - // { - // ed.WriteMessage(exc.Message); - // } - // } - // ents = ents.OrderBy(x => x.Value).ToList(); - var ents = rss.Value.GetEntities(); - // ents.ForEach(ent => extents.AddExtents(ent.GeometricExtents)); - var extents = ents!.GetExtents(); - Point3d pt = extents.MinPoint; - Matrix3d matrix = Matrix3d.Displacement(Point3d.Origin - pt); - // List newEnts = []; - // foreach (var ent in ents) - // { - // var newEnt = ent.Key; - // newEnt.TransformBy(matrix); - // newEnts.Add(newEnt); - // } - // if (tr.BlockTable.Has(blockName)) - // { - // Acap.ShowAlertDialog(Environment.NewLine + "块名重复,程序退出!"); - // return; - // } - ents.ForEach(ent => - ent?.ForWrite(e => e?.TransformBy(matrix))); - // var newents = ents.Select(ent => - // { - // var maping = new IdMapping(); - // return ent.DeepClone(ent, maping, true) as Entity; - // }); - var newents = ents.Select(ent => ent?.Clone() as Entity); - - // ents.ForEach(ent => ent.ForWrite(e => e.Erase(true))); // 删除实体就会卡死,比较奇怪,估计是Clone()函数的问题 - // 经过测试不是删除的问题 - var btrId = tr.BlockTable.Add(blockName, newents!); - ents.ForEach(ent => ent?.ForWrite(e => e?.Erase(true))); - var bId = tr.CurrentSpace.InsertBlock(pt, blockName); - // tr.GetObject(bId, OpenMode.ForWrite).Move(Point3d.Origin, Point3d.Origin); - // var ed = Acap.DocumentManager.MdiActiveDocument.Editor; - // ed.Regen(); - // tr.Editor.Regen(); - // 调用regen() 卡死 - } - // tr.Editor.Regen(); - // ed.Regen(); - // using (var tr = new DBTrans()) - // { - // tr.CurrentSpace.InsertBlock(Point3d.Origin, blockName); - // tr.Editor.Regen(); - // } - } - - [CommandMethod(nameof(Test_QuickBlockDef1))] - public void Test_QuickBlockDef1() - { - var dm = Acap.DocumentManager; - var doc = dm.MdiActiveDocument; - var db = doc.Database; - var ed = doc.Editor; - - PromptSelectionOptions promptOpt = new() - { - MessageForAdding = "请选择需要快速制作块的对象" - }; - string blockName = "W_BLOCK_" + DateTime.Now.ToString("yyyyMMdd_HHmmss"); - var rss = Env.Editor.GetSelection(promptOpt); - if (rss.Status != PromptStatus.OK) - return; - - using var tr = db.TransactionManager.StartTransaction(); - var ids = rss.Value.GetObjectIds(); - var bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable; - var btr = new BlockTableRecord - { - Name = blockName - }; - foreach (var item in ids) - { - var ent = tr.GetObject(item, OpenMode.ForRead) as Entity; - btr.AppendEntity(ent!.Clone() as Entity); - ent.ForWrite(e => e.Erase(true)); - } - bt!.UpgradeOpen(); - bt.Add(btr); - tr.AddNewlyCreatedDBObject(btr, true); - bt.DowngradeOpen(); - // tr.Commit(); - // } - - // using (var tr1 = db.TransactionManager.StartTransaction()) - // { - // var bt = tr1.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable; - var btr1 = tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord; - var brf = new BlockReference(Point3d.Origin, bt[blockName]) - { - ScaleFactors = default - }; - btr1!.AppendEntity(brf); - tr.AddNewlyCreatedDBObject(brf, true); - btr1.DowngradeOpen(); - ed.Regen(); - tr.Commit(); - // ed.Regen(); - } - - void Wblock() - { - var curdb = HostApplicationServices.WorkingDatabase; - PromptSelectionOptions opts = new() - { - MessageForAdding = "选择对象" - }; - var ss = Env.Editor.GetSelection(opts).Value; - using ObjectIdCollection ids = new(ss.GetObjectIds()); - var db = curdb.Wblock(ids, Point3d.Origin); - db.SaveAs(@"c:\test.dwg", DwgVersion.Current); - } - [CommandMethod(nameof(ChangeDynameicBlock))] - public void ChangeDynameicBlock() - { - var pro = new Dictionary - { - { "haha", 1 } - }; - var blockid = Env.Editor.GetEntity("选择个块").ObjectId; - using DBTrans tr = new(); - var brf = tr.GetObject(blockid)!; - brf.ChangeDynamicBlockProperty(pro); - // 这是第一个函数的用法 - } - [CommandMethod(nameof(ChangeBlockProperty))] - public void ChangeBlockProperty() - { - Dictionary? pro = new() - { - { "haha", "1" } - }; - var blockid = Env.Editor.GetEntity("选择个块").ObjectId; - using DBTrans tr = new(); - var brf = tr.GetObject(blockid)!; - brf.ChangeBlockProperty(pro); - // 这是第一个函数的用法 - } - - [CommandMethod(nameof(Test_Back))] - public void Test_Back() - { - string dir = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory); - string dwg = dir + "\\test.dwg"; - if (!File.Exists(dwg)) - { - System.Windows.Forms.MessageBox.Show(dwg, "你还没有创建此文件"); - return; - } - - using DBTrans tr = new(dwg); - tr.ModelSpace.GetEntities().ForEach(ent => - { - ent.ForWrite(e => e.ColorIndex = 3); - }); - tr.Database.SaveAs(dwg, DwgVersion.Current); - - tr.ModelSpace.GetEntities().ForEach(ent => - { - ent.ForWrite(e => e.ColorIndex = 4); - }); - tr.Database.SaveAs(dwg, DwgVersion.Current); - } - - [CommandMethod(nameof(Test_ExplodeBlock))] - public void Test_ExplodeBlock() - { - var r1 = Env.Editor.GetEntity("pick block"); - if (r1.Status != PromptStatus.OK) - return; - using var tr = new DBTrans(); - if (tr.GetObject(r1.ObjectId, OpenMode.ForWrite) is not BlockReference brf) - return; - var dboc = new DBObjectCollection(); - // brf.Explode(dboc); - brf.ExplodeToOwnerSpace(); - // foreach (Entity item in dboc) - // { - // tr.CurrentSpace.AddEntity(item); - // } - using (brf.ForWrite()) - { - brf.Erase(); - } - } -} - - - -public static class Blocks -{ - - [CommandMethod("TestExplodeToOwnerSpace3")] - public static void TestExplodeToOwnerSpace3_Method() - { - Editor ed = Application.DocumentManager.MdiActiveDocument.Editor; - try - { - PromptEntityOptions prEntOpt = new PromptEntityOptions("\nSelect an INSERT:"); - prEntOpt.SetRejectMessage("\nIt is not an INSERT!"); - prEntOpt.AddAllowedClass(typeof(BlockReference), true); - PromptEntityResult selRes = ed.GetEntity(prEntOpt); - if (selRes.Status == PromptStatus.OK) - { - ObjectIdCollection ids = ExplodeToOwnerSpace3(selRes.ObjectId); - ed.WriteMessage("{0} entities were added into database.", ids.Count); - } - else - { - ed.WriteMessage("\nEntity Selection failed!"); - } - } - catch (System.Exception ex) - { - ed.WriteMessage(ex.Message); - } - } - - public static void ExplodeToOwnerSpace2(ObjectId id, bool erase = true) - { - ExplodeToOwnerSpace3(id, erase); - } - - public static void ExplodeToOwnerSpace2(this BlockReference br) - { - ExplodeToOwnerSpace3(br); - } - - public static ObjectIdCollection ExplodeToOwnerSpace3(ObjectId id, bool erase = true) - { - ObjectIdCollection ids; - - using (Transaction tr = id.Database.TransactionManager.StartTransaction()) - { - BlockReference br = (BlockReference)tr.GetObject(id, OpenMode.ForRead); - ids = br.ExplodeToOwnerSpace3(); - - if (erase) - { - br.UpgradeOpen(); - br.Erase(); - } - - tr.Commit(); - } - - return ids; - } - - private static ObjectIdCollection idsAdded = []; - public static ObjectIdCollection ExplodeToOwnerSpace3(this BlockReference br) - { - idsAdded = new ObjectIdCollection(); - - Transaction tr = br.Database.TransactionManager.TopTransaction; - BlockTableRecord spaceBtr = (BlockTableRecord)tr.GetObject(br.BlockId, OpenMode.ForWrite); - LoopThroughInsertAndAddEntity2n3(br.BlockTransform, br, spaceBtr); - - return idsAdded; - } - // 不能用于非等比 - public static void LoopThroughInsertAndAddEntity2n3(Matrix3d mat, BlockReference br, BlockTableRecord space) - { - Transaction tr = space.Database.TransactionManager.TopTransaction; - BlockTableRecord btr = (BlockTableRecord)tr.GetObject(br.BlockTableRecord, OpenMode.ForRead); - - foreach (ObjectId id in btr) - { - DBObject obj = tr.GetObject(id, OpenMode.ForRead); - Entity? ent = obj.Clone() as Entity; - if (ent is BlockReference) - { - BlockReference br1 = (BlockReference)ent; - LoopThroughInsertAndAddEntity2n3(br1.BlockTransform.PreMultiplyBy(mat), br1, space); - } - else - { - ent?.TransformBy(mat); - space.AppendEntity(ent); - tr.AddNewlyCreatedDBObject(ent, true); - - idsAdded.Add(ent!.ObjectId); - } - } - } - -} - - -public class BlockImportClass -{ - [CommandMethod(nameof(Test_Cbll))] - public void Test_Cbll() - { - string filename = @"C:\Users\vic\Desktop\Drawing1.dwg"; - using DBTrans tr = new(); - using DBTrans tr1 = new(filename); - // tr.BlockTable.GetBlockFrom(filename, true); - string blkdefname = SymbolUtilityServices.RepairSymbolName(SymbolUtilityServices.GetSymbolNameFromPathName(filename, "dwg"), false); - tr.Database.Insert(blkdefname, tr1.Database, false); // 插入了块定义,未插入块参照 - } - - - [CommandMethod(nameof(Test_CombineBlocksIntoLibrary))] - public void Test_CombineBlocksIntoLibrary() - { - Document doc = Acap.DocumentManager.MdiActiveDocument; - Editor ed = doc.Editor; - Database destDb = doc.Database; - - PromptResult pr = ed.GetString("\nEnter the folder of source drawings: "); - - if (pr.Status != PromptStatus.OK) - return; - string pathName = pr.StringResult; - if (!Directory.Exists(pathName)) - { - ed.WriteMessage("\nDirectory does not exist: {0}", pathName); - return; - } - string[] fileNames = Directory.GetFiles(pathName, "*.dwg"); - int imported = 0, failed = 0; - foreach (string fileName in fileNames) - { - if (fileName.EndsWith(".dwg", - StringComparison.InvariantCultureIgnoreCase)) - { - // Catch exceptions at the file level to allow skipping - try - { - // Suggestion from Thorsten Meinecke... - - string destName = - SymbolUtilityServices.GetSymbolNameFromPathName( - fileName, "dwg" - ); - - // And from Dan Glassman... - - destName = - SymbolUtilityServices.RepairSymbolName( - destName, false - ); - - // Create a source database to load the DWG into - - using Database db = new(false, true); - // Read the DWG into our side database - - db.ReadDwgFile(fileName, FileShare.Read, true, ""); - bool isAnno = db.AnnotativeDwg; - - // Insert it into the destination database as - // a named block definition - - ObjectId btrId = destDb.Insert( - destName, - db, - false - ); - - if (isAnno) - { - // If an annotative block, open the resultant BTR - // and set its annotative definition status - - Transaction tr = - destDb.TransactionManager.StartTransaction(); - using (tr) - { - BlockTableRecord btr = - (BlockTableRecord)tr.GetObject( - btrId, - OpenMode.ForWrite - ); - btr.Annotative = AnnotativeStates.True; - tr.Commit(); - } - } - - // Print message and increment imported block counter - - ed.WriteMessage("\nImported from \"{0}\".", fileName); - imported++; - } - catch (System.Exception ex) - { - ed.WriteMessage( - "\nProblem importing \"{0}\": {1} - file skipped.", - fileName, ex.Message - ); - failed++; - } - } - } - - ed.WriteMessage( - "\nImported block definitions from {0} files{1} in " + - "\"{2}\" into the current drawing.", - imported, - failed > 0 ? " (" + failed + " failed)" : "", - pathName - ); - } - -} \ No newline at end of file diff --git a/tests/TestShared/TestCadFilePath.cs b/tests/TestShared/TestCadFilePath.cs deleted file mode 100644 index 4a32dd5..0000000 --- a/tests/TestShared/TestCadFilePath.cs +++ /dev/null @@ -1,30 +0,0 @@ - -namespace Test; - -public class TestCadFilePath -{ - [CommandMethod("TestCadFilePath")] - public void TestCadFilePathfun() - { - string key = HostApplicationServices.Current.UserRegistryProductRootKey; - // 计算机\HKEY_CURRENT_USER\SOFTWARE\Autodesk\AutoCAD\R24.0\ACAD-4101:804 - RegistryKey ackey = Registry.CurrentUser.OpenSubKey(key); - var profileskey = ackey.OpenSubKey("Profiles"); - - var listkey = profileskey.GetSubKeyNames(); - foreach (var item in listkey) - { - var acadkey = profileskey.OpenSubKey($@"{item}\General",true); - var name = "ACAD"; - var str = acadkey.GetValue(name)?.ToString(); - if (str is not null && !str.Contains("nihao")) - { - Env.Print(str); - acadkey.SetValue(name, $@"{str}\nihao;", RegistryValueKind.String); - } - - - } - - } -} diff --git a/tests/TestShared/TestConvexHull.cs b/tests/TestShared/TestConvexHull.cs deleted file mode 100644 index 03692ae..0000000 --- a/tests/TestShared/TestConvexHull.cs +++ /dev/null @@ -1,76 +0,0 @@ -namespace Test; - - -public class TestConvexHull -{ - [CommandMethod(nameof(Test_ConvexHull))] - public void Test_ConvexHull() - { - // using DBTrans tr = new(); - // List pts = []; - // var flag = true; - // while (flag) - // { - // var pt = tr.Editor.GetPoint("qudian"); - // if (pt.Status == PromptStatus.OK) - // { - // pts.Add(pt.Value); - // tr.CurrentSpace.AddEntity(new DBPoint(pt.Value)); - // } - // else - // { - // flag = false; - // } - - // } - - // var ptt = ConvexHull.GetConvexHull(pts); - - // Polyline pl = new Polyline(); - // for (int i = 0; i < ptt.Count; i++) - // { - // pl.AddVertexAt(i, ptt[i].Point2d(), 0, 0, 0); - // } - //// pl.AddVertexAt(0, new Point2d(0, 0), 0, 0, 0); - //// pl.AddVertexAt(1, new Point2d(10, 10), 0, 0, 0); - //// pl.AddVertexAt(2, new Point2d(20, 20), 0, 0, 0); - //// pl.AddVertexAt(3, new Point2d(30, 30), 0, 0, 0); - //// pl.AddVertexAt(4, new Point2d(40, 40), 0, 0, 0); - // pl.Closed = true; - // pl.Color = Color.FromColorIndex(ColorMethod.ByColor, 6); - // tr.CurrentSpace.AddEntity(pl); - - // var a1 = GeometryEx.GetArea(new Point2d(0, 0), new Point2d(1, 0), new Point2d(1, 1)); - // var a2 = ConvexHull.cross(new Point3d(0, 0, 0), new Point3d(1, 0, 0), new Point3d(1, 1, 0)); - // tr.Editor.WriteMessage(a1.ToString()); - // tr.Editor.WriteMessage(a2.ToString()); - - - // var vec1 = new Vector2d(1, 1); - // var vec2 = new Vector2d(-1, 1); - - // var vec3 = vec1.GetPerpendicularVector(); - // var vec4 = vec2.GetPerpendicularVector(); - - // var area1 = vec2.DotProduct(vec1.GetPerpendicularVector()); - // var area2 = vec1.DotProduct(vec2.GetPerpendicularVector()); - - // var area3 = vec2.DotProduct(vec1); - // var area4 = vec1.DotProduct(vec2); - - var area5 = GeometryEx.GetArea(new List { new Point2d(0, 0), new Point2d(1, 1), new Point2d(-1, 1) }); - - var area6 = GeometryEx.GetArea(new List { new Point2d(0, 0), new Point2d(-1, 1), new Point2d(1, 1) }); - // Env.Editor.WriteMessage($"vec1 的法向量= {vec3} \n"); - // Env.Editor.WriteMessage($"vec2 的法向量= {vec4} \n"); - - // Env.Editor.WriteMessage($"vec2 点乘 vec1的法向量= {area1} \n"); - // Env.Editor.WriteMessage($"vec1 点乘 vec2的法向量= {area2} \n"); - - // Env.Editor.WriteMessage($"vec2 点乘 vec1= {area3} \n"); - // Env.Editor.WriteMessage($"vec1 点乘 vec2= {area4} \n"); - - Env.Editor.WriteMessage($"点集的有向面积:{area5} \n"); - Env.Editor.WriteMessage($"点集的有向面积:{area6} \n"); - } -} \ No newline at end of file diff --git a/tests/TestShared/TestCurve.cs b/tests/TestShared/TestCurve.cs deleted file mode 100644 index 075bcc9..0000000 --- a/tests/TestShared/TestCurve.cs +++ /dev/null @@ -1,319 +0,0 @@ -namespace Test; - -public class TestGraph -{ - [CommandMethod(nameof(Test_PointInDict))] - public void Test_PointInDict() - { - var pt1 = new Point3d(0.0255, 0.452, 0); - var pt2 = new Point3d(0.0255001, 0.452003, 0); - var pt3 = new Point3d(0.0255002, 0.4520001, 0); - var pt4 = new Point3d(0.0255450, 0.45287893, 0); - var pt5 = new Point3d(0.02554935, 0.452092375, 0); - var dict = new Dictionary - { - { pt1, 1 }, - { pt2, 2 }, - { pt3, 3 }, - { pt4, 4 }, - { pt5, 5 } - }; - Env.Print(dict[pt1]); - } - - [CommandMethod(nameof(Test_Graph1))] - public void Test_Graph1() - { - using DBTrans tr = new(); - var ents = Env.Editor.SSGet()?.Value?.GetEntities(); - if (ents == null) - return; - Tools.TestTimes2(1, "new", () => { - var res = ents!.GetAllCycle(); - - // res.ForEach((i, t) => t.ForWrite(e => e.ColorIndex = i + 1)); - Env.Print(res.Count()); - tr.CurrentSpace.AddEntity(res); - }); - } - - [CommandMethod(nameof(Test_Graphspeed))] - public void Test_Graphspeed() - { - using DBTrans tr = new(); - var ents = Env.Editor.SSGet()?.Value?.GetEntities(); - if (ents == null) - return; - - var graph = new IFoxCAD.Cad.Graph(); // 为了调试先把图的访问改为internal - foreach (var curve in ents) - { - graph.AddEdge(curve!.GetGeCurve()); - } - - // 新建 dfs - var dfs = new DepthFirst(); -#if true - Tools.TestTimes2(100, "new", () => { - // 查询全部的 闭合环 - dfs.FindAll(graph); - }); - Tools.TestTimes2(1000, "new", () => { - // 查询全部的 闭合环 - dfs.FindAll(graph); - }); -#else - Tools.TestTimes2(100, "old", () => { - // 查询全部的 闭合环 - dfs.FindAll(graph); - }); - Tools.TestTimes2(1000, "old", () => { - // 查询全部的 闭合环 - dfs.FindAll(graph); - }); -#endif - // res.ForEach((i, t) => t.ForWrite(e => e.ColorIndex = i + 1)); - - // tr.CurrentSpace.AddEntity(res); - } -} - - - -public partial class TestCurve -{ - [CommandMethod(nameof(Test_CurveExtend))] - public void Test_CurveExtend() - { - using var tr = new DBTrans(); - var ent = Env.Editor.GetEntity("pick curve").ObjectId.GetObject(); - if (ent is Curve curve) - curve.ForWrite(e => e.Extend(e.EndParam + 1)); - - } - - - private Arc ToArc1(CircularArc2d a2d) - { - double startangle, endangle; - double refangle = a2d.ReferenceVector.Angle; - - if (a2d.IsClockWise) - { - startangle = -a2d.EndAngle + refangle; - endangle = -a2d.StartAngle + refangle; - } - else - { - startangle = a2d.StartAngle + refangle; - endangle = a2d.EndAngle + refangle; - } - - return - new Arc( - new Point3d(new Plane(), a2d.Center), - Vector3d.ZAxis, - a2d.Radius, - startangle, - endangle); - } - - - [CommandMethod(nameof(Test_Curve_ToArc))] - public void Test_Curve_ToArc() - { - using var tr = new DBTrans(); - var gearc = new CircularArc2d(new Point2d(0,0),new Point2d(0.5,0.5),new Point2d(1,0)); - var dbarc = gearc.ToArc(); - var dbarc1 = ToArc1(gearc); - dbarc.ColorIndex = 1; - tr.CurrentSpace.AddEntity(dbarc); - dbarc1.ColorIndex = 2; - tr.CurrentSpace.AddEntity(dbarc1); - - var gearc3 = new CircularArc3d(new(0,0,0),new(0.5,0.5,0),new Point3d(1,0,0)); - var dbarc3 = (Arc)Curve.CreateFromGeCurve(gearc3); - dbarc3.ColorIndex = 3; - tr.CurrentSpace.AddEntity(dbarc3); - - - - Polyline pl0 = new();//创建有圆弧的多段线 - - pl0.AddVertexAt(0, new(-520, 200), -0.74, 0, 0); - pl0.AddVertexAt(1, new(-100, 140), 0.52, 0, 0); - pl0.AddVertexAt(2, new(16, -120), -0.27, 0, 0); - pl0.AddVertexAt(3, new(400, -130), 0.75, 0, 0); - pl0.AddVertexAt(4, new(450, 200), -0.69, 0, 0); - tr.CurrentSpace.AddEntity(pl0); - - - for (int FFF = 0; FFF < pl0.NumberOfVertices; FFF++) - { - if (pl0.GetSegmentType(FFF) == SegmentType.Arc) - { - var bulge = pl0.GetBulgeAt(FFF); - - //将 CircularArc2d 转为Arc 颜色为红 - CircularArc2d arc2d = pl0.GetArcSegment2dAt(FFF); - - Arc arc = arc2d.ToArc(); - if (bulge < 0) arc.ReverseCurve(); - arc.ColorIndex = 1; - tr.CurrentSpace.AddEntity(arc); - Env.Printl($"arc的ge:ReferenceVector:{MathEx.ConvertRadToDeg(arc2d.ReferenceVector.Angle)}"); - Env.Printl($"arc的ge:顺时针:{arc2d.IsClockWise}"); - Env.Printl($"arc的ge:起点角度:{MathEx.ConvertRadToDeg(arc2d.StartAngle)},终点角度:{MathEx.ConvertRadToDeg(arc2d.EndAngle)}"); - Env.Printl($"arc的db:起点角度:{MathEx.ConvertRadToDeg(arc.StartAngle)},终点角度:{MathEx.ConvertRadToDeg(arc.EndAngle)}"); - - //将 CircularArc2d 转为Arc 颜色为黄 - CircularArc2d arc2d1 = pl0.GetArcSegment2dAt(FFF); - Arc arc1 = ToArc1(arc2d1); - if (bulge < 0) arc1.ReverseCurve(); - arc1.ColorIndex = 2; - tr.CurrentSpace.AddEntity(arc1); - Env.Printl($"arc1的ge:ReferenceVector:{MathEx.ConvertRadToDeg(arc2d1.ReferenceVector.Angle)}"); - Env.Printl($"arc的ge:顺时针:{arc2d1.IsClockWise}"); - Env.Printl($"arc1的ge:起点角度:{MathEx.ConvertRadToDeg(arc2d1.StartAngle)} ,终点角度: {MathEx.ConvertRadToDeg(arc2d1.EndAngle)}"); - Env.Printl($"arc1的db:起点角度:{MathEx.ConvertRadToDeg(arc1.StartAngle)} ,终点角度: {MathEx.ConvertRadToDeg(arc1.EndAngle)}"); - - //将 CircularArc3d 转为Arc 颜色为黄色 - CircularArc3d arc3d = pl0.GetArcSegmentAt(FFF); - Arc arc2 = arc3d.ToArc(); - - arc2.ColorIndex = 3; - tr.CurrentSpace.AddEntity(arc2); - Env.Printl($"arc2的ge:ReferenceVector:{MathEx.ConvertRadToDeg(arc3d.ReferenceVector.AngleOnPlane(new Plane()))}"); - Env.Printl($"arc2的ge:起点角度:{MathEx.ConvertRadToDeg(arc3d.StartAngle)} ,终点角度: {MathEx.ConvertRadToDeg(arc3d.EndAngle)}"); - Env.Printl($"arc2的db:起点角度:{MathEx.ConvertRadToDeg(arc2.StartAngle)} ,终点角度: {MathEx.ConvertRadToDeg(arc2.EndAngle)}"); - -/* - - -arc的ge: ReferenceVector:154.872779886857 -arc的ge: 顺时针:True -arc的ge:起点角度:0,终点角度:146.005764482025 -arc的db: 起点角度:334.872779886857,终点角度:120.878544368882 -arc1的ge: ReferenceVector:154.872779886857 -arc的ge: 顺时针:True -arc1的ge:起点角度:0 ,终点角度: 146.005764482025 -arc1的db: 起点角度:334.872779886857 ,终点角度: 120.878544368882 -arc2的ge: ReferenceVector:154.872779886857 -arc2的ge: 起点角度:0 ,终点角度: 146.005764482025 -arc2的db: 起点角度:25.1272201131434 ,终点角度: 171.132984595169 - - -arc的ge: ReferenceVector:149.095360016814 -arc的ge: 顺时针:False -arc的ge:起点角度:0,终点角度:109.897726505109 -arc的db: 起点角度:149.095360016814,终点角度:258.993086521922 -arc1的ge: ReferenceVector:149.095360016814 -arc的ge: 顺时针:False -arc1的ge:起点角度:0 ,终点角度: 109.897726505109 -arc1的db: 起点角度:149.095360016814 ,终点角度: 258.993086521922 -arc2的ge: ReferenceVector:149.095360016814 -arc2的ge: 起点角度:0 ,终点角度: 109.897726505109 -arc2的db: 起点角度:149.095360016814 ,终点角度: 258.993086521922 - - -arc的ge: ReferenceVector:118.727409809308 -arc的ge: 顺时针:True -arc的ge:起点角度:0,终点角度:60.4383004893619 -arc的db: 起点角度:298.727409809308,终点角度:359.16571029867 -arc1的ge: ReferenceVector:118.727409809308 -arc的ge: 顺时针:True -arc1的ge:起点角度:0 ,终点角度: 60.4383004893619 -arc1的db: 起点角度:298.727409809308 ,终点角度: 359.16571029867 -arc2的ge: ReferenceVector:118.727409809308 -arc2的ge: 起点角度:0 ,终点角度: 60.4383004893619 -arc2的db: 起点角度:61.2725901906918 ,终点角度: 121.710890680054 - - -arc的ge: ReferenceVector:277.644556524148 -arc的ge: 顺时针:False -arc的ge:起点角度:0,终点角度:147.479590583376 -arc的db: 起点角度:277.644556524148,终点角度:65.124147107524 -arc1的ge: ReferenceVector:277.644556524148 -arc的ge: 顺时针:False -arc1的ge:起点角度:0 ,终点角度: 147.479590583376 -arc1的db: 起点角度:277.644556524148 ,终点角度: 65.124147107524 -arc2的ge: ReferenceVector:277.644556524148 -arc2的ge: 起点角度:0 ,终点角度: 147.479590583376 -arc2的db: 起点角度:277.644556524148 ,终点角度: 65.124147107524 - - - - - - -*/ - } - } - - } -} - - -public partial class TestCurve -{ - [CommandMethod(nameof(Test_BreakCurve))] - public void Test_BreakCurve() - { - using DBTrans tr = new(); - var ents = Env.Editor.SSGet()?.Value.GetEntities(); - if (ents is null) - return; - var tt = CurveEx.BreakCurve(ents.ToList()!); - tt.ForEach(t => t.ForWrite(e => e.ColorIndex = 1)); - tr.CurrentSpace.AddEntity(tt); - } - - [CommandMethod(nameof(Test_CurveCurveIntersector3d))] - public void Test_CurveCurveIntersector3d() - { - using DBTrans tr = new(); - var ents = Env.Editor.SSGet()? - .Value.GetEntities() - .Select(e => e?.ToCompositeCurve3d()).ToList(); - if (ents == null) - return; - - var cci3d = new CurveCurveIntersector3d(); - for (int i = 0; i < ents.Count; i++) - { - var gc1 = ents[i]; - var int1 = gc1?.GetInterval(); - // var pars1 = paramss[i]; - for (int j = i; j < ents.Count; j++) - { - var gc2 = ents[j]; - // var pars2 = paramss[j]; - var int2 = gc2?.GetInterval(); - cci3d.Set(gc1, gc2, int1, int2, Vector3d.ZAxis); - var d = cci3d.OverlapCount(); - var a = cci3d.GetIntersectionRanges(); - Env.Print($"{a[0].LowerBound}-{a[0].UpperBound} and {a[1].LowerBound}-{a[1].UpperBound}"); - for (int m = 0; m < d; m++) - { - var b = cci3d.GetOverlapRanges(m); - Env.Print($"{b[0].LowerBound}-{b[0].UpperBound} and {b[1].LowerBound}-{b[1].UpperBound}"); - } - - for (int k = 0; k < cci3d.NumberOfIntersectionPoints; k++) - { - // var a = cci3d.GetOverlapRanges(k); - // var b = cci3d.IsTangential(k); - // var c = cci3d.IsTransversal(k); - // var d = cci3d.OverlapCount(); - // var e = cci3d.OverlapDirection(); - var pt = cci3d.GetIntersectionParameters(k); - var pts = cci3d.GetIntersectionPoint(k); - Env.Print(pts); - } - } - } - // var tt = CurveEx.Topo(ents.ToList()); - // tt.ForEach(t => t.ForWrite(e => e.ColorIndex = 1)); - // tr.CurrentSpace.AddEntity(tt); - } -} \ No newline at end of file diff --git a/tests/TestShared/TestDBTrans.cs b/tests/TestShared/TestDBTrans.cs deleted file mode 100644 index 41eb67d..0000000 --- a/tests/TestShared/TestDBTrans.cs +++ /dev/null @@ -1,203 +0,0 @@ -namespace Test; - -public class TestTrans -{ - [CommandMethod(nameof(Test_DBTrans))] - public void Test_DBTrans() - { - using DBTrans tr = new(); - if (tr.Editor is null) - return; - tr.Editor.WriteMessage("\n测试 Editor 属性是否工作!"); - tr.Editor.WriteMessage("\n----------开始测试--------------"); - tr.Editor.WriteMessage("\n测试document属性是否工作"); - if (tr.Document == Getdoc()) - { - tr.Editor.WriteMessage("\ndocument 正常"); - } - tr.Editor.WriteMessage("\n测试database属性是否工作"); - if (tr.Database == Getdb()) - { - tr.Editor.WriteMessage("\ndatabase 正常"); - } - } - - private static Database Getdb() - { - var db = Acaop.DocumentManager.MdiActiveDocument.Database; - return db; - } - - private static Document Getdoc() - { - var doc = Acaop.DocumentManager.MdiActiveDocument; - return doc; - } - - - - - [CommandMethod(nameof(CmdTest_DBTransActiveOpenDwg), CommandFlags.Session)] - public static void CmdTest_DBTransActiveOpenDwg() - { - using DBTrans tr = new(@"D:\桌面\AA.dwg", activeOpen: true); - } - - [CommandMethod(nameof(CmdTest_ForEachDemo))] - public static void CmdTest_ForEachDemo() - { - using DBTrans tr = new(); - - // 泛型扩展(用变量名来使用它) - tr.BlockTable.ForEach(action: (id) => { - //Debugger.Break();// 为什么cad工程不能断点进入呢? - id.Print(); - Console.WriteLine(id); - }); - - //tr.BlockTable.ForEach(asdad); - //void asdad(object id) - //{ - // id.Print(); - //} - - tr.BlockTable.ForEach(action: (id) => { - id.Print(); - }); - tr.BlockTable.ForEach(action: (id, state, index) => { - id.Print(); - }); - - // 符号表扩展(会顶替泛型扩展) - tr.BlockTable.ForEach((btr) => { // 预处理设置不进入ForEach函数体内 - btr.Print();// 此处可以设置断点 - }, OpenMode.ForRead, checkIdOk: true); - tr.BlockTable.ForEach((btr, state) => {// 预处理设置不进入ForEach函数体内 - btr.Print();// 此处可以设置断点 - }, OpenMode.ForRead, checkIdOk: true); - tr.BlockTable.ForEach((btr, state, index) => { // 预处理设置不进入ForEach函数体内 - btr.Print();// 此处可以设置断点 - }, OpenMode.ForRead, checkIdOk: true); - - // 修改:此处有缺陷:cad08会获取已经删除的块表记录,需要检查id.IsOk(),用ForEach代替 - // tr.BlockTable.Change("块表记录", btr => { - // }); - - // 修改:此处无缺陷 - tr.BlockTable.Change(tr.ModelSpace.ObjectId, modelSpace => { // 特性设置不进入函数体内 - var ents = modelSpace.GetEntities(); // 此处不会检查id.IsOk() - - modelSpace.ForEach(id => { // 利用遍历检查id.IsOk() - if (id.IsOk()) - id.Print(); - }); - }); - } - - - - // 后台:不存在路径的dwg会在桌面进行临时保存 - [CommandMethod(nameof(FileNotExist))] - public void FileNotExist() - { - using DBTrans tr = new("test.dwg"); - tr.Database.SaveFile((DwgVersion)24, false); - } - - // 前台:由于是弹出面板,此时路径不会起任何作用 - [CommandMethod(nameof(FileNotExist2))] - public void FileNotExist2() - { - using DBTrans tr = new(); - tr.Database.SaveFile(saveAsFile: "D:\\"); - } - - // 后台:只有路径,没有文件名 - [CommandMethod(nameof(FileNotExist3))] - public void FileNotExist3() - { - using DBTrans tr = new("D:\\"); - tr.Database.SaveDwgFile(); - - using DBTrans tr2 = new("D:\\"); - tr2.Database.SaveFile(saveAsFile: "D:\\"); - } - - - [CommandMethod(nameof(Test_SaveDwgFile))] - public void Test_SaveDwgFile() - { - string filename = @"C:\Users\vic\Desktop\test.dwg"; - using DBTrans tr = new(filename); - var circle = CircleEx.CreateCircle(new Point3d(10, 10, 0), 20)!; - tr.ModelSpace.AddEntity(circle); - // tr.Database.SaveAs(filename,DwgVersion.Current); - tr.Database.SaveDwgFile(); - } - [CommandMethod(nameof(Test_DBTransAbort))] - public void Test_DBTransAbort() - { - using DBTrans tr = new(); - var circle = CircleEx.CreateCircle(new Point3d(10, 10, 0), 20)!; - tr.ModelSpace.AddEntity(circle); - tr.Abort(); - // tr.Commit(); - } - - // AOP 应用 预计示例: - // 1. 无参数 - // [AOP] - // [CommandMethod(nameof(Test_AOP1))] - // public void TestAOP1() - // { - // // 不用 using DBTrans tr = new(); - // var tr = DBTrans.Top; - // tr.ModelSpace.AddCircle(new Point3d(0, 0, 0), 20); - // } - - // 2. 有参数 - // [AOP("file")] - // [CommandMethod(nameof(Test_AOP2))] - // public void TestAOP2() - // { - // // 不用 using var tr = new DBTrans(file); - // var tr = DBTrans.Top; - // tr.ModelSpace.AddCircle(new Point3d(0, 0, 0), 20); - // } - - - [CommandMethod(nameof(Test_TopTransaction))] - public void Test_TopTransaction() - { - // var pt = Env.Editor.GetPoint("pick pt:").Value; - // var pl = Env.Editor.GetEntity("pick pl").ObjectId; - - var tr1 = HostApplicationServices.WorkingDatabase.TransactionManager.TopTransaction; - using DBTrans tr2 = new(); - var tr3 = HostApplicationServices.WorkingDatabase.TransactionManager.TopTransaction; - var tr6 = Acaop.DocumentManager.MdiActiveDocument.TransactionManager.TopTransaction; - Env.Print(tr2.Transaction == tr3); - Env.Print(tr3 == tr6); - using DBTrans tr4 = new(); - var tr5 = HostApplicationServices.WorkingDatabase.TransactionManager.TopTransaction; - var tr7 = Acaop.DocumentManager.MdiActiveDocument.TransactionManager.TopTransaction; - Env.Print(tr4.Transaction == tr5); - Env.Print(tr5 == tr7); - var trm = HostApplicationServices.WorkingDatabase.TransactionManager; - - } - - [CommandMethod(nameof(Test_DBTrans_BlockCount))] - public void Test_DBTrans_BlockCount() - { - using var tr = new DBTrans(); - var i = tr.CurrentSpace - .GetEntities() - .Where(ent => ent.GetBlockName() == "自定义块"); - - var block = i.ToList()[0]; - Env.Print(i.Count()); - } - - -} \ No newline at end of file diff --git a/tests/TestShared/TestDBobject.cs b/tests/TestShared/TestDBobject.cs deleted file mode 100644 index f0cb142..0000000 --- a/tests/TestShared/TestDBobject.cs +++ /dev/null @@ -1,27 +0,0 @@ - - -namespace TestShared -{ - public static class TestDBobject - { - [CommandMethod(nameof(TestForWrite))] - public static void TestForWrite() - { - using var tr = new DBTrans(); - var ent = Env.Editor.GetEntity("\npick entity"); - if (ent.Status is not PromptStatus.OK) return; - var entid = ent.ObjectId.GetObject()!; - Tools.TestTimes3(100000, "using:", i => { - using (entid.ForWrite()) - { - entid.ColorIndex = i % 7; - } - }); - Tools.TestTimes3(100000, "action:", i => { - entid.ForWrite(e => { - e.ColorIndex = i % 7; - }); - }); - } - } -} diff --git a/tests/TestShared/TestDwgFilerEx.cs b/tests/TestShared/TestDwgFilerEx.cs deleted file mode 100644 index 6513cda..0000000 --- a/tests/TestShared/TestDwgFilerEx.cs +++ /dev/null @@ -1,161 +0,0 @@ -#if false -namespace Test; - -using DxfFiler = IFoxCAD.Cad.DxfFiler; - -public class CmdTestDwgFilerEx -{ - [CommandMethod(nameof(CmdTest_DwgFilerEx))] - public static void CmdTest_DwgFilerEx() - { - var dm = Acap.DocumentManager; - var doc = dm.MdiActiveDocument; - var db = doc.Database; - var ed = doc.Editor; - ed.WriteMessage("\n****测试,序列化图元"); - - var ssPsr = ed.SelectImplied();// 预选 - if (ssPsr.Status != PromptStatus.OK) - { - ssPsr = ed.GetSelection();// 手选 这里输入al会变成all,无法删除ssget的all关键字 - if (ssPsr.Status != PromptStatus.OK) - return; - } - - using DBTrans tr = new(); - var ids = ssPsr.Value.GetObjectIds(); - foreach (var id in ids) - { - if (!id.IsOk()) - continue; - var ent = tr.GetObject(id, OpenMode.ForRead); - if (ent is null) - continue; - var dwgFilerEx = new DwgFilerEx(ent); - ed.WriteMessage(Environment.NewLine + dwgFilerEx.ToString()); - } - } - - [CommandMethod(nameof(CmdTest_EntDxfout))] - public static void CmdTest_EntDxfout() - { - var dm = Acap.DocumentManager; - var doc = dm.MdiActiveDocument; - var db = doc.Database; - var ed = doc.Editor; - - // 定义选择集选项 - var pso = new PromptSelectionOptions - { - RejectObjectsOnLockedLayers = true, // 不选择锁定图层对象 - AllowDuplicates = true, // 不允许重复选择 - }; - var ssPsr = ed.GetSelection(pso);// 手选 这里输入al会变成all,无法删除ssget的all关键字 - if (ssPsr.Status != PromptStatus.OK) - return; - - using DBTrans tr = new(); - var ids = ssPsr.Value.GetObjectIds(); - foreach (var id in ids) - { - if (!id.IsOk()) - continue; - var ent = tr.GetObject(id, OpenMode.ForRead); - if (ent is null) - continue; - // ResultBuffer rbDxf = new(); - var filer = new DxfFiler(ent.UnmanagedObject, true);/// 这里有问题 - ent.DxfOut(filer); - } - } - - - [CommandMethod(nameof(CmdTest_TextOut))] - public static void CmdTest_TextOut() - { - var dm = Acap.DocumentManager; - var doc = dm.MdiActiveDocument; - var db = doc.Database; - var ed = doc.Editor; - -#if true - var peo1 = new PromptEntityOptions(Environment.NewLine + "点选源TCH_WIREDIM2:") - { - AllowObjectOnLockedLayer = false, - AllowNone = false - }; - var gt1 = ed.GetEntity(peo1); - if (gt1.Status != PromptStatus.OK) - return; -#else - var peo2 = new PromptEntityOptions(Environment.NewLine + "点选目标TCH_WIREDIM2:") - { - AllowObjectOnLockedLayer = false, - AllowNone = false - }; - var gt2 = ed.GetEntity(peo2); - if (gt2.Status != PromptStatus.OK) - return; -#endif - - using DBTrans tr = new(); - var dwgFilerEx = new DwgFilerEx(); - var bText = tr.GetObject(gt1.ObjectId, OpenMode.ForRead); - if (bText is null) - return; - - // DwgFilerEx.StringList[0] = "1@2@3@4@5@6@7@"; - // 复制 TCH_WIREDIM2 不行,TEXT 也不行,直接崩溃。line等线就没事 - bText.DwgOut(dwgFilerEx.DwgFiler); - - int testNum = 1 | 2 | 4 | 8; - - if ((testNum & 1) == 1) - { - // 错误,原地克隆也是不行的,它会生成在了模型中. - var sIds = new List - { - bText.ObjectId - }; - // 克隆到目标块表内 - using ObjectIdCollection bindIds = new(sIds.ToArray()); - using IdMapping map = new(); - - tr.CurrentSpace.DeepCloneEx(bindIds, map); - var newTexts = map.GetValues().GetObject(); - newTexts.ForEach(nText => { - if (nText == null) - return; - // 通过上面的克隆就已经在块表上面了.所以下面的设置也跟设置到已有图元上一样报错. - nText.UpgradeOpen(); - nText.DwgIn(dwgFilerEx); - tr.CurrentSpace.AddEntity(nText); - nText.DowngradeOpen(); - }); - } - if ((testNum & 2) == 2) - { - // 出错 - // 直接设置 - bText.DwgIn(dwgFilerEx); - } - if ((testNum & 4) == 4) - { - // 出错 - // 此时是内存中对象.... - var nText = (DBText)bText.Clone(); - nText.DwgIn(dwgFilerEx); - tr.CurrentSpace.AddEntity(nText); - } - if ((testNum & 8) == 8) - { - // 新对象相当于克隆,是ok的 - DBText nText = new(); - nText.SetDatabaseDefaults(); - nText.DwgIn(dwgFilerEx); - tr.CurrentSpace.AddEntity(nText); - } - } -} - -#endif \ No newline at end of file diff --git a/tests/TestShared/TestDwgMark.cs b/tests/TestShared/TestDwgMark.cs deleted file mode 100644 index cf0d712..0000000 --- a/tests/TestShared/TestDwgMark.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Test; -using IFoxCAD.Cad; -public class TestDwgMark { - [CommandMethod(nameof(DwgMarktest))] - public void DwgMarktest() { - FileInfo file = new FileInfo(@"D:\TEST\1.dwg"); - DwgMark.AddMark(file, 0x4D); - DwgMark.RemoveMark(file); - int A = DwgMark.GetMark(file); - } -} \ No newline at end of file diff --git a/tests/TestShared/TestEditor.cs b/tests/TestShared/TestEditor.cs deleted file mode 100644 index 52b99aa..0000000 --- a/tests/TestShared/TestEditor.cs +++ /dev/null @@ -1,87 +0,0 @@ -namespace Test; - -public class Testeditor -{ - [CommandMethod(nameof(Test_Editor))] - public void Test_Editor() - { - var pts = new List - { - new Point2d(0,0), - new Point2d(0,1), - new Point2d(1,1), - new Point2d(1,0) - }; - var res = EditorEx.GetLines(pts, false); - var res1 = EditorEx.GetLines(pts, true); - var res2 = pts.Select(pt => new TypedValue((int)LispDataType.Point2d, pt)).ToList(); - - Editor ed = Acap.DocumentManager.MdiActiveDocument.Editor; - var pt = ed.GetPoint("qudiam", new Point3d(0, 0, 0)); - var d = ed.GetDouble("qudoule"); - var i = ed.GetInteger("quint"); - var s = ed.GetString("qustr"); - Env.Editor.WriteMessage(""); - } - [CommandMethod(nameof(Test_Zoom))] - public void Test_Zoom() - { - using DBTrans tr = new(); - var res = Env.Editor.GetEntity("\npick ent:"); - if (res.Status == PromptStatus.OK) - Env.Editor.ZoomObject(res.ObjectId.GetObject()!); - } - [CommandMethod(nameof(Test_ZoomExtents))] - public void Test_ZoomExtents() - { - // using DBTrans tr = new(); - // var res = Env.Editor.GetEntity("\npick ent:"); - // if (res.Status == PromptStatus.OK) - // { - // Env.Editor.ZoomObject(res.ObjectId.GetObject()); - // } - - Env.Editor.ZoomExtents(); - } - - [CommandMethod(nameof(Test_Zoom_1))] - public void Test_Zoom_1() - { - Env.Editor.Zoom(new(0, 0, 0),200,200); - } - [CommandMethod(nameof(Test_Zoom_2))] - public void Test_Zoom_2() - { - Env.Editor.ZoomWindow(new(-100,-100,0),new(100,100,0)); - } - - [CommandMethod(nameof(Test_Ssget))] - public void Test_Ssget() - { - - var keyword = new Dictionary - { - { "D", ("你好", () => { Env.Print("this is c"); }) }, - { "B", ("hello", () => { Env.Print("this is b"); }) } - }; - - var ss = Env.Editor.SSGet(/*":S", */ messages: ("get", "del" ), - keywords: keyword); - Env.Print(ss!); - } - - [CommandMethod(nameof(Test_ExportWMF), CommandFlags.Modal | CommandFlags.UsePickSet)] - public void Test_ExportWMF() - { - var psr = Env.Editor.SelectImplied();// 预选 - if (psr.Status != PromptStatus.OK) - psr = Env.Editor.GetSelection();// 手选 - if (psr.Status != PromptStatus.OK) - return; - - var ids = psr.Value.GetObjectIds(); - // acad21(acad08没有)先选择再执行..会让你再选择一次 - // 而且只发生在启动cad之后第一次执行. - Env.Editor.ComExportWMF(@"C:\Users\vic\Desktop\aaa.dwg", ids); - } -} \ No newline at end of file diff --git a/tests/TestShared/TestEntity/TestAddEntity.cs b/tests/TestShared/TestEntity/TestAddEntity.cs deleted file mode 100644 index 920e6e0..0000000 --- a/tests/TestShared/TestEntity/TestAddEntity.cs +++ /dev/null @@ -1,157 +0,0 @@ -namespace Test; - -public class TestAddEntity -{ -#region 直线 - [CommandMethod(nameof(Test_AddLinetoCurrentSpace))] - public void Test_AddLinetoCurrentSpace() - { - using DBTrans tr = new(); // 开启事务 - - Line line = new(new(0, 0, 0), new(1, 1, 0)); // 定义一个直线 - tr.CurrentSpace.AddEntity(line); // 将直线添加到当前空间 - } - - [CommandMethod(nameof(Test_AddLinetoModelSpace))] - public void Test_AddLinetoModelSpace() - { - using DBTrans tr = new(); // 开启事务 - - Line line = new(new(0, 0, 0), new(1, 1, 0)); // 定义一个直线 - tr.ModelSpace.AddEntity(line); // 将直线添加到模型空间 - } - - [CommandMethod(nameof(Test_AddLinetoPaperSpace))] - public void Test_AddLinetoPaperSpace() - { - using DBTrans tr = new(); // 开启事务 - - Line line = new(new(0, 0, 0), new(1, 1, 0)); // 定义一个直线 - tr.PaperSpace.AddEntity(line); // 将直线添加到图纸空间 - } - - [CommandMethod(nameof(Test_AddEntities))] - public void Test_AddEntities() - { - // 开启事务 - using DBTrans tr = new(); - // 定义三条直线 - Line line1 = new(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); - Line line2 = new(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); - Line line3 = new(new Point3d(1, 1, 0), new Point3d(3, 3, 0)); - Circle circle = new(); - // 一次性添加到当前空间 - tr.CurrentSpace.AddEntity(line2, line2, line3, circle); - // 或者可以传入个列表 - List lines = [line1, line2, line3]; - tr.CurrentSpace.AddEntity(lines); - // 或者可以传入个数组 - Line[] lines1 = [line1, line2, line3]; - tr.CurrentSpace.AddEntity(lines1); - // 图元数组 - Entity[] lines2 = [line1, line2, line3, circle]; - tr.CurrentSpace.AddEntity(lines2); - // c#12 新语法,集合表达式 - tr.CurrentSpace.AddEntity([line1, line2, circle]); - } -#endregion - -#region 圆 - [CommandMethod(nameof(Test_AddCircle))] - public void Test_AddCircle() - { - var cir = CircleEx.CreateCircle(Point3d.Origin, new(1,0,0)); // 两点创建圆 - var cir1 = CircleEx.CreateCircle(Point3d.Origin, new(1,1,0), new(2,0,0)); //三点创建圆 - var cir2 = CircleEx.CreateCircle(Point3d.Origin, 5); // 圆心半径创建圆 - - using DBTrans tr = new(); - tr.CurrentSpace.AddEntity(cir, cir2); - - // 由于三点不一定能成功创建一个圆,因此返回值是可空的,需要判空 - if (cir1 is not null) - { - tr.CurrentSpace.AddEntity(cir1); - } - } -#endregion - -#region 圆弧 - [CommandMethod(nameof(Test_AddArc))] - public void Test_AddArc() - { - using DBTrans tr = new(); - Arc arc1 = ArcEx.CreateArcSCE(new Point3d(2, 0, 0), new Point3d(0, 0, 0), new Point3d(0, 2, 0));// 起点,圆心,终点 - Arc arc2 = ArcEx.CreateArc(new Point3d(4, 0, 0), new Point3d(0, 0, 0), Math.PI / 2); // 起点,圆心,弧度 - Arc arc3 = ArcEx.CreateArc(new Point3d(1, 0, 0), new Point3d(0, 0, 0), new Point3d(0, 1, 0)); // 起点,圆上一点,终点 - tr.CurrentSpace.AddEntity(arc1, arc2, arc3); - } - -#endregion - - - - - -#region 多段线 - [CommandMethod(nameof(Test_AddPolyline1))] - public void Test_AddPolyline1() - { - using DBTrans tr = new(); - Polyline pl = new(); - pl.SetDatabaseDefaults(); - pl.AddVertexAt(0, new Point2d(0, 0), 0, 0, 0); - pl.AddVertexAt(1, new Point2d(10, 10), 0, 0, 0); - pl.AddVertexAt(2, new Point2d(20, 20), 0, 0, 0); - pl.AddVertexAt(3, new Point2d(30, 30), 0, 0, 0); - pl.AddVertexAt(4, new Point2d(40, 40), 0, 0, 0); - pl.Closed = true; - pl.Color = Color.FromColorIndex(ColorMethod.ByColor, 6); - tr.CurrentSpace.AddEntity(pl); - } - - [CommandMethod(nameof(Test_AddPolyline2))] - public void Test_AddPolyline2() - { - // 集合表达式 - List<(Point3d, double, double, double)> pts = - [ - (new Point3d(0,0,0),0,0,0), - (new Point3d(10,0,0),0,0,0), - (new Point3d(10,10,0),0,0,0), - (new Point3d(0,10,0),0,0,0), - (new Point3d(5,5,0),0,0,0) - ]; - - using DBTrans tr = new(); - var pl = pts.CreatePolyline(); - tr.CurrentSpace.AddEntity(pl); - } - - [CommandMethod(nameof(Test_AddPolyline3))] - public void Test_AddPolyline3() - { - using var tr = new DBTrans(); - - List pts = - [ - new(0, 0, 0), - new(0, 1, 0), - new(1, 1, 0), - new(1, 0, 0) - ]; - var pline = pts.CreatePolyline(); - tr.CurrentSpace.AddEntity(pline); - - // 可以通过委托,一次性的创建多段线并设置属性 - var pline1 = pts.CreatePolyline(p => - { - p.Closed = true; - p.ConstantWidth = 0.2; - p.ColorIndex = 1; - }); - tr.CurrentSpace.AddEntity(pline1); - } - -#endregion - -} diff --git a/tests/TestShared/TestEnv.cs b/tests/TestShared/TestEnv.cs deleted file mode 100644 index 1b2d8c5..0000000 --- a/tests/TestShared/TestEnv.cs +++ /dev/null @@ -1,184 +0,0 @@ -namespace Test; - -public class Testenv -{ - [CommandMethod(nameof(Test_Enum))] - public void Test_Enum() - { - Env.CmdEcho = true; - } - [CommandMethod(nameof(Test_Enum1))] - public void Test_Enum1() - { - Env.CmdEcho = false; - } - - [CommandMethod(nameof(Test_Dimblk))] - public void Test_Dimblk() - { - Env.Dimblk = Env.DimblkType.Dot; - Env.Print(Env.Dimblk); - Env.Print(Env.GetDimblkId(Env.DimblkType.Dot)); - Env.Dimblk = Env.DimblkType.Defult; - Env.Print(Env.Dimblk); - Env.Print(Env.GetDimblkId(Env.DimblkType.Defult)); - Env.Dimblk = Env.DimblkType.Oblique; - Env.Print(Env.Dimblk); - Env.Print(Env.GetDimblkId(Env.DimblkType.Oblique)); - Env.Dimblk = Env.DimblkType.ArchTick; - Env.Print(Env.Dimblk); - Env.Print(Env.GetDimblkId(Env.DimblkType.ArchTick)); - } - [CommandMethod(nameof(Test_Dimblk1))] - public void Test_Dimblk1() - { - var dim = Env.Dimblk; - Env.Editor.WriteMessage(dim.ToString()); - } - - [CommandMethod(nameof(Test_Osmode))] - public void Test_Osmode() - { - // 设置osmode变量,多个值用逻辑或 - Env.OSMode = Env.OSModeType.End | Env.OSModeType.Middle; - // 也可以直接写数值,进行强转 - Env.OSMode = (Env.OSModeType)5179; - // 追加模式 - Env.OSMode |= Env.OSModeType.Center; - // 检查是否有某个模式 - var os = Env.OSMode.Include(Env.OSModeType.Center); - // 取消某个模式 - Env.OSMode ^= Env.OSModeType.Center; - Env.Editor.WriteMessage(Env.OSMode.ToString()); - } - [CommandMethod(nameof(Test_Osmode1))] - public void Test_Osmode1() - { - var dim = Env.OSMode; - Env.Editor.WriteMessage(dim.ToString()); - } -#if !zcad - [CommandMethod(nameof(Test_Cadver))] - public void Test_Cadver() - { - // Env.Print(AcadVersion.Versions); - AcadVersion.Versions.ForEach(v => Env.Print(v)); - AcadVersion.FromApp(Acap.AcadApplication)?.Print(); - 1.Print(); - "1".Print(); - } -#endif - [CommandMethod(nameof(Test_GetVar))] - public void Test_GetVar() - { - // test getvar - var a = Env.GetVar("dbmod"); - a.Print(); - Env.SetVar("dbmod1", 1); - } - - - - //[CommandMethod(nameof(Test_DwgVersion))] - //public void TestDwgVersion() - //{ - // string filename = @"C:\Users\vic\Desktop\test.dwg"; - // var a = Helper.GetCadFileVersion(filename); - // a.Print(); - // ((DwgVersion)a).Print(); - //} - - -#if !zcad - // 通过此功能获取全部变量,尚不清楚此处如何设置,没有通过测试 - [CommandMethod(nameof(Test_GetvarAll))] - public static void Test_GetvarAll() - { - GetvarAll(); - } - - public static Dictionary GetvarAll() - { - var dict = new Dictionary(); - var en = new SystemVariableEnumerator(); - while (en.MoveNext()) - { - Console.WriteLine(en.Current.Name + "-----" + en.Current.Value);// Value会出现异常 - dict.Add(en.Current.Name, en.Current.Value); - } - return dict; - } -#endif - - [CommandMethod(nameof(Test_GetEnv))] - public static void Test_GetEnv() - { - var dir = Env.GetEnv("PrinterConfigDir"); - Env.Printl("pc3打印机位置:" + dir); - - Env.SetEnv("abc", "656"); - - var obj = Env.GetEnv("abc"); - Env.Printl("GetEnv:" + obj); - - Env.Printl("GetEnv:" + Env.GetEnv("abc")); - Env.Printl("GetEnv PATH:" + Env.GetEnv("PATH")); - - Env.Printl($"getenv-acad: {Env.GetEnv("ACAD")}"); - Env.Printl($"getvar-acad: {Env.GetVar("TRUSTEDPATHS")}"); - Env.Printl($"getenv-TRUSTEDPATHS: {Env.GetEnv("TRUSTEDPATHS")}"); - Env.Printl($"getenv-osmode: {Env.GetEnv("osmode")}"); - Env.Printl($"getvar-osmode: {Env.GetVar("osmode")}"); - } - [CommandMethod(nameof(Test_AppendPath))] - public static void Test_AppendPath() - { - Directory.Exists(@"C:\Folder4").Print(); - Env.AppendSupportPath(@"C:\Folder4", @"C:\Folder5", @"C:\Folder6"); - // Env.AppendTrustedPath(@"c:\a\x",@"c:\a\c"); - // AppendSupportPath(@"c:\a\c"); - Env.GetEnv("ACAD").Print(); - // Env.SetEnv("ACAD", @"C:\Folder1;"+Env.GetEnv("ACAD")); - Env.GetEnv("ACAD").Contains(@"C:\Folder1").Print(); - - } - - [CommandMethod(nameof(Test_RemovePath))] - public static void Test_RemovePath() - { - // var acad = Acaop.TryGetSystemVariable("ACAD").ToString(); - // acad.Print(); - // Acaop.SetSystemVariable("ACAD", acad + @";c:\a\x"); - Env.GetEnv("ACAD").Print(); - Env.RemoveSupportPath(); - // Env.RemoveTrustedPath(@"c:\a\x"); - Env.GetEnv("ACAD").Print(); - } - - public static void AppendSupportPath(string path) - { - - string key = HostApplicationServices.Current.UserRegistryProductRootKey; - // 计算机\HKEY_CURRENT_USER\SOFTWARE\Autodesk\AutoCAD\R24.0\ACAD-4101:804 - var ackey = Registry.CurrentUser.OpenSubKey($@"{key}\Profiles") ?? null; - - if (ackey != null) - { - var listkey = ackey.GetSubKeyNames(); - foreach (var item in listkey) - { - var acadkey = ackey.OpenSubKey($@"{item}\General", true); - const string name = "ACAD"; - var str = acadkey?.GetValue(name)?.ToString(); - if (str != null && !str.ToLower().Contains(path.ToLower())) - { - acadkey?.SetValue(name, $@"{str}{path};"); - } - } - } - - ackey?.Close(); - } - - -} \ No newline at end of file diff --git a/tests/TestShared/TestExtents.cs b/tests/TestShared/TestExtents.cs deleted file mode 100644 index 96c04db..0000000 --- a/tests/TestShared/TestExtents.cs +++ /dev/null @@ -1,108 +0,0 @@ -namespace TestShared; - -public class TestExtents -{ - [CommandMethod(nameof(Test_BlockExtents))] - public void Test_BlockExtents() - { - using var tr = new DBTrans(); - var ent = Env.Editor.GetEntity("pick the entity"); - if (ent.Status != PromptStatus.OK ) - { - return; - } - - var block = ent.ObjectId.GetObject(); - if (block != null && block.Bounds.HasValue) - { - var extent = block.GeometricExtents; - List pts = [ - extent.MinPoint, - new Point3d(extent.MinPoint.X,extent.MaxPoint.Y,0), - extent.MaxPoint, - new Point3d(extent.MaxPoint.X,extent.MinPoint.Y,0), - - ]; - - tr.CurrentSpace.AddEntity(pts.CreatePolyline(action: e => e.ColorIndex = 1)); - - if (block is BlockReference block1) - { - var extents = block1.GeometryExtentsBestFit(); - List pts1 = - [ - extents.MinPoint, - new Point3d(extents.MinPoint.X, extents.MaxPoint.Y, 0), - extents.MaxPoint, - new Point3d(extents.MaxPoint.X, extents.MinPoint.Y, 0), - ]; - tr.CurrentSpace.AddEntity(pts.CreatePolyline(action: e => e.ColorIndex = 2)); - - var extents2 = block1.GetBoundingBoxEx(); - tr.CurrentSpace.AddEntity(pts.CreatePolyline(action: e => e.ColorIndex = 3)); - - // 此处是计算块定义的包围盒,不是块参照的,所以一般情况下不需要使用。 - var ext = new Extents3d(); - ext.AddBlockExtents(block1.BlockTableRecord.GetObject()); - tr.CurrentSpace.AddEntity(ext.CreatePolyline(action: e => e.ColorIndex = 4)); - } - - - } - } - - [CommandMethod(nameof(Test_entextents))] - public void Test_entextents() - { - using var tr = new DBTrans(); - var a = Env.Editor.GetSelection().Value. - GetEntities(OpenMode.ForWrite); - foreach (var e in a) - { - var b = e.Bounds.HasValue; //获取是否有包围盒 - var name = e.ObjectId.ObjectClass.DxfName; - Env.Print($"{name}是否有包围盒-" + b); - if (b) - { - tr.CurrentSpace.AddEntity(e.Bounds!.Value.CreatePolyline(action: e => - { - e.ColorIndex = 4; - e.Closed = true; - })); - var ext = e.GetBoundingBoxEx(); - if (ext.HasValue) - { - tr.CurrentSpace.AddEntity( - ext.Value.Extents3d.CreatePolyline(action: e => - { - e.ColorIndex = 5; - e.Closed = true; - })); - } - - if (e is Curve spline) - { - var ge = spline.GetGeCurve(); - var box = ge.BoundBlock; - List lst = - [ - box.BasePoint, - box.BasePoint + box.Direction1, - box.BasePoint + box.Direction2, - box.BasePoint + box.Direction3, - ]; - tr.CurrentSpace.AddEntity(lst.CreatePolyline(action: e => - { - e.ColorIndex = 6; - e.Closed = true; - })); - } - - } - - - - - } - } -} \ No newline at end of file diff --git a/tests/TestShared/TestFileDatabase.cs b/tests/TestShared/TestFileDatabase.cs deleted file mode 100644 index e5c58c3..0000000 --- a/tests/TestShared/TestFileDatabase.cs +++ /dev/null @@ -1,28 +0,0 @@ -namespace Test; - -/************************************************************** -*作者:Leon -*创建时间:2022/2/11 9:55:32 -**************************************************************/ - -public class TestFileDatabase -{ - [CommandMethod(nameof(Test_FileDatabaseInit))] - public void Test_FileDatabaseInit() - { - try - { - var fileName = @"C:\Users\Administrator\Desktop\合并详图测试BUG.dwg"; - using DBTrans trans = new(fileName); - trans.ModelSpace.AddEntity(new Line(new(0, 0, 0), new(1000, 1000, 0))); - if (trans.Document is not null && trans.Document.IsActive) - trans.Document.SendStringToExecute("_qsave\n", false, true, true); - else - trans.Database.SaveAs(fileName, (DwgVersion)27); - } - catch (System.Exception e) - { - System.Windows.MessageBox.Show(e.Message); - } - } -} \ No newline at end of file diff --git a/tests/TestShared/TestHatchinfo.cs b/tests/TestShared/TestHatchinfo.cs deleted file mode 100644 index 1b765e5..0000000 --- a/tests/TestShared/TestHatchinfo.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace Test; - -public class TestHatchinfo -{ - [CommandMethod(" TestHatchInfo")] - public void TestHatchInfo() - { - using var tr = new DBTrans(); - var sf = new SelectionFilter(new TypedValue[] { new TypedValue(0, "*line,circle,arc") }); - var ids = Env.Editor.SSGet(null, sf).Value?.GetObjectIds(); - if (ids.Count() > 0) - { - HatchInfo hf = new HatchInfo(ids!, false, null, 1, 0).Mode2UserDefined(); - hf.Build(tr.CurrentSpace); - } - } -} - diff --git a/tests/TestShared/TestId.cs b/tests/TestShared/TestId.cs deleted file mode 100644 index 57f19cf..0000000 --- a/tests/TestShared/TestId.cs +++ /dev/null @@ -1,72 +0,0 @@ -namespace Test; - -public class Testid -{ - [CommandMethod(nameof(Test_Id))] - public void Test_Id() - { - using DBTrans tr = new(); - Line line = new(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); - tr.CurrentSpace.AddEntity(line); - tr.Dispose(); - - var res = Env.Editor.GetEntity("\npick ent:"); - if (res.Status == PromptStatus.OK) - { - res.ObjectId.Erase(); - } - // using (var tr = new DBTrans()) - // { - // var res = Env.Editor.GetEntity("\npick ent:"); - // if(res.Status == PromptStatus.OK) - // { - // res.ObjectId.Erase(); - // } - - // } - } - - [CommandMethod(nameof(Test_MyCommand))] - public void Test_MyCommand() - { - using DBTrans dbtrans = new(Env.Document, true, false); - using var trans = Env.Database.TransactionManager.StartTransaction(); - - var l1 = new Line(new Point3d(0, 0, 0), new Point3d(100, 100, 0)); - var blkred = trans.GetObject(Env.Database.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord; - blkred?.AppendEntity(l1); - trans.AddNewlyCreatedDBObject(l1, true); - trans.Commit(); - // dbtrans.Dispose(); - } - [CommandMethod(nameof(Test_TextStyle))] - public void Test_TextStyle() - { - using DBTrans tr = new(); - tr.TextStyleTable.Add("宋体", "宋体.ttf", 0.8); - - tr.TextStyleTable.Add("宋体1", FontTTF.宋体, 0.8); - tr.TextStyleTable.Add("仿宋体", FontTTF.仿宋, 0.8); - tr.TextStyleTable.Add("fsgb2312", FontTTF.仿宋GB2312, 0.8); - tr.TextStyleTable.Add("arial", FontTTF.Arial, 0.8); - tr.TextStyleTable.Add("romas", FontTTF.Romans, 0.8); - - - - tr.TextStyleTable.Add("daziti", ttr => { - ttr.FileName = "ascii.shx"; - ttr.BigFontFileName = "gbcbig.shx"; - }); - } - - [CommandMethod(nameof(Test_TextStyleChange))] - public void Test_TextStyleChange() - { - using DBTrans tr = new(); - - - tr.TextStyleTable.AddWithChange("宋体1", "simfang.ttf", height: 5); - tr.TextStyleTable.AddWithChange("仿宋体", "宋体.ttf"); - tr.TextStyleTable.AddWithChange("fsgb2312", "Romans", "gbcbig"); - } -} \ No newline at end of file diff --git a/tests/TestShared/TestJig.cs b/tests/TestShared/TestJig.cs deleted file mode 100644 index e5711c9..0000000 --- a/tests/TestShared/TestJig.cs +++ /dev/null @@ -1,313 +0,0 @@ -namespace Test; - -using System.Windows.Forms; - -public class Commands_Jig -{ - // 已在数据库的图元如何进入jig - [CommandMethod(nameof(Test_Jig33))] - public static void Test_Jig33() - { - using DBTrans tr = new(); - var per = tr.Editor?.GetEntity("\n点选圆形:"); - if (per?.Status != PromptStatus.OK) - return; - var cir = tr.GetObject(per.ObjectId, OpenMode.ForWrite); - if (cir == null) - return; - var oldSp = cir.StartPoint; - JigEx? moveJig = null; - moveJig = new JigEx((mousePoint, drawEntitys) => { - moveJig!.SetOptions(oldSp);// 回调过程中也可以修改基点 - // cir.UpgradeOpen();// 已经提权了,所以这里不需要提权 - cir.Move(cir.StartPoint, mousePoint); - // cir.DowngradeOpen(); - - // 此处会Dispose图元, - // 所以此处不加入已经在数据库的图元,而是加入new Entity的. - // drawEntitys.Enqueue(cir); - }); - moveJig.SetOptions(cir.GeometricExtents.MinPoint, orthomode: true); - - // 此处详见方法注释 - moveJig.DatabaseEntityDraw(draw => { - draw.RawGeometry.Draw(cir); - }); - - while (true) - { - var prDrag = moveJig.Drag(); - if (prDrag.Status == PromptStatus.OK) - break; - } - moveJig.Dispose(); - } - - - // 不在数据库的图元如何进入jig - [CommandMethod(nameof(Test_Jig44))] - public void Test_Jig44() - { - using DBTrans tr = new(); - var per = Env.Editor.GetEntity("\n请选择一条多段线:"); - if (per.Status != PromptStatus.OK) - return; - var ent = tr.GetObject(per.ObjectId, OpenMode.ForWrite); - if (ent is not Polyline pl) - return; - - /* - * 鼠标采样器执行时修改鼠标基点 - * 原因: 多段线与鼠标垂直点作为 BasePoint,jig鼠标点为确定点 - * 所以需要先声明再传入指针,但是我发现null也可以. - */ - JigPromptPointOptions? options = null; - using var jig = new JigEx((mousePoint, drawEntitys) => { - var closestPt = pl.GetClosestPointTo(mousePoint, false); - - // 回调过程中SetOptions会覆盖配置,所以如果想增加关键字或者修改基点, - // 不要这样做: jig.SetOptions(closestPt) 而是使用底层暴露 - options!.BasePoint = closestPt; - - // 允许在循环中替换关键字,需要避免重复加入同一个关键字 - if (!options.Keywords.Contains("A")) - options.Keywords.Add("A"); - - // 生成文字 - var dictString = (pl.GetDistAtPoint(closestPt) * 0.001).ToString("0.00"); - var acText = DBTextEx.CreateDBText(closestPt, dictString, 200); - - // 加入刷新队列 - drawEntitys.Enqueue(acText); - }); - - options = jig.SetOptions(per.PickedPoint); - - // 在这里加入关键字 - // 如果没有这个,那么空格只会是 PromptStatus.None 而不是 PromptStatus.Keyword - // options.Keywords.Add(" ", " ", "空格结束啊"); - // jig.SetSpaceIsKeyword(); - options.Keywords.Add("A","A","A"); - - - bool flag = true; - while (flag) - { - var pr = jig.Drag(); - if (pr.Status == PromptStatus.Keyword) - { - switch (pr.StringResult) - { - case "A": - tr.Editor?.WriteMessage($"\n 您触发了关键字{pr.StringResult}"); - flag = false; - break; - case " ": - tr.Editor?.WriteMessage("\n 触发关键字空格"); - flag = false; - break; - } - } - else if (pr.Status != PromptStatus.OK)// PromptStatus.None == 右键,空格,回车,都在这里结束 - { - tr.Editor?.WriteMessage(Environment.NewLine + pr.Status.ToString()); - return; - } - else - flag = false; - } - tr.CurrentSpace.AddEntity(jig.Entitys); - } - - [CommandMethod(nameof(Test_MessageFilter))] - public void Test_MessageFilter() - { - var dm = Acap.DocumentManager; - var ed = dm.MdiActiveDocument.Editor; - - // Create and add our message filter - MyMessageFilter filter = new(); - System.Windows.Forms.Application.AddMessageFilter(filter); - // Start the loop - while (true) - { - // Check for user input events - System.Windows.Forms.Application.DoEvents(); - // Check whether the filter has set the flag - if (filter.bCanceled == true) - { - ed.WriteMessage("\nLoop cancelled."); - break; - } - ed.WriteMessage($"\nInside while loop...and {filter.Key}"); - } - // We're done - remove the message filter - System.Windows.Forms.Application.RemoveMessageFilter(filter); - } - // Our message filter class - public class MyMessageFilter : IMessageFilter - { - public const int WM_KEYDOWN = 0x0100; - public bool bCanceled = false; - public Keys Key { get; private set; } - public bool PreFilterMessage(ref Message m) - { - if (m.Msg == WM_KEYDOWN) - { - // Check for the Escape keypress - Keys kc = (Keys)(int)m.WParam & Keys.KeyCode; - if (m.Msg == WM_KEYDOWN && kc == Keys.Escape) - bCanceled = true; - Key = kc; - // Return true to filter all keypresses - return true; - } - // Return false to let other messages through - return false; - } - } - - - [CommandMethod(nameof(Test_QuickText))] - static public void Test_QuickText() - { - var dm = Acap.DocumentManager; - var doc = dm.MdiActiveDocument; - var db = doc.Database; - var ed = doc.Editor; - - PromptStringOptions pso = new("\nEnter text string") - { - AllowSpaces = true - }; - var pr = ed.GetString(pso); - if (pr.Status != PromptStatus.OK) - return; - - using var tr = doc.TransactionManager.StartTransaction(); - var btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite); - // Create the text object, set its normal and contents - - var acText = DBTextEx.CreateDBText(Point3d.Origin, pr.StringResult, 200); - - acText.Normal = ed.CurrentUserCoordinateSystem.CoordinateSystem3d.Zaxis; - btr.AppendEntity(acText); - tr.AddNewlyCreatedDBObject(acText, true); - - // Create our jig - var pj = new TextPlacementJig(tr, db, acText); - // Loop as we run our jig, as we may have keywords - var state = PromptStatus.Keyword; - while (state == PromptStatus.Keyword) - { - var res = ed.Drag(pj); - state = res.Status; - if (state != PromptStatus.OK && state != PromptStatus.Keyword) - return; - } - tr.Commit(); - } - -#if true - class TextPlacementJig : EntityJig - { - // Declare some internal state - readonly Database _db; - readonly Transaction _tr; - - Point3d _position; - double _angle, _txtSize; - - // Constructor - public TextPlacementJig(Transaction tr, Database db, Entity ent) : base(ent) - { - _db = db; - _tr = tr; - _angle = 0; - _txtSize = 1; - } - - protected override SamplerStatus Sampler(JigPrompts jp) - { - // We acquire a point but with keywords - JigPromptPointOptions po = new("\nPosition of text") - { - UserInputControls = - UserInputControls.Accept3dCoordinates | - UserInputControls.NullResponseAccepted | - UserInputControls.NoNegativeResponseAccepted | - UserInputControls.GovernedByOrthoMode - }; - po.SetMessageAndKeywords( - "\nSpecify position of text or " + - "[Bold/Italic/LArger/Smaller/" + - "ROtate90/LEft/Middle/RIght]: ", - "Bold Italic LArger Smaller " + - "ROtate90 LEft Middle RIght" - ); - - PromptPointResult ppr = jp.AcquirePoint(po); - if (ppr.Status == PromptStatus.Keyword) - { - switch (ppr.StringResult) - { - case "Bold": - break; - case "Italic": - break; - case "LArger": - { - // Multiple the text size by two - _txtSize *= 2; - break; - } - case "Smaller": - { - // Divide the text size by two - _txtSize /= 2; - break; - } - case "ROtate90": - { - // To rotate clockwise we subtract 90 degrees and - // then normalise the angle between 0 and 360 - _angle -= Math.PI / 2; - while (_angle < Math.PI * 2) - { - _angle += Math.PI * 2; - } - break; - } - case "LEft": - break; - case "RIght": - break; - case "Middle": - break; - } - return SamplerStatus.OK; - } - else if (ppr.Status == PromptStatus.OK) - { - // Check if it has changed or not (reduces flicker) - if (_position.DistanceTo(ppr.Value) < Tolerance.Global.EqualPoint) - return SamplerStatus.NoChange; - - _position = ppr.Value; - return SamplerStatus.OK; - } - return SamplerStatus.Cancel; - } - - protected override bool Update() - { - // Set properties on our text object - DBText txt = (DBText)Entity; - txt.Position = _position; - txt.Height = _txtSize; - txt.Rotation = _angle; - return true; - } - } -#endif -} \ No newline at end of file diff --git a/tests/TestShared/TestJigExTransient.cs b/tests/TestShared/TestJigExTransient.cs deleted file mode 100644 index 52eb3f4..0000000 --- a/tests/TestShared/TestJigExTransient.cs +++ /dev/null @@ -1,88 +0,0 @@ - -namespace Test; - -public partial class Test -{ - [CommandMethod(nameof(Test_JigExTransient))] - public void Test_JigExTransient() - { - // 先取1点,建2个圆 - var getpt = Env.Editor.GetPoint("\n选择点"); - if (getpt.Status != PromptStatus.OK) - return; - var pt = getpt.Value.Ucs2Wcs(); - - var c1 = new Circle(pt, Vector3d.ZAxis, 100); - var c2 = new Circle(pt.Polar(0, 300), Vector3d.ZAxis, 100); - - // 创建瞬态容器 - using JigExTransient jet = new(); - - // 将c1以默认模式,c2以亮显模式加到瞬态容器,即在图纸上显示 - jet.Add(c1); - jet.Add(c2, Acgi.TransientDrawingMode.Highlight); - - // 再取一点,再建一个圆c3 - var r2 = Env.Editor.GetPoint("\n选择下一点"); - if (r2.Status != PromptStatus.OK) - return; - var pt2 = r2.Value.Ucs2Wcs(); - - // 将c1从瞬态容器中移除,将c2修改颜色,c3加入瞬态容器 - jet.Remove(c1); - - c2.ColorIndex = 1; - var c3 = new Circle(pt2, Vector3d.ZAxis, 150); - jet.Add(c3); - - // 由于c2进行了修改,所以需要更新, - // 可以单个更新或更新整个瞬态容器 - jet.Update(c2); - // jet.UpdateAll(); - - Env.Editor.GetPoint("\n此拾取无意义,仅为了暂停查看"); - - // 加到图纸中,为测试瞬态容器可以自行dispose消失,所以未全部加入 - using DBTrans tr = new(); - tr.CurrentSpace.AddEntity(c3); - - // 若想将容器中所有图元全部加入提供了Entities属性 - // tr.CurrentSpace.AddEntity(jet.Entities); - } - - [CommandMethod(nameof(Test_JigExTransentDim))] - public static void Test_JigExTransentDim() - { - PromptPointOptions ppo = new("") - { - AppendKeywordsToMessage = false, - }; - List pts = new(); - for (int i = 0; i < 3; i++) - { - ppo.Message = $"\n选择标注点{i + 1}"; - var ppr = Env.Editor.GetPoint(ppo); - if (ppr.Status != PromptStatus.OK) - return; - pts.Add(ppr.Value); - } - - using DBTrans tr = new(); - - using RotatedDimension dimension = new(); - dimension.SetDatabaseDefaults();// cad16没有这个不显示 - dimension.Rotation = 0; - dimension.XLine1Point = pts[0]; - dimension.XLine2Point = pts[1]; - dimension.DimLinePoint = pts[2]; - dimension.DimensionText = "<>"; - dimension.DimensionStyle = tr.Database.Dimstyle; - - using JigExTransient jet = new(); - jet.Add(dimension, TransientDrawingMode.Highlight); - jet.UpdateAll(); - - Env.Editor.GetPoint("\n此拾取无意义,仅为了暂停查看"); - tr.CurrentSpace.AddEntity(dimension); - } -} diff --git a/tests/TestShared/TestJson.cs b/tests/TestShared/TestJson.cs deleted file mode 100644 index 9e48561..0000000 --- a/tests/TestShared/TestJson.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace TestShared; - -public class TestJson -{ - /* - * 需要引入: - * - * - * - * - */ - [CommandMethod(nameof(JavaScriptSerializer))] - public void JavaScriptSerializer() - { - List RegisteredUsers = []; - RegisteredUsers.Add(0); - RegisteredUsers.Add(1); - RegisteredUsers.Add(2); - RegisteredUsers.Add(3); - - var serializer = new System.Web.Script.Serialization.JavaScriptSerializer(); - var serializedResult = serializer.Serialize(RegisteredUsers); - var deserializedResult = serializer.Deserialize>(serializedResult); - } -} \ No newline at end of file diff --git a/tests/TestShared/TestLayer.cs b/tests/TestShared/TestLayer.cs deleted file mode 100644 index 6405a5c..0000000 --- a/tests/TestShared/TestLayer.cs +++ /dev/null @@ -1,66 +0,0 @@ -namespace Test; - -public class TestLayer -{ - [CommandMethod(nameof(Test_LayerAdd0))] - public void Test_LayerAdd0() - { - using DBTrans tr = new(); - tr.LayerTable.Add("1"); - tr.LayerTable.Add("2", lt => { - lt.Color = Color.FromColorIndex(ColorMethod.ByColor, 1); - lt.LineWeight = LineWeight.LineWeight030; - }); - tr.LayerTable.Remove("3"); - tr.LayerTable.Delete("0"); - tr.LayerTable.Change("4", lt => { - lt.Color = Color.FromColorIndex(ColorMethod.ByColor, 2); - }); - } - - - // 添加图层 - [CommandMethod(nameof(Test_LayerAdd1))] - public void Test_LayerAdd1() - { - using DBTrans tr = new(); - tr.LayerTable.Add("test1", Color.FromColorIndex(ColorMethod.ByColor, 1)); - } - - // 添加图层 - [CommandMethod(nameof(Test_LayerAdd2))] - public void Test_LayerAdd2() - { - using DBTrans tr = new(); - tr.LayerTable.Add("test2", 2); - // tr.LayerTable["3"] = new LayerTableRecord(); - } - // 删除图层 - [CommandMethod(nameof(Test_LayerDel))] - public void Test_LayerDel() - { - using DBTrans tr = new(); - Env.Printl(tr.LayerTable.Delete("0").ToString()); // 删除图层 0 - Env.Printl(tr.LayerTable.Delete("Defpoints").ToString());// 删除图层 Defpoints - Env.Printl(tr.LayerTable.Delete("1").ToString()); // 删除不存在的图层 1 - Env.Printl(tr.LayerTable.Delete("2").ToString()); // 删除有图元的图层 2 - Env.Printl(tr.LayerTable.Delete("3").ToString()); // 删除图层 3 - - tr.LayerTable.Remove("2"); // 测试是否能强制删除 - } - - [CommandMethod(nameof(Test_PrintLayerName))] - public void Test_PrintLayerName() - { - using DBTrans tr = new(); - foreach (var layerRecord in tr.LayerTable.GetRecords()) - { - Env.Printl(layerRecord.Name); - } - foreach (var layerRecord in tr.LayerTable.GetRecords()) - { - Env.Printl(layerRecord.Name); - break; - } - } -} \ No newline at end of file diff --git a/tests/TestShared/TestLisp.cs b/tests/TestShared/TestLisp.cs deleted file mode 100644 index 4bd7b19..0000000 --- a/tests/TestShared/TestLisp.cs +++ /dev/null @@ -1,122 +0,0 @@ -namespace Test; - -public class TestLisp -{ - // 定义lisp函数 - [LispFunction(nameof(LispTest_RunLisp))] - public static object LispTest_RunLisp(ResultBuffer rb) - { - CmdTest_RunLisp(); - return null!; - } - - // 模态命令,只有当CAD发出命令提示或当前没有其他的命令或程序活动的时候才可以被触发 - [CommandMethod("CmdTest_RunLisp1")] - // 透明命令,可以在一个命令提示输入的时候触发例如正交切换,zoom等 - [CommandMethod("CmdTest_RunLisp2", CommandFlags.Transparent)] - // 选择图元之后执行命令将可以从 获取图元 - [CommandMethod("CmdTest_RunLisp3", CommandFlags.UsePickSet)] - // 命令执行前已选中部分实体.在命令执行过程中这些标记不会被清除 - [CommandMethod("CmdTest_RunLisp4", CommandFlags.Redraw)] - // 命令不能在透视图中使用 - [CommandMethod("CmdTest_RunLisp5", CommandFlags.NoPerspective)] - // 命令不能通过 MULTIPLE命令 重复触发 - [CommandMethod("CmdTest_RunLisp6", CommandFlags.NoMultiple)] - // 不允许在模型空间使用命令 - [CommandMethod("CmdTest_RunLisp7", CommandFlags.NoTileMode)] - // 不允许在布局空间使用命令 - [CommandMethod("CmdTest_RunLisp8", CommandFlags.NoPaperSpace)] - // 命令不能在OEM产品中使用 - [CommandMethod("CmdTest_RunLisp9", CommandFlags.NoOem)] - // 不能直接使用命令名调用,必须使用 组名.全局名 调用 - [CommandMethod("CmdTest_RunLisp10", CommandFlags.Undefined)] - // 定义lisp方法.已废弃 请使用lispfunction - [CommandMethod("CmdTest_RunLisp11", CommandFlags.Defun)] - // 命令不会被存储在新的命令堆上 - [CommandMethod("CmdTest_RunLisp12", CommandFlags.NoNewStack)] - // 命令不能被内部锁定(命令锁) - [CommandMethod("CmdTest_RunLisp13", CommandFlags.NoInternalLock)] - // 调用命令的文档将会被锁定为只读 - [CommandMethod("CmdTest_RunLisp14", CommandFlags.DocReadLock)] - // 调用命令的文档将会被锁定,类似document.lockdocument - [CommandMethod("CmdTest_RunLisp15", CommandFlags.DocExclusiveLock)] - // 命令在CAD运行期间都能使用,而不只是在当前文档 - [CommandMethod("CmdTest_RunLisp16", CommandFlags.Session)] - // 获取用户输入时,可以与属性面板之类的交互 - [CommandMethod("CmdTest_RunLisp17", CommandFlags.Interruptible)] - // 命令不会被记录在命令历史记录 - [CommandMethod("CmdTest_RunLisp18", CommandFlags.NoHistory)] -#if (!zcad) - // 命令不会被 UNDO取消 - [CommandMethod("CmdTest_RunLisp19", CommandFlags.NoUndoMarker)] - // 不能在参照块中使用命令 - [CommandMethod("CmdTest_RunLisp20", CommandFlags.NoBlockEditor)] - - // acad09增,不会被动作录制器 捕捉到 - [CommandMethod("CmdTest_RunLisp21", CommandFlags.NoActionRecording)] - // acad09增,会被动作录制器捕捉 - [CommandMethod("CmdTest_RunLisp22", CommandFlags.ActionMacro)] - - - // 推断约束时不能使用命令 - [CommandMethod("CmdTest_RunLisp23", CommandFlags.NoInferConstraint)] - // 命令允许在选择图元时临时显示动态尺寸 - [CommandMethod("CmdTest_RunLisp24", CommandFlags.TempShowDynDimension)] -#endif - public static void CmdTest_RunLisp() - { - // 测试方法1: (command "CmdTest_RunLisp1") - // 测试方式2: (LispTest_RunLisp) - var dm = Acap.DocumentManager; - var doc = dm.MdiActiveDocument; - var ed = doc.Editor; - - var sb = new StringBuilder(); - foreach (var item in Enum.GetValues(typeof(EditorEx.RunLispFlag))) - { - sb.Append((byte)item); - sb.Append(','); - } - sb.Remove(sb.Length - 1, 1); - var option = new PromptIntegerOptions($"\n输入RunLispFlag枚举值:[{sb}]"); - var ppr = ed.GetInteger(option); - - if (ppr.Status != PromptStatus.OK) - return; - var flag = (EditorEx.RunLispFlag)ppr.Value; - - if (flag == EditorEx.RunLispFlag.AdsQueueexpr) - { - // 同步 - Env.Editor.RunLisp("(setq a 10)(princ)", - EditorEx.RunLispFlag.AdsQueueexpr); - Env.Editor.RunLisp("(princ a)", - EditorEx.RunLispFlag.AdsQueueexpr);// 成功输出 - } - else if (flag == EditorEx.RunLispFlag.AcedEvaluateLisp) - { - // 使用(command "CmdTest_RunLisp1")发送,然后 !b 查看变量,acad08是有值的,高版本是null - var strlisp0 = "(setq b 20)"; - var res0 = Env.Editor.RunLisp(strlisp0, - EditorEx.RunLispFlag.AcedEvaluateLisp); // 有lisp的返回值 - - var strlisp1 = "(defun f1( / )(princ \"aa\"))"; - var res1 = Env.Editor.RunLisp(strlisp1, - EditorEx.RunLispFlag.AcedEvaluateLisp); // 有lisp的返回值 - - var strlisp2 = "(defun f2( / )(command \"line\"))"; - var res2 = Env.Editor.RunLisp(strlisp2, - EditorEx.RunLispFlag.AcedEvaluateLisp); // 有lisp的返回值 - } - else if (flag == EditorEx.RunLispFlag.SendStringToExecute) - { - // 测试异步 - // (command "CmdTest_RunLisp1")和(LispTest_RunLisp)4都是异步 - var str = "(setq c 40)(princ)"; - Env.Editor.RunLisp(str, - EditorEx.RunLispFlag.SendStringToExecute); // 异步,后发送 - Env.Editor.RunLisp("(princ c)", - EditorEx.RunLispFlag.AdsQueueexpr); // 同步,先发送了,输出是null - } - } -} \ No newline at end of file diff --git a/tests/TestShared/TestLoop.cs b/tests/TestShared/TestLoop.cs deleted file mode 100644 index 438253a..0000000 --- a/tests/TestShared/TestLoop.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace Test; -public class TestLoop -{ - [CommandMethod(nameof(Test_LoopList))] - public void Test_LoopList() - { - var loop = new LoopList - { - 0, - 1, - 2, - 3, - 4, - 5 - }; - - Env.Print(loop); - - loop.SetFirst(loop.Last!); - Env.Print(loop); - Env.Print(loop.Min()); - loop.SetFirst(new LoopListNode(loop.Min(), loop)); - Env.Print(loop); - } -} \ No newline at end of file diff --git a/tests/TestShared/TestMarshal.cs b/tests/TestShared/TestMarshal.cs deleted file mode 100644 index 7beb84b..0000000 --- a/tests/TestShared/TestMarshal.cs +++ /dev/null @@ -1,123 +0,0 @@ -using System.Diagnostics; -using static IFoxCAD.Basal.WindowsAPI; - -namespace TestShared; - -public class TestMarshal -{ - [CommandMethod(nameof(TestToBytes))] - public void TestToBytes() - { - var ptA = new Point3d(123, 456, 789); - var bytes = StructToBytes(ptA); - var ptB = BytesToStruct(bytes); - Env.Printl(ptB); - } - - [CommandMethod(nameof(Test_ChangeLinePoint))] - public void Test_ChangeLinePoint() - { - var prs = Env.Editor.SSGet("\n 选择直线"); - if (prs.Status != PromptStatus.OK) - return; - - using DBTrans tr = new(); - - prs.Value.GetObjectIds().ForEach(id => { - var line = id.GetObject(); - if (line == null) - return; - using (line.ForWrite()) - unsafe - { - // 不允许直接 &这个表达式进行取址(因为它是属性,不是字段) - // 实际上就是默认拷贝一份副本出来 - var p1 = line.StartPoint; - ((Point3D*)&p1)->X = 0; - ((Point3D*)&p1)->Y = 0; - ((Point3D*)&p1)->Z = 0; - line.StartPoint = p1;// 又放回去,节省了一个变量 - - var p2 = line.EndPoint; - ((Point3D*)&p2)->X = 100; - ((Point3D*)&p2)->Y = 100; - ((Point3D*)&p2)->Z = 0; - line.EndPoint = p2; - } - }); - } - - [CommandMethod(nameof(Test_ImplicitPoint3D))] - public void Test_ImplicitPoint3D() - { - // 无法用指针转换类型,所以隐式转换是无法不new的, - // 貌似是因为 - // 如果发生了获取对象的成员引用指针,没有new的话,会发生引用不计数...造成GC释放失效... - // 而微软没有提供一种计数转移的方法...造成我无法实现此操作... - unsafe - { - Point3d pt1 = new(1, 56, 89); - var a1 = (Point3D*)&pt1; - DebugEx.Printl("指针类型转换,获取x::" + a1->X); - - var pt2 = Point3D.Create(new IntPtr(&pt1)); - DebugEx.Printl("pt1地址::" + (int)&pt1); - DebugEx.Printl("pt2地址::" + (int)&pt2); - Debug.Assert(&pt1 == &pt2);//不相等,是申请了新内存 - } - } - - [CommandMethod(nameof(Test_Marshal))] - public void Test_Marshal() - { - var dm = Acap.DocumentManager; - var doc = dm.MdiActiveDocument; - var ed = doc.Editor; - // 0x01 如何修改Point3d内容? - Point3d pt = new(100, 50, 0); - ed.WriteMessage("\n原始:" + pt.ToString()); - - // 0x02 最佳方法: - // 将Point3d内存转为Point3D,以此避开get保护,实现修改内部值 - // 为了避免在安全类型中转换,多了栈帧(无法内联),直接用指针处理 - unsafe - { - ((Point3D*)&pt)->X = 12345;//必须强转成这个指针类型,不然它为(Point3d*) - } - ed.WriteMessage("\n指针法:" + pt.ToString()); - - // 0x03 此方法仍然需要不安全操作,而且多了几个函数调用... - unsafe - { - var p = new IntPtr(&pt); - var result2 = Point3D.Create(p); - result2.X = 220; - result2.ToPtr(p); - } - "封送法:".Print(); - pt.Print(); - - // 拷贝到数组,还原指针到结构,最后将内存空间转换为目标结构体 - // 浪费内存,这不闹嘛~ - int typeSize = Marshal.SizeOf(pt); - byte[] bytes = new byte[typeSize]; - IntPtr structPtr = Marshal.AllocHGlobal(Marshal.SizeOf(pt)); - Marshal.StructureToPtr(pt, structPtr, true); - Marshal.Copy(structPtr, bytes, 0, typeSize); - var result = (Point3d)Marshal.PtrToStructure(structPtr, typeof(Point3d)); - "内存拷贝:".Print(); - result.Print(); - - //这个是不对的,会获取类型的指针,替换了就错误了 - //RuntimeTypeHandle handle = structObj.GetType().TypeHandle; - //IntPtr ptr = handle.Value; - //var result3 = (Point3D)Marshal.PtrToStructure(ptr, typeof(Point3D)); - //result3.SetX(330); - //Marshal.StructureToPtr(result3, ptr, true); - //"打印D:".Print(); - //structObj.Print(); - - // 释放内存 - Marshal.FreeHGlobal(structPtr); - } -} \ No newline at end of file diff --git a/tests/TestShared/TestMirrorFile.cs b/tests/TestShared/TestMirrorFile.cs deleted file mode 100644 index 76ac033..0000000 --- a/tests/TestShared/TestMirrorFile.cs +++ /dev/null @@ -1,73 +0,0 @@ -namespace Test; - -public class MirrorFile -{ - const string file = "D:/JX.dwg"; - const string fileSave = "D:/JX222.dwg"; - - /// - /// 测试:后台打开图纸,镜像文字是否存在文字偏移 - /// 答案:不存在 - /// - [CommandMethod(nameof(CmdTest_MirrorFile))] - public static void CmdTest_MirrorFile() - { - var yaxis = new Point3d(0, 1, 0); - using DBTrans tr = new(file, fileOpenMode: FileOpenMode.OpenForReadAndReadShare); - tr.BlockTable.Change(tr.ModelSpace.ObjectId, modelSpace => { - modelSpace.ForEach(entId => { - var dbText = tr.GetObject(entId, OpenMode.ForRead)!; - if (dbText is null) - return; - - dbText.UpgradeOpen(); - var pos = dbText.Position; - // text.Move(pos, Point3d.Origin); - // Y轴 - dbText.Mirror(Point3d.Origin, yaxis); - // text.Move(Point3d.Origin, pos); - dbText.DowngradeOpen(); - }); - }); - var ver = (DwgVersion)27;/*AC1021 AutoCAD 2007/2008/2009.*/ - tr.Database.SaveAs(fileSave, ver); - } - - /// - /// 测试:后台设置 dbText.IsMirroredInX 属性会令文字偏移 - /// 答案:存在,并提出解决方案 - /// - [CommandMethod(nameof(CmdTest_MirrorFile2))] - public static void CmdTest_MirrorFile2() - { - using DBTrans tr = new(file); - - tr.Task(() => { - var yaxis = new Point3d(0, 1, 0); - tr.BlockTable.Change(tr.ModelSpace.ObjectId, modelSpace => { - modelSpace.ForEach(entId => { - var entity = tr.GetObject(entId, OpenMode.ForWrite)!; - if (entity is DBText dbText) - { - dbText.Mirror(Point3d.Origin, yaxis); - dbText.IsMirroredInX = true; // 这句将导致文字偏移 - - // 指定文字的垂直对齐方式 - if (dbText.VerticalMode == TextVerticalMode.TextBase) - dbText.VerticalMode = TextVerticalMode.TextBottom; - - // 指定文字的水平对齐方式 - dbText.HorizontalMode = dbText.HorizontalMode switch - { - TextHorizontalMode.TextLeft => TextHorizontalMode.TextRight, - TextHorizontalMode.TextRight => TextHorizontalMode.TextLeft, - _ => dbText.HorizontalMode - }; - dbText.AdjustAlignment(tr.Database); - } - }); - }); - }); - tr.Database.SaveAs(fileSave, (DwgVersion)27 /*AC1021 AutoCAD 2007/2008/2009.*/); - } -} \ No newline at end of file diff --git a/tests/TestShared/TestPoint.cs b/tests/TestShared/TestPoint.cs deleted file mode 100644 index 9431873..0000000 --- a/tests/TestShared/TestPoint.cs +++ /dev/null @@ -1,202 +0,0 @@ -namespace Test; -public class TestPoint -{ - [CommandMethod(nameof(Test_GetAngle))] - public void Test_GetAngle() - { - var pt1 = new Point2d(0, 0); - var pt2 = new Point2d(1, 1); - var angle_pt1_pt2 = pt1.GetAngle(pt2); - var angle_pt2_pt1 = pt2.GetAngle(pt1); - Env.Printl($"pt1-pt2 angle is : {angle_pt1_pt2}, 角度是: {MathEx.ConvertRadToDeg(angle_pt1_pt2)}"); - Env.Printl($"pt2-pt1 angle is : {angle_pt2_pt1}, 角度是: {MathEx.ConvertRadToDeg(angle_pt2_pt1)}"); - - var polar = pt1.Polar(Math.PI / 2, 10); - Env.Printl($"pt1 90° 距离10的点是: {polar}"); - - } - [CommandMethod(nameof(Test_Endtoend))] - public void Test_Endtoend() - { - var pts = new Point2dCollection - { - new(0, 0), - new(0, 1), - new(1, 1), - new(1, 0) - }; - - - foreach (Point2d pt in pts) - { - Env.Printl($"X={pt.X},Y={pt.Y}"); - } - pts.End2End(); - Env.Printl("-------"); - foreach (Point2d pt in pts) - { - Env.Printl($"X={pt.X},Y={pt.Y}"); - } - Env.Printl("--------"); - var ptss = new Point3dCollection - { - new(0, 0,0), - new(0, 1,0), - new(1, 1,0), - new(1, 0,0) - }; - - foreach (Point3d pt in ptss) - { - Env.Printl($"X={pt.X},Y={pt.Y},Z={pt.Z}"); - } - ptss.End2End(); - Env.Printl("-------"); - foreach (Point3d pt in ptss) - { - Env.Printl($"X={pt.X},Y={pt.Y},Z={pt.Z}"); - } - - } - - /// - /// 红黑树排序点集 - /// - [CommandMethod(nameof(Test_PtSortedSet))] - public void Test_PtSortedSet() - { - var ss1 = new SortedSet - { - new Point2d(1, 1), - new Point2d(4.6, 2), - new Point2d(8, 3), - new Point2d(4, 3), - new Point2d(5, 40), - new Point2d(6, 5), - new Point2d(1, 6), - new Point2d(7, 6), - new Point2d(9, 6) - }; - - /*判断区间,超过就中断*/ - foreach (var item in ss1) - { - if (item.X > 3 && item.X < 7) - DebugEx.Printl(item); - else if (item.X >= 7) - break; - } - } - - - - [CommandMethod(nameof(Test_PtGethash))] - public void Test_PtGethash() - { - // test - var pt = Env.Editor.GetPoint("pick pt").Value; - // Tools.TestTimes2(1_000_000, "新语法", () => { - // pt.GetHashString2(); - // }); - Tools.TestTimes2(1_000_000, "旧语法", () => { - pt.GetHashString(); - }); - } - - [CommandMethod(nameof(Test_Point3dHash))] - public void Test_Point3dHash() - { - Env.Print($"4位小数的hash:{new Point3d(0.0_001, 0.0_002, 0.0).GetHashCode()}"); - Env.Print($"5位小数的hash:{new Point3d(0.00_001, 0.00_002, 0.0).GetHashCode()}"); - Env.Print($"6位小数的hash:{new Point3d(0.000_001, 0.000_002, 0.0).GetHashCode()}"); - Env.Print($"7位小数的hash:{new Point3d(0.000_0_001, 0.000_0_002, 0.0).GetHashCode()}"); - Env.Print($"8位小数的hash:{new Point3d(0.000_00_001, 0.000_00_002, 0.0).GetHashCode()}"); - Env.Print($"9位小数的hash:{new Point3d(0.000_000_001, 0.000_000_002, 0.0).GetHashCode()}"); - Env.Print($"10位小数的hash:{new Point3d(0.000_000_0001, 0.000_000_0002, 0.0).GetHashCode()}"); - Env.Print($"10位小数的hash:{new Point3d(0.000_000_0001, 0.000_000_0001, 0.0).GetHashCode()}"); - - Env.Print($"11位小数的hash:{new Point3d(0.000_000_000_01, 0.000_000_000_02, 0.0).GetHashCode()}"); - Env.Print($"11位小数的hash:{new Point3d(0.000_000_000_01, 0.000_000_000_01, 0.0).GetHashCode()}"); - - Env.Print($"12位小数的hash:{new Point3d(0.000_000_000_001, 0.000_000_000_002, 0.0).GetHashCode()}"); - Env.Print($"12位小数的hash:{new Point3d(0.000_000_000_001, 0.000_000_000_001, 0.0).GetHashCode()}"); - - Env.Print($"13位小数的hash:{new Point3d(0.000_000_000_0001, 0.000_000_000_0002, 0.0).GetHashCode()}"); - Env.Print($"13位小数的hash:{new Point3d(0.000_000_000_0001, 0.000_000_000_0001, 0.0).GetHashCode()}"); - - Env.Print($"14位小数的hash:{new Point3d(0.000_000_000_000_01, 0.000_000_000_000_02, 0.0).GetHashCode()}"); - Env.Print($"14位小数的hash:{new Point3d(0.000_000_000_000_01, 0.000_000_000_000_01, 0.0).GetHashCode()}"); - - Env.Print($"15位小数的hash:{new Point3d(0.000_000_000_000_001, 0.000_000_000_000_002, 0.0).GetHashCode()}"); - Env.Print($"15位小数的hash:{new Point3d(0.000_000_000_000_001, 0.000_000_000_000_001, 0.0).GetHashCode()}"); - - Env.Print($"16位小数的hash:{new Point3d(0.000_000_000_000_000_1, 0.000_000_000_000_000_2, 0.0).GetHashCode()}"); - Env.Print($"16位小数的hash:{new Point3d(0.000_000_000_000_000_1, 0.000_000_000_000_000_1, 0.0).GetHashCode()}"); - - Env.Print($"17位小数的hash:{new Point3d(0.000_000_000_000_000_01, 0.000_000_000_000_000_02, 0.0).GetHashCode()}"); - Env.Print($"17位小数的hash:{new Point3d(0.000_000_000_000_000_01, 0.000_000_000_000_000_01, 0.0).GetHashCode()}"); - - Env.Print($"18位小数的hash:{new Point3d(0.000_000_000_000_000_001, 0.000_000_000_000_000_002, 0.0).GetHashCode()}"); - Env.Print($"18位小数的hash:{new Point3d(0.000_000_000_000_000_001, 0.000_000_000_000_000_001, 0.0).GetHashCode()}"); - - Env.Print($"19位小数的hash:{new Point3d(0.000_000_000_000_000_000_1, 0.000_000_000_000_000_000_2, 0.0).GetHashCode()}"); - Env.Print($"19位小数的hash:{new Point3d(0.000_000_000_000_000_000_1, 0.000_000_000_000_000_000_1, 0.0).GetHashCode()}"); - - Env.Print($"20位小数的hash:{new Point3d(0.000_000_000_000_000_000_01, 0.000_000_000_000_000_000_02, 0.0).GetHashCode()}"); - Env.Print($"20位小数的hash:{new Point3d(0.000_000_000_000_000_000_01, 0.000_000_000_000_000_000_01, 0.0).GetHashCode()}"); - } - - [CommandMethod(nameof(Test_ListEqualspeed))] - public void Test_ListEqualspeed() - { - var lst1 = new List { 1, 2, 3, 4 }; - var lst2 = new List { 1, 2, 3, 4 }; - lst1.SequenceEqual(null!); - Tools.TestTimes2(1000000, "eqaulspeed:", () => { - lst1.SequenceEqual(lst2); - }); - } - - [CommandMethod(nameof(Test_Contains))] - public void Test_Contains() - { - // test list and dict contains speed - var lst = new List { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 }; - var hashset = new HashSet { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 }; - var dict = new Dictionary - { - { 1, 0 }, - { 2, 1 }, - { 3, 2 }, - { 4, 3 }, - { 5, 4 }, - { 6, 5 }, - { 7, 6 }, - { 8, 7 }, - { 9, 8 }, - { 10, 9 }, - { 11, 11 }, - { 12, 12 }, - { 13, 13 }, - { 14, 14 }, - { 15, 15 }, - { 16, 16 }, - { 17, 17 }, - { 18, 18 }, - { 19, 19 }, - { 20, 20 }, - }; - - Tools.TestTimes2(100_0000, "list:", () => { - lst.Contains(20); - }); - - Tools.TestTimes2(100_0000, "hashset:", () => { - hashset.Contains(20); - }); - - Tools.TestTimes2(100_0000, "dict:", () => { - dict.ContainsKey(20); - }); - } -} \ No newline at end of file diff --git a/tests/TestShared/TestQuadTree.cs b/tests/TestShared/TestQuadTree.cs deleted file mode 100644 index 1c2e2a8..0000000 --- a/tests/TestShared/TestQuadTree.cs +++ /dev/null @@ -1,457 +0,0 @@ -namespace Test; - -/* - * 这里属于用户调用例子, - * 调用时候必须要继承它,再提供给四叉树 - * 主要是用户可以扩展属性 - */ -public class CadEntity : QuadEntity -{ - public ObjectId ObjectId; - // 这里加入其他字段 - public List? Link;// 碰撞链 - public System.Drawing.Color Color; - public double Angle; - public CadEntity(ObjectId objectId, Rect box) : base(box) - { - ObjectId = objectId; - } - public int CompareTo(CadEntity? other) - { - if (other == null) - return -1; - return GetHashCode() ^ other.GetHashCode(); - } - public override int GetHashCode() - { - return (base.GetHashCode(), ObjectId.GetHashCode()).GetHashCode(); - } -} - - - - - -public partial class TestQuadTree -{ - QuadTree? _quadTreeRoot; - #region 四叉树创建并加入 - [CommandMethod(nameof(Test_QuadTree))] - public void Test_QuadTree() - { - using DBTrans tr = new(); - - Rect dbExt; - // 使用数据库边界来进行 - var dbExtent = tr.Database.GetValidExtents3d(); - if (dbExtent == null) - { - // throw new ArgumentException("画一个矩形"); - - // 这个初始值的矩形是很有意义, - // 主要是四叉树分裂过程中产生多个Rect,Rect内有很多重复的double值,是否可以内存复用,以此减少内存大小? - // 接着想了一下,Rect可以是int,long,这样可以利用位运算它扩展和缩小, - // 最小就是1,并且可以控制四叉树深度,不至于无限递归. - // 而且指针长度跟值是一样的,所以就不需要复用了,毕竟跳转一个函数地址挺麻烦的. - // 但是因为啊惊懒的原因,并没有单独制作这样的矩形, - // 而且非常糟糕的是,c#不支持模板约束运算符,使得值类型之间需要通过一层接口来委婉处理,拉低了效率..引用类型倒是无所谓.. - // 要么忍着,要么换c++去搞四叉树吧 - dbExt = new Rect(0, 0, 1 << 10, 1 << 10); - } - else - { - var a = new Point2d(dbExtent.Value.MinPoint.X, dbExtent.Value.MinPoint.Y); - var b = new Point2d(dbExtent.Value.MaxPoint.X, dbExtent.Value.MaxPoint.Y); - dbExt = new Rect(a, b); - } - - // 创建四叉树 - _quadTreeRoot = new QuadTree(dbExt); - - // 数据库边界 - var pl = dbExt.ToPoints(); - var databaseBoundary = new List<(Point3d, double, double, double)> - { - (new Point3d(pl[0].X,pl[0].Y,0),0,0,0), - (new Point3d(pl[1].X,pl[1].Y,0),0,0,0), - (new Point3d(pl[2].X,pl[2].Y,0),0,0,0), - (new Point3d(pl[3].X,pl[3].Y,0),0,0,0), - }; - tr.CurrentSpace.AddEntity(databaseBoundary.CreatePolyline(action: e => e.Closed = true)); - - // 生成多少个图元,导致cad会令undo出错(八叉树深度过大 treemax) - // int maximumItems = 30_0000; - int maximumItems = 1000; - - // 随机图元生成 - List ces = new(); // 用于随机获取图元 - Tools.TestTimes(1, "画圆消耗时间:", () => { - // 生成外边界和随机圆形 - var grc = GenerateRandomCircle(maximumItems, dbExt); - foreach (var ent in grc) - { - // 初始化图元颜色 - ent!.ColorIndex = 1; // Color.FromRgb(0, 0, 0);// 黑色 - var edge = ent.GeometricExtents; - // 四叉树数据 - var entRect = new Rect(edge.MinPoint.X, edge.MinPoint.Y, edge.MaxPoint.X, edge.MaxPoint.Y); - var entId = tr.CurrentSpace.AddEntity(ent); - - var ce = new CadEntity(entId, entRect) - { - Color = RandomEx.NextColor() - }; - ces.Add(ce); - /*加入随机点*/ - var p = edge.MinPoint + new Vector3d(10, 10, 0); - entRect = new Rect(p.Point2d(), p.Point2d()); - entId = tr.CurrentSpace.AddEntity(new DBPoint(p)); - var dbPointCe = new CadEntity(entId, entRect); - ces.Add(dbPointCe); - } - });// 30万图元±3秒.cad2021 - - // 测试只加入四叉树的时间 - Tools.TestTimes(1, "插入四叉树时间:", () => { - for (int i = 0; i < ces.Count; i++) - _quadTreeRoot.Insert(ces[i]); - });// 30万图元±0.7秒.cad2021 - - tr.Editor?.WriteMessage($"\n加入图元数量:{maximumItems}"); - } - - /// - /// 创建随机圆形 - /// - /// 创建数量 - /// 数据库边界 - static IEnumerable GenerateRandomCircle(int createNumber, Rect dbExt) - { - var x1 = (int)dbExt.X; - var x2 = (int)(dbExt.X + dbExt.Width); - var y1 = (int)dbExt.Y; - var y2 = (int)(dbExt.Y + dbExt.Height); - - var rand = RandomEx.GetRandom(); - for (int i = 0; i < createNumber; i++) - { - var x = rand.Next(x1, x2) + rand.NextDouble(); - var y = rand.Next(y1, y2) + rand.NextDouble(); - yield return CircleEx.CreateCircle(new Point3d(x, y, 0), rand.Next(1, 100)); // 起点,终点 - } - } - - /* 啊惊: 有点懒不想改了*/ -#if true2 - - // 选择加入到四叉树 - [CommandMethod(nameof(CmdTest_QuadTree21))] - public void CmdTest_QuadTree21() - { - var dm = Acap.DocumentManager; - var doc = dm.MdiActiveDocument; - var db = doc.Database; - var ed = doc.Editor; - ed.WriteMessage("\n选择单个图元加入已有的四叉树"); - - var ss = ed.Ssget(); - if (ss.Count == 0) - return; - - AddQuadTreeRoot(db, ed, ss); - } - - // 自动加入全图到四叉树 - [CommandMethod(nameof(CmdTest_QuadTree20))] - public void CmdTest_QuadTree20() - { - var dm = Acap.DocumentManager; - var doc = dm.MdiActiveDocument; - var db = doc.Database; - var ed = doc.Editor; - ed.WriteMessage("\n自动加入全图到四叉树"); - - List ss = []; - int entnum = 0; - var time1 = Timer.RunTime(() => { - db.Action(tr => { - db.TraverseBlockTable(tr, btRec => { - if (!btRec.IsLayout)// 布局跳过 - return false; - - foreach (var item in btRec) - { - // var ent = item.ToEntity(tr); - ss.Add(item); - ++entnum;// 图元数量:100000, 遍历全图时间:0.216秒 CmdTest_QuadTree2 - } - return false; - }); - }); - }); - ed.WriteMessage($"\n图元数量:{entnum}, 遍历全图时间:{time1 / 1000.0}秒"); - - // 清空原有的 - _quadTreeRoot = null; - AddQuadTreeRoot(db, ed, ss); - } - - void AddQuadTreeRoot(Database db, Editor ed, List ss) - { - if (_quadTreeRoot is null) - { - ed.WriteMessage("\n四叉树是空的,重新初始化"); - - Rect dbExt; - // 使用数据库边界来进行 - var dbExtent = db.GetValidExtents3d(); - if (dbExtent == null) - { - // throw new ArgumentException("画一个矩形"); - - // 测试时候画个矩形,在矩形内画随机坐标的圆形 - dbExt = new Rect(0, 0, 32525, 32525); - } - else - { - dbExt = new Rect(dbExtent.Value.MinPoint.Point2d(), dbExtent.Value.MaxPoint.Point2d()); - } - _quadTreeRoot = new(dbExt); - } - - /* 测试: - * 为了测试删除内容释放了分支,再重复加入是否报错 - * 先创建 CmdTest_QuadTree1 - * 再减去 CmdTest_QuadTree0 - * 然后原有黑色边界,再生成边界 CmdTest_Create00,对比删除效果. - * 然后加入 CmdTest_QuadTree2 - * 然后原有黑色边界,再生成边界 CmdTest_Create00,对比删除效果. - */ - - List ces = new(); - db.Action(tr => { - ss.ForEach(entId => { - var ent = entId.ToEntity(tr); - if (ent is null) - return; - var edge = new EdgeEntity(ent); - // 四叉树数据 - var ce = new CadEntity(entId, edge.Edge) - { - Color = Utility.RandomColor - }; - ces.Add(ce); - - edge.Dispose(); - }); - }); - - var time2 = Timer.RunTime(() => { - _quadTreeRoot.Insert(ces); - }); - ed.WriteMessage($"\n图元数量:{ces.Count}, 加入四叉树时间:{time2 / 1000.0}秒"); - } -#endif - - #endregion - - /* 啊惊: 有点懒不想改了*/ -#if true2 - - #region 节点边界显示 - // 四叉树减去节点 - [CommandMethod(nameof(CmdTest_QuadTree0))] - public void CmdTest_QuadTree0() - { - var dm = Acap.DocumentManager; - var doc = dm.MdiActiveDocument; - // var db = doc.Database; - var ed = doc.Editor; - ed.WriteMessage("\n四叉树减区"); - - if (_quadTreeRoot is null) - { - ed.WriteMessage("\n四叉树是空的"); - return; - } - var rect = GetCorner(ed); - if (rect is null) - return; - _quadTreeRoot.Remove(rect); - } - - // 创建节点边界 - [CommandMethod(nameof(CmdTest_CreateNodesRect))] - public void CmdTest_CreateNodesRect() - { - var dm = Acap.DocumentManager; - var doc = dm.MdiActiveDocument; - var db = doc.Database; - var ed = doc.Editor; - ed.WriteMessage("\n创建边界"); - - if (_quadTreeRoot is null) - { - ed.WriteMessage("\n四叉树是空的"); - return; - } - - // 此处发现了一个事务处理的bug,提交数量过多的时候,会导致 ctrl+z 无法回滚, - // 需要把事务放在循环体内部 - // 报错: 0x6B00500A (msvcr80.dll)处(位于 acad.exe 中)引发的异常: 0xC0000005: 写入位置 0xFFE00000 时发生访问冲突。 - // 画出所有的四叉树节点边界,因为事务放在外面引起 - List nodeRects = []; - _quadTreeRoot.ForEach(node => { - nodeRects.Add(node); - return false; - }); - List rectIds = []; - foreach (var item in nodeRects)// Count = 97341 当数量接近这个量级 - { - db.Action(tr => { - var pts = item.ToPoints(); - var rec = EntityAdd.AddPolyLineToEntity(pts.ToPoint2d()); - rec.ColorIndex = 250; - rectIds.Add(tr.AddEntityToMsPs(db, rec)); - }); - } - db.Action(tr => { - db.CoverGroup(tr, rectIds); - }); - - // 获取四叉树深度 - int dep = 0; - _quadTreeRoot.ForEach(node => { - dep = dep > node.Depth ? dep : node.Depth; - return false; - }); - ed.WriteMessage($"\n四叉树深度是: {dep}"); - } - #endregion - -#endif - - #region 四叉树查询节点 - // 选择范围改图元颜色 - [CommandMethod(nameof(CmdTest_QuadTree3))] - public void CmdTest_QuadTree3() - { - Ssget(QuadTreeSelectMode.IntersectsWith); - } - - [CommandMethod(nameof(CmdTest_QuadTree4))] - public void CmdTest_QuadTree4() - { - Ssget(QuadTreeSelectMode.Contains); - } - - /// - /// 改颜色 - /// - /// - void Ssget(QuadTreeSelectMode mode) - { - if (_quadTreeRoot is null) - return; - - using DBTrans tr = new(); - if (tr.Editor is null) - return; - var rect = GetCorner(tr.Editor); - if (rect is null) - return; - - tr.Editor.WriteMessage("选择模式:" + mode); - - // 仿选择集 - var ces = _quadTreeRoot.Query(rect, mode); - ces.ForEach(item => { - var ent = tr.GetObject(item.ObjectId, OpenMode.ForWrite); - ent!.Color = Color.FromColor(item.Color); - ent.DowngradeOpen(); - ent.Dispose(); - }); - } - - /// - /// 交互获取 - /// - /// - /// - public static Rect? GetCorner(Editor ed) - { - var optionsA = new PromptPointOptions($"{Environment.NewLine}起点位置:"); - var pprA = ed.GetPoint(optionsA); - if (pprA.Status != PromptStatus.OK) - return null; - var optionsB = new PromptCornerOptions(Environment.NewLine + "输入矩形角点2:", pprA.Value) - { - UseDashedLine = true,// 使用虚线 - AllowNone = true,// 回车 - }; - var pprB = ed.GetCorner(optionsB); - if (pprB.Status != PromptStatus.OK) - return null!; - - return new Rect(new Point2d(pprA.Value.X, pprA.Value.Y), - new Point2d(pprB.Value.X, pprB.Value.Y), - true); - } - #endregion -} - -// public partial class TestQuadTree -// { -// public void Cmd_tt6() -// { -// using DBTrans tr = new(); -// var ed = tr.Editor; -// // 创建四叉树,默认参数无所谓 -// var TreeRoot = new QuadTree(new Rect(0, 0, 32525, 32525)); - -// var fil = OpFilter.Build(e => e.Dxf(0) == "LINE"); -// var psr = ed.SSGet("\n 选择需要连接的直线", fil); -// if (psr.Status != PromptStatus.OK) return; -// var LineEnts = new List(psr.Value.GetEntities(OpenMode.ForWrite)!); -// // 将实体插入到四岔树 -// foreach (var line in LineEnts) -// { -// var edge = line.GeometricExtents; -// var entRect = new Rect(edge.MinPoint.X, edge.MinPoint.Y, edge.MaxPoint.X, edge.MaxPoint.Y); -// var ce = new CadEntity(line.Id, entRect) -// { -// // 四叉树数据 -// Angle = line.Angle -// }; -// TreeRoot.Insert(ce); -// } - -// var ppo = new PromptPointOptions(Environment.NewLine + "\n指定标注点:<空格退出>") -// { -// AllowArbitraryInput = true,// 任意输入 -// AllowNone = true // 允许回车 -// }; -// var ppr = ed.GetPoint(ppo);// 用户点选 -// if (ppr.Status != PromptStatus.OK) -// return; -// var rect = new Rect(ppr.Value.Point2d(), 100, 100); -// tr.CurrentSpace.AddEntity(rect.ToPolyLine());// 显示选择靶标范围 - -// var nent = TreeRoot.FindNearEntity(rect);// 查询最近实体,按逆时针 -// var ent = tr.GetObject(nent.ObjectId, OpenMode.ForWrite);// 打开实体 -// ent.ColorIndex = Utility.GetRandom().Next(1, 256);// 1~256随机色 -// ent.DowngradeOpen();// 实体降级 -// ent.Dispose(); - -// var res = TreeRoot.Query(rect, QuadTreeSelectMode.IntersectsWith);// 查询选择靶标范围相碰的ID -// res.ForEach(item => { -// if (item.Angle == 0 || item.Angle == Math.PI) // 过滤直线角度为0或180的直线 -// { -// var ent = tr.GetObject(item.ObjectId, OpenMode.ForWrite); -// ent.ColorIndex = Utility.GetRandom().Next(1, 7); -// ent.DowngradeOpen(); -// ent.Dispose(); -// } -// }); -// } -// } \ No newline at end of file diff --git a/tests/TestShared/TestSelectfilter.cs b/tests/TestShared/TestSelectfilter.cs deleted file mode 100644 index cab6c92..0000000 --- a/tests/TestShared/TestSelectfilter.cs +++ /dev/null @@ -1,58 +0,0 @@ -namespace Test; - -public class Testselectfilter -{ - [CommandMethod(nameof(Test_Filter))] - public void Test_Filter() - { - var p = new Point3d(10, 10, 0); - var f = OpFilter.Build( - e => !(e.Dxf(0) == "line" & e.Dxf(8) == "0") - | e.Dxf(0) != "circle" & e.Dxf(8) == "2" & e.Dxf(10) >= p); - - - var f2 = OpFilter.Build( - e => e.Or( - !e.And(e.Dxf(0) == "line", e.Dxf(8) == "0"), - e.And(e.Dxf(0) != "circle", e.Dxf(8) == "2", - e.Dxf(10) <= new Point3d(10, 10, 0)))); - - SelectionFilter f3 = f; - SelectionFilter f4 = f2; - - Env.Editor.WriteMessage(""); - } - - [CommandMethod(nameof(Test_Selectanpoint))] - public void Test_Selectanpoint() - { - var sel2 = Env.Editor.SelectAtPoint(new Point3d(0, 0, 0)); - Env.Editor.WriteMessage(""); - } -} - -public class TestSelectObjectType -{ - [CommandMethod(nameof(Test_Select_type))] - public void Test_Select_type() - { - var sel = Env.Editor.SSGet(); - if (sel.Status != PromptStatus.OK) return; - var ids = sel.Value.GetObjectIds(); - foreach (var item in ids) - { - item.Print(); - } - - var dxfName = RXObject.GetClass(typeof(Dimension)).DxfName; - dxfName.Print(); - var idss = sel.Value.GetObjectIds(); - foreach (var item in idss) - { - item.Print(); - item.ObjectClass.DxfName.Print(); - } - - } - -} \ No newline at end of file diff --git a/tests/TestShared/TestShared.projitems b/tests/TestShared/TestShared.projitems deleted file mode 100644 index 28b5f94..0000000 --- a/tests/TestShared/TestShared.projitems +++ /dev/null @@ -1,50 +0,0 @@ - - - - $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - true - ced63d2d-0af6-4831-806d-5e8e9b0d0a07 - - - TestShared - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/tests/TestShared/TestShared.shproj b/tests/TestShared/TestShared.shproj deleted file mode 100644 index 31ea779..0000000 --- a/tests/TestShared/TestShared.shproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - ced63d2d-0af6-4831-806d-5e8e9b0d0a07 - 14.0 - - - - - - - - diff --git a/tests/TestShared/TestSingleKeyWordHook.cs b/tests/TestShared/TestSingleKeyWordHook.cs deleted file mode 100644 index 73fe216..0000000 --- a/tests/TestShared/TestSingleKeyWordHook.cs +++ /dev/null @@ -1,48 +0,0 @@ -namespace TestShared; -public static class TestSingleKeyWordHook -{ - [CommandMethod(nameof(TestSingleKeyWordHookDemo))] - public static void TestSingleKeyWordHookDemo() - { - var line1 = new Line(Point3d.Origin, new Point3d(100, 100, 0)); - line1.SetDatabaseDefaults(); - using var j1 = new JigEx((mpw, _) => { - line1.Move(line1.StartPoint, mpw); - }); - j1.DatabaseEntityDraw(wd => wd.Geometry.Draw(line1)); - var jppo = j1.SetOptions("\n选择位置或"); - jppo.Keywords.Add("A", "A", "旋转90°(A)"); - jppo.Keywords.Add("D", "D", "旋转45°(D)"); - // 创建关键字钩子 - using var skwh = new SingleKeyWordHook(); - // 添加关键字 - skwh.AddKeys(jppo.Keywords); - while (true) - { - // 循环开始时复位 - skwh.Reset(); - var r1 = Env.Editor.Drag(j1); - if (skwh.IsResponsed || r1.Status == PromptStatus.Keyword) - { - // 此钩子完整保留了原关键字的鼠标点击功能,所以要同时支持两种情况,也方便在已经写好的关键字功能上扩展 - // 如果响应了关键字 - switch (skwh.IsResponsed ? skwh.StringResult : r1.StringResult.ToUpper()) - { - case "A": - line1.Rotation(line1.StartPoint, Math.PI * 0.5, Vector3d.ZAxis); - break; - case "D": - line1.Rotation(line1.StartPoint, Math.PI * 0.25, Vector3d.ZAxis); - break; - } - continue; - } - if (r1.Status == PromptStatus.OK) - { - using var tr = new DBTrans(); - tr.CurrentSpace.AddEntity(line1); - } - return; - } - } -} diff --git a/tests/TestShared/TestText.cs b/tests/TestShared/TestText.cs deleted file mode 100644 index b25dab6..0000000 --- a/tests/TestShared/TestText.cs +++ /dev/null @@ -1,49 +0,0 @@ - -namespace TestShared; - -public class TestText -{ - - [CommandMethod(nameof(TestDBText))] - public void TestDBText() - { - using var tr = new DBTrans(); - tr.CurrentSpace.AddEntity(DBTextEx.CreateDBText(new(-1, -1, 0), "123", 2.5, action:t=> t.ColorIndex = 1)); - - tr.CurrentSpace.AddEntity(DBTextEx.CreateDBText(new(-1, -1, 0), "123", 2.5, action: t => { - t.Justify = AttachmentPoint.BaseCenter; - t.AlignmentPoint = new(1, 1, 0); - t.ColorIndex = 2; - })); - } - - [CommandMethod(nameof(TestBackDBText))] - public void TestBackDBText() - { - using var tr = new DBTrans(@"C:\Users\vic\Desktop\test.dwg"); - tr.CurrentSpace.AddEntity(DBTextEx.CreateDBText(new(-1, -1, 0), "123", 2.5, action: t => t.ColorIndex = 1)); - - tr.CurrentSpace.AddEntity(DBTextEx.CreateDBText(new(-1, -1, 0), "123", 2.5, action: t => - { - t.Justify = AttachmentPoint.BaseCenter; - t.AlignmentPoint = new(1, 1, 0); - t.ColorIndex = 2; - })); - tr.Database.SaveDwgFile(); - } - - - - [CommandMethod(nameof(TestMText))] - public void TestMText() - { - using var tr = new DBTrans(); - tr.CurrentSpace.AddEntity(MTextEx.CreateMText(new(5, 5, 0), "123", 2.5, action: t => t.ColorIndex = 1)); - - tr.CurrentSpace.AddEntity(MTextEx.CreateMText(new(5, 5, 0), "123", 2.5, action: t => { - t.Attachment = AttachmentPoint.TopCenter; - t.ColorIndex = 2; - })); - } - -} diff --git a/tests/TestShared/TestXRecord.cs b/tests/TestShared/TestXRecord.cs deleted file mode 100644 index 1fcb85c..0000000 --- a/tests/TestShared/TestXRecord.cs +++ /dev/null @@ -1,252 +0,0 @@ -//#define ExtendedDataBinaryChunk -#define XTextString - -#if NewtonsoftJson -using System.Diagnostics; -using Newtonsoft.Json; -using static IFoxCAD.Cad.WindowsAPI; - -namespace Test_XRecord; - -public class TestCmd_XRecord -{ - [CommandMethod(nameof(TestSerializeSetXRecord))] - public void TestSerializeSetXRecord() - { - var prs = Env.Editor.SSGet("\n 序列化,选择多段线:"); - if (prs.Status != PromptStatus.OK) - return; - - using var tr = new DBTrans(); - var pls = prs.Value.GetEntities(); - Tools.TestTimes(1, nameof(TestSerializeSetXRecord), () => { - foreach (var pl in pls) - { - if (pl == null) - continue; - - TestABCList datas = new(); - for (int i = 0; i < 1000; i++) - { - datas.Add(new() - { - AAA = i, - BBB = i.ToString(), - CCCC = i * 0.5, - DDDD = i % 2 != 0, - EEEE = new(0, i, 0) - }); - } - - using (pl.ForWrite()) - pl.SerializeToXRecord(datas); - } - }); - } - - [CommandMethod(nameof(TestDeserializeGetXRecord))] - public void TestDeserializeGetXRecord() - { - var prs = Env.Editor.GetEntity("\n 反序列化,选择多段线:"); - if (prs.Status != PromptStatus.OK) - return; - - using var tr = new DBTrans(); - - TestABCList? datas = null; - Tools.TestTimes(1, nameof(TestDeserializeGetXRecord), () => { - var pl = prs.ObjectId.GetObject(); - if (pl == null) - return; -#if XTextString - datas = pl.DeserializeToXRecord(); -#endif - -#if ExtendedDataBinaryChunk - // 这里有数据容量限制,而且很小 - var xd = pl.GetXDictionary(); - if (xd == null) - return; - if (xd.XData == null) - return; - - XDataList data = xd.XData; - var sb = new StringBuilder(); - data.ForEach(a => { - if (a.TypeCode == (short)DxfCode.ExtendedDataBinaryChunk) - if (a.Value is byte[] bytes) - sb.Append(Encoding.UTF8.GetString(bytes)); - }); - datas = JsonConvert.DeserializeObject(sb.ToString(), XRecordHelper._sset); -#endif - }); - if (datas == null) - { - Env.Printl("没有反序列的东西"); - return; - } - - var sb = new StringBuilder(); - for (int i = 0; i < datas.Count; i++) - sb.Append(datas[i]); - Env.Printl(sb); - } -} - -public static class XRecordHelper -{ - #region 序列化方式 - internal static JsonSerializerSettings _sset = new() - { - Formatting = Formatting.Indented, - TypeNameHandling = TypeNameHandling.Auto - }; - - /// - /// 设定信息 - /// - /// 储存对象 - /// 储存数据 - public static void SerializeToXRecord(this DBObject dbo, T data) - { - var xd = dbo.GetXDictionary(); - if (xd == null) - return; - - // XRecordDataList 不能超过2G大小 - const int GigaByte2 = 2147483647; - // 单条只能 16KiBit => 2048 * 16 == 32768 - const int KiBit16 = (2048 * 16) - 1; - - // 就算这个写法支持,计算机也不一定有那么多内存,所以遇到此情况最好换成内存拷贝 - var json = JsonConvert.SerializeObject(data, _sset);// 此时内存占用了2G - var buffer = Encoding.UTF8.GetBytes(json); // 此时内存又占用了2G.. - - BytesTask(buffer, GigaByte2, bts => { -#if XTextString - XRecordDataList datas = new(); - BytesTask(buffer, KiBit16, bts => { - datas.Add(DxfCode.XTextString, Encoding.UTF8.GetString(bts)); // 这对的 - // datas.Add(DxfCode.XTextString, bts);//这样 bts 变成 "System.Byte[]" - }); - xd.SetXRecord(typeof(T).FullName, datas); -#endif - -#if ExtendedDataBinaryChunk - // 这里有数据容量限制,而且很小 - var appname = typeof(T).FullName; - DBTrans.Top.RegAppTable.Add(appname); - - XDataList datas = new(); - datas.Add(DxfCode.ExtendedDataRegAppName, appname); - BytesTask(buffer, KiBit16, bts => { - datas.Add(DxfCode.ExtendedDataBinaryChunk, bts); - }); - using (xd.ForWrite()) - xd.XData = datas; // Autodesk.AutoCAD.Runtime.Exception:“eXdataSizeExceeded” -#endif - }); - } - - [DebuggerHidden] - static void BytesTask(byte[] buffer, int max, Action action) - { - int index = 0; - while (index < buffer.Length) - { - // 每次 max,然后末尾剩余就单独 - byte[] bts; - if (buffer.Length - index > max) - bts = new byte[max]; - else - bts = new byte[buffer.Length - index]; - - for (int i = 0; i < bts.Length; i++) - bts[i] = buffer[index++]; - - action.Invoke(bts); - } - } - - /// - /// 提取信息 - /// - /// 类型 - /// 储存对象 - /// 提取数据生成的对象 - public static T? DeserializeToXRecord(this DBObject dbo) - { - var xd = dbo.GetXDictionary(); - if (xd == null) - return default; - - var datas = xd.GetXRecord(typeof(T).FullName); - if (datas == null) - return default; - - var sb = new StringBuilder(); - for (int i = 0; i < datas.Count; i++) - sb.Append(datas[i].Value); - - return JsonConvert.DeserializeObject(sb.ToString(), _sset); - } - #endregion - - - /// - /// 设置描述(容量无限) - /// - /// - /// - /// - public static void SetSummaryInfoAtt(this Database db, string key, object value) - { - var info = new DatabaseSummaryInfoBuilder(db.SummaryInfo); - if (!info.CustomPropertyTable.Contains(key)) - info.CustomPropertyTable.Add(key, value); - else - info.CustomPropertyTable[key] = value; - db.SummaryInfo = info.ToDatabaseSummaryInfo(); - } - /// - /// 获取描述 - /// - /// - /// - /// - public static object? GetSummaryInfoAtt(this Database db, string key) - { - var info = new DatabaseSummaryInfoBuilder(db.SummaryInfo); - if (info.CustomPropertyTable.Contains(key)) - return info.CustomPropertyTable[key]; - return null; - } - -} - -public class TestABCList : List -{ -} - -[ComVisible(true)] -[Serializable] -[DebuggerDisplay("{DebuggerDisplay,nq}")] -[DebuggerTypeProxy(typeof(TestABC))] -[StructLayout(LayoutKind.Sequential, Pack = 4)] -public class TestABC -{ - [DebuggerBrowsable(DebuggerBrowsableState.Never)] - private string DebuggerDisplay => ToString(); - - public int AAA; - public string? BBB; - public double CCCC; - public bool DDDD; - public Point3D EEEE; - - public override string ToString() - { - return JsonConvert.SerializeObject(this, XRecordHelper._sset); - } -} -#endif \ No newline at end of file diff --git a/tests/TestShared/TestXdata.cs b/tests/TestShared/TestXdata.cs deleted file mode 100644 index a0c10af..0000000 --- a/tests/TestShared/TestXdata.cs +++ /dev/null @@ -1,132 +0,0 @@ -namespace Test; - -public class TestXdata -{ - // 测试扩展数据 - private const string Appname = "myapp2"; - - // 增 - [CommandMethod(nameof(Test_AddXdata))] - public void Test_AddXdata() - { - using DBTrans tr = new(); - - tr.RegAppTable.Add("myapp1"); - tr.RegAppTable.Add(Appname); // add函数会默认的在存在这个名字的时候返回这个名字的regapp的id,不存在就新建 - tr.RegAppTable.Add("myapp3"); - tr.RegAppTable.Add("myapp4"); - - var line = new Line(new Point3d(0, 0, 0), new Point3d(1, 1, 0)) - { - XData = new XDataList() - { - { DxfCode.ExtendedDataRegAppName, "myapp1" }, // 可以用dxfcode和int表示组码 - { DxfCode.ExtendedDataAsciiString, "xxxxxxx" }, - {1070, 12 }, - { DxfCode.ExtendedDataRegAppName, Appname }, // 可以用dxfcode和int表示组码,移除中间的测试 - { DxfCode.ExtendedDataAsciiString, "要移除的我" }, - { DxfCode.ExtendedDataAsciiString, "要移除的我" }, - { DxfCode.ExtendedDataAsciiString, "要移除的我" }, - { DxfCode.ExtendedDataAsciiString, "要移除的我" }, - {1070, 12 }, - { DxfCode.ExtendedDataRegAppName, "myapp3" }, // 可以用dxfcode和int表示组码 - { DxfCode.ExtendedDataAsciiString, "aaaaaaaaa" }, - {1070, 12 }, - { DxfCode.ExtendedDataRegAppName, "myapp4" }, // 可以用dxfcode和int表示组码 - { DxfCode.ExtendedDataAsciiString, "bbbbbbbbb" }, - {1070, 12 } - } - }; - - var line1 = new Line(new(0, 0, 0), new(2, 0, 0)); - line1.XData = new XDataList() - { - { DxfCode.ExtendedDataRegAppName, "myapp1" }, // 可以用dxfcode和int表示组码 - { DxfCode.ExtendedDataAsciiString, "xxxxxxx" }, - { 1070, 12 }, - { DxfCode.ExtendedDataRegAppName, Appname }, // 可以用dxfcode和int表示组码,移除中间的测试 - { DxfCode.ExtendedDataAsciiString, "要移除的我" }, - { DxfCode.ExtendedDataAsciiString, "要移除的我" }, - { DxfCode.ExtendedDataAsciiString, "要移除的我" }, - { DxfCode.ExtendedDataAsciiString, "要移除的我" }, - { 1070, 12 }, - { DxfCode.ExtendedDataRegAppName, "myapp3" }, // 可以用dxfcode和int表示组码 - { DxfCode.ExtendedDataAsciiString, "aaaaaaaaa" }, - { DxfCode.ExtendedDataAsciiString, "ccccccccc" }, - { 1070, 12 }, - { DxfCode.ExtendedDataRegAppName, "myapp4" }, // 可以用dxfcode和int表示组码 - { DxfCode.ExtendedDataAsciiString, "bbbbbbbbb" }, - { 1070, 12 } - }; - - tr.CurrentSpace.AddEntity(line,line1); - } - // 删 - [CommandMethod(nameof(Test_RemoveXdata))] - public void Test_RemoveXdata() - { - var res = Env.Editor.GetEntity("\n select the entity:"); - if (res.Status != PromptStatus.OK) return; - - using DBTrans tr = new(); - var ent = tr.GetObject(res.ObjectId); - if (ent == null || ent.XData == null) - return; - - Env.Printl("\n移除前:" + ent.XData); - - ent.RemoveXData(Appname, DxfCode.ExtendedDataAsciiString); - Env.Printl("\n移除成员后:" + ent.XData); - - ent.RemoveXData(Appname); - Env.Printl("\n移除appName后:" + ent.XData); - } - // 查 - [CommandMethod(nameof(Test_GetXdata))] - public void Test_GetXdata() - { - using DBTrans tr = new(); - tr.RegAppTable.ForEach(id => - id.GetObject()?.Name.Print()); - tr.RegAppTable.GetRecords().ForEach(rec => rec.Name.Print()); - tr.RegAppTable.GetRecordNames().ForEach(name => name.Print()); - tr.RegAppTable.ForEach(reg => reg.Name.Print(), checkIdOk: false); - - // 查询appName里面是否含有某个 - - var res = Env.Editor.GetEntity("\n select the entity:"); - if (res.Status != PromptStatus.OK) return; - - var ent = tr.GetObject(res.ObjectId); - if (ent == null || ent.XData == null) - return; - - XDataList data = ent.XData; - if (data.Contains(Appname)) - Env.Printl("含有appName:" + Appname); - else - Env.Printl("不含有appName:" + Appname); - - const string str = "要移除的我"; - if (data.Contains(Appname, str)) - Env.Printl("含有内容:" + str); - else - Env.Printl("不含有内容:" + str); - } - // 改 - [CommandMethod(nameof(Test_ChangeXdata))] - public void Test_ChangeXdata() - { - var res = Env.Editor.GetEntity("\n select the entity:"); - if (res.Status != PromptStatus.OK) return; - - using DBTrans tr = new(); - var data = tr.GetObject(res.ObjectId)!; - data.ChangeXData(Appname, DxfCode.ExtendedDataAsciiString, "change"); - - if (data.XData == null) - return; - Env.Printl(data.XData.ToString()); - } - -} \ No newline at end of file diff --git a/tests/TestShared/TestXrefEx.cs b/tests/TestShared/TestXrefEx.cs deleted file mode 100644 index 7fa7f3e..0000000 --- a/tests/TestShared/TestXrefEx.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace Test; - -public class TestCmd_BindXrefs -{ - //后台绑定 - [CommandMethod(nameof(Test_Bind1))] - public static void Test_Bind1() - { - string fileName = @"D:\Test.dwg"; - using var tr = new DBTrans(fileName, - fileOpenMode: FileOpenMode.OpenForReadAndAllShare/*后台绑定特别注意*/); - tr.XrefFactory(XrefModes.Bind); - tr.Database.SaveDwgFile(); - } - - //前台绑定 - [CommandMethod(nameof(Test_Bind2))] - public static void Test_Bind2() - { - using var tr = new DBTrans(); - tr.XrefFactory(XrefModes.Bind); - tr.Database.SaveDwgFile(); - } -} \ No newline at end of file diff --git a/tests/TestShared/readme.md b/tests/TestShared/readme.md deleted file mode 100644 index 81b106f..0000000 --- a/tests/TestShared/readme.md +++ /dev/null @@ -1,20 +0,0 @@ -# 测试项目文件结构 -- 图元类 - TestEntity - + TestAddEntity.cs - + TestRemoveEntity.cs - + .... -- 事务类 - TestDBtrans -- 符号表类 - TestSymTable - + TestLayer.cs - + TestTextStyle.cs - + ... -- 选择集类 -- 扩展数据类 -- editor类 -- 数据库对象类 -- env类 -- jig类 -- 数据交互类 -- lisp类 -- 算法类 -- \ No newline at end of file diff --git a/tests/TestZcad2024/GlobalUsings.cs b/tests/TestZcad2024/GlobalUsings.cs deleted file mode 100644 index 543b726..0000000 --- a/tests/TestZcad2024/GlobalUsings.cs +++ /dev/null @@ -1,47 +0,0 @@ -/// 系统引用 -global using System; -global using System.Collections; -global using System.Collections.Generic; -global using System.IO; -global using System.Linq; -global using System.Text; -global using System.Reflection; -global using System.Text.RegularExpressions; -global using Microsoft.Win32; -global using System.ComponentModel; -global using System.Runtime.InteropServices; -global using System.Collections.Specialized; - -global using Exception = System.Exception; - -global using Registry = Microsoft.Win32.Registry; -global using RegistryKey = Microsoft.Win32.RegistryKey; - -// cad 引用 -global using ZwSoft.ZwCAD.ApplicationServices; -global using ZwSoft.ZwCAD.EditorInput; -global using ZwSoft.ZwCAD.Colors; -global using ZwSoft.ZwCAD.DatabaseServices; -global using ZwSoft.ZwCAD.Geometry; -global using ZwSoft.ZwCAD.Runtime; -global using Acap = ZwSoft.ZwCAD.ApplicationServices.Application; -global using Acaop = ZwSoft.ZwCAD.ApplicationServices.Application; -global using AcException = ZwSoft.ZwCAD.Runtime.Exception; -global using ZwSoft.ZwCAD.DatabaseServices.Filters; -global using Acgi = ZwSoft.ZwCAD.GraphicsInterface; -// jig命名空间会引起Viewport/Polyline等等重义,最好逐个引入 using ZwSoft.ZwCAD.GraphicsInterface -global using ZwSoft.ZwCAD.GraphicsInterface; -global using WorldDraw = ZwSoft.ZwCAD.GraphicsInterface.WorldDraw; -global using Manager = ZwSoft.ZwCAD.GraphicsSystem.Manager; -global using Group = ZwSoft.ZwCAD.DatabaseServices.Group; -global using Viewport = ZwSoft.ZwCAD.DatabaseServices.Viewport; -global using Polyline = ZwSoft.ZwCAD.DatabaseServices.Polyline; -global using Cad_DwgFiler = ZwSoft.ZwCAD.DatabaseServices.DwgFiler; -global using Cad_DxfFiler = ZwSoft.ZwCAD.DatabaseServices.DxfFiler; -global using Cad_ErrorStatus = ZwSoft.ZwCAD.Runtime.ErrorStatus; - - -/// ifoxcad -global using IFoxCAD.Cad; -global using IFoxCAD.Basal; - diff --git a/tests/TestZcad2024/TestZcad2024.csproj b/tests/TestZcad2024/TestZcad2024.csproj deleted file mode 100644 index 2dd8650..0000000 --- a/tests/TestZcad2024/TestZcad2024.csproj +++ /dev/null @@ -1,29 +0,0 @@ - - - preview - enable - - NET48 - true - true - x64 - True - - - - $(Configuration);zcad - - - - - - - - - - - - - - - -- Gitee From 05e487f75bb079b843dd4417d71096e3bd383876 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Fri, 22 Mar 2024 18:25:33 +0800 Subject: [PATCH 254/453] =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E5=88=9D=E5=A7=8B?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IFoxCAD.CAD/IFoxCAD.CAD.csproj | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 IFoxCAD.CAD/IFoxCAD.CAD.csproj diff --git a/IFoxCAD.CAD/IFoxCAD.CAD.csproj b/IFoxCAD.CAD/IFoxCAD.CAD.csproj new file mode 100644 index 0000000..78b6684 --- /dev/null +++ b/IFoxCAD.CAD/IFoxCAD.CAD.csproj @@ -0,0 +1,25 @@ + + + + net48 + Preview + enable + x64 + + + + full + True + + + + full + True + + + + + + + + -- Gitee From aec3bf968a9379ef7cf59a0bc46a495bfcbc021f Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Fri, 22 Mar 2024 19:43:26 +0800 Subject: [PATCH 255/453] =?UTF-8?q?DBTrans=E7=AD=89=E5=B8=B8=E7=94=A8?= =?UTF-8?q?=E7=B1=BB=E8=BF=81=E7=A7=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IFoxCAD.Cad/Basal/General/LoopState.cs | 71 ++ IFoxCAD.Cad/Basal/Nullable/ArgumentNullEx.cs | 25 + .../CallerArgumentExpressionAttribute.cs | 22 + IFoxCAD.Cad/ExtensionMethod/DBObjectEx.cs | 194 ++++ IFoxCAD.Cad/ExtensionMethod/ObjectIdEx.cs | 139 +++ IFoxCAD.Cad/ExtensionMethod/TransactionEx.cs | 41 + IFoxCAD.Cad/GlobalUsing.cs | 51 + .../IFoxCAD.Cad.csproj | 10 +- IFoxCAD.Cad/ResultData/TypedValueList.cs | 64 ++ IFoxCAD.Cad/ResultData/XdataList.cs | 146 +++ IFoxCAD.Cad/Runtime/DBTrans.cs | 687 ++++++++++++++ IFoxCAD.Cad/Runtime/Env.cs | 881 ++++++++++++++++++ IFoxCAD.Cad/Runtime/IdleAction.cs | 66 ++ IFoxCAD.Cad/Runtime/SymbolTable.cs | 401 ++++++++ IFoxCAD.sln | 14 +- IFoxCAD.sln.DotSettings | 13 + 16 files changed, 2821 insertions(+), 4 deletions(-) create mode 100644 IFoxCAD.Cad/Basal/General/LoopState.cs create mode 100644 IFoxCAD.Cad/Basal/Nullable/ArgumentNullEx.cs create mode 100644 IFoxCAD.Cad/Basal/Nullable/CallerArgumentExpressionAttribute.cs create mode 100644 IFoxCAD.Cad/ExtensionMethod/DBObjectEx.cs create mode 100644 IFoxCAD.Cad/ExtensionMethod/ObjectIdEx.cs create mode 100644 IFoxCAD.Cad/ExtensionMethod/TransactionEx.cs create mode 100644 IFoxCAD.Cad/GlobalUsing.cs rename IFoxCAD.CAD/IFoxCAD.CAD.csproj => IFoxCAD.Cad/IFoxCAD.Cad.csproj (59%) create mode 100644 IFoxCAD.Cad/ResultData/TypedValueList.cs create mode 100644 IFoxCAD.Cad/ResultData/XdataList.cs create mode 100644 IFoxCAD.Cad/Runtime/DBTrans.cs create mode 100644 IFoxCAD.Cad/Runtime/Env.cs create mode 100644 IFoxCAD.Cad/Runtime/IdleAction.cs create mode 100644 IFoxCAD.Cad/Runtime/SymbolTable.cs create mode 100644 IFoxCAD.sln.DotSettings diff --git a/IFoxCAD.Cad/Basal/General/LoopState.cs b/IFoxCAD.Cad/Basal/General/LoopState.cs new file mode 100644 index 0000000..1367e86 --- /dev/null +++ b/IFoxCAD.Cad/Basal/General/LoopState.cs @@ -0,0 +1,71 @@ +// ReSharper disable InconsistentNaming +#pragma warning disable CS1591 // 缺少对公共可见类型或成员的 XML 注释 +namespace IFoxCAD.Basal; + +#line hidden // 调试的时候跳过它 +/// +/// 控制循环结束 +/// +public class LoopState +{ + private const int PlsNone = 0; + private const int PlsExceptional = 1; + private const int PlsBroken = 2; + private const int PlsStopped = 4; + private const int PlsCanceled = 8; + + private volatile int _flag = PlsNone; + + public bool IsRun => _flag == PlsNone; + public bool IsExceptional => (_flag & PlsExceptional) == PlsExceptional; + public bool IsBreak => (_flag & PlsBroken) == PlsBroken; + public bool IsStop => (_flag & PlsStopped) == PlsStopped; + public bool IsCancel => (_flag & PlsCanceled) == PlsCanceled; + + public void Exceptional() + { + if ((_flag & PlsExceptional) != PlsExceptional) + _flag |= PlsExceptional; + } + public void Break() => _flag = PlsBroken; + public void Stop() => _flag = PlsStopped; + public void Cancel() => _flag = PlsCanceled; + public void Reset() => _flag = PlsNone; +} +#line default + +/// +/// 控制程序流程 +/// +public class ProState +{ + private const int PlsNone = 0; // 初始化(构造就立马运行,将导致构造函数中也被检测,这是浪费性能及挖坑给自己的) + private const int PlsRun = 1; // 运行 + private const int PlsBroken = 2; + private const int PlsStopped = 4; + private const int PlsCanceled = 8; + private const int PlsExceptional = 16; // 异常 用于附加状态 + + private volatile int _flag = PlsNone; + + public bool IsNone => _flag == PlsNone; + public bool IsRun => (_flag & PlsRun) == PlsRun; + public bool IsBreak => (_flag & PlsBroken) == PlsBroken; + public bool IsStop => (_flag & PlsStopped) == PlsStopped; + public bool IsCancel => (_flag & PlsCanceled) == PlsCanceled; + public bool IsExceptional => (_flag & PlsExceptional) == PlsExceptional; + + public void Exceptional() + { + if ((_flag & PlsExceptional) != PlsExceptional) + _flag |= PlsExceptional; + } + public void Break() => _flag = PlsBroken; + public void Stop() => _flag = PlsStopped; + public void Cancel() => _flag = PlsCanceled; + public void Start() => _flag = PlsRun; + public void None() => _flag = PlsNone; +} +#line default + +#pragma warning restore CS1591 // 缺少对公共可见类型或成员的 XML 注释 \ No newline at end of file diff --git a/IFoxCAD.Cad/Basal/Nullable/ArgumentNullEx.cs b/IFoxCAD.Cad/Basal/Nullable/ArgumentNullEx.cs new file mode 100644 index 0000000..8b030b6 --- /dev/null +++ b/IFoxCAD.Cad/Basal/Nullable/ArgumentNullEx.cs @@ -0,0 +1,25 @@ +namespace IFoxCAD.Basal; + +/// +/// 参数null检查类 +/// +public static class ArgumentNullEx +{ + /// + /// 检查参数是否为 null + /// + /// 参数 + /// 参数名字 + public static void ThrowIfNull([NotNull] object? argument, + [CallerArgumentExpression(nameof(argument))] + string? paramName = null) + { + if (argument is null) + { + Throw(paramName); + } + } + + [DoesNotReturn] + private static void Throw(string? paramName) => throw new ArgumentNullException(paramName); +} \ No newline at end of file diff --git a/IFoxCAD.Cad/Basal/Nullable/CallerArgumentExpressionAttribute.cs b/IFoxCAD.Cad/Basal/Nullable/CallerArgumentExpressionAttribute.cs new file mode 100644 index 0000000..dc8587f --- /dev/null +++ b/IFoxCAD.Cad/Basal/Nullable/CallerArgumentExpressionAttribute.cs @@ -0,0 +1,22 @@ +namespace System.Runtime.CompilerServices; + +/// +/// 指示参数将为另一个参数传递的表达式捕获为字符串。 +/// +[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] +internal sealed class CallerArgumentExpressionAttribute : Attribute +{ + /// + /// 初始化 CallerArgumentExpressionAttribute 类的新实例。 + /// + /// 参数名 + public CallerArgumentExpressionAttribute(string parameterName) + { + ParameterName = parameterName; + } + + /// + /// 获取其表达式应捕获为字符串的参数的名称。 + /// + public string ParameterName { get; } +} \ No newline at end of file diff --git a/IFoxCAD.Cad/ExtensionMethod/DBObjectEx.cs b/IFoxCAD.Cad/ExtensionMethod/DBObjectEx.cs new file mode 100644 index 0000000..6eb802a --- /dev/null +++ b/IFoxCAD.Cad/ExtensionMethod/DBObjectEx.cs @@ -0,0 +1,194 @@ +namespace IFoxCAD.Cad; + +/// +/// 实体对象扩展类 +/// +public static class DBObjectEx +{ + /// + /// 获取块的有效名字 + /// + /// 块参照 + /// 名字 + public static string GetBlockName(this BlockReference blk) + { + ArgumentNullEx.ThrowIfNull(blk); + if (blk.IsDynamicBlock) + { + var btrid = blk.DynamicBlockTableRecord; + var tr = btrid.Database.TransactionManager.TopTransaction; + ArgumentNullEx.ThrowIfNull(tr); + var btr = (BlockTableRecord)tr.GetObject(btrid); + return btr.Name; + } + return blk.Name; + } + + #region Linq + /// + /// 删除数据库对象 + /// + /// 数据库对象列表 + public static void Erase(this IEnumerable dBObjects) + { + foreach (var dbo in dBObjects) + { + if (dbo.IsNewObject || dbo.IsErased) + continue; + using (dbo.ForWrite()) + { + dbo.Erase(); + } + } + } + #endregion + + #region Xdata扩展 + /// + /// 删除扩展数据 + /// + /// 对象实例 + /// 应用程序名称 + /// 要删除数据的组码 + public static void RemoveXData(this DBObject obj, string appName, DxfCode dxfCode) + { + if (obj.XData == null) + return; + XDataList data = obj.XData; + + // 移除指定App的扩展 + var indexs = data.GetXdataAppIndex(appName, new DxfCode[] { dxfCode }); + if (indexs.Count == 0) + return; + + for (int i = indexs.Count - 1; i >= 0; i--) + data.RemoveAt(indexs[i]); + + using (obj.ForWrite()) + obj.XData = data; + } + /// + /// 删除扩展数据 + /// + /// 对象实例 + /// 应用程序名称 + public static void RemoveXData(this DBObject obj, string appName) + { + if (obj.XData == null) + return; + + // 直接赋值进去等于清空名称 + using (obj.ForWrite()) + obj.XData = new XDataList() { { 1001, appName } }; + } + /// + /// 克隆对象 + /// + /// 对象类型 + /// 对象 + /// 克隆后的对象 + /// + public static T CloneEx(this T ent) where T : RXObject + { + return ent.Clone() is T tEnt ? tEnt : throw new ArgumentException(nameof(CloneEx) + "克隆出错"); + } + /// + /// 修改扩展数据 + /// + /// 对象实例 + /// 应用程序名称 + /// 要修改数据的组码 + /// 新的数据 + public static void ChangeXData(this DBObject obj, string appName, DxfCode dxfCode, object newvalue) + { + if (obj.XData == null) + return; + XDataList data = obj.XData; + + var indexs = data.GetXdataAppIndex(appName, new DxfCode[] { dxfCode }); + if (indexs.Count == 0) + return; + + for (int i = indexs.Count - 1; i >= 0; i--) + data[indexs[i]] = new TypedValue((short)dxfCode, newvalue); + + using (obj.ForWrite()) + obj.XData = data; + } + #endregion + + #region 读写模式切换 + +#line hidden // 调试的时候跳过它 + /// + /// 实体自动管理读写函数,此函数性能比using模式低一倍 + /// + /// 实体类型 + /// 实体对象 + /// 操作委托 + public static void ForWrite(this T obj, Action action) where T : DBObject + { + var _isNotifyEnabled = obj.IsNotifyEnabled; + var _isWriteEnabled = obj.IsWriteEnabled; + if (_isNotifyEnabled) + obj.UpgradeFromNotify(); + else if (!_isWriteEnabled) + obj.UpgradeOpen(); + + action?.Invoke(obj); + + if (_isNotifyEnabled) + obj.DowngradeToNotify(_isWriteEnabled); + else if (!_isWriteEnabled) + obj.DowngradeOpen(); + } + + /// + /// 打开模式提权 + /// + /// 实体对象 + /// 提权类对象 + public static UpgradeOpenManager ForWrite(this DBObject obj) + { + return new UpgradeOpenManager(obj); + } + + /// + /// 提权类 + /// + public class UpgradeOpenManager : IDisposable + { + private readonly DBObject _obj; + private readonly bool _isNotifyEnabled; + private readonly bool _isWriteEnabled; + + internal UpgradeOpenManager(DBObject obj) + { + _obj = obj; + _isNotifyEnabled = _obj.IsNotifyEnabled; + _isWriteEnabled = _obj.IsWriteEnabled; + if (_isNotifyEnabled) + _obj.UpgradeFromNotify(); + else if (!_isWriteEnabled) + _obj.UpgradeOpen(); + } + + #region IDisposable 成员 + + /// + /// 注销函数 + /// + public void Dispose() + { + if (_isNotifyEnabled) + _obj.DowngradeToNotify(_isWriteEnabled); + else if (!_isWriteEnabled) + _obj.DowngradeOpen(); + GC.SuppressFinalize(this); + } + + #endregion IDisposable 成员 + } +#line default + #endregion +} \ No newline at end of file diff --git a/IFoxCAD.Cad/ExtensionMethod/ObjectIdEx.cs b/IFoxCAD.Cad/ExtensionMethod/ObjectIdEx.cs new file mode 100644 index 0000000..aa9d163 --- /dev/null +++ b/IFoxCAD.Cad/ExtensionMethod/ObjectIdEx.cs @@ -0,0 +1,139 @@ +namespace IFoxCAD.Cad; + +/// +/// 对象id扩展类 +/// +public static class ObjectIdEx +{ + #region GetObject + /// + /// 获取指定类型对象 + /// + /// 指定的泛型 + /// 对象id + /// 打开模式 + /// 是否打开已删除对象,默认为不打开 + /// 是否打开锁定图层对象,默认为不打开 + /// 指定类型对象 + public static T? GetObject(this ObjectId id, + OpenMode openMode = OpenMode.ForRead, + bool openErased = false, + bool openLockedLayer = false) where T : DBObject + { + var tr = DBTrans.GetTopTransaction(id.Database); + return tr.GetObject(id, openMode, openErased, openLockedLayer) as T; + } + + /// + /// 获取指定类型对象集合 + /// + /// 指定的泛型 + /// 对象id集合 + /// 打开模式 + /// 是否打开已删除对象,默认为不打开 + /// 是否打开锁定图层对象,默认为不打开 + /// 指定类型对象集合 + [DebuggerStepThrough] + public static IEnumerable GetObject(this IEnumerable ids, + OpenMode openMode = OpenMode.ForRead, + bool openErased = false, + bool openLockedLayer = false) where T : DBObject + { + var rxc = RXObject.GetClass(typeof(T)); + return ids.Where(id => id.ObjectClass.IsDerivedFrom(rxc)) + .Select(id => id.GetObject(openMode, openErased, openLockedLayer)) + .OfType(); + } + /// + /// 获取指定类型对象集合 + /// + /// 指定的泛型 + /// 对象id集合 + /// 打开模式 + /// 是否打开已删除对象,默认为不打开 + /// 是否打开锁定图层对象,默认为不打开 + /// 指定类型对象集合 + [DebuggerStepThrough] + public static IEnumerable GetObject(this ObjectIdCollection ids, + OpenMode openMode = OpenMode.ForRead, + bool openErased = false, + bool openLockedLayer = false) where T : DBObject + { + return ids.Cast().GetObject(openMode, openErased, openLockedLayer); + } + /// + /// 返回符合类型的对象id + /// + /// 对象类型 + /// 对象id集合 + /// 精确匹配 + /// 对象id集合 + public static IEnumerable IsDerivedFrom(this IEnumerable ids, bool exactMatch = false) where T : DBObject + { + var rxc = RXClass.GetClass(typeof(T)); + if (exactMatch) + { + var dxfName = rxc.DxfName; + return ids.Where(id => id.ObjectClass.DxfName == dxfName); + } + + return ids.Where(id => id.ObjectClass.IsDerivedFrom(rxc)); + } + #endregion GetObject + + /// + /// 根据对象句柄字符串获取对象Id + /// + /// 数据库 + /// 句柄字符串 + /// 对象的ObjectId + public static ObjectId GetObjectId(this Database db, string handleString) + { + return db.GetObjectId(handleString.ConvertToHandle()); + } + /// + /// 根据对象句柄获取对象ObjectId + /// + /// 数据库 + /// 句柄 + /// 对象的ObjectId + public static ObjectId GetObjectId(this Database db, Handle? handle) + { + return handle is not null && db.TryGetObjectId(handle.Value, out ObjectId id) ? id : ObjectId.Null; + } + /// + /// 句柄字符串转句柄 + /// + /// 句柄字符串 + /// 句柄 + public static Handle? ConvertToHandle(this string handleString) + { + return long.TryParse(handleString, NumberStyles.HexNumber, null, out long l) ? new Handle(l) : null; + } + /// + /// id是否有效,未被删除 + /// + /// 对象id + /// id有效返回 ,反之返回 + public static bool IsOk(this ObjectId id) + { + return id is { IsNull: false, IsValid: true, IsErased: false, IsEffectivelyErased: false, IsResident: true }; + } + + /// + /// 删除id代表的对象 + /// + /// 对象id + public static void Erase(this ObjectId id) + { + if (id.IsOk()) + { + var ent = id.GetObject()!; + using (ent.ForWrite()) + { + ent.Erase(); + }// 第一种读写权限自动转换写法 + // Env.Editor.Regen(); + } + } +} \ No newline at end of file diff --git a/IFoxCAD.Cad/ExtensionMethod/TransactionEx.cs b/IFoxCAD.Cad/ExtensionMethod/TransactionEx.cs new file mode 100644 index 0000000..698f503 --- /dev/null +++ b/IFoxCAD.Cad/ExtensionMethod/TransactionEx.cs @@ -0,0 +1,41 @@ +namespace IFoxCAD.Cad; + +/// +/// cad的事务的扩展类 +/// +public static class TransactionEx +{ + /// + /// 根据对象id获取对象 + /// + /// + /// 对象id + /// 打开模式,默认为只读 + /// 是否打开已删除对象,默认为不打开 + /// 是否打开锁定图层对象,默认为不打开 + /// 数据库DBObject对象 + public static DBObject GetObject(this Transaction tr, ObjectId id, + OpenMode openMode = OpenMode.ForRead, + bool openErased = false, + bool openLockedLayer = false) + { + return tr.GetObject(id, openMode, openErased, openLockedLayer); + } + /// + /// 根据对象id获取图元对象 + /// + /// 要获取的图元对象的类型 + /// + /// 对象id + /// 打开模式,默认为只读 + /// 是否打开已删除对象,默认为不打开 + /// 是否打开锁定图层对象,默认为不打开 + /// 图元对象,类型不匹配时抛异常 + public static T? GetObject(this Transaction tr, ObjectId id, + OpenMode openMode = OpenMode.ForRead, + bool openErased = false, + bool openLockedLayer = false) where T : DBObject + { + return tr.GetObject(id, openMode, openErased, openLockedLayer) as T; + } +} \ No newline at end of file diff --git a/IFoxCAD.Cad/GlobalUsing.cs b/IFoxCAD.Cad/GlobalUsing.cs new file mode 100644 index 0000000..53a464b --- /dev/null +++ b/IFoxCAD.Cad/GlobalUsing.cs @@ -0,0 +1,51 @@ +global using Autodesk.AutoCAD.ApplicationServices; +global using Autodesk.AutoCAD.DatabaseServices; +global using Autodesk.AutoCAD.EditorInput; +global using Autodesk.AutoCAD.Geometry; +global using Autodesk.AutoCAD.GraphicsInterface; +global using Autodesk.AutoCAD.Runtime; +global using Autodesk.AutoCAD.Windows; +global using Autodesk.AutoCAD.Colors; +global using Autodesk.AutoCAD.DatabaseServices.Filters; +global using Autodesk.AutoCAD.GraphicsSystem; +global using LineWeight = Autodesk.AutoCAD.DatabaseServices.LineWeight; +global using Viewport = Autodesk.AutoCAD.DatabaseServices.Viewport; +global using Color = Autodesk.AutoCAD.Colors.Color; +global using Acap = Autodesk.AutoCAD.ApplicationServices.Application; +global using Acaop = Autodesk.AutoCAD.ApplicationServices.Core.Application; +global using Polyline = Autodesk.AutoCAD.DatabaseServices.Polyline; +global using Group = Autodesk.AutoCAD.DatabaseServices.Group; +global using CursorType = Autodesk.AutoCAD.EditorInput.CursorType; +global using ColorDialog = Autodesk.AutoCAD.Windows.ColorDialog; +global using StatusBar = Autodesk.AutoCAD.Windows.StatusBar; +global using Utils = Autodesk.AutoCAD.Internal.Utils; +global using SystemVariableChangedEventArgs = Autodesk.AutoCAD.ApplicationServices.SystemVariableChangedEventArgs; +global using AcException = Autodesk.AutoCAD.Runtime.Exception; +global using System; +global using System.Reflection; +global using System.Collections; +global using System.Collections.Generic; +global using System.IO; +global using System.Linq; +global using System.Threading; +global using System.Text; +global using System.Runtime.InteropServices; +global using System.ComponentModel; +global using Exception = System.Exception; +global using DrawingColor = System.Drawing.Color; +global using Registry = Microsoft.Win32.Registry; +global using RegistryKey = Microsoft.Win32.RegistryKey; +global using Region = Autodesk.AutoCAD.DatabaseServices.Region; +global using Microsoft.Win32; +global using System.Linq.Expressions; +global using System.Collections.ObjectModel; +// 系统引用 +global using System.Text.RegularExpressions; +global using System.Runtime.CompilerServices; +global using System.Diagnostics; +global using System.Windows.Input; +global using System.Globalization; +// global using System.Windows.Data; +global using System.Net; +global using System.Diagnostics.CodeAnalysis; +global using IFoxCAD.Basal; \ No newline at end of file diff --git a/IFoxCAD.CAD/IFoxCAD.CAD.csproj b/IFoxCAD.Cad/IFoxCAD.Cad.csproj similarity index 59% rename from IFoxCAD.CAD/IFoxCAD.CAD.csproj rename to IFoxCAD.Cad/IFoxCAD.Cad.csproj index 78b6684..24e8653 100644 --- a/IFoxCAD.CAD/IFoxCAD.CAD.csproj +++ b/IFoxCAD.Cad/IFoxCAD.Cad.csproj @@ -5,21 +5,29 @@ Preview enable x64 + IFoxCAD.Cad + true full True + $(DefineConstants);acad full True + $(DefineConstants);acad + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + - diff --git a/IFoxCAD.Cad/ResultData/TypedValueList.cs b/IFoxCAD.Cad/ResultData/TypedValueList.cs new file mode 100644 index 0000000..9275488 --- /dev/null +++ b/IFoxCAD.Cad/ResultData/TypedValueList.cs @@ -0,0 +1,64 @@ +namespace IFoxCAD.Cad; + +/// +/// 用于集中管理扩展数据/扩展字典/resultBuffer的类 +/// +public class TypedValueList : List +{ + #region 构造函数 + /// + /// 默认无参构造函数 + /// + protected TypedValueList() { } + /// + /// 采用 TypedValue 迭代器构造 TypedValueList + /// + /// + protected TypedValueList(IEnumerable values) : base(values) { } + #endregion + + #region 添加数据 + /// + /// 添加数据 + /// + /// 组码 + /// 组码值 + public virtual void Add(int code, object obj) + { + Add(new TypedValue(code, obj)); + } + + #endregion + + #region 转换器 + /// + /// ResultBuffer 隐式转换到 TypedValueList + /// + /// ResultBuffer 实例 + public static implicit operator TypedValueList(ResultBuffer buffer) => new(buffer.AsArray()); + /// + /// TypedValueList 隐式转换到 TypedValue 数组 + /// + /// TypedValueList 实例 + public static implicit operator TypedValue[](TypedValueList values) => values.ToArray(); + /// + /// TypedValueList 隐式转换到 ResultBuffer + /// + /// TypedValueList 实例 + public static implicit operator ResultBuffer(TypedValueList values) => new(values); + /// + /// TypedValue 数组隐式转换到 TypedValueList + /// + /// TypedValue 数组 + public static implicit operator TypedValueList(TypedValue[] values) => new(values); + /// + /// 转换为字符串 + /// + /// ResultBuffer 字符串 + public override string ToString() + { + using ResultBuffer a = new(this); + return a.ToString(); + } + #endregion +} \ No newline at end of file diff --git a/IFoxCAD.Cad/ResultData/XdataList.cs b/IFoxCAD.Cad/ResultData/XdataList.cs new file mode 100644 index 0000000..1baf0f4 --- /dev/null +++ b/IFoxCAD.Cad/ResultData/XdataList.cs @@ -0,0 +1,146 @@ +namespace IFoxCAD.Cad; + +/// +/// 扩展数据封装类 +/// +public class XDataList : TypedValueList +{ + #region 构造函数 + /// + /// 扩展数据封装类 + /// + public XDataList() { } + + /// + /// 扩展数据封装类 + /// + public XDataList(IEnumerable values) : base(values) { } + #endregion + + #region 添加数据 + /// + /// 添加数据 + /// + /// 组码 + /// 组码值 + public override void Add(int code, object obj) + { + if (code is < 1000 or > 1071) + throw new Exception("传入的组码值不是 XData 有效范围!"); + + Add(new TypedValue(code, obj)); + } + + /// + /// 添加数据 + /// + /// dxfcode枚举值 + /// 组码值 + public void Add(DxfCode code, object obj) + { + Add((int)code, obj); + } + + /// + /// 是否含有注册名 + /// + /// 注册名 + public bool Contains(string appName) + { + bool result = false; + RangeTask(appName, (_, state, _) => { + result = true; + state.Break(); + }); + return result; + } + + /// + /// 注册名下含有指定成员 + /// + /// 注册名 + /// 内容 + public bool Contains(string appName, object value) + { + bool result = false; + RangeTask(appName, (tv, state, _) => { + if (tv.Value.Equals(value)) + { + result = true; + state.Break(); + } + }); + return result; + } + + /// + /// 获取appName的索引区间 + /// + /// 注册名称 + /// 任务组码对象 + /// 返回任务组码的索引 + public List GetXdataAppIndex(string appName, DxfCode[] dxfCodes) + { + List indexes = new(); + RangeTask(appName, (tv, _, i) => { + if (dxfCodes.Contains((DxfCode)tv.TypeCode)) + indexes.Add(i); + }); + return indexes; + } + + /// + /// 区间任务 + /// + /// + /// + private void RangeTask(string appName, Action action) + { + LoopState state = new(); + // 在名称和名称之间找 + int appNameIndex = -1; + for (int i = 0; i < this.Count; i++) + { + if (this[i].TypeCode == (short)DxfCode.ExtendedDataRegAppName) + { + if (this[i].Value.ToString() == appName) + { + appNameIndex = i; + continue; + } + if (appNameIndex != -1)//找到了下一个名称 + break; + } + + if (appNameIndex == -1) continue; // 找下一个的时候,获取任务(移除)的对象 + action(this[i], state, i); + if (!state.IsRun) + break; + } + } + + #endregion + + #region 转换器 + /// + /// ResultBuffer 隐式转换到 XDataList + /// + /// ResultBuffer 实例 + public static implicit operator XDataList(ResultBuffer buffer) => new(buffer.AsArray()); + /// + /// XDataList 隐式转换到 TypedValue 数组 + /// + /// TypedValueList 实例 + public static implicit operator TypedValue[](XDataList values) => values.ToArray(); + /// + /// XDataList 隐式转换到 ResultBuffer + /// + /// TypedValueList 实例 + public static implicit operator ResultBuffer(XDataList values) => new(values); + /// + /// TypedValue 数组隐式转换到 XDataList + /// + /// TypedValue 数组 + public static implicit operator XDataList(TypedValue[] values) => new(values); + #endregion +} \ No newline at end of file diff --git a/IFoxCAD.Cad/Runtime/DBTrans.cs b/IFoxCAD.Cad/Runtime/DBTrans.cs new file mode 100644 index 0000000..3d155b1 --- /dev/null +++ b/IFoxCAD.Cad/Runtime/DBTrans.cs @@ -0,0 +1,687 @@ +namespace IFoxCAD.Cad; + +using System.Diagnostics; +using System.IO; + +/// +/// 事务栈 +/// 隐匿事务在数据库其中担任的角色 +/// +[DebuggerDisplay("{DebuggerDisplay,nq}")] +[DebuggerTypeProxy(typeof(DBTrans))] +public sealed class DBTrans : IDisposable +{ + [DebuggerBrowsable(DebuggerBrowsableState.Never)] + private string DebuggerDisplay => ToString(); + + #region 静态函数 + + /// + /// 获取顶层事务 + /// + /// 数据库 + /// 事务对象 + public static Transaction GetTopTransaction(Database database) + { + ArgumentNullEx.ThrowIfNull(database); + return database.TransactionManager.TopTransaction ?? throw new Exception("没有顶层事务!"); + } + + /// + /// 获取给定数据库的顶层 DBTrans 事务 + /// + /// 数据库 + /// DBTrans 事务 + /// + public static DBTrans GetTop(Database database) + { + ArgumentNullEx.ThrowIfNull(database); + var trans = database.TransactionManager.TopTransaction; + ArgumentNullEx.ThrowIfNull(trans); + + foreach (var item in _dBTrans) + { + if (item.Transaction.UnmanagedObject == trans.UnmanagedObject) + { + return item; + } + } // 匹配事务栈内DBTrans的transaction的指针与数据库的顶层事务的指针 + + + return Top; + } + + #endregion + + #region 私有字段 + + /// + /// 事务栈 + /// + private static readonly Stack _dBTrans = new(); + + /// + /// 文档锁 + /// + private readonly DocumentLock? _documentLock; + + /// + /// 是否提交事务 + /// + private bool _commit; + + /// + /// 文件名 + /// + private readonly string? _fileName; + + #endregion + + #region 公开属性 + + /// + /// 返回当前事务 + /// + public static DBTrans Top + { + get + { + /* + * 0x01 + * 事务栈上面有事务,这个事务属于当前文档, + * 那么直接提交原本事务然后再开一个(一直把栈前面的同数据库提交清空) + * 那不就发生跨事务读取图元了吗?....否决 + * + * 0x02 + * 跨文档事务出错 Autodesk.AutoCAD.Runtime.Exception:“eNotFromThisDocument” + * Curves.GetEntities()会从Top获取事务(Top会new一个),此时会是当前文档; + * 然后命令文中发生了 using DBTrans tr = new(); + * 当退出命令此事务释放,但是从来不释放Top, + * 然后我新建了一个文档,再进行命令=>又进入Top,Top返回了前一个文档的事务 + * 因此所以无法清理栈,所以Dispose不触发,导致无法刷新图元和Ctrl+Z出错 + * 所以用AOP方式修复 + * + * 0x03 + * 经过艰苦卓绝的测试,aop模式由于不能断点调试,所以暂时放弃。 + */ + + // 由于大量的函数依赖本属性,强迫用户先开启事务 + if (_dBTrans.Count == 0) + throw new ArgumentNullException("事务栈没有任何事务,请在调用前创建:" + nameof(DBTrans)); + var trans = _dBTrans.Peek(); + return trans; + } + } + + + /// + /// 文档 + /// + public Document? Document { get; private set; } + + /// + /// 命令行 + /// + public Editor? Editor { get; private set; } + + /// + /// 事务管理器 + /// + public Transaction Transaction { get; private set; } + + /// + /// 数据库 + /// + public Database Database { get; private set; } + + #endregion + + #region 构造函数 + + /// + /// 事务栈 + /// 默认构造函数,默认为打开当前文档,默认提交事务 + /// + /// 要打开的文档 + /// 事务是否提交 + /// 是否锁文档 + public DBTrans(Document? doc = null, bool commit = true, bool docLock = false) + { + Document = doc ?? Acaop.DocumentManager.MdiActiveDocument; + Database = Document.Database; + Editor = Document.Editor; + Transaction = Database.TransactionManager.StartTransaction(); + _commit = commit; + if (docLock) + _documentLock = Document.LockDocument(); + + _dBTrans.Push(this); + } + + /// + /// 事务栈 + /// 打开数据库,默认提交事务 + /// + /// 要打开的数据库 + /// 事务是否提交 + public DBTrans(Database database, bool commit = true) + { + Database = database; + Document = Acap.DocumentManager.GetDocument(database); + Editor = Document?.Editor; + Transaction = Database.TransactionManager.StartTransaction(); + _commit = commit; + _dBTrans.Push(this); + } + + /// + /// 事务栈 + /// 打开文件,默认提交事务 + /// + /// 要打开的文件名 + /// 事务是否提交 + /// 开图模式 + /// 密码 + /// 后台打开false;前台打开true(必须设置CommandFlags.Session) + public DBTrans(string fileName, + bool commit = true, + FileOpenMode fileOpenMode = FileOpenMode.OpenForReadAndWriteNoShare, + string? password = null, + bool activeOpen = false) + { + if (string.IsNullOrWhiteSpace(fileName)) + throw new ArgumentNullException(nameof(fileName)); + + _fileName = fileName.Replace("/", "\\"); // doc.Name总是"D:\\JX.dwg" + + // 此处若为失败的文件名,那么保存的时候就会丢失名称, + // 因此用 _fileName 储存 + if (!File.Exists(_fileName)) + { + if (activeOpen) + { + throw new IOException("错误:事务栈明确为前台开图时,文件不存在"); + } + else + { + // cad08测试: + // 第2个参数使用false,将导致关闭cad的时候出现致命错误: + // Unhandled Access Violation Reading Ox113697a0 Exception at 4b4154h + Database = new Database(true, true); + } + } + else + { + var doc = Acaop.DocumentManager + .Cast() + .FirstOrDefault(doc => !doc.IsDisposed && doc.Name == _fileName); + + if (activeOpen) + { + if (doc is null) + { + try + { + // 设置命令标记: CommandFlags.Session + // 若没有设置: Open()之后的会进入中断状态(不会执行,直到切换文档ctrl+tab或者关闭文档) + doc = Acaop.DocumentManager.Open(fileName, fileOpenMode == FileOpenMode.OpenForReadAndReadShare, password); + } + catch (Exception e) + { + throw new IOException($"错误:此文件打开错误:{fileName}\n错误信息:{e.Message}"); + } + } + + // 设置命令标记: CommandFlags.Session + // 若没有设置: doc.IsActive 会异常 + if (!doc.IsActive) + Acaop.DocumentManager.MdiActiveDocument = doc; + + // Open()是跨文档,所以必须要锁文档 + // 否则 Editor?.Redraw() 的 tm.QueueForGraphicsFlush() 将报错提示文档锁 + _documentLock = doc.LockDocument(); + + Database = doc.Database; + Document = doc; + Editor = doc.Editor; + } + else + { + if (doc is null) + { + Database = new Database(false, true); + if (Path.GetExtension(_fileName).ToLower().Contains("dxf")) + { + Database.DxfIn(_fileName, null); + } + else + { + Database.ReadDwgFile(_fileName, fileOpenMode, true, password); + } + + Database.CloseInput(true); + } + else + { + Database = doc.Database; + Document = doc; + Editor = doc.Editor; + } + } + } + + Transaction = Database.TransactionManager.StartTransaction(); + _commit = commit; + _dBTrans.Push(this); + } + + #endregion + + #region 类型转换 + + /// + /// 隐式转换为Transaction + /// + /// 事务管理器 + /// 事务管理器 + public static implicit operator Transaction(DBTrans tr) + { + return tr.Transaction; + } + + #endregion + + #region 符号表 + + /// + /// 块表 + /// + public SymbolTable BlockTable => _blockTable ??= new(this, Database.BlockTableId); + + private SymbolTable? _blockTable; + + /// + /// 当前绘图空间 + /// + public BlockTableRecord CurrentSpace + { + get + { + if (_currentSpace is null || Database.CurrentSpaceId != _lastCurrentSpaceId) + { + _lastCurrentSpaceId = Database.CurrentSpaceId; + _currentSpace = BlockTable.GetRecord(Database.CurrentSpaceId)!; + } + + return _currentSpace; + } + } + + private ObjectId _lastCurrentSpaceId = ObjectId.Null; + private BlockTableRecord? _currentSpace; + + + /// + /// 模型空间 + /// + public BlockTableRecord ModelSpace => _modelSpace ??= BlockTable.GetRecord(BlockTable.CurrentSymbolTable[BlockTableRecord.ModelSpace])!; + + private BlockTableRecord? _modelSpace; + + /// + /// 图纸空间 + /// + public BlockTableRecord PaperSpace => BlockTable.GetRecord(BlockTable.CurrentSymbolTable[BlockTableRecord.PaperSpace])!; + + /// + /// 层表 + /// + public SymbolTable LayerTable => _layerTable ??= new(this, Database.LayerTableId); + + private SymbolTable? _layerTable; + + /// + /// 文字样式表 + /// + public SymbolTable TextStyleTable => _textStyleTable ??= new(this, Database.TextStyleTableId); + + private SymbolTable? _textStyleTable; + + /// + /// 注册应用程序表 + /// + public SymbolTable RegAppTable => _regAppTable ??= new(this, Database.RegAppTableId); + + private SymbolTable? _regAppTable; + + /// + /// 标注样式表 + /// + public SymbolTable DimStyleTable => _dimStyleTable ??= new(this, Database.DimStyleTableId); + + private SymbolTable? _dimStyleTable; + + /// + /// 线型表 + /// + public SymbolTable LinetypeTable => _linetypeTable ??= new(this, Database.LinetypeTableId); + + private SymbolTable? _linetypeTable; + + /// + /// 用户坐标系表 + /// + public SymbolTable UcsTable => _ucsTable ??= new(this, Database.UcsTableId); + + private SymbolTable? _ucsTable; + + /// + /// 视图表 + /// + public SymbolTable ViewTable => _viewTable ??= new(this, Database.ViewTableId); + + private SymbolTable? _viewTable; + + /// + /// 视口表 + /// + public SymbolTable ViewportTable => _viewportTable ??= new(this, Database.ViewportTableId); + + private SymbolTable? _viewportTable; + + #endregion + + #region 字典 + + /// + /// 命名对象字典 + /// + public DBDictionary NamedObjectsDict => GetObject(Database.NamedObjectsDictionaryId)!; + + /// + /// 组字典 + /// + public DBDictionary GroupDict => GetObject(Database.GroupDictionaryId)!; + + /// + /// 多重引线样式字典 + /// + public DBDictionary MLeaderStyleDict => GetObject(Database.MLeaderStyleDictionaryId)!; + + /// + /// 多线样式字典 + /// + // ReSharper disable once InconsistentNaming + public DBDictionary MLStyleDict => GetObject(Database.MLStyleDictionaryId)!; + + /// + /// 材质字典 + /// + public DBDictionary MaterialDict => GetObject(Database.MaterialDictionaryId)!; + + /// + /// 表格样式字典 + /// + public DBDictionary TableStyleDict => GetObject(Database.TableStyleDictionaryId)!; + + /// + /// 视觉样式字典 + /// + public DBDictionary VisualStyleDict => GetObject(Database.VisualStyleDictionaryId)!; + + /// + /// 颜色字典 + /// + public DBDictionary ColorDict => GetObject(Database.ColorDictionaryId)!; + + /// + /// 打印设置字典 + /// + public DBDictionary PlotSettingsDict => GetObject(Database.PlotSettingsDictionaryId)!; + + /// + /// 打印样式表名字典 + /// + public DBDictionary PlotStyleNameDict => GetObject(Database.PlotStyleNameDictionaryId)!; + + /// + /// 布局字典 + /// + public DBDictionary LayoutDict => GetObject(Database.LayoutDictionaryId)!; + +#if !zcad // 中望官方的问题 + /// + /// 数据链接字典 + /// + public DBDictionary DataLinkDict => GetObject(Database.DataLinkDictionaryId)!; + + /// + /// 详细视图样式字典 + /// + public DBDictionary DetailViewStyleDict => GetObject(Database.DetailViewStyleDictionaryId)!; + + /// + /// 剖面视图样式字典 + /// + public DBDictionary SectionViewStyleDict => GetObject(Database.SectionViewStyleDictionaryId)!; + +#endif + + #endregion + + #region 获取对象 + + /// + /// 根据对象id获取对象 + /// + /// 对象id + /// 打开模式,默认为只读 + /// 是否打开已删除对象,默认为不打开 + /// 是否打开锁定图层对象,默认为不打开 + /// 数据库DBObject对象 + public DBObject GetObject(ObjectId id, + OpenMode openMode = OpenMode.ForRead, + bool openErased = false, + bool openLockedLayer = false) + { + return Transaction.GetObject(id, openMode, openErased, openLockedLayer); + } + + /// + /// 根据对象id获取图元对象 + /// + /// 要获取的图元对象的类型 + /// 对象id + /// 打开模式,默认为只读 + /// 是否打开已删除对象,默认为不打开 + /// 是否打开锁定图层对象,默认为不打开 + /// 图元对象 + public T? GetObject(ObjectId id, + OpenMode openMode = OpenMode.ForRead, + bool openErased = false, + bool openLockedLayer = false) where T : DBObject + { + return Transaction.GetObject(id, openMode, openErased, openLockedLayer) as T; + } + + /// + /// 根据对象句柄字符串获取对象Id + /// + /// 句柄字符串 + /// 对象id + public ObjectId GetObjectId(string handleString) + { + // ToDo 这个函数考虑移走 + var handle = new Handle(Convert.ToInt64(handleString, 16)); + return Database.TryGetObjectId(handle, out var id) ? id : ObjectId.Null; + } + + #endregion + + #region 前台后台任务 + + /// + /// 前台后台任务分别处理 + /// + /// + /// 备注:
+ /// 0x01 文字偏移问题主要出现线性引擎函数上面,
+ /// 在 参照绑定/深度克隆 的底层共用此函数导致
+ /// 0x02 后台是利用前台当前数据库进行处理的
+ /// 0x03 跨进程通讯暂无测试(可能存在bug)
+ ///
+ /// 委托 + /// 开启单行文字偏移处理 + // ReSharper disable once InconsistentNaming + public void Task(Action action, bool handlingDBTextDeviation = true) + { + ArgumentNullEx.ThrowIfNull(action); + // 前台开图 || 后台直接处理 + if (Document != null || !handlingDBTextDeviation) + { + action.Invoke(); + return; + } + + // 后台 + // 这种情况发生在关闭了所有文档之后,进行跨进程通讯 + // 此处要先获取激活的文档,不能直接获取当前数据库否则异常 + var dm = Acaop.DocumentManager; + var doc = dm.MdiActiveDocument; + if (doc == null) + { + action.Invoke(); + return; + } + + // 处理单行文字偏移 + // 前台绑定参照的时候不能用它,否则抛出异常:eWasErased + // 所以本函数自动识别前后台做处理 + var dbBak = doc.Database; + HostApplicationServices.WorkingDatabase = Database; + action.Invoke(); + HostApplicationServices.WorkingDatabase = dbBak; + } + + #endregion + + #region IDisposable接口相关函数 + + /// + /// 取消事务 + /// + public void Abort() + { + _commit = false; + Dispose(); + } + + /// + /// 提交事务 + /// + public void Commit() + { + _commit = true; + Dispose(); + } + + /// + /// 是否释放事务 + /// + public bool IsDisposed { get; private set; } + + /// + /// 手动调用释放 + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// 析构函数调用释放 + /// + ~DBTrans() + { + Dispose(false); + } + + /// + /// 释放函数 + /// + /// + private void Dispose(bool disposing) + { + /* 事务dispose流程: + * 1. 根据传入的参数确定是否提交,true为提交,false为不提交 + * 2. 如果锁文档就将文档锁dispose + * 3. 不管是否提交,既然进入dispose,就要将事务栈的当前事务弹出 + * 注意这里的事务栈不是cad的事务管理器,而是DBTrans的事务 + * 4. 清理非托管的字段 + */ + + // 不重复释放,并设置已经释放 + if (IsDisposed) return; + + if (disposing) + { + // 致命错误时候此处是空,直接跳过 + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract + if (Transaction != null) + { + if (_commit) + { + // 调用cad的事务进行提交,释放托管状态(托管对象) + Transaction.Commit(); + } + else + { + // 防止事务回滚造成的视图回滚 + using var vtr = Editor?.GetCurrentView(); + // 否则取消所有的修改 + Transaction.Abort(); + if (Editor is not null && vtr is not null) + Editor.SetCurrentView(vtr); + } + + // 将cad事务进行销毁 + if (!Transaction.IsDisposed) + Transaction.Dispose(); + } + + // 将文档锁销毁 + _documentLock?.Dispose(); + } + + // 将当前事务栈弹栈 + _dBTrans.Pop(); + IsDisposed = true; + } + + #endregion + + #region ToString + + /// + public override string ToString() + + { + List lines = + [ + $"StackCount = {_dBTrans.Count}", + $"_fileName = \"{_fileName}\"", + $"_commit = {_commit}", + $"_documentLock = {_documentLock != null}", + + $"Document = {Document != null}", + $"Editor = {Editor != null}", + $"Transaction = {Transaction.UnmanagedObject}", + $"Database = {Database.Filename}" + ]; + + return string.Join("\n", lines.ToArray()); + } + + #endregion +} \ No newline at end of file diff --git a/IFoxCAD.Cad/Runtime/Env.cs b/IFoxCAD.Cad/Runtime/Env.cs new file mode 100644 index 0000000..0258058 --- /dev/null +++ b/IFoxCAD.Cad/Runtime/Env.cs @@ -0,0 +1,881 @@ +using System.Security; +// ReSharper disable StringLiteralTypo + +namespace IFoxCAD.Cad; + +/// +/// 系统管理类 +/// +/// 封装了一些系统 osmode;cmdecho;dimblk 系统变量
+/// 封装了常用的 文档 编辑器 数据库等对象为静态变量
+/// 封装了配置页面的注册表信息获取函数 +///
+///
+public static class Env +{ + #region Goal + + /// + /// 当前的数据库 + /// + public static Database Database => HostApplicationServices.WorkingDatabase; + + /// + /// 当前文档 + /// + public static Document Document => Acaop.DocumentManager.MdiActiveDocument; + + /// + /// 编辑器对象 + /// + public static Editor Editor => Document.Editor; + + /// + /// 图形管理器 + /// + public static Manager GsManager => Document.GraphicsManager; + + #endregion Goal + + #region Preferences + +#if !zcad // 中望官方的问题 + /// + /// 获取当前配置的数据 + /// + /// 小节名 + /// 数据名 + /// 对象 + public static object GetCurrentProfileProperty(string subSectionName, string propertyName) + { + var ucm = Acaop.UserConfigurationManager; + var cpf = ucm.OpenCurrentProfile(); + var ss = cpf.OpenSubsection(subSectionName); + return ss.ReadProperty(propertyName, ""); + } + + + /// + /// 获取对话框配置的数据 + /// + /// 对话框对象 + /// 配置项 + public static IConfigurationSection GetDialogSection(object dialog) + { + var ucm = Acaop.UserConfigurationManager; + var ds = ucm.OpenDialogSection(dialog); + return ds; + } + + /// + /// 获取公共配置的数据 + /// + /// 数据名 + /// 配置项 + public static IConfigurationSection GetGlobalSection(string propertyName) + { + var ucm = Acaop.UserConfigurationManager; + var gs = ucm.OpenGlobalSection(); + var ss = gs.OpenSubsection(propertyName); + return ss; + } +#endif + + #endregion Preferences + + #region Enum + + /// + /// 控制在AutoLISP的command函数运行时AutoCAD是否回显提示和输入, 为显示, 为不显示 + /// + public static bool CmdEcho + { + get => Convert.ToInt16(Acaop.GetSystemVariable("cmdecho")) == 1; + set => Acaop.SetSystemVariable("cmdecho", Convert.ToInt16(value)); + } + + /// + /// 获取Cad当前是否有活动命令 + /// + public static bool CmdActive => Convert.ToBoolean(Acaop.GetSystemVariable("CMDACTIVE")); + + /// + /// 控制在光标是否为正交模式, 为打开正交, 为关闭正交 + /// + public static bool OrthoMode + { + get => Convert.ToInt16(Acaop.GetSystemVariable("ORTHOMODE")) == 1; + set => Acaop.SetSystemVariable("ORTHOMODE", Convert.ToInt16(value)); + } + + /// + /// 读写系统变量LastPoint的坐标(UCS) + /// + public static Point3d LastPoint + { + get => (Point3d)Acaop.GetSystemVariable("LASTPOINT"); + set => Acaop.SetSystemVariable("LASTPOINT", value); + } + + #region Dimblk + + /// + /// 标注箭头类型 + /// + public enum DimblkType + { + /// + /// 实心闭合 + /// + Default, + + /// + /// 点 + /// + Dot, + + /// + /// 小点 + /// + DotSmall, + + /// + /// 空心点 + /// + DotBlank, + + /// + /// 原点标记 + /// + Origin, + + /// + /// 原点标记2 + /// + Origin2, + + /// + /// 打开 + /// + Open, + + /// + /// 直角 + /// + Open90, + + /// + /// 30度角 + /// + Open30, + + /// + /// 闭合 + /// + Closed, + + /// + /// 空心小点 + /// + Small, + + /// + /// 无 + /// + None, + + /// + /// 倾斜 + /// + Oblique, + + /// + /// 实心框 + /// + BoxFilled, + + /// + /// 方框 + /// + BoxBlank, + + /// + /// 空心闭合 + /// + ClosedBlank, + + /// + /// 实心基准三角形 + /// + DatumFilled, + + /// + /// 基准三角形 + /// + DatumBlank, + + /// + /// 完整标记 + /// + Integral, + + /// + /// 建筑标记 + /// + ArchTick + } + + private static readonly Dictionary _dimDescDict = new() + { + { "实心闭合", DimblkType.Default }, + { "点", DimblkType.Dot }, + { "小点", DimblkType.DotSmall }, + { "空心点", DimblkType.DotBlank }, + { "原点标记", DimblkType.Origin }, + { "原点标记 2", DimblkType.Origin2 }, + { "打开", DimblkType.Open }, + { "直角", DimblkType.Open90 }, + { "30 度角", DimblkType.Open30 }, + { "闭合", DimblkType.Closed }, + { "空心小点", DimblkType.Small }, + { "无", DimblkType.None }, + { "倾斜", DimblkType.Oblique }, + { "实心框", DimblkType.BoxFilled }, + { "方框", DimblkType.BoxBlank }, + { "空心闭合", DimblkType.ClosedBlank }, + { "实心基准三角形", DimblkType.DatumFilled }, + { "基准三角形", DimblkType.DatumBlank }, + { "完整标记", DimblkType.Integral }, + { "建筑标记", DimblkType.ArchTick }, + + { "", DimblkType.Default }, + { "_DOT", DimblkType.Dot }, + { "_DOTSMALL", DimblkType.DotSmall }, + { "_DOTBLANK", DimblkType.DotBlank }, + { "_ORIGIN", DimblkType.Origin }, + { "_ORIGIN2", DimblkType.Origin2 }, + { "_OPEN", DimblkType.Open }, + { "_OPEN90", DimblkType.Open90 }, + { "_OPEN30", DimblkType.Open30 }, + { "_CLOSED", DimblkType.Closed }, + { "_SMALL", DimblkType.Small }, + { "_NONE", DimblkType.None }, + { "_OBLIQUE", DimblkType.Oblique }, + { "_BOXFILLED", DimblkType.BoxFilled }, + { "_BOXBLANK", DimblkType.BoxBlank }, + { "_CLOSEDBLANK", DimblkType.ClosedBlank }, + { "_DATUMFILLED", DimblkType.DatumFilled }, + { "_DATUMBLANK", DimblkType.DatumBlank }, + { "_INTEGRAL", DimblkType.Integral }, + { "_ARCHTICK", DimblkType.ArchTick } + }; + + + /// + /// 标注箭头属性 + /// + public static DimblkType Dimblk + { + get + { + var s = ((string)Acaop.GetSystemVariable("dimblk")).ToUpper(); + return _dimDescDict[s]; + } + set + { + var s = GetDimblkName(value); + Acaop.SetSystemVariable("dimblk", s); + } + } + + /// + /// 获取标注箭头名 + /// + /// 标注箭头类型 + /// 箭头名 + public static string GetDimblkName(DimblkType dimblk) + { + return + dimblk == DimblkType.Default + ? "." + : "_" + dimblk.GetName(); + } + + /// + /// 获取标注箭头ID + /// + /// 标注箭头类型 + /// 箭头ID + public static ObjectId GetDimblkId(DimblkType dimblk) + { + var oldDimblk = Dimblk; + Dimblk = dimblk; + var id = HostApplicationServices.WorkingDatabase.Dimblk; + Dimblk = oldDimblk; + return id; + } + + #endregion Dimblk + + #region OsMode + + /// + /// 捕捉模式系统变量类型 + /// + [Flags] + public enum OSModeType + { + /// + /// 无 + /// + None = 0, + + /// + /// 端点 + /// + End = 1, + + /// + /// 中点 + /// + Middle = 2, + + /// + /// 圆心 + /// + Center = 4, + + /// + /// 节点 + /// + Node = 8, + + /// + /// 象限点 + /// + Quadrant = 16, + + /// + /// 交点 + /// + Intersection = 32, + + /// + /// 插入点 + /// + Insert = 64, + + /// + /// 垂足 + /// + Pedal = 128, + + /// + /// 切点 + /// + Tangent = 256, + + /// + /// 最近点 + /// + Nearest = 512, + + /// + /// 几何中心 + /// + Quick = 1024, + + /// + /// 外观交点 + /// + Appearance = 2048, + + /// + /// 延伸 + /// + Extension = 4096, + + /// + /// 平行 + /// + Parallel = 8192 + } + + /// + /// 捕捉模式系统变量 + /// + // ReSharper disable once InconsistentNaming + public static OSModeType OSMode + { + get => (OSModeType)Convert.ToInt16(Acaop.GetSystemVariable("osmode")); + set => Acaop.SetSystemVariable("osmode", (int)value); + } + + /// + /// 捕捉模式osm1是否包含osm2 + /// + /// 原模式 + /// 要比较的模式 + /// 包含时返回 ,不包含时返回 + public static bool Include(this OSModeType osm1, OSModeType osm2) + { + return (osm1 & osm2) == osm2; + } + + #endregion OsMode + + + private static string? GetName(this T value) + { + return Enum.GetName(typeof(T), value!); + } + + #endregion Enum + + #region 系统变量 + + /// + /// 获取cad系统变量 + /// + /// 变量名 + /// 变量值 + public static object GetVar(string varName) + { + return Acaop.GetSystemVariable(varName); + } + + /// + /// 设置cad系统变量
+ /// 0x01 建议先获取现有变量值和设置的是否相同,否则直接设置会发生异常
+ /// 0x02 建议锁文档,否则 Psltscale 设置发生异常
+ /// 发生异常的时候vs输出窗口会打印一下,但是如果不介意也没啥问题 + ///
+ /// 变量名 + /// 变量值 + /// 输出异常,默认true;此设置仅为打印到命令栏,无法控制vs输出 + public static void SetVar(string varName, object value, bool echo = true) + { + try + { + Acaop.SetSystemVariable(varName, value); + } + catch (Exception) + { + if (echo) + Print($"{varName} 是不存在的变量!"); + } + } + + #endregion + + #region 环境变量 + +#if acad + [SuppressUnmanagedCodeSecurity] + [DllImport("accore.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, + EntryPoint = "acedGetEnv")] + private static extern int AcedGetEnv(string? envName, StringBuilder returnValue); + + [SuppressUnmanagedCodeSecurity] + [DllImport("accore.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, + EntryPoint = "acedSetEnv")] + private static extern int AcedSetEnv(string? envName, StringBuilder newValue); +#endif + +#if gcad + [System.Security.SuppressUnmanagedCodeSecurity] + [DllImport("gced.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, EntryPoint = + "gcedGetEnv")] + static extern int AcedGetEnv(string? envName, StringBuilder ReturnValue); + + [System.Security.SuppressUnmanagedCodeSecurity] + [DllImport("gced.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, EntryPoint = + "gcedSetEnv")] + static extern int AcedSetEnv(string? envName, StringBuilder NewValue); +#endif + + // TODO: 中望没有测试,此处仅为不报错;本工程所有含有"中望"均存在问题 +#if zcad + [System.Security.SuppressUnmanagedCodeSecurity] + [DllImport("zced.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, EntryPoint = + "zcedGetEnv")] + static extern int AcedGetEnv(string? envName, StringBuilder ReturnValue); + + [System.Security.SuppressUnmanagedCodeSecurity] + [DllImport("zced.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, EntryPoint = + "zcedSetEnv")] + static extern int AcedSetEnv(string? envName, StringBuilder NewValue); +#endif + + /// + /// 读取acad环境变量
+ /// 也能获取win环境变量 + ///
+ /// 变量名 + /// 返回值从不为null,需判断 + public static string GetEnv(string name) + { + // 它将混合查询以下路径: + // acad2008注册表路径: 计算机\HKEY_CURRENT_USER\SOFTWARE\Autodesk\AutoCAD\R17.1\ACAD-6001:804\FixedProfile\General + // 用户: 计算机\HKEY_CURRENT_USER\Environment + // 系统: 计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment + + // GetEnv("Path")长度很长: + // 可用内存 (最新格式) 1 MB (标准格式) + // https://docs.microsoft.com/zh-cn/windows/win32/sysinfo/registry-element-size-limits + + var sbRes = new StringBuilder(1 << 23); + _ = AcedGetEnv(name, sbRes); + return sbRes.ToString(); + } + + /// + /// 设置acad环境变量
+ /// 它是不会报错的,但是直接设置会写入注册表的,
+ /// 如果是设置高低版本cad不同的变量,建议先读取判断再设置
+ ///
+ /// 变量名 + /// 变量值 + /// + public static int SetEnv(string name, string var) + { + return AcedSetEnv(name, new StringBuilder(var)); + } + + #endregion + + #region win环境变量/由于 Aced的 能够同时获取此变量与cad内的,所以废弃 + + // /// + // /// 获取系统环境变量 + // /// + // /// 变量名 + // /// 指定的环境变量的值;或者如果找不到环境变量,则返回 null + // public static string? GetEnv(string? var) + // { + // // 从当前进程或者从当前用户或本地计算机的 Windows 操作系统注册表项检索环境变量的值 + // // 用户: 计算机\HKEY_CURRENT_USER\Environment + // // 系统: 计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment + // return Environment.GetEnvironmentVariable(var); + // } + // /// + // /// 设置系统环境变量 + // /// + // /// 变量名 + // /// 变量值 + // public static void SetEnv(string? var, string? value) + // { + // // 创建、修改或删除当前进程中或者为当前用户或本地计算机保留的 Windows 操作系统注册表项中存储的环境变量 + // Environment.SetEnvironmentVariable(var, value); + // } + + #endregion + + #region 支持文件目录 + + /// + /// 添加目录至CAD支持搜索的路径 + /// + /// 目录 + public static void AppendSupportPath(params string[] folders) + { + if (!folders.Any()) return; + var acadPath = GetEnv("ACAD"); + var acadPathLowerArr = + acadPath + .ToLower() + .Split(';') + .Where(item => item != "") + .Select(item => + item[^1] == '\\' ? item.Remove(item.Length - 1) : item) + .ToHashSet(); + foreach (var folder in folders) + { + if (!Directory.Exists(folder)) continue; + var folderLower = + folder[^1] == '\\' ? folder.Remove(folder.Length - 1).ToLower() : folder.ToLower(); + if (!acadPathLowerArr.Contains(folderLower)) + acadPath = folder + ";" + acadPath; //加到前面方便检查 + } + + SetEnv("ACAD", acadPath); + } + + /// + /// 删除支持搜索文件目录 + /// + /// 目录 + public static void RemoveSupportPath(params string[] folders) + { + if (!folders.Any()) return; + var acadPathArr = GetEnv("ACAD").Split(';').ToList(); + foreach (var folder in folders) + { + var folderLower = + folder[^1] == '\\' ? folder.Remove(folder.Length - 1).ToLower() : folder.ToLower(); + acadPathArr.RemoveAll(item => + (item[^1] == '\\' ? item.Remove(item.Length - 1).ToLower() : item.ToLower()) == folderLower); + } + + SetEnv("ACAD", string.Join(";", acadPathArr)); + } + + /// + /// 添加目录至CAD受信任的位置 + /// + /// 目录 + public static void AppendTrustedPath(params string[] folders) + { + if (!folders.Any()) return; + var trustedPath = GetVar("TRUSTEDPATHS").ToString(); + var trustedPathLowerArr = + trustedPath + .ToLower() + .Split(';') + .Where(item => item != "") + .Select(item => + item[^1] == '\\' ? item.Remove(item.Length - 1) : item) + .ToHashSet(); + foreach (var folder in folders) + { + if (!Directory.Exists(folder)) continue; + var folderLower = + folder[^1] == '\\' ? folder.Remove(folder.Length - 1).ToLower() : folder.ToLower(); + if (!trustedPathLowerArr.Contains(folderLower)) + trustedPath = folder + ";" + trustedPath; //加到前面方便检查 + } + + SetVar("TRUSTEDPATHS", trustedPath); + } + + /// + /// 移除信任目录 + /// + /// 目录 + public static void RemoveTrustedPath(params string[] folders) + { + if (!folders.Any()) return; + var trustedPathArr = GetVar("TRUSTEDPATHS").ToString().Split(';').ToList(); + foreach (var folder in folders) + { + var folderLower = + folder[^1] == '\\' ? folder.Remove(folder.Length - 1).ToLower() : folder.ToLower(); + trustedPathArr.RemoveAll(item => + (item[^1] == '\\' ? item.Remove(item.Length - 1).ToLower() : item.ToLower()) == folderLower); + } + + SetVar("TRUSTEDPATHS", string.Join(";", trustedPathArr)); + } + + #endregion + + /// + /// 命令行打印,会自动调用对象的toString函数 + /// + /// 要打印的对象 + public static void Print(object message) + { + // ReSharper disable once ConditionalAccessQualifierIsNonNullableAccordingToAPIContract + Document?.Editor.WriteMessage($"{message}\n"); + } + + /// + /// 命令行打印,会自动调用对象的toString函数,在打印内容前添加换行 + /// + /// 要打印的对象 + public static void Printl(object message) + { + // ReSharper disable once ConditionalAccessQualifierIsNonNullableAccordingToAPIContract + Document?.Editor.WriteMessage($"{Environment.NewLine}{message}\n"); + } + + /// + /// 判断当前是否在UCS坐标下 + /// + /// Bool + public static bool IsUcs() + { + return (short)GetVar("WORLDUCS") == 0; + } + + + #region dwg版本号/cad版本号/年份 + + /// + /// 获取当前配置文件的保存版本 + /// + /// + public static DwgVersion GetDefaultDwgVersion() + { + var ffs = GetEnv("DefaultFormatForSave"); + var version = ffs switch + { + "1" => DwgVersion.AC1009, // R12/LT12 dxf + "8" => DwgVersion.AC1014, // R14/LT98/LT97 dwg + "12" => DwgVersion.AC1015, // 2000 dwg + "13" => DwgVersion.AC1800a, // 2000 dxf + "24" => DwgVersion.AC1800, // 2004 dwg + "25" => (DwgVersion)26, // 2004 dxf + "36" => (DwgVersion)27, // 2007 dwg DwgVersion.AC1021 + "37" => (DwgVersion)28, // 2007 dxf + + // "38" => (DwgVersion),// dwt 样板文件...啊惊没找到这个是什么 + "48" => (DwgVersion)29, // 2010 dwg DwgVersion.AC1024 + "49" => (DwgVersion)30, // 2010 dxf + "60" => (DwgVersion)31, // 2013 dwg DwgVersion.AC1027 + "61" => (DwgVersion)32, // 2013 dxf + "64" => (DwgVersion)33, // 2018 dwg DwgVersion.AC1032 + "65" => (DwgVersion)34, // 2018 dxf + _ => throw new NotImplementedException() // 提醒维护 + }; + return version; + } + + /// + /// 是否为dxf版本号 + /// + /// + /// + public static bool IsDxfVersion(this DwgVersion dwgVersion) + { + var result = (int)dwgVersion switch + { + 16 => true, // R12/LT12 dxf + 24 => true, // 2000 dxf + 26 => true, // 2004 dxf + 28 => true, // 2007 dxf + 30 => true, // 2010 dxf + 32 => true, // 2013 dxf + 34 => true, // 2018 dxf + _ => false + }; + return result; + } + + /// + /// 获取cad年份 + /// + /// 超出年份就报错 + public static int GetAcadVersion() + { + var ver = Acaop.Version.Major + "." + Acaop.Version.Minor; + var acadVersion = ver switch + { + "16.2" => 2006, + "17.0" => 2007, + "17.1" => 2008, + "17.2" => 2009, + "18.0" => 2010, + "18.1" => 2011, + "18.2" => 2012, + "19.0" => 2013, + "19.1" => 2014, + "20.0" => 2015, + "20.1" => 2016, + "21.0" => 2017, + "22.0" => 2018, + "23.0" => 2019, + "23.1" => 2020, + "24.0" => 2021, + "24.1" => 2022, + "24.2" => 2023, + "24.3" => 2024, + _ => throw new NotImplementedException() + }; + return acadVersion; + } + + /// + /// 获取带cad版本号的dll + /// + /// dll名字 + /// dll的前面 + public static string GetAcapVersionDll(string str = "acdb") + { + return str + Acaop.Version.Major + ".dll"; + } + + #endregion + + + #region cad变量功能延伸 + + /// + /// 设置cad系统变量
+ /// 提供一个反序列化后,无cad异常输出的功能
+ /// 注意,您需要再此执行时候设置文档锁
+ /// 否则也将导致修改数据库异常
+ ///
+ /// + /// + /// 成功返回当前值,失败null + /// + public static object? SetVarEx(string key, string value) + { + var currentVar = GetVar(key); + + object? valueType = currentVar.GetType().Name switch + { + "String" => value.Replace("\"", string.Empty), + "Double" => double.Parse(value), + "Int16" => short.Parse(value), + "Int32" => int.Parse(value), + _ => null, + // _ => throw new NotImplementedException() + }; + + if (valueType is null) + return null; + + // 相同的参数进行设置会发生一次异常 + if (!string.Equals(currentVar.ToString(), valueType.ToString(), StringComparison.CurrentCultureIgnoreCase)) + SetVar(key, valueType); + + return currentVar; + } + + /// + /// 设置新系统变量,返回现有系统变量 + /// + /// 设置的变量词典 + /// 返回现有变量词典,然后下次就可以利用它进行设置回来了 + public static Dictionary SaveCadVar(Dictionary args) + { + ArgumentNullEx.ThrowIfNull(args); + var dict = new Dictionary(); + foreach (var item in args) + { + // 判断是否为系统变量 + var ok = SetVarEx(item.Key, item.Value); + if (ok is not null) + { + dict.Add(item.Key, ok.ToString()); + continue; + } + + // 判断是否为系统变量 + var envStr = GetEnv(item.Key); + if (!string.IsNullOrEmpty(envStr)) + { + SetEnv(item.Key, item.Value); + dict.Add(item.Key, envStr); + } + } + + return dict; + } + + /// + /// 延迟更新图层锁定淡显状态 + /// 在有锁定或解锁图层的命令的末尾使用 + /// + public static void DelayUpdateLayLockFade() + { + const string lfName = "LAYLOCKFADECTL"; + var lf = Convert.ToInt32(Acaop.GetSystemVariable(lfName).ToString()); + Acaop.SetSystemVariable(lfName, -lf); + IdleAction.Add(() => Acaop.SetSystemVariable(lfName, lf)); + } + + #endregion +} \ No newline at end of file diff --git a/IFoxCAD.Cad/Runtime/IdleAction.cs b/IFoxCAD.Cad/Runtime/IdleAction.cs new file mode 100644 index 0000000..ebcb297 --- /dev/null +++ b/IFoxCAD.Cad/Runtime/IdleAction.cs @@ -0,0 +1,66 @@ +using Cursor = System.Windows.Forms.Cursor; + +namespace IFoxCAD.Cad; + +/// +/// 空闲执行 +/// by DYH +/// 20230114 +/// +public static class IdleAction +{ + /// + /// 是否已经加载 + /// + private static bool alreadyLoad; + + /// + /// 委托列表 + /// + private static readonly Queue _actions = new(); + + /// + /// 未处理的委托数量 + /// + public static int Count => _actions.Count; + + /// + /// 添加空闲执行委托 + /// + /// 委托 + public static void Add(Action action) + { + _actions.Enqueue(action); + if (alreadyLoad) + return; + Acaop.Idle -= Acap_Idle; + Acaop.Idle += Acap_Idle; + alreadyLoad = true; + } + + /// + /// 空闲处理事件 + /// + /// Acap + /// 事件参数 + private static void Acap_Idle(object sender, EventArgs e) + { + if (Count == 0) + { + alreadyLoad = false; + Acaop.Idle -= Acap_Idle; + return; + } + + try + { + _actions.Dequeue()?.Invoke(); + } + catch + { + // ignored + } + + Cursor.Position = Cursor.Position; + } +} \ No newline at end of file diff --git a/IFoxCAD.Cad/Runtime/SymbolTable.cs b/IFoxCAD.Cad/Runtime/SymbolTable.cs new file mode 100644 index 0000000..632a05c --- /dev/null +++ b/IFoxCAD.Cad/Runtime/SymbolTable.cs @@ -0,0 +1,401 @@ +// ReSharper disable RedundantNameQualifier +namespace IFoxCAD.Cad; +/// +/// 符号表管理类 +/// +/// 符号表 +/// 符号表记录 +public class SymbolTable : IEnumerable + where TTable : SymbolTable + where TRecord : SymbolTableRecord, new() +{ + #region 程序集内部属性 + /// + /// 事务管理器 + /// + private DBTrans DTrans { get; set; } + /// + /// 数据库 + /// + internal Database Database { get; private set; } + + #endregion + + #region 公开属性 + /// + /// 当前符号表 + /// + public TTable CurrentSymbolTable { get; private set; } + #endregion + + #region 构造函数 + /// + /// 构造函数,初始化Trans和CurrentSymbolTable属性 + /// + /// 事务管理器 + /// 符号表id + /// 默认行为:例如打开隐藏图层 + internal SymbolTable(DBTrans tr, ObjectId tableId, bool defaultBehavior = true) + { + DTrans = tr; + Database = tr.Database; + CurrentSymbolTable = DTrans.GetObject(tableId)!; + + if (!defaultBehavior) + return; + + if (CurrentSymbolTable is LayerTable layer) + { + // 层表包含隐藏的,全部显示出来 + layer = layer.IncludingHidden; + if (layer is TTable tt) + CurrentSymbolTable = tt; + } + } + + #endregion + + #region 索引器 + /// + /// 索引器 + /// + /// 对象名称 + /// 对象的id + public ObjectId this[string key] => Has(key) ? CurrentSymbolTable[key] : ObjectId.Null; + + #endregion + + #region Has + /// + /// 判断是否存在符号表记录 + /// + /// 记录名 + /// 存在返回 , 不存在返回 + public bool Has(string key) + { + return CurrentSymbolTable.Has(key); + } + /// + /// 判断是否存在符号表记录 + /// + /// 记录id + /// 存在返回 , 不存在返回 + public bool Has(ObjectId objectId) + { + return CurrentSymbolTable.Has(objectId); + } + #endregion + + #region 添加符号表记录 + /// + /// 添加符号表记录 + /// + /// 符号表记录 + /// 对象id + public ObjectId Add(TRecord record) + { + ObjectId id; + using (CurrentSymbolTable.ForWrite()) + { + id = CurrentSymbolTable.Add(record); + DTrans.Transaction.AddNewlyCreatedDBObject(record, true); + } + return id; + } + /// + /// 添加符号表记录 + /// + /// 符号表记录名 + /// 符号表记录处理函数的无返回值委托 + /// 对象id + public ObjectId Add(string name, Action? action = null) + { + var id = this[name]; + if (!id.IsNull) return id; + var record = new TRecord() + { + Name = name + }; + id = Add(record); + using (record.ForWrite()) + action?.Invoke(record); + return id; + } + #endregion + + #region 删除符号表记录 + /// + /// 删除符号表记录 + /// + /// 符号表记录对象 + private static void Remove(TRecord record) + { + using (record.ForWrite()) + record.Erase(); + } + + /// + /// 删除符号表记录 + /// + /// 符号表记录名 + public void Remove(string name) + { + var record = GetRecord(name); + if (record is not null) + Remove(record); + } + + /// + /// 删除符号表记录 + /// + /// 符号表记录对象id + public void Remove(ObjectId id) + { + var record = GetRecord(id); + if (record is not null) + Remove(record); + } + #endregion + + #region 修改符号表记录 + /// + /// 修改符号表 + /// + /// 符号表记录名 + /// 修改委托 + [System.Diagnostics.DebuggerStepThrough] + public void Change(string name, Action action) + { + var record = GetRecord(name); + if (record is not null) + { + using (record.ForWrite()) + action.Invoke(record); + } + } + + /// + /// 修改符号表 + /// + /// 符号表记录id + /// 修改委托 + [System.Diagnostics.DebuggerStepThrough] + public void Change(ObjectId id, Action action) + { + var record = GetRecord(id); + if (record is not null) + { + using (record.ForWrite()) + action.Invoke(record); + } + } + #endregion + + #region 获取符号表记录 + /// + /// 获取符号表记录 + /// + /// 符号表记录的id + /// 打开模式 + /// 是否打开已删除对象,默认为不打开 + /// 是否打开锁定图层对象,默认为不打开 + /// 符号表记录 + [System.Diagnostics.DebuggerStepThrough] + public TRecord? GetRecord(ObjectId id, + OpenMode openMode = OpenMode.ForRead, + bool openErased = false, + bool openLockedLayer = false) + { + return DTrans.GetObject(id, openMode, openErased, openLockedLayer); + } + + /// + /// 获取符号表记录 + /// + /// 符号表记录名 + /// 打开模式 + /// 是否打开已删除对象,默认为不打开 + /// 是否打开锁定图层对象,默认为不打开 + /// 符号表记录 + [System.Diagnostics.DebuggerStepThrough] + public TRecord? GetRecord(string name, + OpenMode openMode = OpenMode.ForRead, + bool openErased = false, + bool openLockedLayer = false) + { + return GetRecord(this[name], openMode, openErased, openLockedLayer); + } + + /// + /// 获取符号表记录 + /// + /// 符号表记录集合 + public IEnumerable GetRecords() + { + foreach (var item in this) + { + var record = GetRecord(item); + if (record is not null) + yield return record; + } + } + + /// + /// 获取符号表记录的名字集合 + /// + /// 记录的名字集合 + public IEnumerable GetRecordNames() => GetRecords().Select(record => record.Name); + + /// + /// 获取符合过滤条件的符号表记录名字集合 + /// + /// 过滤器委托 + /// 记录的名字集合 + public IEnumerable GetRecordNames(Func filter) + { + foreach (var item in this) + { + var record = GetRecord(item); + if (record is not null && filter.Invoke(record)) + yield return record.Name; + } + } + + /// + /// 从源数据库拷贝符号表记录 + /// + /// 符号表 + /// 符号表记录名 + /// 是否覆盖, 为覆盖, 为不覆盖 + /// 对象id + private ObjectId GetRecordFrom(SymbolTable table, string name, bool over) + { + ArgumentNullEx.ThrowIfNull(table); + + var rid = this[name]; + bool has = rid != ObjectId.Null; + if ((!has || !over) && has) return rid; + var id = table[name]; + using IdMapping map = new(); + using ObjectIdCollection ids = new(); + ids.Add(id); + table.Database.WblockCloneObjects( + ids, + CurrentSymbolTable.Id, + map, + DuplicateRecordCloning.Replace, + false); + rid = map[id].Value; + return rid; + } + + /// + /// 从文件拷贝符号表记录 + /// + /// 符号表过滤器 + /// 文件名 + /// 符号表记录名 + /// 是否覆盖, 为覆盖, 为不覆盖 + /// 对象id + internal ObjectId GetRecordFrom(Func> tableSelector, + string fileName, + string name, + bool over) + { + using DBTrans tr = new(fileName); + return GetRecordFrom(tableSelector(tr), name, over); + } + #endregion + + #region 遍历 +#line hidden // 调试的时候跳过它 + /// + /// 遍历符号表,执行委托 + /// + /// 要运行的委托 + /// 打开模式,默认为只读 + /// 检查id是否删除,默认true + /// 是否打开已删除对象,默认为不打开 + /// 是否打开锁定图层对象,默认为不打开 + public void ForEach(Action task, + OpenMode openMode = OpenMode.ForRead, + bool checkIdOk = true, + bool openErased = false, + bool openLockedLayer = false) + { + ForEach((a, _, _) => { + task.Invoke(a);//由于此处是委托,所以 DebuggerStepThrough 特性会进入,改用预处理方式避免 + }, openMode, checkIdOk, openErased, openLockedLayer); + } + + /// + /// 遍历符号表,执行委托(允许循环中断) + /// + /// 要执行的委托 + /// 打开模式,默认为只读 + /// 检查id是否删除,默认true + /// 是否打开已删除对象,默认为不打开 + /// 是否打开锁定图层对象,默认为不打开 + public void ForEach(Action task, + OpenMode openMode = OpenMode.ForRead, + bool checkIdOk = true, + bool openErased = false, + bool openLockedLayer = false) + { + ForEach((a, b, _) => { + task.Invoke(a, b); + }, openMode, checkIdOk, openErased, openLockedLayer); + } + + /// + /// 遍历符号表,执行委托(允许循环中断,输出索引值) + /// + /// 要执行的委托 + /// 打开模式,默认为只读 + /// 检查id是否删除,默认true + /// 是否打开已删除对象,默认为不打开 + /// 是否打开锁定图层对象,默认为不打开 + [System.Diagnostics.DebuggerStepThrough] + public void ForEach(Action task, + OpenMode openMode = OpenMode.ForRead, + bool checkIdOk = true, + bool openErased = false, + bool openLockedLayer = false) + { + //if (task == null) + // throw new ArgumentNullException(nameof(task)); + ArgumentNullEx.ThrowIfNull(task); + LoopState state = new();/*这种方式比Action改Func更友好*/ + int i = 0; + foreach (var id in this) + { + if (checkIdOk && !id.IsOk()) + continue; + var record = GetRecord(id, openMode, openErased, openLockedLayer); + if (record is not null) + task.Invoke(record, state, i); + if (!state.IsRun) + break; + i++; + } + } +/// +#line default + + #endregion + + #region IEnumerable 成员 + [System.Diagnostics.DebuggerStepThrough] + public IEnumerator GetEnumerator() + { + foreach (var id in CurrentSymbolTable) + yield return id; + } + + [System.Diagnostics.DebuggerStepThrough] + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + #endregion +} \ No newline at end of file diff --git a/IFoxCAD.sln b/IFoxCAD.sln index 90d5280..89923dd 100644 --- a/IFoxCAD.sln +++ b/IFoxCAD.sln @@ -3,15 +3,23 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.8.34309.116 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IFoxCAD.CAD", "IFoxCAD.CAD\IFoxCAD.CAD.csproj", "{6B29955A-5796-4035-9297-210FA15D3846}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IFoxCAD.Cad", "IFoxCAD.Cad\IFoxCAD.Cad.csproj", "{6B29955A-5796-4035-9297-210FA15D3846}" EndProject Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6B29955A-5796-4035-9297-210FA15D3846}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6B29955A-5796-4035-9297-210FA15D3846}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6B29955A-5796-4035-9297-210FA15D3846}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6B29955A-5796-4035-9297-210FA15D3846}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {57CA0128-08DE-436F-B9F1-82C64F49BF67} EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - EndGlobalSection EndGlobal diff --git a/IFoxCAD.sln.DotSettings b/IFoxCAD.sln.DotSettings new file mode 100644 index 0000000..208af26 --- /dev/null +++ b/IFoxCAD.sln.DotSettings @@ -0,0 +1,13 @@ + + DB + OS + True + True + True + True + True + True + True + True + True + True \ No newline at end of file -- Gitee From 5aec378e8bd065eadb0e8d7d53c202250b86417a Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Fri, 22 Mar 2024 19:50:08 +0800 Subject: [PATCH 256/453] =?UTF-8?q?DBTrans=E7=AD=89=E5=B8=B8=E7=94=A8?= =?UTF-8?q?=E7=B1=BB=E8=BF=81=E7=A7=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CallerArgumentExpressionAttribute.cs | 1 + IFoxCAD.Cad/ExtensionMethod/DBObjectEx.cs | 56 +++++++++++-------- IFoxCAD.Cad/ExtensionMethod/ObjectIdEx.cs | 29 ++++++---- IFoxCAD.Cad/ExtensionMethod/TransactionEx.cs | 1 + IFoxCAD.Cad/ResultData/TypedValueList.cs | 18 +++++- IFoxCAD.Cad/ResultData/XdataList.cs | 36 ++++++++---- IFoxCAD.Cad/Runtime/DBTrans.cs | 12 ---- IFoxCAD.Cad/Runtime/Env.cs | 3 +- 8 files changed, 97 insertions(+), 59 deletions(-) diff --git a/IFoxCAD.Cad/Basal/Nullable/CallerArgumentExpressionAttribute.cs b/IFoxCAD.Cad/Basal/Nullable/CallerArgumentExpressionAttribute.cs index dc8587f..6fb3c49 100644 --- a/IFoxCAD.Cad/Basal/Nullable/CallerArgumentExpressionAttribute.cs +++ b/IFoxCAD.Cad/Basal/Nullable/CallerArgumentExpressionAttribute.cs @@ -18,5 +18,6 @@ public CallerArgumentExpressionAttribute(string parameterName) /// /// 获取其表达式应捕获为字符串的参数的名称。 /// + // ReSharper disable once UnusedAutoPropertyAccessor.Global public string ParameterName { get; } } \ No newline at end of file diff --git a/IFoxCAD.Cad/ExtensionMethod/DBObjectEx.cs b/IFoxCAD.Cad/ExtensionMethod/DBObjectEx.cs index 6eb802a..fc4eccf 100644 --- a/IFoxCAD.Cad/ExtensionMethod/DBObjectEx.cs +++ b/IFoxCAD.Cad/ExtensionMethod/DBObjectEx.cs @@ -15,16 +15,18 @@ public static string GetBlockName(this BlockReference blk) ArgumentNullEx.ThrowIfNull(blk); if (blk.IsDynamicBlock) { - var btrid = blk.DynamicBlockTableRecord; - var tr = btrid.Database.TransactionManager.TopTransaction; + var btrId = blk.DynamicBlockTableRecord; + var tr = btrId.Database.TransactionManager.TopTransaction; ArgumentNullEx.ThrowIfNull(tr); - var btr = (BlockTableRecord)tr.GetObject(btrid); + var btr = (BlockTableRecord)tr.GetObject(btrId); return btr.Name; } + return blk.Name; } #region Linq + /// /// 删除数据库对象 /// @@ -41,9 +43,11 @@ public static void Erase(this IEnumerable dBObjects) } } } + #endregion #region Xdata扩展 + /// /// 删除扩展数据 /// @@ -52,21 +56,22 @@ public static void Erase(this IEnumerable dBObjects) /// 要删除数据的组码 public static void RemoveXData(this DBObject obj, string appName, DxfCode dxfCode) { - if (obj.XData == null) + if (obj.XData is null) return; XDataList data = obj.XData; // 移除指定App的扩展 - var indexs = data.GetXdataAppIndex(appName, new DxfCode[] { dxfCode }); - if (indexs.Count == 0) + var indexes = data.GetXdataAppIndex(appName, new DxfCode[] { dxfCode }); + if (indexes.Count == 0) return; - for (int i = indexs.Count - 1; i >= 0; i--) - data.RemoveAt(indexs[i]); + for (var i = indexes.Count - 1; i >= 0; i--) + data.RemoveAt(indexes[i]); using (obj.ForWrite()) obj.XData = data; } + /// /// 删除扩展数据 /// @@ -74,13 +79,14 @@ public static void RemoveXData(this DBObject obj, string appName, DxfCode dxfCod /// 应用程序名称 public static void RemoveXData(this DBObject obj, string appName) { - if (obj.XData == null) + if (obj.XData is null) return; // 直接赋值进去等于清空名称 using (obj.ForWrite()) obj.XData = new XDataList() { { 1001, appName } }; } + /// /// 克隆对象 /// @@ -92,29 +98,31 @@ public static T CloneEx(this T ent) where T : RXObject { return ent.Clone() is T tEnt ? tEnt : throw new ArgumentException(nameof(CloneEx) + "克隆出错"); } + /// /// 修改扩展数据 /// /// 对象实例 /// 应用程序名称 /// 要修改数据的组码 - /// 新的数据 - public static void ChangeXData(this DBObject obj, string appName, DxfCode dxfCode, object newvalue) + /// 新的数据 + public static void ChangeXData(this DBObject obj, string appName, DxfCode dxfCode, object newValue) { - if (obj.XData == null) + if (obj.XData is null) return; XDataList data = obj.XData; - var indexs = data.GetXdataAppIndex(appName, new DxfCode[] { dxfCode }); - if (indexs.Count == 0) + var indexes = data.GetXdataAppIndex(appName, new DxfCode[] { dxfCode }); + if (indexes.Count == 0) return; - for (int i = indexs.Count - 1; i >= 0; i--) - data[indexs[i]] = new TypedValue((short)dxfCode, newvalue); + for (var i = indexes.Count - 1; i >= 0; i--) + data[indexes[i]] = new TypedValue((short)dxfCode, newValue); using (obj.ForWrite()) obj.XData = data; } + #endregion #region 读写模式切换 @@ -128,18 +136,19 @@ public static void ChangeXData(this DBObject obj, string appName, DxfCode dxfCod /// 操作委托 public static void ForWrite(this T obj, Action action) where T : DBObject { - var _isNotifyEnabled = obj.IsNotifyEnabled; - var _isWriteEnabled = obj.IsWriteEnabled; - if (_isNotifyEnabled) + var isNotifyEnabled = obj.IsNotifyEnabled; + var isWriteEnabled = obj.IsWriteEnabled; + if (isNotifyEnabled) obj.UpgradeFromNotify(); - else if (!_isWriteEnabled) + else if (!isWriteEnabled) obj.UpgradeOpen(); + // ReSharper disable once ConditionalAccessQualifierIsNonNullableAccordingToAPIContract action?.Invoke(obj); - if (_isNotifyEnabled) - obj.DowngradeToNotify(_isWriteEnabled); - else if (!_isWriteEnabled) + if (isNotifyEnabled) + obj.DowngradeToNotify(isWriteEnabled); + else if (!isWriteEnabled) obj.DowngradeOpen(); } @@ -190,5 +199,6 @@ public void Dispose() #endregion IDisposable 成员 } #line default + #endregion } \ No newline at end of file diff --git a/IFoxCAD.Cad/ExtensionMethod/ObjectIdEx.cs b/IFoxCAD.Cad/ExtensionMethod/ObjectIdEx.cs index aa9d163..f990f44 100644 --- a/IFoxCAD.Cad/ExtensionMethod/ObjectIdEx.cs +++ b/IFoxCAD.Cad/ExtensionMethod/ObjectIdEx.cs @@ -6,6 +6,7 @@ public static class ObjectIdEx { #region GetObject + /// /// 获取指定类型对象 /// @@ -16,9 +17,9 @@ public static class ObjectIdEx /// 是否打开锁定图层对象,默认为不打开 /// 指定类型对象 public static T? GetObject(this ObjectId id, - OpenMode openMode = OpenMode.ForRead, - bool openErased = false, - bool openLockedLayer = false) where T : DBObject + OpenMode openMode = OpenMode.ForRead, + bool openErased = false, + bool openLockedLayer = false) where T : DBObject { var tr = DBTrans.GetTopTransaction(id.Database); return tr.GetObject(id, openMode, openErased, openLockedLayer) as T; @@ -35,15 +36,16 @@ public static class ObjectIdEx /// 指定类型对象集合 [DebuggerStepThrough] public static IEnumerable GetObject(this IEnumerable ids, - OpenMode openMode = OpenMode.ForRead, - bool openErased = false, - bool openLockedLayer = false) where T : DBObject + OpenMode openMode = OpenMode.ForRead, + bool openErased = false, + bool openLockedLayer = false) where T : DBObject { var rxc = RXObject.GetClass(typeof(T)); return ids.Where(id => id.ObjectClass.IsDerivedFrom(rxc)) - .Select(id => id.GetObject(openMode, openErased, openLockedLayer)) - .OfType(); + .Select(id => id.GetObject(openMode, openErased, openLockedLayer)) + .OfType(); } + /// /// 获取指定类型对象集合 /// @@ -61,6 +63,7 @@ public static IEnumerable GetObject(this ObjectIdCollection ids, { return ids.Cast().GetObject(openMode, openErased, openLockedLayer); } + /// /// 返回符合类型的对象id /// @@ -79,6 +82,7 @@ public static IEnumerable IsDerivedFrom(this IEnumerable return ids.Where(id => id.ObjectClass.IsDerivedFrom(rxc)); } + #endregion GetObject /// @@ -91,6 +95,7 @@ public static ObjectId GetObjectId(this Database db, string handleString) { return db.GetObjectId(handleString.ConvertToHandle()); } + /// /// 根据对象句柄获取对象ObjectId /// @@ -99,8 +104,9 @@ public static ObjectId GetObjectId(this Database db, string handleString) /// 对象的ObjectId public static ObjectId GetObjectId(this Database db, Handle? handle) { - return handle is not null && db.TryGetObjectId(handle.Value, out ObjectId id) ? id : ObjectId.Null; + return handle is not null && db.TryGetObjectId(handle.Value, out var id) ? id : ObjectId.Null; } + /// /// 句柄字符串转句柄 /// @@ -108,8 +114,9 @@ public static ObjectId GetObjectId(this Database db, Handle? handle) /// 句柄 public static Handle? ConvertToHandle(this string handleString) { - return long.TryParse(handleString, NumberStyles.HexNumber, null, out long l) ? new Handle(l) : null; + return long.TryParse(handleString, NumberStyles.HexNumber, null, out var l) ? new Handle(l) : null; } + /// /// id是否有效,未被删除 /// @@ -132,7 +139,7 @@ public static void Erase(this ObjectId id) using (ent.ForWrite()) { ent.Erase(); - }// 第一种读写权限自动转换写法 + } // 第一种读写权限自动转换写法 // Env.Editor.Regen(); } } diff --git a/IFoxCAD.Cad/ExtensionMethod/TransactionEx.cs b/IFoxCAD.Cad/ExtensionMethod/TransactionEx.cs index 698f503..5d2438e 100644 --- a/IFoxCAD.Cad/ExtensionMethod/TransactionEx.cs +++ b/IFoxCAD.Cad/ExtensionMethod/TransactionEx.cs @@ -21,6 +21,7 @@ public static DBObject GetObject(this Transaction tr, ObjectId id, { return tr.GetObject(id, openMode, openErased, openLockedLayer); } + /// /// 根据对象id获取图元对象 /// diff --git a/IFoxCAD.Cad/ResultData/TypedValueList.cs b/IFoxCAD.Cad/ResultData/TypedValueList.cs index 9275488..51bfc5b 100644 --- a/IFoxCAD.Cad/ResultData/TypedValueList.cs +++ b/IFoxCAD.Cad/ResultData/TypedValueList.cs @@ -6,18 +6,26 @@ public class TypedValueList : List { #region 构造函数 + /// /// 默认无参构造函数 /// - protected TypedValueList() { } + protected TypedValueList() + { + } + /// /// 采用 TypedValue 迭代器构造 TypedValueList /// /// - protected TypedValueList(IEnumerable values) : base(values) { } + protected TypedValueList(IEnumerable values) : base(values) + { + } + #endregion #region 添加数据 + /// /// 添加数据 /// @@ -31,26 +39,31 @@ public virtual void Add(int code, object obj) #endregion #region 转换器 + /// /// ResultBuffer 隐式转换到 TypedValueList /// /// ResultBuffer 实例 public static implicit operator TypedValueList(ResultBuffer buffer) => new(buffer.AsArray()); + /// /// TypedValueList 隐式转换到 TypedValue 数组 /// /// TypedValueList 实例 public static implicit operator TypedValue[](TypedValueList values) => values.ToArray(); + /// /// TypedValueList 隐式转换到 ResultBuffer /// /// TypedValueList 实例 public static implicit operator ResultBuffer(TypedValueList values) => new(values); + /// /// TypedValue 数组隐式转换到 TypedValueList /// /// TypedValue 数组 public static implicit operator TypedValueList(TypedValue[] values) => new(values); + /// /// 转换为字符串 /// @@ -60,5 +73,6 @@ public override string ToString() using ResultBuffer a = new(this); return a.ToString(); } + #endregion } \ No newline at end of file diff --git a/IFoxCAD.Cad/ResultData/XdataList.cs b/IFoxCAD.Cad/ResultData/XdataList.cs index 1baf0f4..b238950 100644 --- a/IFoxCAD.Cad/ResultData/XdataList.cs +++ b/IFoxCAD.Cad/ResultData/XdataList.cs @@ -6,18 +6,25 @@ public class XDataList : TypedValueList { #region 构造函数 + /// /// 扩展数据封装类 /// - public XDataList() { } + public XDataList() + { + } /// /// 扩展数据封装类 /// - public XDataList(IEnumerable values) : base(values) { } + public XDataList(IEnumerable values) : base(values) + { + } + #endregion #region 添加数据 + /// /// 添加数据 /// @@ -47,8 +54,9 @@ public void Add(DxfCode code, object obj) /// 注册名 public bool Contains(string appName) { - bool result = false; - RangeTask(appName, (_, state, _) => { + var result = false; + RangeTask(appName, (_, state, _) => + { result = true; state.Break(); }); @@ -62,8 +70,9 @@ public bool Contains(string appName) /// 内容 public bool Contains(string appName, object value) { - bool result = false; - RangeTask(appName, (tv, state, _) => { + var result = false; + RangeTask(appName, (tv, state, _) => + { if (tv.Value.Equals(value)) { result = true; @@ -82,7 +91,8 @@ public bool Contains(string appName, object value) public List GetXdataAppIndex(string appName, DxfCode[] dxfCodes) { List indexes = new(); - RangeTask(appName, (tv, _, i) => { + RangeTask(appName, (tv, _, i) => + { if (dxfCodes.Contains((DxfCode)tv.TypeCode)) indexes.Add(i); }); @@ -98,8 +108,8 @@ private void RangeTask(string appName, Action action { LoopState state = new(); // 在名称和名称之间找 - int appNameIndex = -1; - for (int i = 0; i < this.Count; i++) + var appNameIndex = -1; + for (var i = 0; i < this.Count; i++) { if (this[i].TypeCode == (short)DxfCode.ExtendedDataRegAppName) { @@ -108,7 +118,8 @@ private void RangeTask(string appName, Action action appNameIndex = i; continue; } - if (appNameIndex != -1)//找到了下一个名称 + + if (appNameIndex != -1) //找到了下一个名称 break; } @@ -122,25 +133,30 @@ private void RangeTask(string appName, Action action #endregion #region 转换器 + /// /// ResultBuffer 隐式转换到 XDataList /// /// ResultBuffer 实例 public static implicit operator XDataList(ResultBuffer buffer) => new(buffer.AsArray()); + /// /// XDataList 隐式转换到 TypedValue 数组 /// /// TypedValueList 实例 public static implicit operator TypedValue[](XDataList values) => values.ToArray(); + /// /// XDataList 隐式转换到 ResultBuffer /// /// TypedValueList 实例 public static implicit operator ResultBuffer(XDataList values) => new(values); + /// /// TypedValue 数组隐式转换到 XDataList /// /// TypedValue 数组 public static implicit operator XDataList(TypedValue[] values) => new(values); + #endregion } \ No newline at end of file diff --git a/IFoxCAD.Cad/Runtime/DBTrans.cs b/IFoxCAD.Cad/Runtime/DBTrans.cs index 3d155b1..38af048 100644 --- a/IFoxCAD.Cad/Runtime/DBTrans.cs +++ b/IFoxCAD.Cad/Runtime/DBTrans.cs @@ -504,18 +504,6 @@ public DBObject GetObject(ObjectId id, return Transaction.GetObject(id, openMode, openErased, openLockedLayer) as T; } - /// - /// 根据对象句柄字符串获取对象Id - /// - /// 句柄字符串 - /// 对象id - public ObjectId GetObjectId(string handleString) - { - // ToDo 这个函数考虑移走 - var handle = new Handle(Convert.ToInt64(handleString, 16)); - return Database.TryGetObjectId(handle, out var id) ? id : ObjectId.Null; - } - #endregion #region 前台后台任务 diff --git a/IFoxCAD.Cad/Runtime/Env.cs b/IFoxCAD.Cad/Runtime/Env.cs index 0258058..009f3e4 100644 --- a/IFoxCAD.Cad/Runtime/Env.cs +++ b/IFoxCAD.Cad/Runtime/Env.cs @@ -1,4 +1,5 @@ using System.Security; + // ReSharper disable StringLiteralTypo namespace IFoxCAD.Cad; @@ -826,7 +827,7 @@ public static string GetAcapVersionDll(string str = "acdb") if (valueType is null) return null; - + // 相同的参数进行设置会发生一次异常 if (!string.Equals(currentVar.ToString(), valueType.ToString(), StringComparison.CurrentCultureIgnoreCase)) SetVar(key, valueType); -- Gitee From 7683d2cc9c03cf5e9ad6deab4b4e2edcb30ad757 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sat, 23 Mar 2024 09:51:44 +0800 Subject: [PATCH 257/453] =?UTF-8?q?=E6=B7=BB=E5=8A=A0test=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IFoxCAD.sln | 6 ++++++ Test/Class1.cs | 5 +++++ Test/Test.csproj | 9 +++++++++ 3 files changed, 20 insertions(+) create mode 100644 Test/Class1.cs create mode 100644 Test/Test.csproj diff --git a/IFoxCAD.sln b/IFoxCAD.sln index 89923dd..cbb4424 100644 --- a/IFoxCAD.sln +++ b/IFoxCAD.sln @@ -5,6 +5,8 @@ VisualStudioVersion = 17.8.34309.116 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IFoxCAD.Cad", "IFoxCAD.Cad\IFoxCAD.Cad.csproj", "{6B29955A-5796-4035-9297-210FA15D3846}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test", "Test\Test.csproj", "{0C01F295-0985-436B-A15D-228877C60F1D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -15,6 +17,10 @@ Global {6B29955A-5796-4035-9297-210FA15D3846}.Debug|Any CPU.Build.0 = Debug|Any CPU {6B29955A-5796-4035-9297-210FA15D3846}.Release|Any CPU.ActiveCfg = Release|Any CPU {6B29955A-5796-4035-9297-210FA15D3846}.Release|Any CPU.Build.0 = Release|Any CPU + {0C01F295-0985-436B-A15D-228877C60F1D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0C01F295-0985-436B-A15D-228877C60F1D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0C01F295-0985-436B-A15D-228877C60F1D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0C01F295-0985-436B-A15D-228877C60F1D}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Test/Class1.cs b/Test/Class1.cs new file mode 100644 index 0000000..df347f6 --- /dev/null +++ b/Test/Class1.cs @@ -0,0 +1,5 @@ +namespace Test; + +public class Class1 +{ +} \ No newline at end of file diff --git a/Test/Test.csproj b/Test/Test.csproj new file mode 100644 index 0000000..16521a5 --- /dev/null +++ b/Test/Test.csproj @@ -0,0 +1,9 @@ + + + + net48 + preview + enable + + + -- Gitee From 8b06709b073d23208e7f6873fc63a180e6993fba Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sat, 23 Mar 2024 12:06:43 +0800 Subject: [PATCH 258/453] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=B8=B8=E7=94=A8?= =?UTF-8?q?=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IFoxCAD.Cad/Basal/Nullable/ArgumentNullEx.cs | 3 +- IFoxCAD.Cad/ExtensionMethod/CollectionEx.cs | 331 ++++++++++ IFoxCAD.Cad/ExtensionMethod/DBDictionaryEx.cs | 452 ++++++++++++++ IFoxCAD.Cad/ExtensionMethod/DBObjectEx.cs | 19 - .../Entity/BlockReferenceEx.cs | 264 ++++++++ .../ExtensionMethod/Entity/BoundingInfo.cs | 193 ++++++ .../ExtensionMethod/Entity/CircleEx.cs | 57 ++ .../Entity/EntityBoundingInfo.cs | 231 +++++++ .../ExtensionMethod/Entity/EntityEx.cs | 164 +++++ .../ExtensionMethod/Geomerty/Curve2dEx.cs | 299 ++++++++++ .../ExtensionMethod/Geomerty/Curve3dEx.cs | 564 ++++++++++++++++++ .../ExtensionMethod/Geomerty/PointEx.cs | 260 ++++++++ IFoxCAD.Cad/ExtensionMethod/ObjectIdEx.cs | 16 + IFoxCAD.Cad/ExtensionMethod/RedrawEx.cs | 200 +++++++ .../ExtensionMethod/SymbolTableRecordEx.cs | 364 +++++++++++ IFoxCAD.Cad/GlobalUsing.cs | 3 +- .../ResultData/{XdataList.cs => XDataList.cs} | 0 IFoxCAD.Cad/ResultData/XRecordDataList.cs | 67 +++ IFoxCAD.sln.DotSettings | 4 + Test/Class1.cs | 5 - Test/GlobalUsing.cs | 7 + Test/Test.csproj | 10 + Test/TestAddEntity.cs | 98 +++ Test/Timer.cs | 150 +++++ Test/Tools.cs | 74 +++ 25 files changed, 3809 insertions(+), 26 deletions(-) create mode 100644 IFoxCAD.Cad/ExtensionMethod/CollectionEx.cs create mode 100644 IFoxCAD.Cad/ExtensionMethod/DBDictionaryEx.cs create mode 100644 IFoxCAD.Cad/ExtensionMethod/Entity/BlockReferenceEx.cs create mode 100644 IFoxCAD.Cad/ExtensionMethod/Entity/BoundingInfo.cs create mode 100644 IFoxCAD.Cad/ExtensionMethod/Entity/CircleEx.cs create mode 100644 IFoxCAD.Cad/ExtensionMethod/Entity/EntityBoundingInfo.cs create mode 100644 IFoxCAD.Cad/ExtensionMethod/Entity/EntityEx.cs create mode 100644 IFoxCAD.Cad/ExtensionMethod/Geomerty/Curve2dEx.cs create mode 100644 IFoxCAD.Cad/ExtensionMethod/Geomerty/Curve3dEx.cs create mode 100644 IFoxCAD.Cad/ExtensionMethod/Geomerty/PointEx.cs create mode 100644 IFoxCAD.Cad/ExtensionMethod/RedrawEx.cs create mode 100644 IFoxCAD.Cad/ExtensionMethod/SymbolTableRecordEx.cs rename IFoxCAD.Cad/ResultData/{XdataList.cs => XDataList.cs} (100%) create mode 100644 IFoxCAD.Cad/ResultData/XRecordDataList.cs delete mode 100644 Test/Class1.cs create mode 100644 Test/GlobalUsing.cs create mode 100644 Test/TestAddEntity.cs create mode 100644 Test/Timer.cs create mode 100644 Test/Tools.cs diff --git a/IFoxCAD.Cad/Basal/Nullable/ArgumentNullEx.cs b/IFoxCAD.Cad/Basal/Nullable/ArgumentNullEx.cs index 8b030b6..8552c44 100644 --- a/IFoxCAD.Cad/Basal/Nullable/ArgumentNullEx.cs +++ b/IFoxCAD.Cad/Basal/Nullable/ArgumentNullEx.cs @@ -1,4 +1,5 @@ -namespace IFoxCAD.Basal; + +namespace IFoxCAD.Basal; /// /// 参数null检查类 diff --git a/IFoxCAD.Cad/ExtensionMethod/CollectionEx.cs b/IFoxCAD.Cad/ExtensionMethod/CollectionEx.cs new file mode 100644 index 0000000..f0b8cda --- /dev/null +++ b/IFoxCAD.Cad/ExtensionMethod/CollectionEx.cs @@ -0,0 +1,331 @@ +namespace IFoxCAD.Cad; + +/// +/// 集合扩展类 +/// +public static class CollectionEx +{ + /// + /// 对象id迭代器转换为集合 + /// + /// 对象id的迭代器 + /// 对象id集合,记得释放 + [DebuggerStepThrough] + public static ObjectIdCollection ToCollection(this IEnumerable ids) + { + return new ObjectIdCollection(ids.ToArray()); + } + + + /// + /// 实体迭代器转换为集合 + /// + /// 对象类型 + /// 实体对象的迭代器 + /// 实体集合,记得释放 + [DebuggerStepThrough] + public static DBObjectCollection ToCollection(this IEnumerable objs) where T : DBObject + { + DBObjectCollection objCol = new(); + foreach (var obj in objs) + objCol.Add(obj); + return objCol; + } + + /// + /// double 数值迭代器转换为 double 数值集合 + /// + /// double 数值迭代器 + /// 数值集合,它没有Dispose + [DebuggerStepThrough] + public static DoubleCollection ToCollection(this IEnumerable doubles) + { + return new DoubleCollection(doubles.ToArray()); + } + + /// + /// double 数值迭代器转换为 double 数值集合 + /// + /// double 数值迭代器 + /// 数值集合,它没有Dispose + [DebuggerStepThrough] + public static IntegerCollection ToCollection(this IEnumerable ints) + { + return new IntegerCollection(ints.ToArray()); + } + + /// + /// 二维点迭代器转换为二维点集合 + /// + /// 二维点迭代器 + /// 二维点集合,!acad记得释放 + [DebuggerStepThrough] + public static Point2dCollection ToCollection(this IEnumerable pts) + { + return new Point2dCollection(pts.ToArray()); + } + + /// + /// 三维点迭代器转换为三维点集合 + /// + /// 三维点迭代器 + /// 三维点集合,记得释放 + [DebuggerStepThrough] + public static Point3dCollection ToCollection(this IEnumerable pts) + { + return new Point3dCollection(pts.ToArray()); + } + + /// + /// 对象id集合转换为对象id列表 + /// + /// 对象id集合 + /// 对象id列表 + [DebuggerStepThrough] + public static List ToList(this ObjectIdCollection ids) + { + return ids.Cast().ToList(); + } + + + /// + /// 遍历集合,执行委托 + /// + /// 集合值的类型 + /// 集合 + /// 委托 + [DebuggerStepThrough] + public static void ForEach(this IEnumerable source, Action action) + { + // 这里不要嵌套调用ForEach委托, + // 因为这样可以在调用函数上断点直接跑Action内,不会进入此处(除了cad之外); + // 而cad很奇怪,只能用预处理方式避免 + // 嵌套调用ForEach委托: + // source.ForEach((a, _, _) => { + // action.Invoke(a); + // }); + + foreach (var element in source) + action.Invoke(element); + } + + /// + /// 遍历集合,执行委托 + /// + /// 集合值的类型 + /// 集合 + /// 委托 + [DebuggerStepThrough] + public static void ForEach(this IEnumerable source, Action action) + { + var i = 0; + foreach (var element in source) + { + action.Invoke(i, element); + i++; + } + } + + /// + /// 遍历集合,执行委托(允许循环中断) + /// + /// 集合值的类型 + /// 集合 + /// 委托 + [DebuggerStepThrough] + public static void ForEach(this IEnumerable source, Action action) + { + // 这里不要嵌套调用ForEach委托, + // 因为这样可以在调用函数上断点直接跑Action内,不会进入此处(除了cad之外); + // 而cad很奇怪,只能用预处理方式避免 + // 嵌套调用ForEach委托: + // source.ForEach((a, b, _) => { + // action.Invoke(a, b); + // }); + + LoopState state = new(); /*这种方式比Action改Func更友好*/ + foreach (var element in source) + { + action.Invoke(element, state); + if (!state.IsRun) + break; + } + } + + /// + /// 遍历集合,执行委托(允许循环中断,输出索引值) + /// + /// 集合值的类型 + /// 集合 + /// 委托 + [DebuggerStepThrough] + public static void ForEach(this IEnumerable source, Action action) + { + int i = 0; + LoopState state = new(); /*这种方式比Action改Func更友好*/ + foreach (var element in source) + { + action.Invoke(element, state, i); + if (!state.IsRun) + break; + i++; + } + } + + + #region 关键字集合 + + /// + /// 关键字名字 + /// + public enum KeywordName + { + /// + /// 全局名字 + /// + GlobalName, + + /// + /// 本地名字 + /// + LocalName, + + /// + /// 显示名字 + /// + DisplayName, + } + + /// + /// 含有关键字 + /// + /// 关键字集合 + /// 关键字 + /// 关键字容器字段名 + /// true含有 + [DebuggerStepThrough] + public static bool Contains(this KeywordCollection collection, string name, + KeywordName keywordName = KeywordName.GlobalName) + { + bool contains = false; + switch (keywordName) + { + case KeywordName.GlobalName: + for (int i = 0; i < collection.Count; i++) + { + var item = collection[i]; + + if (item.GlobalName == name) + { + contains = true; + break; + } + } + + break; + case KeywordName.LocalName: + for (int i = 0; i < collection.Count; i++) + { + var item = collection[i]; + + if (item.LocalName == name) + { + contains = true; + break; + } + } + + break; + case KeywordName.DisplayName: + for (int i = 0; i < collection.Count; i++) + { + var item = collection[i]; + + if (item.DisplayName == name) + { + contains = true; + break; + } + } + + break; + } + + return contains; + } + + /// + /// 获取词典, + /// KeywordCollection是允许重复关键字的,没有哈希索引,在多次判断时候会遍历多次O(n),所以生成一个词典进行O(1) + /// + /// + /// + [DebuggerStepThrough] + public static Dictionary ToDictionary(this KeywordCollection collection) + { + Dictionary map = new(); + for (int i = 0; i < collection.Count; i++) + { + var item = collection[i]; + + map.Add(item.GlobalName, item.DisplayName); + } + + return map; + } + + #endregion + + + #region IdMapping + + /// + /// 旧块名 + /// + /// + /// + [DebuggerStepThrough] + public static List GetKeys(this IdMapping idMapping) + { + List ids = new(); + foreach (IdPair item in idMapping) + ids.Add(item.Key); + return ids; + } + + /// + /// 新块名 + /// + /// + /// + [DebuggerStepThrough] + public static List GetValues(this IdMapping idMapping) + { + List ids = new(); + foreach (IdPair item in idMapping) + { + ids.Add(item.Value); + } + + return ids; + } + + /// + /// 转换为词典 + /// + /// + /// + [DebuggerStepThrough] + public static Dictionary ToDictionary(this IdMapping mapping) + { + var keyValuePairs = new Dictionary(); + foreach (IdPair item in mapping) + { + keyValuePairs.Add(item.Key, item.Value); + } + + return keyValuePairs; + } + + #endregion +} \ No newline at end of file diff --git a/IFoxCAD.Cad/ExtensionMethod/DBDictionaryEx.cs b/IFoxCAD.Cad/ExtensionMethod/DBDictionaryEx.cs new file mode 100644 index 0000000..0f735bc --- /dev/null +++ b/IFoxCAD.Cad/ExtensionMethod/DBDictionaryEx.cs @@ -0,0 +1,452 @@ +namespace IFoxCAD.Cad; + +/// +/// 字典扩展类 +/// +public static class DBDictionaryEx +{ + /// + /// 获取字典里的全部对象 + /// + /// 对象类型的泛型 + /// 字典 + /// 对象迭代器 + [System.Diagnostics.DebuggerStepThrough] + public static IEnumerable GetAllObjects(this DBDictionary dict) where T : DBObject + { + var tr = DBTrans.GetTopTransaction(dict.Database); + foreach (var e in dict) + { + if (tr.GetObject(e.Value) is T tobj) + yield return tobj; + } + } + + /// + /// 获取字典内指定key的对象 + /// + /// 对象类型的泛型 + /// 字典 + /// 指定的键值 + /// T 类型的对象 + [Obsolete] + public static T? GetAt(this DBDictionary dict, string key) where T : DBObject + { + var tr = DBTrans.GetTopTransaction(dict.Database); + if (dict.Contains(key)) + { + var id = dict.GetAt(key); + if (!id.IsNull) + return tr.GetObject(id); + } + + return null; + } + + /// + /// 添加条目(键值对)到字典 + /// + /// 对象类型 + /// 字典 + /// 键 + /// 值 + /// 字典项目的id + [Obsolete] + public static ObjectId SetAt(this DBDictionary dict, string key, T newValue) where T : DBObject + { + var tr = DBTrans.GetTopTransaction(dict.Database); + + using (dict.ForWrite()) + { + var id = dict.SetAt(key, newValue); + tr.AddNewlyCreatedDBObject(newValue, true); + return id; + } + } + + /// + /// 获取字典内指定key的对象 + /// + /// 字典 + /// 指定的键值 + /// T 类型的对象 + public static DBObject? GetData(this DBDictionary dict, string key) + { + var tr = DBTrans.GetTopTransaction(dict.Database); + if (dict.Contains(key)) + { + var id = dict.GetAt(key); + if (!id.IsNull) + return tr.GetObject(id); + } + + return null; + } + + /// + /// 获取字典内指定key的对象 + /// + /// 对象类型的泛型 + /// 字典 + /// 指定的键值 + /// T 类型的对象 + public static T? GetData(this DBDictionary dict, string key) where T : DBObject + { + var tr = DBTrans.GetTopTransaction(dict.Database); + if (dict.Contains(key)) + { + var id = dict.GetAt(key); + if (!id.IsNull) + return tr.GetObject(id); + } + + return null; + } + + /// + /// 添加条目(键值对)到字典 + /// + /// 对象类型 + /// 字典 + /// 键 + /// 值 + /// 字典项目的id + public static ObjectId SetData(this DBDictionary dict, string key, T newValue) where T : DBObject + { + var tr = DBTrans.GetTopTransaction(dict.Database); + + using (dict.ForWrite()) + { + var id = dict.SetAt(key, newValue); + tr.AddNewlyCreatedDBObject(newValue, true); + return id; + } + } + + #region XRecord + + /// + /// 从字典中获取扩展数据 + /// + /// 字典 + /// 键值 + /// 扩展数据 + public static XRecordDataList? GetXRecord(this DBDictionary dict, string key) + { + return dict.GetData(key) is Xrecord xr ? xr.Data : null; + } + + /// + /// 保存扩展数据到字典 + /// + /// 扩展数据 + /// 字典 + /// 键值 + public static void SetXRecord(this DBDictionary dict, string key, XRecordDataList rb) + { + // DxfCode.300 字符串可以写 Data + // DxfCode.1004 内存流不给写 Data,只能去写 XData + Xrecord newValue = new(); + newValue.Data = rb; + dict.SetData(key, newValue); + } + + #endregion + + /// + /// 获取扩展字典 + /// + /// 对象 + /// 打开模式 + /// 扩展字典对象 + public static DBDictionary GetXDictionary(this DBObject obj, OpenMode openMode = OpenMode.ForRead) + { + var tr = DBTrans.GetTopTransaction(obj.Database); + var id = obj.ExtensionDictionary; + if (id.IsNull) + { + using (obj.ForWrite()) + obj.CreateExtensionDictionary(); + + id = obj.ExtensionDictionary; + } + + return (DBDictionary)tr.GetObject(id, openMode); + } + + #region 数据表 + + /// + /// 创建数据表 + /// + /// 原数据类型的字典 + /// 表元素(二维数组) + /// 数据表 + public static DataTable CreateDataTable(Dictionary colTypes, object[,] content) + { + DataTable table = new(); + foreach (var t in colTypes) + table.AppendColumn(t.Value, t.Key); + + var ncol = colTypes.Count; + var types = new CellType[ncol]; + colTypes.Values.CopyTo(types, 0); + + var nrow = content.GetLength(0); + for (int i = 0; i < nrow; i++) + { + DataCellCollection row = new(); + for (int j = 0; j < ncol; j++) + { + var cell = new DataCell(); + cell.SetValue(types[j], content[i, j]); + row.Add(cell); + } + + table.AppendRow(row, true); + } + + return table; + } + + /// + /// 设定单元格数据 + /// + /// 单元格 + /// 类型 + /// 数据 + public static void SetValue(this DataCell cell, CellType type, object value) + { + switch (type) + { + case CellType.Bool: + cell.SetBool((bool)value); + break; + + case CellType.CharPtr: + cell.SetString((string)value); + break; + + case CellType.Integer: + cell.SetInteger((int)value); + break; + + case CellType.Double: + cell.SetDouble((double)value); + break; + + case CellType.ObjectId: + cell.SetObjectId((ObjectId)value); + break; + + case CellType.Point: + cell.SetPoint((Point3d)value); + break; + + case CellType.Vector: + cell.SetVector((Vector3d)value); + break; + + case CellType.HardOwnerId: + cell.SetHardOwnershipId((ObjectId)value); + break; + + case CellType.HardPtrId: + cell.SetHardPointerId((ObjectId)value); + break; + + case CellType.SoftOwnerId: + cell.SetSoftOwnershipId((ObjectId)value); + break; + + case CellType.SoftPtrId: + cell.SetSoftPointerId((ObjectId)value); + break; + } + } + + #endregion + + #region 子字典 + + /// + /// 获取子字典 + /// + /// 根字典 + /// 是否创建子字典 + /// 键值列表 + /// 字典 + public static DBDictionary? GetSubDictionary(this DBDictionary dict, + bool createSubDictionary, + IEnumerable dictNames) + { + DBDictionary? newdict = null; + + if (createSubDictionary) + { + using (dict.ForWrite()) + dict.TreatElementsAsHard = true; + + foreach (string name in dictNames) + { + if (dict.Contains(name)) + { + newdict = dict.GetData(name) as DBDictionary; + } + else + { + DBDictionary subDict = new(); + dict.SetData(name, subDict); + newdict = subDict; + newdict.TreatElementsAsHard = true; + } + } + } + else + { + foreach (string name in dictNames) + { + if (dict.Contains(name)) + newdict = dict.GetData(name); + else + return null; + } + } + + return newdict; + } + + + ///// + ///// 获取对象扩展字典的子字典 + ///// + ///// 对象 + ///// 事务 + ///// 是否创建子字典 + ///// 键值列表 + ///// 字典 + // public static DBDictionary GetSubDictionary(this DBObject obj, bool createSubDictionary, params string[] dictNames) + // { + // return obj.GetXDictionary().GetSubDictionary(createSubDictionary, dictNames); + // } + + #endregion + + #region 组字典 + + /// + /// 添加编组 + /// + /// 字典 + /// 组名 + /// 实体Id集合 + /// 编组Id + public static ObjectId AddGroup(this DBDictionary dict, string name, ObjectIdCollection ids) + { + if (dict.Contains(name)) + return ObjectId.Null; + + using (dict.ForWrite()) + { + Group g = new(); + g.Append(ids); + dict.SetAt(name, g); + var tr = DBTrans.GetTopTransaction(dict.Database); + tr.AddNewlyCreatedDBObject(g, true); + return g.ObjectId; + } + } + + /// + /// 添加编组 + /// + /// 字典 + /// 组名 + /// 实体Id集合 + /// 编组Id + public static ObjectId AddGroup(this DBDictionary dict, string name, IEnumerable ids) + { + if (dict.Contains(name)) + return ObjectId.Null; + + using ObjectIdCollection idc = new(ids.ToArray()); //需要using吗? 暂无测试 + return dict.AddGroup(name, idc); + } + + + /// + /// 按选择条件获取编组集合 + /// + /// 字典 + /// 选择条件,过滤函数 + /// g.NumEntities < 2);]]> + /// 编组集合 + public static IEnumerable GetGroups(this DBDictionary dict, Func func) + { + return dict.GetAllObjects() + .Where(func); + } + + /// + /// 返回实体的所在编组的集合 + /// + /// 图元实体 + /// 编组集合 + public static IEnumerable GetGroups(this Entity ent) + { + return ent.GetPersistentReactorIds() + .Cast() + .Select(id => id.GetObject()) + .OfType(); + } + + /// + /// 移除所有的空组 + /// + /// 被移除编组的名称集合 + public static List RemoveNullGroup(this DBDictionary dict) + { + var groups = dict.GetGroups(g => g.NumEntities < 2); + List names = new(); + foreach (var g in groups) + { + names.Add(g.Name); + using (g.ForWrite()) + { + g.Erase(); + } + } + + return names; + } + + /// + /// 移除所有空组 + /// + /// + /// 过滤条件,过滤要删除的组名的规则函数 + /// + /// g.StartsWith("hah"));]]> + /// + /// 被移除编组的名称集合 + public static List RemoveNullGroup(this DBDictionary dict, Func func) + { + var groups = dict.GetGroups(g => g.NumEntities < 2); + List names = new(); + foreach (var g in groups) + { + if (func(g.Name)) + { + names.Add(g.Name); + using (g.ForWrite()) + { + g.Erase(); + } + } + } + + return names; + } + + #endregion +} \ No newline at end of file diff --git a/IFoxCAD.Cad/ExtensionMethod/DBObjectEx.cs b/IFoxCAD.Cad/ExtensionMethod/DBObjectEx.cs index fc4eccf..f99b1b1 100644 --- a/IFoxCAD.Cad/ExtensionMethod/DBObjectEx.cs +++ b/IFoxCAD.Cad/ExtensionMethod/DBObjectEx.cs @@ -5,25 +5,6 @@ /// public static class DBObjectEx { - /// - /// 获取块的有效名字 - /// - /// 块参照 - /// 名字 - public static string GetBlockName(this BlockReference blk) - { - ArgumentNullEx.ThrowIfNull(blk); - if (blk.IsDynamicBlock) - { - var btrId = blk.DynamicBlockTableRecord; - var tr = btrId.Database.TransactionManager.TopTransaction; - ArgumentNullEx.ThrowIfNull(tr); - var btr = (BlockTableRecord)tr.GetObject(btrId); - return btr.Name; - } - - return blk.Name; - } #region Linq diff --git a/IFoxCAD.Cad/ExtensionMethod/Entity/BlockReferenceEx.cs b/IFoxCAD.Cad/ExtensionMethod/Entity/BlockReferenceEx.cs new file mode 100644 index 0000000..325cd12 --- /dev/null +++ b/IFoxCAD.Cad/ExtensionMethod/Entity/BlockReferenceEx.cs @@ -0,0 +1,264 @@ +namespace IFoxCAD.Cad; + +/// +/// 块参照扩展类 +/// +public static class BlockReferenceEx +{ + #region 裁剪块参照 + + private const string filterDictName = "ACAD_FILTER"; + private const string spatialName = "SPATIAL"; + + /// + /// 裁剪块参照 + /// + /// 块参照 + /// 裁剪多边形点表 + public static void ClipBlockRef(this BlockReference brf, IEnumerable pt3ds) + { + var mat = brf.BlockTransform.Inverse(); + var pts = + pt3ds + .Select(p => p.TransformBy(mat).Point2d()) + .ToCollection(); + + SpatialFilterDefinition sfd = new(pts, Vector3d.ZAxis, 0.0, 0.0, 0.0, true); + using SpatialFilter sf = new(); + sf.Definition = sfd; + var dict = brf.GetXDictionary().GetSubDictionary(true, [filterDictName])!; + dict.SetData(spatialName, sf); + } + + /// + /// 裁剪块参照 + /// + /// 块参照 + /// 第一角点 + /// 第二角点 + public static void ClipBlockRef(this BlockReference brf, Point3d pt1, Point3d pt2) + { + var mat = brf.BlockTransform.Inverse(); + pt1 = pt1.TransformBy(mat); + pt2 = pt2.TransformBy(mat); + + Point2dCollection pts = + [ + new Point2d(Math.Min(pt1.X, pt2.X), Math.Min(pt1.Y, pt2.Y)), + new Point2d(Math.Max(pt1.X, pt2.X), Math.Max(pt1.Y, pt2.Y)) + ]; + + using SpatialFilter sf = new(); + sf.Definition = new(pts, Vector3d.ZAxis, 0.0, 0.0, 0.0, true); + var dict = brf.GetXDictionary() + .GetSubDictionary(true, [filterDictName])!; + dict.SetData(spatialName, sf); +#if !acad + pts.Dispose(); +#endif + } + + #endregion + + #region 属性 + + /// + /// 更新动态块属性值 + /// + public static void ChangeDynamicBlockProperty(this BlockReference blockReference, + Dictionary propertyNameValues) + { + using (blockReference.ForWrite()) + { + foreach (DynamicBlockReferenceProperty item in blockReference.DynamicBlockReferencePropertyCollection) + { + if (propertyNameValues.TryGetValue(item.PropertyName, out var value)) + { + item.Value = value; + } + } + } + } + + /// + /// 更新普通块的属性值 + /// + public static void ChangeBlockAttribute(this BlockReference blockReference, Dictionary propertyNameValues) + { + var tr = DBTrans.GetTopTransaction(blockReference.Database); + foreach (var item in blockReference.AttributeCollection) + { + AttributeReference att; + if (item is ObjectId id) + { + // 通常情况下返回的都是 ObjectId + att = (AttributeReference)tr.GetObject(id); + } + else + { + // 某些情况下,比如你exploded炸开块后的子块块参照是没有在数据库里的,这时候返回的结果就是 AttributeReference + att = (AttributeReference)item; + } + + using (att.ForWrite()) + { + if (propertyNameValues.TryGetValue(att.Tag, out var value)) + { + att.TextString = value; + } + } + } + } + + /// + /// 获取嵌套块的位置(wcs) + /// + /// 父块 + /// 子块名 + /// 子块的位置 + /// + public static Point3d? GetNestedBlockPosition(this BlockReference parentBlockRef, string nestedBlockName) + { + var tr = DBTrans.GetTopTransaction(parentBlockRef.Database); + + var btr = tr.GetObject(parentBlockRef.BlockTableRecord); + if (btr == null) return null; + foreach (var id in btr) + { + if (id.ObjectClass.Name == "AcDbBlockReference") + { + var nestedBlockRef = tr.GetObject(id); + if (nestedBlockRef?.Name == nestedBlockName) + { + return nestedBlockRef.Position.TransformBy(parentBlockRef.BlockTransform); + } + } + } + + return null; + } + + /// + /// 获取普通块参照的属性集合 + /// + /// 普通块参照 + /// 属性集合 + public static IEnumerable GetAttributes(this BlockReference owner) + { + if (owner.Database != null) + { + var trans = DBTrans.GetTopTransaction(owner.Database); + foreach (ObjectId id in owner.AttributeCollection) + yield return (AttributeReference)trans.GetObject(id); + } + else + { + foreach (AttributeReference att in owner.AttributeCollection) + yield return att; + } + } + + #endregion + + /// + /// 获取块的有效名字 + /// + /// 块参照 + /// 名字 + public static string GetBlockName(this BlockReference blk) + { + ArgumentNullEx.ThrowIfNull(blk); + if (blk.IsDynamicBlock) + { + var btrId = blk.DynamicBlockTableRecord; + var tr = btrId.Database.TransactionManager.TopTransaction; + ArgumentNullEx.ThrowIfNull(tr); + var btr = (BlockTableRecord)tr.GetObject(btrId); + return btr.Name; + } + + return blk.Name; + } + + /// + /// 遍历块内 + /// + /// + /// + [DebuggerStepThrough] + public static void ForEach(this BlockReference brf, Action action) + { + ArgumentNullEx.ThrowIfNull(action); + var tr = DBTrans.GetTopTransaction(brf.Database); + if (tr.GetObject(brf.BlockTableRecord) is BlockTableRecord btr) + { + btr.ForEach(action); + } + } + + /// + /// 遍历块内 + /// + /// + /// + /// + [DebuggerStepThrough] + public static void ForEach(this BlockReference brf, Action action) + { + ArgumentNullEx.ThrowIfNull(action); + var tr = DBTrans.GetTopTransaction(brf.Database); + if (tr.GetObject(brf.BlockTableRecord) is BlockTableRecord btr) + { + btr.ForEach(action); + } + } + + /// + /// 遍历块内 + /// + /// + /// + /// + [DebuggerStepThrough] + public static void ForEach(this BlockReference brf, Action action) + { + ArgumentNullEx.ThrowIfNull(action); + var tr = DBTrans.GetTopTransaction(brf.Database); + if (tr.GetObject(brf.BlockTableRecord) is BlockTableRecord btr) + { + btr.ForEach(action); + } + } + + /// + /// 遍历嵌套块中块图元 + /// + /// 块参照 + /// 委托 + /// 事务 + public static void NestedForEach(this Entity blockReference, Action action, DBTrans? tr = null) + { + tr ??= DBTrans.GetTop(blockReference.IsNewObject ? Env.Database : blockReference.Database); + var queue = new Queue<(Entity, Matrix3d)>(); + queue.Enqueue((blockReference, Matrix3d.Identity)); + while (queue.Any()) + { + var (ent, mt) = queue.Dequeue(); + action?.Invoke(ent, mt); + if (ent is BlockReference brfTemp) + { + var mtNext = mt * brfTemp.BlockTransform; + tr.BlockTable.Change(brfTemp.BlockTableRecord, btr => + { + foreach (var id in btr) + { + if (tr.GetObject(id) is Entity entNext) + { + queue.Enqueue((entNext, mtNext)); + } + } + }); + } + } + } +} \ No newline at end of file diff --git a/IFoxCAD.Cad/ExtensionMethod/Entity/BoundingInfo.cs b/IFoxCAD.Cad/ExtensionMethod/Entity/BoundingInfo.cs new file mode 100644 index 0000000..be90241 --- /dev/null +++ b/IFoxCAD.Cad/ExtensionMethod/Entity/BoundingInfo.cs @@ -0,0 +1,193 @@ +namespace IFoxCAD.Cad; + +/// +/// 和尚777 重构 +/// 包围盒信息 +/// +public struct BoundingInfo +{ + #region 成员 + + /// + /// MinPoint.X + /// + public double MinX { get; private set; } + + /// + /// MinPoint.Y + /// + public double MinY { get; private set; } + + /// + /// MinPoint.Z + /// + public double MinZ { get; private set; } + + /// + /// MaxPoint.X + /// + public double MaxX { get; private set; } + + /// + /// MaxPoint.Y + /// + public double MaxY { get; private set; } + + /// + /// MaxPoint.Z + /// + public double MaxZ { get; private set; } + + #region 包围盒9位码坐标 + + /* + * 包围盒9位码坐标 + * P7---------------P8----------------P9 + * | | | + * | | | + * | | | + * P4---------------P5----------------P6 + * | | | + * | | | + * | | | + * P1---------------P2----------------P3 + */ + /// + /// MinPoint 左下点 P1 + /// + public readonly Point3d BottomLeft => new(MinX, MinY, MinZ); + + /// + /// P2 + /// + public readonly Point3d BottomCenter => BottomLeft.GetMidPointTo(BottomRight); + + /// + /// P3 + /// + public readonly Point3d BottomRight => new(MaxX, MinY, MinZ); + + /// + /// P4 + /// + public readonly Point3d MidLeft => BottomLeft.GetMidPointTo(TopLeft); + + /// + /// P5 + /// + public readonly Point3d MidCenter => BottomLeft.GetMidPointTo(TopRight); + + /// + /// P6 + /// + public readonly Point3d MidRight => BottomRight.GetMidPointTo(TopRight); + + /// + /// P7 + /// + public readonly Point3d TopLeft => new(MinX, MaxY, MinZ); + + /// + /// P8 + /// + public readonly Point3d TopCenter => TopLeft.GetMidPointTo(TopRight); + + /// + /// MaxPoint 右上点 P9 + /// + public readonly Point3d TopRight => new(MaxX, MaxY, MaxZ); + + // public Point3d Min => new(MinX, MinY, MinZ); + + // public Point3d Max => new(MaxX, MaxY, MaxZ); + + #endregion + + /// + /// 高 + /// + public readonly double Height => Math.Abs(MaxY - MinY); + + /// + /// 宽 + /// + public readonly double Width => Math.Abs(MaxX - MinX); + + /// + /// 面积 + /// + public readonly double Area => Height * Width; + + /// + /// 3D包围盒 + /// + public Extents3d Extents3d { get; } + + /// + /// 2D包围盒 + /// + public readonly Extents2d Extents2d => new(MinX, MinY, MaxX, MaxY); + + #endregion + + #region 构造 + + /// + /// 包围盒信息3D构造 + /// + /// 包围盒 + public BoundingInfo(Extents3d ext) + { + MinX = ext.MinPoint.X; + MinY = ext.MinPoint.Y; + MinZ = ext.MinPoint.Z; + MaxX = ext.MaxPoint.X; + MaxY = ext.MaxPoint.Y; + MaxZ = ext.MaxPoint.Z; + Extents3d = ext; + } + + /// + /// 包围盒信息2D构造 + /// + /// 包围盒 + public BoundingInfo(Extents2d ext) + { + MinX = ext.MinPoint.X; + MinY = ext.MinPoint.Y; + MinZ = 0; + MaxX = ext.MaxPoint.X; + MaxY = ext.MaxPoint.Y; + MaxZ = 0; + var pt1 = new Point3d(MinX, MinY, 0); + var pt9 = new Point3d(MaxX, MaxY, 0); + Extents3d = new Extents3d(pt1, pt9); + } + + #endregion + + /// + /// 重写ToString + /// + /// 返回MinPoint,MaxPoint坐标 + public override string ToString() + { + return Extents3d.ToString(); + } + + /// + /// 移动包围盒 + /// + /// 基点 + /// 目标点 + public void Move(Point3d pt1, Point3d pt2) + { + var ve = pt1 - pt2; + MinX -= ve.X; + MinY -= ve.Y; + MinZ -= ve.Z; + MaxX -= ve.X; + MaxY -= ve.Y; + MaxZ -= ve.Z; + } +} \ No newline at end of file diff --git a/IFoxCAD.Cad/ExtensionMethod/Entity/CircleEx.cs b/IFoxCAD.Cad/ExtensionMethod/Entity/CircleEx.cs new file mode 100644 index 0000000..d0fba8a --- /dev/null +++ b/IFoxCAD.Cad/ExtensionMethod/Entity/CircleEx.cs @@ -0,0 +1,57 @@ +namespace IFoxCAD.Cad; + +/// +/// 圆扩展类 +/// +public static class CircleEx +{ + /// + /// 两点创建圆(两点中点为圆心) + /// + /// 起点 + /// 终点 + /// + public static Circle CreateCircle(Point3d startPoint, Point3d endPoint) + { + Circle circle = new(); + circle.SetDatabaseDefaults(); + circle.Center = startPoint.GetMidPointTo(endPoint); + circle.Radius = startPoint.DistanceTo(endPoint) * 0.5; + return circle; + } + + /// + /// 三点法创建圆(失败则返回Null) + /// + /// 第一点 + /// 第二点 + /// 第三点 + /// + public static Circle? CreateCircle(Point3d pt1, Point3d pt2, Point3d pt3) + { + // 先判断三点是否共线,得到pt1点指向pt2、pt2点的矢量 + var va = pt2 - pt1; + var vb = pt3 - pt2; + // 如两矢量夹角为0或180度(π弧度),则三点共线. + if (va.GetAngleTo(vb) == 0 | va.GetAngleTo(vb).Equals(Math.PI)) + return null; + + // 创建一个几何类的圆弧对象 + CircularArc3d geArc = new(pt1, pt2, pt3); + return geArc.ToCircle(); + } + + /// + /// 通过圆心,半径绘制圆形 + /// + /// 圆心 + /// 半径 + /// 法向量的X + /// 法向量的Y + /// 法向量的Z + /// + public static Circle CreateCircle(Point3d center, double radius, double vex = 0, double vey = 0, double vez = 1) + { + return new Circle(center, new Vector3d(vex, vey, vez), radius); // 平面法向量XY方向 + } +} \ No newline at end of file diff --git a/IFoxCAD.Cad/ExtensionMethod/Entity/EntityBoundingInfo.cs b/IFoxCAD.Cad/ExtensionMethod/Entity/EntityBoundingInfo.cs new file mode 100644 index 0000000..a92534d --- /dev/null +++ b/IFoxCAD.Cad/ExtensionMethod/Entity/EntityBoundingInfo.cs @@ -0,0 +1,231 @@ +namespace IFoxCAD.Cad; + +/// +/// 获取实体包围盒信息方法 +/// +internal static class EntityBoundingInfo +{ + + /// + /// 获取包围盒信息 + /// + /// 包围盒 + /// 包围盒信息 + public static BoundingInfo? GetBoundingInfo(this Extents3d ext) + { + return new(ext); + } + /// + /// 获取多行文本的正交包围盒 + /// + /// 多行文本 + /// 包围盒 + static Extents3d GetMTextBox(MText mText) + { + var ext = new Extents3d(); + foreach (var p in GetMTextBoxCorners(mText)) + { + ext.AddPoint(p); + } + return ext; + } + /// + /// 获取块的包围盒 + /// + /// 实体 + /// + /// + static void GetBlockBox(this Entity en, ref Extents3d ext, ref Matrix3d mat) + { + if (en is BlockReference block) + { + var matins = mat * block.BlockTransform; + if (block.BlockTableRecord.GetObject() is BlockTableRecord btr) + foreach (var id in btr) + { + if (id.GetObject() is Entity ent1) + { + if (ent1.Visible != true) + continue; + if (ent1 is AttributeDefinition att) + { + if (!att.Constant || att.Invisible) + continue; + } + GetBlockBox(ent1, ref ext, ref matins); + } + } + if (block.AttributeCollection.Count > 0) + { + foreach (var att in block.GetAttributes()) + { + if (!att.Invisible && att.Visible) + GetBlockBox(att, ref ext, ref mat); + } + } + } + else + { + if (mat.IsUniscaledOrtho()) + { + using (var ent1 = en.GetTransformedCopy(mat)) + { + if (ext.IsEmptyExt()) + { + //var e = ent1.GetEntityBox(); + var e = GetEntityBoxEx(ent1); + if (e.HasValue) + ext = e.Value; + } + else + { + //var e = ent1.GetEntityBox(); + var e = GetEntityBoxEx(ent1); + if (e.HasValue) + ext.AddExtents(e.Value); + } + } + } + else + { + //var e = en.GetEntityBox(); + var e = GetEntityBoxEx(en); + if (e.HasValue) + { + Extents3d entext = e.Value; + entext.TransformBy(mat); + if (ext.IsEmptyExt()) + ext = entext; + else + ext.AddExtents(entext); + } + return; + } + } + return; + } + /// + /// 获取多行文字最小包围盒4点坐标 + /// + /// 多行文本 + /// 最小包围盒4点坐标 + public static Point3d[] GetMTextBoxCorners(MText mtext) + { + double width = mtext.ActualWidth; + double height = mtext.ActualHeight; + Point3d point1, point2; + switch (mtext.Attachment) + { + case AttachmentPoint.TopLeft: + default: + point1 = new Point3d(0.0, -height, 0.0); + point2 = new Point3d(width, 0.0, 0.0); + break; + case AttachmentPoint.TopCenter: + point1 = new Point3d(-width * 0.5, -height, 0.0); + point2 = new Point3d(width * 0.5, 0.0, 0.0); + break; + case AttachmentPoint.TopRight: + point1 = new Point3d(-width, -height, 0.0); + point2 = new Point3d(0.0, 0.0, 0.0); + break; + case AttachmentPoint.MiddleLeft: + point1 = new Point3d(0.0, -height * 0.5, 0.0); + point2 = new Point3d(width, height * 0.5, 0.0); + break; + case AttachmentPoint.MiddleCenter: + point1 = new Point3d(-width * 0.5, -height * 0.5, 0.0); + point2 = new Point3d(width * 0.5, height * 0.5, 0.0); + break; + case AttachmentPoint.MiddleRight: + point1 = new Point3d(-width, -height * 0.5, 0.0); + point2 = new Point3d(0.0, height * 0.5, 0.0); + break; + case AttachmentPoint.BottomLeft: + point1 = new Point3d(0.0, 0.0, 0.0); + point2 = new Point3d(width, height, 0.0); + break; + case AttachmentPoint.BottomCenter: + point1 = new Point3d(-width * 0.5, 0.0, 0.0); + point2 = new Point3d(width * 0.5, height, 0.0); + break; + case AttachmentPoint.BottomRight: + point1 = new Point3d(-width, 0.0, 0.0); + point2 = new Point3d(0.0, height, 0.0); + break; + } + + var xform = + Matrix3d.Displacement(mtext.Location.GetAsVector()) * + Matrix3d.Rotation(mtext.Rotation, mtext.Normal, Point3d.Origin) * + Matrix3d.PlaneToWorld(new Plane(Point3d.Origin, mtext.Normal)); + + return new[] + { + point1.TransformBy(xform), + new Point3d(point2.X, point1.Y, 0.0).TransformBy(xform), + point2.TransformBy(xform), + new Point3d(point1.X, point2.Y, 0.0).TransformBy(xform) + }; + } + /// + /// 获取实体包围盒 + /// + /// 实体 + /// 包围盒 + public static Extents3d? GetEntityBoxEx(Entity ent) + { + Extents3d? ext = null; + switch (ent) + { + case Spline spl: + ext = spl.ToPolyline().GeometricExtents; + break; + case MText mtext: + ext = GetMTextBox(mtext); + break; + case Table table: + if (table.IsNewObject) + table.GenerateLayout(); + table.RecomputeTableBlock(true); + ext = table.GeometricExtents; + break; + case Dimension dim: + if (dim.IsNewObject) + dim.GenerateLayout(); // 新new的实体生成布局,即可获取包围盒 + dim.RecomputeDimensionBlock(true); + ext = dim.GeometricExtents; + break; + case BlockReference block: + Extents3d blockExt = default; + var mat = Matrix3d.Identity; + block!.GetBlockBox(ref blockExt, ref mat); + if (!blockExt.IsEmptyExt()) + ext = blockExt; + break; + default: + if (ent.Bounds.HasValue) + ext = ent.GeometricExtents; + break; + } + if (ext != null) + //实体不是点时,pass + if (ent is not DBPoint && ext.Value.MinPoint.IsEqualTo(ext.Value.MaxPoint)) + return null; + return ext; + } + + /// + /// 判断包围盒是否有效 + /// + /// 包围盒 + /// + static bool IsEmptyExt(this Extents3d ext) + { + if (ext.MinPoint.DistanceTo(ext.MaxPoint) < Tolerance.Global.EqualPoint) + return true; + else + return false; + } + +} \ No newline at end of file diff --git a/IFoxCAD.Cad/ExtensionMethod/Entity/EntityEx.cs b/IFoxCAD.Cad/ExtensionMethod/Entity/EntityEx.cs new file mode 100644 index 0000000..1f50541 --- /dev/null +++ b/IFoxCAD.Cad/ExtensionMethod/Entity/EntityEx.cs @@ -0,0 +1,164 @@ +namespace IFoxCAD.Cad; + +/// +/// 实体图元扩展类 +/// +public static class EntityEx +{ + #region 实体线性变换 + + /// + /// 移动实体 + /// + /// 实体 + /// 基点 + /// 目标点 + public static void Move(this Entity ent, Point3d from, Point3d to) + { + Move(ent, to - from); + } + + /// + /// 移动实体 + /// + /// 实体 + /// 向量 + public static void Move(this Entity ent, Vector3d vector) + { + using (ent.ForWrite()) + { + ent.TransformBy(Matrix3d.Displacement(vector)); + } + } + + /// + /// 缩放实体 + /// + /// 实体 + /// 缩放基点坐标 + /// 缩放比例 + public static void Scale(this Entity ent, Point3d center, double scaleValue) + { + using (ent.ForWrite()) + { + ent.TransformBy(Matrix3d.Scaling(scaleValue, center)); + } + } + + /// + /// 旋转实体 + /// + /// 实体 + /// 旋转中心 + /// 转角,弧度制,正数为顺时针 + /// 旋转平面的法向矢量 + public static void Rotation(this Entity ent, Point3d center, double angle, Vector3d normal) + { + using (ent.ForWrite()) + { + ent.TransformBy(Matrix3d.Rotation(angle, normal, center)); + } + } + + /// + /// 在XY平面内旋转实体 + /// + /// 实体 + /// 旋转中心 + /// 转角,弧度制,正数为顺时针 + public static void Rotation(this Entity ent, Point3d center, double angle) + { + using (ent.ForWrite()) + { + ent.TransformBy(Matrix3d.Rotation(angle, Vector3d.ZAxis.TransformBy(ent.Ecs), center)); + } + } + + /// + /// 按对称轴镜像实体 + /// + /// 实体 + /// 对称轴起点 + /// 对称轴终点 + public static void Mirror(this Entity ent, Point3d startPoint, Point3d endPoint) + { + using (ent.ForWrite()) + { + using var line3d = new Line3d(startPoint, endPoint); + ent.TransformBy(Matrix3d.Mirroring(line3d)); + } + } + + /// + /// 按对称面镜像实体 + /// + /// 实体 + /// 对称平面 + public static void Mirror(this Entity ent, Plane plane) + { + using (ent.ForWrite()) + { + ent.TransformBy(Matrix3d.Mirroring(plane)); + } + } + + /// + /// 按对称点镜像实体 + /// + /// 实体 + /// 对称点 + public static void Mirror(this Entity ent, Point3d basePoint) + { + using (ent.ForWrite()) + { + ent.TransformBy(Matrix3d.Mirroring(basePoint)); + } + } + + #endregion + + #region 实体范围 + + /// + /// 获取实体集合的范围 + /// + /// 实体迭代器 + /// 实体集合的范围 + public static Extents3d GetExtents(this IEnumerable ents) + { + var ext = new Extents3d(); + foreach (var item in ents) + { + var e = item.GetBoundingBoxEx(); + if (e.HasValue) + ext.AddExtents(e.Value.Extents3d); + } + + return ext; + } + + #endregion + + + /// + /// 获取图元包围盒 + /// + /// + /// 包围盒信息 + public static BoundingInfo? GetBoundingBoxEx(this Entity ent) + { + return EntityBoundingInfo.GetEntityBoxEx(ent)?.GetBoundingInfo(); + } + + /// + /// 获取拉伸点 + /// + /// 实体 + /// 点集 + public static List GetStretchPoints(this Entity ent) + { + using var p3dc = new Point3dCollection(); + ent.GetStretchPoints(p3dc); + return p3dc.Cast().ToList(); + } +} \ No newline at end of file diff --git a/IFoxCAD.Cad/ExtensionMethod/Geomerty/Curve2dEx.cs b/IFoxCAD.Cad/ExtensionMethod/Geomerty/Curve2dEx.cs new file mode 100644 index 0000000..8dec36b --- /dev/null +++ b/IFoxCAD.Cad/ExtensionMethod/Geomerty/Curve2dEx.cs @@ -0,0 +1,299 @@ +// ReSharper disable SuggestVarOrType_SimpleTypes + +namespace IFoxCAD.Cad; + +/// +/// 二维解析类曲线转换为二维实体曲线扩展类 +/// +public static class Curve2dEx +{ + private static readonly Plane _planeCache = new(); + + #region Curve2d + + /// + /// 按矩阵转换Ge2d曲线为Db曲线 + /// + /// Ge2d曲线 + /// 曲线转换矩阵 + /// Db曲线 + public static Curve? ToCurve(this Curve2d curve, Matrix3d mat) + { + return curve switch + { + LineSegment2d li => ToCurve(li, mat), + NurbCurve2d nu => ToCurve(nu, mat), + EllipticalArc2d el => ToCurve(el, mat), + CircularArc2d ci => ToCurve(ci, mat), + PolylineCurve2d po => ToCurve(po, mat), + Line2d l2 => ToCurve(l2, mat), + CompositeCurve2d co => ToCurve(co, mat), + _ => null + }; + } + + #endregion Curve2d + + #region CircularArc2d + + /// + /// 判断点是否位于圆内及圆上 + /// + /// 二维解析类圆弧对象 + /// 二维点 + /// 位于圆内及圆上返回 ,反之返回 + public static bool IsIn(this CircularArc2d ca2d, Point2d pnt) + { + return ca2d.IsOn(pnt) || ca2d.IsInside(pnt); + } + + /// + /// 将二维解析类圆弧转换为实体圆或者圆弧,然后进行矩阵变换 + /// + /// 二维解析类圆弧对象 + /// 变换矩阵 + /// 实体圆或者圆弧 + public static Curve ToCurve(this CircularArc2d ca2d, Matrix3d mat) + { + Curve c = ToCurve(ca2d); + c.TransformBy(mat); + return c; + } + + /// + /// 将二维解析类圆弧转换为实体圆或者圆弧 + /// + /// 二维解析类圆弧对象 + /// 实体圆或者圆弧 + public static Curve ToCurve(this CircularArc2d ca2d) + { + if (ca2d.IsClosed()) + return ToCircle(ca2d); + else + return ToArc(ca2d); + } + + /// + /// 将二维解析类圆弧转换为实体圆 + /// + /// 二维解析类圆弧对象 + /// 实体圆 + public static Circle ToCircle(this CircularArc2d c2d) + { + return + new Circle( + new Point3d(_planeCache, c2d.Center), + Vector3d.ZAxis, + c2d.Radius); + } + + /// + /// 将二维解析类圆弧转换为实体圆弧 + /// + /// 二维解析类圆弧对象 + /// 圆弧 + public static Arc ToArc(this CircularArc2d a2d) + { + double startAngle, endAngle; + double refAngle = a2d.ReferenceVector.Angle; + + if (a2d.IsClockWise) + { + startAngle = -a2d.EndAngle + refAngle; + endAngle = -a2d.StartAngle + refAngle; + } + else + { + startAngle = a2d.StartAngle + refAngle; + endAngle = a2d.EndAngle + refAngle; + } + + return + new Arc( + new Point3d(_planeCache, a2d.Center), + Vector3d.ZAxis, + a2d.Radius, + startAngle, + endAngle); + } + + #endregion CircularArc2d + + #region EllipticalArc2d + + // 椭圆弧 + /// + /// 将二维解析类椭圆弧转换为实体椭圆弧,然后进行矩阵变换 + /// + /// 二维解析类椭圆弧对象 + /// 变换矩阵 + /// 实体椭圆弧 + public static Ellipse ToCurve(this EllipticalArc2d ea2d, Matrix3d mat) + { + Ellipse e = ToCurve(ea2d); + e.TransformBy(mat); + return e; + } + + /// + /// 将二维解析类椭圆弧转换为实体椭圆弧 + /// + /// 二维解析类椭圆弧对象 + /// 实体椭圆弧 + public static Ellipse ToCurve(this EllipticalArc2d ea2d) + { + Ellipse ell = new( + new Point3d(_planeCache, ea2d.Center), + Vector3d.ZAxis, + new Vector3d(_planeCache, ea2d.MajorAxis) * ea2d.MajorRadius, + ea2d.MinorRadius / ea2d.MajorRadius, + 0, + Math.PI * 2); + if (!ea2d.IsClosed()) + { + if (ea2d.IsClockWise) + { + ell.StartAngle = -ell.GetAngleAtParameter(ea2d.EndAngle); + ell.EndAngle = -ell.GetAngleAtParameter(ea2d.StartAngle); + } + else + { + ell.StartAngle = ell.GetAngleAtParameter(ea2d.StartAngle); + ell.EndAngle = ell.GetAngleAtParameter(ea2d.EndAngle); + } + } + + return ell; + } + + #endregion EllipticalArc2d + + #region Line2d + + /// + /// 将二维解析类直线转换为实体类构造线 + /// + /// 二维解析类直线 + /// 实体类构造线 + public static Xline ToCurve(this Line2d line2d) + { + return new Xline + { + BasePoint = new Point3d(_planeCache, line2d.PointOnLine), + SecondPoint = new Point3d(_planeCache, line2d.PointOnLine + line2d.Direction) + }; + } + + /// + /// 将二维解析类直线转换为实体类构造线,然后进行矩阵变换 + /// + /// 二维解析类直线 + /// 变换矩阵 + /// 实体类构造线 + public static Xline ToCurve(this Line2d line2d, Matrix3d mat) + { + Xline xl = ToCurve(line2d); + xl.TransformBy(mat); + return xl; + } + + /// + /// 将二维解析类构造线转换为二维解析类线段 + /// + /// 二维解析类构造线 + /// 起点参数 + /// 终点参数 + /// 二维解析类线段 + public static LineSegment2d ToLineSegment2d(this Line2d line2d, double fromParameter, double toParameter) + { + return + new LineSegment2d + ( + line2d.EvaluatePoint(fromParameter), + line2d.EvaluatePoint(toParameter) + ); + } + + #endregion Line2d + + #region LineSegment2d + + /// + /// 将二维解析类线段转换为实体类直线,并进行矩阵变换 + /// + /// 二维解析类线段 + /// 变换矩阵 + /// 实体类直线 + public static Line ToCurve(this LineSegment2d ls2d, Matrix3d mat) + { + Line l = ToCurve(ls2d); + l.TransformBy(mat); + return l; + } + + /// + /// 将二维解析类线段转换为实体类直线 + /// + /// 二维解析类线段 + /// 实体类直线 + public static Line ToCurve(this LineSegment2d ls2d) + { + return + new Line( + new Point3d(_planeCache, ls2d.StartPoint), + new Point3d(_planeCache, ls2d.EndPoint)); + } + + #endregion LineSegment2d + + #region NurbCurve2d + + /// + /// 将二维解析类NURB曲线转换为实体类样条曲线,并进行矩阵变换 + /// + /// 二维解析类NURB曲线 + /// 变换矩阵 + /// 实体类样条曲线 + public static Spline ToCurve(this NurbCurve2d nc2d, Matrix3d mat) + { + Spline spl = ToCurve(nc2d); + spl.TransformBy(mat); + return spl; + } + + /// + /// 将二维解析类NURB曲线转换为实体类样条曲线 + /// + /// 二维解析类NURB曲线 + /// 实体类样条曲线 + public static Spline ToCurve(this NurbCurve2d nc2d) + { + using Point3dCollection ctlPts = new(); + for (int i = 0; i < nc2d.NumControlPoints; i++) + ctlPts.Add(new Point3d(_planeCache, nc2d.GetControlPointAt(i))); + + DoubleCollection knots = new(); + for (int i = 0; i < nc2d.Knots.Count; i++) + knots.Add(nc2d.Knots[i]); + + DoubleCollection weights = new(); + for (int i = 0; i < nc2d.NumWeights; i++) + weights.Add(nc2d.GetWeightAt(i)); + + NurbCurve2dData nurbCurve2dData = nc2d.DefinitionData; + + return + new Spline( + nurbCurve2dData.Degree, + nurbCurve2dData.Rational, + nc2d.IsClosed(), + nurbCurve2dData.Periodic, + ctlPts, + knots, + weights, + 0, + nc2d.Knots.Tolerance) { Type = SplineType.FitPoints }; + } + + #endregion NurbCurve2d +} \ No newline at end of file diff --git a/IFoxCAD.Cad/ExtensionMethod/Geomerty/Curve3dEx.cs b/IFoxCAD.Cad/ExtensionMethod/Geomerty/Curve3dEx.cs new file mode 100644 index 0000000..ac8b192 --- /dev/null +++ b/IFoxCAD.Cad/ExtensionMethod/Geomerty/Curve3dEx.cs @@ -0,0 +1,564 @@ +// ReSharper disable SuggestVarOrType_SimpleTypes + +namespace IFoxCAD.Cad; + +/// +/// 三维解析类曲线转换为三维实体曲线扩展类 +/// +public static class Curve3dEx +{ + /// + /// 判断两个浮点数是否相等 + /// + /// 容差 + /// 第一个数 + /// 第二个数 + /// 两个数的差值的绝对值小于容差返回 ,反之返回 + [MethodImpl] + public static bool IsEqualPoint(this Tolerance tol, double d1, double d2) + { + return Math.Abs(d1 - d2) < tol.EqualPoint; + } + + #region Curve3d + + /// + /// 获取三维解析类曲线(自交曲线)的交点参数 + /// + /// 三维解析类曲线 + /// 是否排序 + /// 曲线参数的列表 + public static List GetParamsAtIntersectionPoints(this Curve3d c3d, bool sort = true) + { + CurveCurveIntersector3d cci = new(c3d, c3d, Vector3d.ZAxis); + List pars = []; + for (int i = 0; i < cci.NumberOfIntersectionPoints; i++) + pars.AddRange(cci.GetIntersectionParameters(i)); + if (sort) + pars.Sort(); + return pars; + } + + /// + /// 获取三维解析类子曲线 + /// + /// 三维解析类曲线 + /// 子段曲线起点参数 + /// 子段曲线终点参数 + /// 三维解析类曲线 + public static Curve3d GetSubCurve(this Curve3d curve, double from, double to) + { + Interval inter = curve.GetInterval(); + bool atStart = Tolerance.Global.IsEqualPoint(inter.LowerBound, from); + bool atEnd = Tolerance.Global.IsEqualPoint(inter.UpperBound, to); + if (atStart && atEnd) + return (Curve3d)curve.Clone(); + if (curve is NurbCurve3d) + { + if (from < to) + { + NurbCurve3d clone = (NurbCurve3d)curve.Clone(); + if (atStart || atEnd) + { + clone.HardTrimByParams(from, to); + return clone; + } + else + { + clone.HardTrimByParams(inter.LowerBound, to); + clone.HardTrimByParams(from, to); + return clone; + } + } + else + { + NurbCurve3d clone1 = (NurbCurve3d)curve.Clone(); + clone1.HardTrimByParams(from, inter.UpperBound); + NurbCurve3d clone2 = (NurbCurve3d)curve.Clone(); + clone2.HardTrimByParams(inter.LowerBound, to); + clone1.JoinWith(clone2); + return clone1; + } + } + else + { + Curve3d clone = (Curve3d)curve.Clone(); + clone.SetInterval(new Interval(from, to, Tolerance.Global.EqualPoint)); + return clone; + } + } + + /// + /// 将三维解析类曲线转换为三维实体类曲线 + /// + /// 三维解析类曲线 + /// 三维实体类曲线 + public static Curve? ToCurve(this Curve3d curve) + { + return curve switch + { + CompositeCurve3d co => ToCurve(co), + LineSegment3d li => ToCurve(li), + EllipticalArc3d el => ToCurve(el), + CircularArc3d ci => ToCurve(ci), + NurbCurve3d nu => ToCurve(nu), + PolylineCurve3d pl => ToCurve(pl), + Line3d l3 => ToCurve(l3), + _ => null + }; + } + + /// + /// 将三维解析类曲线转换为三维解析类Nurb曲线 + /// + /// 三维解析类曲线 + /// 三维解析类Nurb曲线 + public static NurbCurve3d? ToNurbCurve3d(this Curve3d curve) + { + return curve switch + { + LineSegment3d line => new NurbCurve3d(line), + EllipticalArc3d el => new NurbCurve3d(el), + CircularArc3d cir => new NurbCurve3d(ToEllipticalArc3d(cir)), + NurbCurve3d nur => nur, + PolylineCurve3d pl => new NurbCurve3d(3, pl, false), + _ => null + }; + } + + #endregion Curve3d + + #region CompositeCurve3d + + /// + /// 判断是否为圆和椭圆 + /// + /// 三维解析类曲线 + /// 完整圆及完整的椭圆返回 ,反之返回 + public static bool IsCircular(this Curve3d curve) + { + return curve switch + { + CircularArc3d or EllipticalArc3d => curve.IsClosed(), + _ => false + }; + } + + /// + /// 将三维复合曲线按曲线参数分割 + /// + /// 三维复合曲线 + /// 曲线参数列表 + /// 三维复合曲线列表 + public static List? GetSplitCurves(this CompositeCurve3d c3d, List pars) + { + // 曲线参数剔除重复的 + if (pars.Count > 0) + { + pars.Sort(); + for (int i = pars.Count - 1; i > 0; i--) + if (Tolerance.Global.IsEqualPoint(pars[i], pars[i - 1])) + pars.RemoveAt(i); + } + + if (pars.Count == 0) + return null; + + // 这个是曲线参数类 + var inter = c3d.GetInterval(); + // 曲线们 + var c3ds = c3d.GetCurves(); + if (c3ds.Length == 1 && c3ds[0].IsClosed()) + { + // 闭合曲线不允许打断于一点 + if (pars.Count < 2) + return null; + + // 如果包含起点 + if (Tolerance.Global.IsEqualPoint(pars[0], inter.LowerBound)) + { + pars[0] = inter.LowerBound; + // 又包含终点,去除终点 + if (Tolerance.Global.IsEqualPoint(pars[^1], inter.UpperBound)) + { + pars.RemoveAt(pars.Count - 1); + if (pars.Count == 1) + return null; + } + } + else if (Tolerance.Global.IsEqualPoint(pars[^1], inter.UpperBound)) + { + pars[^1] = inter.UpperBound; + } + + // 加入第一点以支持反向打断 + pars.Add(pars[0]); + } + else + { + // 非闭合曲线加入起点和终点 + if (Tolerance.Global.IsEqualPoint(pars[0], inter.LowerBound)) + pars[0] = inter.LowerBound; + else + pars.Insert(0, inter.LowerBound); + if (Tolerance.Global.IsEqualPoint(pars[^1], inter.UpperBound)) + pars[^1] = inter.UpperBound; + else + pars.Add(inter.UpperBound); + } + + List curves = new(); + List cc3ds = new(); + for (int i = 0; i < pars.Count - 1; i++) + { + cc3ds.Clear(); + // 复合曲线参数转换到包含曲线参数 + var cp1 = c3d.GlobalToLocalParameter(pars[i]); + var cp2 = c3d.GlobalToLocalParameter(pars[i + 1]); + if (cp1.SegmentIndex == cp2.SegmentIndex) + { + cc3ds.Add( + c3ds[cp1.SegmentIndex].GetSubCurve( + cp1.LocalParameter, + cp2.LocalParameter)); + } + else + { + inter = c3ds[cp1.SegmentIndex].GetInterval(); + cc3ds.Add( + c3ds[cp1.SegmentIndex].GetSubCurve( + cp1.LocalParameter, + inter.UpperBound)); + + for (int j = cp1.SegmentIndex + 1; j < cp2.SegmentIndex; j++) + cc3ds.Add((Curve3d)c3ds[j].Clone()); + + inter = c3ds[cp2.SegmentIndex].GetInterval(); + cc3ds.Add( + c3ds[cp2.SegmentIndex].GetSubCurve( + inter.LowerBound, + cp2.LocalParameter)); + } + + curves.Add(new(cc3ds.ToArray())); + } + + // 封闭多段线 口口 并排形状,第二个口切割不成功,注释下面就成功了 + //if (c3d.IsClosed() && c3ds.Length > 1) + //{ + // var cus1 = curves[^1].GetCurves(); + // var cus2 = curves[0].GetCurves(); + // var cs = cus1.Combine2(cus2); + // curves[^1] = new(cs); + // curves.RemoveAt(0); + //} + return curves; + } + + /// + /// 将复合曲线转换为实体类曲线 + /// + /// 三维复合曲线 + /// 实体曲线 + public static Curve? ToCurve(this CompositeCurve3d curve) + { + Curve3d[] cs = curve.GetCurves(); + if (cs.Length == 0) + return null; + if (cs.Length == 1) + return ToCurve(cs[0]); + + bool hasNurb = false; + + foreach (var c in cs) + { + if (c is not (NurbCurve3d or EllipticalArc3d)) + continue; + hasNurb = true; + break; + } + + if (hasNurb) + { + var nc3d = cs[0].ToNurbCurve3d(); + for (var i = 1; i < cs.Length; i++) + nc3d?.JoinWith(cs[i].ToNurbCurve3d()); + return nc3d?.ToCurve(); + } + + return ToPolyline(curve); + } + + /// + /// 将三维复合曲线转换为实体类多段线 + /// + /// 三维复合曲线 + /// 实体类多段线 + public static Polyline ToPolyline(this CompositeCurve3d cc3d) + { + Polyline pl = new(); + pl.SetDatabaseDefaults(); + pl.Elevation = cc3d.StartPoint[2]; + + Plane plane = pl.GetPlane(); + Point2d endVer = Point2d.Origin; + int i = 0; + foreach (Curve3d c3d in cc3d.GetCurves()) + { + if (c3d is CircularArc3d ca3d) + { + double b = Math.Tan(0.25 * (ca3d.EndAngle - ca3d.StartAngle)) * ca3d.Normal[2]; + pl.AddVertexAt(i, c3d.StartPoint.Convert2d(plane), b, 0, 0); + endVer = c3d.EndPoint.Convert2d(plane); + } + else + { + pl.AddVertexAt(i, c3d.StartPoint.Convert2d(plane), 0, 0, 0); + endVer = c3d.EndPoint.Convert2d(plane); + } + + i++; + } + + pl.AddVertexAt(i, endVer, 0, 0, 0); + return pl; + } + + #endregion CompositeCurve3d + + #region Line3d + + /// + /// 将解析类三维构造线转换为实体类构造线 + /// + /// 解析类三维构造线 + /// 实体类构造线 + public static Xline ToCurve(this Line3d line3d) + { + return + new Xline + { + BasePoint = line3d.PointOnLine, + SecondPoint = line3d.PointOnLine + line3d.Direction + }; + } + + /// + /// 将三维解析类构造线转换为三维解析类线段 + /// + /// 三维解析类构造线 + /// 起点参数 + /// 终点参数 + /// 三维解析类线段 + public static LineSegment3d ToLineSegment3d(this Line3d line3d, double fromParameter, double toParameter) + { + return + new LineSegment3d + ( + line3d.EvaluatePoint(fromParameter), + line3d.EvaluatePoint(toParameter) + ); + } + + #endregion Line3d + + #region LineSegment3d + + /// + /// 将三维解析类线段转换为实体类直线 + /// + /// 三维解析类线段 + /// 实体类直线 + public static Line ToCurve(this LineSegment3d lineSeg3d) + { + return new Line(lineSeg3d.StartPoint, lineSeg3d.EndPoint); + } + + #endregion LineSegment3d + + #region CircularArc3d + + /// + /// 将三维解析类圆/弧转换为实体圆/弧 + /// + /// 三维解析类圆/弧 + /// 实体圆/弧 + public static Curve ToCurve(this CircularArc3d ca3d) + { + if (ca3d.IsClosed()) + { + return ToCircle(ca3d); + } + else + { + return ToArc(ca3d); + } + } + + /// + /// 将三维解析类圆/弧转换为实体圆 + /// + /// 三维解析类圆/弧 + /// 实体圆 + public static Circle ToCircle(this CircularArc3d ca3d) => + new(ca3d.Center, ca3d.Normal, ca3d.Radius); + + /// + /// 将三维解析类圆/弧转换为实体圆弧 + /// + /// 三维解析类圆/弧 + /// 实体圆弧 + public static Arc ToArc(this CircularArc3d ca3d) + { + // 必须新建,而不能直接使用GetPlane()获取 + double angle = ca3d.ReferenceVector.AngleOnPlane(new Plane(ca3d.Center, ca3d.Normal)); + return new Arc(ca3d.Center, ca3d.Normal, ca3d.Radius, ca3d.StartAngle + angle, ca3d.EndAngle + angle); + } + + /// + /// 将三维解析类圆/弧转换为三维解析类椭圆弧 + /// + /// 三维解析类圆/弧 + /// 三维解析类椭圆弧 + public static EllipticalArc3d ToEllipticalArc3d(this CircularArc3d ca3d) + { + Vector3d zAxis = ca3d.Normal; + Vector3d xAxis = ca3d.ReferenceVector; + Vector3d yAxis = zAxis.CrossProduct(xAxis); + + return + new EllipticalArc3d( + ca3d.Center, + xAxis, + yAxis, + ca3d.Radius, + ca3d.Radius, + ca3d.StartAngle, + ca3d.EndAngle); + } + + /// + /// 将三维解析类圆/弧转换为三维解析类Nurb曲线 + /// + /// 三维解析类圆/弧 + /// 三维解析类Nurb曲线 + public static NurbCurve3d ToNurbCurve3d(this CircularArc3d ca3d) + { + EllipticalArc3d ea3d = ToEllipticalArc3d(ca3d); + NurbCurve3d nc3d = new(ea3d); + return nc3d; + } + + #endregion CircularArc3d + + #region EllipticalArc3d + + /// + /// 将三维解析类椭圆弧转换为实体类椭圆弧 + /// + /// 三维解析类椭圆弧 + /// 实体类椭圆弧 + public static Ellipse ToCurve(this EllipticalArc3d ea3d) + { + Ellipse ell = + new( + ea3d.Center, + ea3d.Normal, + ea3d.MajorAxis * ea3d.MajorRadius, + ea3d.MinorRadius / ea3d.MajorRadius, + 0, + Math.PI * 2); + // Ge椭圆角度就是Db椭圆的参数 + if (!ea3d.IsClosed()) + { + ell.StartAngle = ell.GetAngleAtParameter(ea3d.StartAngle); + ell.EndAngle = ell.GetAngleAtParameter(ea3d.EndAngle); + } + + return ell; + } + + #endregion EllipticalArc3d + + #region NurbCurve3d + + /// + /// 将三维解析类Nurb曲线转换为实体类样条曲线 + /// + /// 三维解析类Nurb曲线 + /// 实体类样条曲线 + public static Spline ToCurve(this NurbCurve3d nc3d) + { + Spline spl; + if (nc3d.HasFitData) + { + NurbCurve3dFitData fData = nc3d.FitData; + if (fData.TangentsExist) + { + spl = new Spline( + fData.FitPoints, + fData.StartTangent, + fData.EndTangent, + nc3d.Order, + fData.FitTolerance.EqualPoint); + } + else + { + spl = new Spline( + fData.FitPoints, + nc3d.Order, + fData.FitTolerance.EqualPoint); + } + } + else + { + DoubleCollection knots = new(); + foreach (double knot in nc3d.Knots) + knots.Add(knot); + + NurbCurve3dData nurbCurve3dData = nc3d.DefinitionData; + + spl = new Spline( + nurbCurve3dData.Degree, + nurbCurve3dData.Rational, + nc3d.IsClosed(), + nurbCurve3dData.Periodic, + nurbCurve3dData.ControlPoints, + knots, + nurbCurve3dData.Weights, + Tolerance.Global.EqualPoint, + nurbCurve3dData.Knots.Tolerance); + } + + return spl; + } + + #endregion NurbCurve3d + + #region PolylineCurve3d + + /// + /// 将三维解析类多段线转换为实体类三维多段线 + /// + /// 三维解析类多段线 + /// 实体类三维多段线 + public static Polyline3d ToCurve(this PolylineCurve3d pl3d) + { + using Point3dCollection pt3dCollection = new(); + + for (var i = 0; i < pl3d.NumberOfControlPoints; i++) + pt3dCollection.Add(pl3d.ControlPointAt(i)); + + bool closed = false; + var n = pt3dCollection.Count - 1; + if (pt3dCollection[0] == pt3dCollection[n]) + { + pt3dCollection.RemoveAt(n); + closed = true; + } + + return new Polyline3d(Poly3dType.SimplePoly, pt3dCollection, closed); + } + + #endregion PolylineCurve3d +} \ No newline at end of file diff --git a/IFoxCAD.Cad/ExtensionMethod/Geomerty/PointEx.cs b/IFoxCAD.Cad/ExtensionMethod/Geomerty/PointEx.cs new file mode 100644 index 0000000..7b06d90 --- /dev/null +++ b/IFoxCAD.Cad/ExtensionMethod/Geomerty/PointEx.cs @@ -0,0 +1,260 @@ +namespace IFoxCAD.Cad; + +/// +/// 点 +/// +public static class PointEx +{ + /// + /// 获取点的hash字符串,同时可以作为pt的字符串表示 + /// + /// 点 + /// 指示计算几维坐标的标志,1为计算x,2为计算x,y,其他为计算x,y,z + /// 保留的小数位数 + /// hash字符串 + public static string GetHashString(this Point3d pt, int xyz = 3, int decimalRetain = 6) + { + var de = $"f{decimalRetain}"; + return xyz switch + { + 1 => $"({pt.X.ToString(de)})", + 2 => $"({pt.X.ToString(de)},{pt.Y.ToString(de)})", + _ => $"({pt.X.ToString(de)},{pt.Y.ToString(de)},{pt.Z.ToString(de)})" + }; + } + + // 为了频繁触发所以弄个缓存 + static Plane? _planeCache; + + /// + /// 两点计算弧度范围0到2Pi + /// + /// 起点 + /// 终点 + /// 方向 + /// 弧度值 + public static double GetAngle(this Point3d startPoint, Point3d endPoint, Vector3d? direction = null) + { + if (direction != null) + _planeCache = new Plane(new Point3d(), direction.Value); + if (_planeCache == null) + _planeCache = new Plane(new Point3d(), Vector3d.ZAxis); + return startPoint.GetVectorTo(endPoint).AngleOnPlane(_planeCache); + } + + /// + /// 两点计算弧度范围0到2Pi + /// + /// 起点 + /// 终点 + /// 弧度值 + public static double GetAngle(this Point2d startPoint, Point2d endPoint) + { + return startPoint.GetVectorTo(endPoint).Angle; + } + + /// + /// 获取中点 + /// + /// + /// + /// + public static Point2d GetMidPointTo(this Point2d a, Point2d b) + { + // (p1 + p2) / 2; // 溢出风险 + return new Point2d(a.X * 0.5 + b.X * 0.5, + a.Y * 0.5 + b.Y * 0.5); + } + + /// + /// 获取两个点之间的中点 + /// + /// 第一点 + /// 第二点 + /// 返回两个点之间的中点 + public static Point3d GetMidPointTo(this Point3d pt1, Point3d pt2) + { + return new(pt1.X * 0.5 + pt2.X * 0.5, + pt1.Y * 0.5 + pt2.Y * 0.5, + pt1.Z * 0.5 + pt2.Z * 0.5); + } + + /// + /// Z值归零 + /// + /// 点 + /// 新点 + public static Point3d Z20(this Point3d point) + { + return new Point3d(point.X, point.Y, 0); + } + + /// + /// 将三维点转换为二维点 + /// + /// 三维点 + /// 二维点 + public static Point2d Point2d(this Point3d pt) + { + return new(pt.X, pt.Y); + } + + /// + /// 将三维点集转换为二维点集 + /// + /// 三维点集 + /// 二维点集 + public static IEnumerable Point2d(this IEnumerable pts) + { + return pts.Select(pt => pt.Point2d()); + } + + /// + /// 将二维点转换为三维点 + /// + /// 二维点 + /// Z值 + /// 三维点 + public static Point3d Point3d(this Point2d pt, double z = 0) + { + return new(pt.X, pt.Y, z); + } + + + /// + /// 根据世界坐标计算用户坐标 + /// + /// 基点世界坐标 + /// 基点用户坐标 + /// 目标世界坐标 + /// 坐标网旋转角,按x轴正向逆时针弧度 + /// 目标用户坐标 + public static Point3d TransPoint(this Point3d basePt, Point3d userPt, Point3d transPt, double ang) + { + var transMat = Matrix3d.Displacement(userPt - basePt); + var roMat = Matrix3d.Rotation(-ang, Vector3d.ZAxis, userPt); + return transPt.TransformBy(roMat * transMat); + } + + /// + /// 计算指定距离和角度的点 + /// + /// 本函数仅适用于x-y平面 + /// 基点 + /// 角度,x轴正向逆时针弧度 + /// 距离 + /// 目标点 + public static Point3d Polar(this Point3d pt, double ang, double len) + { + return pt + Vector3d.XAxis.RotateBy(ang, Vector3d.ZAxis) * len; + } + + /// + /// 计算指定距离和角度的点 + /// + /// 本函数仅适用于x-y平面 + /// 基点 + /// 角度,x轴正向逆时针弧度 + /// 距离 + /// 目标点 + public static Point2d Polar(this Point2d pt, double ang, double len) + { + return pt + Vector2d.XAxis.RotateBy(ang) * len; + } + + /// http://www.lee-mac.com/bulgeconversion.html + /// + /// 求凸度,判断三点是否一条直线上 + /// + /// 圆弧起点 + /// 圆弧腰点 + /// 圆弧尾点 + /// 容差 + /// 逆时针为正,顺时针为负 + public static double GetArcBulge(this Point2d arc1, Point2d arc2, Point2d arc3, double tol = 1e-10) + { + var dStartAngle = arc2.GetAngle(arc1); + var dEndAngle = arc2.GetAngle(arc3); + // 求的P1P2与P1P3夹角 + var talAngle = (Math.PI - dStartAngle + dEndAngle) / 2; + // 凸度==拱高/半弦长==拱高比值/半弦长比值 + // 有了比值就不需要拿到拱高值和半弦长值了,因为接下来是相除得凸度 + var bulge = Math.Sin(talAngle) / Math.Cos(talAngle); + + switch (bulge) + { + // 处理精度 + case > 0.9999 and < 1.0001: + bulge = 1; + break; + case < -0.9999 and > -1.0001: + bulge = -1; + break; + default: + { + if (Math.Abs(bulge) < tol) + bulge = 0; + break; + } + } + + return bulge; + } + + /// + /// 求两点在Z平面的距离 + /// + /// 点1 + /// 点2 + /// 距离 + public static double Distance2dTo(this Point3d pt1, Point3d pt2) + { + return new Vector2d(pt2.X - pt1.X, pt2.Y - pt1.Y).Length; + } + + #region 首尾相连 + + /// + /// 首尾相连 + /// + [DebuggerStepThrough] + public static void End2End(this Point2dCollection ptCollection) + { + ArgumentNullEx.ThrowIfNull(ptCollection); + + if (ptCollection.Count == 0 || ptCollection[0].Equals(ptCollection[^1])) // 首尾相同直接返回 + return; + + // 首尾不同,去加一个到最后 + var lst = new Point2d[ptCollection.Count + 1]; + for (int i = 0; i < ptCollection.Count; i++) + lst[i] = ptCollection[i]; + lst[^1] = lst[0]; + + ptCollection.Clear(); + ptCollection.AddRange(lst); + } + + /// + /// 首尾相连 + /// + [DebuggerStepThrough] + public static void End2End(this Point3dCollection ptCollection) + { + ArgumentNullEx.ThrowIfNull(ptCollection); + if (ptCollection.Count == 0 || ptCollection[0].Equals(ptCollection[^1])) // 首尾相同直接返回 + return; + + // 首尾不同,去加一个到最后 + var lst = new Point3d[ptCollection.Count + 1]; + for (int i = 0; i < ptCollection.Count; i++) + lst[i] = ptCollection[i]; + lst[^1] = lst[0]; + + ptCollection.Clear(); + foreach (var t in lst) + ptCollection.Add(t); + } + + #endregion +} \ No newline at end of file diff --git a/IFoxCAD.Cad/ExtensionMethod/ObjectIdEx.cs b/IFoxCAD.Cad/ExtensionMethod/ObjectIdEx.cs index f990f44..e5540d8 100644 --- a/IFoxCAD.Cad/ExtensionMethod/ObjectIdEx.cs +++ b/IFoxCAD.Cad/ExtensionMethod/ObjectIdEx.cs @@ -7,6 +7,22 @@ public static class ObjectIdEx { #region GetObject + /// + /// 获取指定类型对象 + /// + /// 对象id + /// 打开模式 + /// 是否打开已删除对象,默认为不打开 + /// 是否打开锁定图层对象,默认为不打开 + /// 指定类型对象 + public static DBObject GetObject(this ObjectId id, + OpenMode openMode = OpenMode.ForRead, + bool openErased = false, + bool openLockedLayer = false) + { + var tr = DBTrans.GetTopTransaction(id.Database); + return tr.GetObject(id, openMode, openErased, openLockedLayer); + } /// /// 获取指定类型对象 /// diff --git a/IFoxCAD.Cad/ExtensionMethod/RedrawEx.cs b/IFoxCAD.Cad/ExtensionMethod/RedrawEx.cs new file mode 100644 index 0000000..2e42c47 --- /dev/null +++ b/IFoxCAD.Cad/ExtensionMethod/RedrawEx.cs @@ -0,0 +1,200 @@ +namespace IFoxCAD.Cad; +/// +/// 亮显模式 +/// +[Flags] +public enum BrightEntity +{ + /// + /// 块更新 + /// + RecordGraphicsModified = 1, + /// + /// 标注更新 + /// + RecomputeDimensionBlock = 2, + /// + /// 重画 + /// + Draw = 4, + /// + /// 亮显 + /// + Highlight = 8, + /// + /// 亮显取消 + /// + Unhighlight = 16, + /// + /// 显示图元 + /// + VisibleTrue = 32, + /// + /// 隐藏图元 + /// + VisibleFalse = 64, + /// + /// 平移更新,可以令ctrl+z撤回时候保证刷新 + /// + MoveZero = 128, +} +/// +/// 刷新模式 +/// +[Flags] +public enum BrightEditor +{ + /// + /// 刷新屏幕,图元不生成(例如块还是旧的显示) + /// + UpdateScreen = 1, + /// + /// 刷新全图 + /// + Regen = 2, + /// + /// 清空选择集 + /// + SelectionClean = 4, + /// + /// 视口外 + /// + ViewportsFrom = 8, + /// + /// 视口内 + /// + ViewportsIn = 16, +} +/// +/// 重绘扩展 +/// +public static class RedrawEx +{ + /// + /// 刷新屏幕 + /// + /// 编辑器 + /// 图元 + public static void Redraw(this Editor ed, Entity? ent = null) + { + using (ent?.ForWrite()) + { + // 刷新图元 + ent?.Redraw(BrightEntity.Draw | + BrightEntity.RecordGraphicsModified | + BrightEntity.RecomputeDimensionBlock | + BrightEntity.MoveZero); + // 刷新 + ed.Redraw(BrightEditor.UpdateScreen); + } + + + /* + * 我发现命令加 CommandFlags.Redraw 就不需要以下处理了: + * 数据库事务和文档事务不一样,文档事务有刷新函数. + * var doc = Acap.DocumentManager.MdiActiveDocument; + * var ed = doc.Editor; + * var tm = doc.TransactionManager; + * tm.QueueForGraphicsFlush();// 如果在最外层事务结束之前需要更新图形,此句把目前为止所做的更改放入 刷新队列 + * tm.FlushGraphics(); // 将当前 刷新队列 的图形提交到显示器 + * ed.UpdateScreen(); // 仅刷新屏幕,图元不生成(例如块还是旧的显示) + */ + var dm = Acap.DocumentManager; + var doc = dm.MdiActiveDocument; + var tm = doc.TransactionManager; + tm.QueueForGraphicsFlush(); + tm.FlushGraphics(); + + // acad2014及以上要加,立即处理队列上面的消息 + System.Windows.Forms.Application.DoEvents(); + } + + /// + /// 刷新屏幕 + /// + /// 编辑器 + /// 更新的方式 + public static void Redraw(this Editor ed, BrightEditor bright) + { + if ((bright & BrightEditor.UpdateScreen) == BrightEditor.UpdateScreen) + { + // 两个函数底层差不多 + // Acap.UpdateScreen(); + ed.UpdateScreen(); + } + + if ((bright & BrightEditor.Regen) == BrightEditor.Regen) + ed.Regen(); + + if ((bright & BrightEditor.SelectionClean) == BrightEditor.SelectionClean) + ed.SetImpliedSelection(Array.Empty()); + + if ((bright & BrightEditor.ViewportsFrom) == BrightEditor.ViewportsFrom) + ed.UpdateTiledViewportsFromDatabase(); // 更新视口外 + + if ((bright & BrightEditor.ViewportsIn) == BrightEditor.ViewportsIn) + ed.UpdateTiledViewportsInDatabase(); // 更新视口内 + } + + /// + /// 更改图元显示 + /// + /// 图元,调用时候图元必须提权 + /// 更新的方式 + public static void Redraw(this Entity ent, BrightEntity bright) + { + // 调用时候图元必须提权,参数true表示关闭图元后进行UpData,实现局部刷新块. + if ((bright & BrightEntity.RecordGraphicsModified) == BrightEntity.RecordGraphicsModified) + ent.RecordGraphicsModified(true); + + if ((bright & BrightEntity.RecomputeDimensionBlock) == BrightEntity.RecomputeDimensionBlock) + if (ent is Dimension dim) + dim.RecomputeDimensionBlock(true); + + if ((bright & BrightEntity.Draw) == BrightEntity.Draw) + ent.Draw(); + + if ((bright & BrightEntity.Highlight) == BrightEntity.Highlight) + ent.Highlight(); + + if ((bright & BrightEntity.Unhighlight) == BrightEntity.Unhighlight) + ent.Unhighlight(); + + if ((bright & BrightEntity.VisibleTrue) == BrightEntity.VisibleTrue) + ent.Visible = true; + + if ((bright & BrightEntity.VisibleFalse) == BrightEntity.VisibleFalse) + ent.Visible = false; + + // 戴耀辉: + // 删除块内图元的时候需要刷新块, + // 用 RecordGraphicsModified 显示是没有问题, + // 但是 ctrl+z 撤销会有显示问题, + // 所以平移0可以在撤回数据库的时候刷新指定图元 + if ((bright & BrightEntity.MoveZero) == BrightEntity.MoveZero) + ent.Move(Point3d.Origin, Point3d.Origin); + } + + + #region 实体刷新 + /// + /// 刷新实体显示 + /// + /// 实体对象 + [Obsolete("此处已经被RedrawEx代替")] + public static void Flush(this Entity entity) + { + var tr = DBTrans.GetTop(entity.Database); + entity.RecordGraphicsModified(true); + tr.Transaction.TransactionManager.QueueForGraphicsFlush(); + tr.Document?.TransactionManager.FlushGraphics(); + } + + /// + /// 刷新实体显示 + /// + /// 实体id + [Obsolete("此处已经被RedrawEx代替")] + public static void Flush(this ObjectId id) => Flush(id.GetObject()!); + #endregion +} \ No newline at end of file diff --git a/IFoxCAD.Cad/ExtensionMethod/SymbolTableRecordEx.cs b/IFoxCAD.Cad/ExtensionMethod/SymbolTableRecordEx.cs new file mode 100644 index 0000000..f330df3 --- /dev/null +++ b/IFoxCAD.Cad/ExtensionMethod/SymbolTableRecordEx.cs @@ -0,0 +1,364 @@ +namespace IFoxCAD.Cad; + +/// +/// 符号表记录扩展类 +/// +public static class SymbolTableRecordEx +{ + #region 块表记录 + + #region 克隆实体id + + /// + /// 深度克隆id到块表记录 + /// + /// 0x01 此方法不允许是未添加数据库的图元,因此它是id
+ /// 0x02 若为未添加数据库图元,则利用entity.Clone();同时不需要考虑动态块属性,可以使用entity.GetTransformedCopy + ///
+ ///
+ /// 块表记录 + /// + /// 克隆到当前块表记录,相当于原地克隆
+ /// 克隆到目标块表记录内,相当于制作新块 + ///
+ /// + /// 图元id集合,注意所有成员都要在同一个空间中 + /// 返回克隆后的id词典 + public static void DeepCloneEx(this BlockTableRecord btr, ObjectIdCollection objIds, IdMapping maoOut) + { + if (objIds is null || objIds.Count == 0) + throw new ArgumentNullException(nameof(objIds)); + + var db = objIds[0].Database; + using (btr.ForWrite()) + { + try + { + db.DeepCloneObjects(objIds, btr.ObjectId, maoOut, false); + + // 不在此提取,为了此函数被高频调用 + // 获取克隆键值对(旧块名,新块名) + // foreach (ObjectId item in blockIds) + // result.Add(mapping[item].Value); + } + catch + { + // ignored + } + } + } + + /// + /// 深度克隆id到块表记录 + /// + /// 块表记录 + /// 图元id集合 + /// id词典 + public static IdMapping DeepCloneEx(this BlockTableRecord btr, ObjectIdCollection objIds) + { + if (objIds is null || objIds.Count == 0) + throw new ArgumentNullException(nameof(objIds)); + + var db = objIds[0].Database; + IdMapping mapOut = new(); + using (btr.ForWrite()) + { + try + { + db.DeepCloneObjects(objIds, btr.ObjectId, mapOut, false); + + // 不在此提取,为了此函数被高频调用 + // 获取克隆键值对(旧块名,新块名) + // foreach (ObjectId item in blockIds) + // result.Add(mapping[item].Value); + } + catch + { + // ignored + } + } + + return mapOut; + } + + #endregion + + #region 添加实体 + + /// + /// 添加实体对象 + /// + /// 块表记录 + /// 实体 + /// 对象 id + public static ObjectId AddEntity(this BlockTableRecord btr, Entity entity) + { + ObjectId id; + var tr = DBTrans.GetTopTransaction(btr.Database); + using (btr.ForWrite()) + { + id = btr.AppendEntity(entity); + tr.AddNewlyCreatedDBObject(entity, true); + } + + return id; + } + + /// + /// 添加实体集合 + /// + /// 块表记录 + /// 实体集合 + /// 对象 id 列表 + public static IEnumerable AddEntity(this BlockTableRecord btr, IEnumerable ents) + { + var tr = DBTrans.GetTopTransaction(btr.Database); + using (btr.ForWrite()) + { + return ents.Select(ent => + { + var id = btr.AppendEntity(ent); + tr.AddNewlyCreatedDBObject(ent, true); + return id; + }).ToList(); + } + } + + /// + /// 添加多个实体 + /// + /// 块表记录 + /// 实体集合 + /// 对象 id 列表 + public static IEnumerable AddEntity(this BlockTableRecord btr, params Entity[] ents) + { + return btr.AddEntity(ents.ToList()); + } + + #endregion + + #region 获取实体/实体id + + /// + /// 获取块表记录内的指定类型的实体 + /// (此处不会检查id.IsOk()) + /// + /// 实体类型 + /// 块表记录 + /// 打开模式 + /// 是否打开已删除对象,默认为不打开 + /// 是否打开锁定图层对象,默认为不打开 + /// 实体集合 + public static IEnumerable GetEntities(this BlockTableRecord btr, + OpenMode openMode = OpenMode.ForRead, + bool openErased = false, + bool openLockedLayer = false) where T : Entity + { + var rxc = RXObject.GetClass(typeof(T)); + return + btr + .Cast() + .Where(id => id.ObjectClass.IsDerivedFrom(rxc)) + .Select(id => id.GetObject(openMode, openErased, openLockedLayer)) + .OfType(); + } + + /// + /// 按类型获取实体Id + /// + /// 实体类型 + /// 块表记录 + /// 实体Id集合 + public static IEnumerable GetObjectIds(this BlockTableRecord btr) where T : Entity + { + string dxfName = RXClass.GetClass(typeof(T)).DxfName; + return btr.Cast() + .Where(id => id.ObjectClass.DxfName == dxfName); + } + + /// + /// 按类型获取实体Id的分组 + /// + /// 块表记录 + /// 实体Id分组 + public static IEnumerable> GetObjectIds(this BlockTableRecord btr) + { + return btr.Cast() + .GroupBy(id => id.ObjectClass.DxfName); + } + + + /// + /// 获取绘制顺序表 + /// + /// 块表 + /// 开启方式 + /// 是否打开已删除对象,默认为不打开 + /// 是否打开锁定图层对象,默认为不打开 + /// 绘制顺序表 + public static DrawOrderTable GetDrawOrderTable(this BlockTableRecord btr, + OpenMode openMode = OpenMode.ForRead, + bool openErased = false, + bool openLockedLayer = false) + { + var tr = DBTrans.GetTopTransaction(btr.Database); + return (DrawOrderTable)tr.GetObject(btr.DrawOrderTableId, openMode, openErased, openLockedLayer); + } + + #endregion + + #region 插入块参照 + + /// + /// 插入块参照 + /// + /// 块表记录 + /// 插入点 + /// 块名 + /// 块插入比例,默认为1 + /// 块插入旋转角(弧度),默认为0 + /// 属性字典{Tag,Value},默认为null + /// 块参照对象id + public static ObjectId InsertBlock(this BlockTableRecord blockTableRecord, Point3d position, + string blockName, + Scale3d scale = default, + double rotation = default, + Dictionary? atts = null) + { + var tr = DBTrans.GetTop(blockTableRecord.Database); + if (!tr.BlockTable.Has(blockName)) + { + tr.Editor?.WriteMessage($"\n不存在名字为{blockName}的块定义。"); + return ObjectId.Null; + } + + return blockTableRecord.InsertBlock(position, tr.BlockTable[blockName], scale, rotation, atts); + } + + /// + /// 插入块参照 + /// + /// 块表记录 + /// 插入点 + /// 块定义id + /// 块插入比例,默认为1 + /// 块插入旋转角(弧度),默认为0 + /// 属性字典{Tag,Value},默认为null + /// 块参照对象id + public static ObjectId InsertBlock(this BlockTableRecord blockTableRecord, + Point3d position, + ObjectId blockId, + Scale3d scale = default, + double rotation = default, + Dictionary? atts = null) + { + //trans ??= DBTrans.Top.Transaction; + var tr = DBTrans.GetTop(blockTableRecord.Database); + + if (!tr.BlockTable.Has(blockId)) + { + tr.Editor?.WriteMessage($"\n不存在块定义。"); + return ObjectId.Null; + } + + + using var blockRef = new BlockReference(position, blockId); + blockRef.ScaleFactors = scale; + blockRef.Rotation = rotation; + var objectId = blockTableRecord.AddEntity(blockRef); + // 检查块的注释性 + using var ocm = blockTableRecord.Database.ObjectContextManager; + using var occ = ocm.GetContextCollection("ACDB_ANNOTATIONSCALES"); + if (blockRef.Annotative == AnnotativeStates.True) + blockRef.AddContext(occ.CurrentContext); + + var btr = tr.GetObject(blockRef.BlockTableRecord)!; + + if (!btr.HasAttributeDefinitions) + return objectId; + + var attdefs = btr.GetEntities(); + foreach (var attdef in attdefs) + { + using AttributeReference attref = new(); + attref.SetDatabaseDefaults(); + attref.SetAttributeFromBlock(attdef, blockRef.BlockTransform); + attref.Position = attdef.Position.TransformBy(blockRef.BlockTransform); + attref.AdjustAlignment(tr.Database); + if (atts is not null && atts.TryGetValue(attdef.Tag, out string str)) + { + attref.TextString = str; + } + + if (blockRef.Annotative == AnnotativeStates.True) + attref.AddContext(occ.CurrentContext); + + blockRef.AttributeCollection.AppendAttribute(attref); + tr.Transaction.AddNewlyCreatedDBObject(attref, true); + } + + return objectId; + } + + #endregion + + #endregion + + #region 遍历 + +#line hidden // 调试的时候跳过它 + /// + /// 遍历符号表记录,执行委托 + /// + /// 符号表记录 + /// 要运行的委托 + public static void ForEach(this TRecord record, Action task) + where TRecord : SymbolTableRecord, IEnumerable + { + foreach (ObjectId id in record) + task.Invoke(id); + } + + /// + /// 遍历符号表记录,执行委托(允许循环中断) + /// + /// 符号表记录 + /// 要执行的委托 + public static void ForEach(this TRecord record, Action task) + where TRecord : SymbolTableRecord, IEnumerable + { + LoopState state = new(); /*这种方式比Action改Func更友好*/ + foreach (ObjectId id in record) + { + task.Invoke(id, state); + if (!state.IsRun) + break; + } + } + + /// + /// 遍历符号表记录,执行委托(允许循环中断,输出索引值) + /// + /// 符号表记录 + /// 要执行的委托 + [System.Diagnostics.DebuggerStepThrough] + public static void ForEach(this TRecord record, Action task) + where TRecord : SymbolTableRecord, IEnumerable + { + //if (task == null) + // throw new ArgumentNullException(nameof(task)); + ArgumentNullEx.ThrowIfNull(task); + int i = 0; + LoopState state = new(); /*这种方式比Action改Func更友好*/ + foreach (ObjectId id in record) + { + task.Invoke(id, state, i); + if (!state.IsRun) + break; + i++; + } + } +#line default + + #endregion +} \ No newline at end of file diff --git a/IFoxCAD.Cad/GlobalUsing.cs b/IFoxCAD.Cad/GlobalUsing.cs index 53a464b..67dcfff 100644 --- a/IFoxCAD.Cad/GlobalUsing.cs +++ b/IFoxCAD.Cad/GlobalUsing.cs @@ -42,9 +42,10 @@ // 系统引用 global using System.Text.RegularExpressions; global using System.Runtime.CompilerServices; -global using System.Diagnostics; global using System.Windows.Input; global using System.Globalization; +global using System.Diagnostics; + // global using System.Windows.Data; global using System.Net; global using System.Diagnostics.CodeAnalysis; diff --git a/IFoxCAD.Cad/ResultData/XdataList.cs b/IFoxCAD.Cad/ResultData/XDataList.cs similarity index 100% rename from IFoxCAD.Cad/ResultData/XdataList.cs rename to IFoxCAD.Cad/ResultData/XDataList.cs diff --git a/IFoxCAD.Cad/ResultData/XRecordDataList.cs b/IFoxCAD.Cad/ResultData/XRecordDataList.cs new file mode 100644 index 0000000..3d577c7 --- /dev/null +++ b/IFoxCAD.Cad/ResultData/XRecordDataList.cs @@ -0,0 +1,67 @@ +namespace IFoxCAD.Cad; + +/// +/// 扩展字典数据封装类 +/// +public class XRecordDataList : TypedValueList +{ + #region 构造函数 + /// + /// 扩展字典数据封装类 + /// + public XRecordDataList() { } + + /// + /// 扩展字典数据封装类 + /// + public XRecordDataList(IEnumerable values) : base(values) { } + #endregion + + #region 添加数据 + /// + /// 添加数据 + /// + /// 组码 + /// 组码值 + public override void Add(int code, object obj) + { + if (code >= 1000) + throw new Exception("传入的组码值不是 XRecordData 有效范围!"); + + Add(new TypedValue(code, obj)); + } + + /// + /// 添加数据 + /// + /// dxfcode枚举值 + /// 组码值 + public void Add(DxfCode code, object obj) + { + Add((int)code, obj); + } + #endregion + + #region 转换器 + /// + /// ResultBuffer 隐式转换到 XRecordDataList + /// + /// ResultBuffer 实例 + public static implicit operator XRecordDataList(ResultBuffer? buffer) => new(buffer?.AsArray()??[]); + /// + /// XRecordDataList 隐式转换到 TypedValue 数组 + /// + /// TypedValueList 实例 + public static implicit operator TypedValue[](XRecordDataList values) => values.ToArray(); + /// + /// XRecordDataList 隐式转换到 ResultBuffer + /// + /// TypedValueList 实例s + public static implicit operator ResultBuffer(XRecordDataList values) => new(values); + /// + /// TypedValue 数组隐式转换到 XRecordDataList + /// + /// TypedValue 数组 + public static implicit operator XRecordDataList(TypedValue[] values) => new(values); + #endregion +} \ No newline at end of file diff --git a/IFoxCAD.sln.DotSettings b/IFoxCAD.sln.DotSettings index 208af26..62845c2 100644 --- a/IFoxCAD.sln.DotSettings +++ b/IFoxCAD.sln.DotSettings @@ -2,11 +2,15 @@ DB OS True + True True True True + True True + True True + True True True True diff --git a/Test/Class1.cs b/Test/Class1.cs deleted file mode 100644 index df347f6..0000000 --- a/Test/Class1.cs +++ /dev/null @@ -1,5 +0,0 @@ -namespace Test; - -public class Class1 -{ -} \ No newline at end of file diff --git a/Test/GlobalUsing.cs b/Test/GlobalUsing.cs new file mode 100644 index 0000000..a7b8c49 --- /dev/null +++ b/Test/GlobalUsing.cs @@ -0,0 +1,7 @@ +global using IFoxCAD.Cad; +global using Acap =Autodesk.AutoCAD.ApplicationServices.Application; +global using Autodesk.AutoCAD.DatabaseServices; +global using Autodesk.AutoCAD.Geometry; +global using Autodesk.AutoCAD.Runtime; +global using System.ComponentModel; +global using System.Runtime.InteropServices; \ No newline at end of file diff --git a/Test/Test.csproj b/Test/Test.csproj index 16521a5..c0139b4 100644 --- a/Test/Test.csproj +++ b/Test/Test.csproj @@ -2,8 +2,18 @@ net48 + true preview enable + + + + + + + + + diff --git a/Test/TestAddEntity.cs b/Test/TestAddEntity.cs new file mode 100644 index 0000000..d70932c --- /dev/null +++ b/Test/TestAddEntity.cs @@ -0,0 +1,98 @@ +namespace Test; + +public partial class Test +{ + [CommandMethod(nameof(Test_Rec))] + public void Test_Rec() + { + Point2d p1 = new(10000.2, 100000.5); + Point2d p2 = new(15000.9, 100000.5); + Point2d p3 = new(15000.9, 105000.7); + Point2d p4 = new(10000.2, 105000.7); + + var p12 = p2 - p1; + var p23 = p3 - p2; + var p34 = p4 - p3; + var p41 = p1 - p4; + var p13 = p3 - p1; + var p24 = p4 - p2; + + + const double pi90 = Math.PI / 2; + Env.Print(pi90); + + Tools.TestTimes(1000000, "对角线", () => + { + var result = false; + if (Math.Abs(p13.Length - p24.Length) <= 1e8) + { + result = p41.IsParallelTo(p12); + } + }); + +#pragma warning disable CS0219 // 变量已被赋值,但从未使用过它的值 + Tools.TestTimes(1000000, "三次点乘", () => + { + bool result = Math.Abs(p12.DotProduct(p23)) < 1e8 && + Math.Abs(p23.DotProduct(p34)) < 1e8 && + Math.Abs(p34.DotProduct(p41)) < 1e8; + }); + + Tools.TestTimes(1000000, "三次垂直", () => + { + bool result = p12.IsParallelTo(p23) && + p23.IsParallelTo(p34) && + p34.IsParallelTo(p41); + }); +#pragma warning restore CS0219 // 变量已被赋值,但从未使用过它的值 + } + + + [CommandMethod(nameof(Test_EntRoration))] + public void Test_EntRoration() + { + var line = new Line(new(0, 0, 0), new(100, 0, 0)); + + using DBTrans tr = new(); + tr.CurrentSpace.AddEntity(line); + var line2 = (Line)line.Clone(); + tr.CurrentSpace.AddEntity(line2); + line2.Rotation(new(100, 0, 0), Math.PI / 2); + } + + [CommandMethod(nameof(Test_TypeSpeed))] + public void Test_TypeSpeed() + { + var line = new Line(); + var line1 = line as Entity; + Tools.TestTimes(100000, "is 匹配:", () => + { + var t = line1 is Line; + }); + Tools.TestTimes(100000, "name 匹配:", () => + { + // var t = line.GetType().Name; + var tt = line1.GetType().Name == nameof(Line); + }); + Tools.TestTimes(100000, "dxfname 匹配:", () => + { + // var t = line.GetType().Name; + var tt = line1.GetRXClass().DxfName == nameof(Line); + }); + } + + [CommandMethod(nameof(Test_sleeptrans))] + public static void Test_sleeptrans() + { + using var tr = new DBTrans(); + for (int i = 0; i < 100; i++) + { + var cir = CircleEx.CreateCircle(new Point3d(i, i, 0), 0.5); + + cir.ColorIndex = i; + tr.CurrentSpace.AddEntity(cir); + tr.Editor?.Redraw(cir); + Thread.Sleep(10); + } + } +} \ No newline at end of file diff --git a/Test/Timer.cs b/Test/Timer.cs new file mode 100644 index 0000000..6bd03f1 --- /dev/null +++ b/Test/Timer.cs @@ -0,0 +1,150 @@ + + +namespace Test; + +/* +// 测试例子,同时验证两个计时器 +var stopwatch = new Stopwatch(); +Timer.RunTime(() => { + stopwatch.Start(); + for (int i = 0; i < 10000000; i++) + i++; + stopwatch.Stop(); +}, Timer.TimeEnum.Millisecond, "运行:"); +Console.WriteLine("运行毫秒:" + stopwatch.ElapsedMilliseconds); + */ + +/// +/// 时间定时类 +/// +public class Timer +{ + /// + /// 时间单位枚举 + /// + public enum TimeEnum + { + /// + /// 秒 + /// + Second, + /// + /// 毫秒 + /// + Millisecond, + /// + /// 微秒 + /// + Microsecond, + /// + /// 纳秒 + /// + Nanosecond, + } + + [DllImport("Kernel32.dll")] + private static extern bool QueryPerformanceCounter(out long lpPerformanceCount); + + /// + /// 这个函数会检索性能计数器的频率. + /// 性能计数器的频率在系统启动时是固定的,并且在所有处理器上都是一致的 + /// 因此,只需在应用初始化时查询频率,即可缓存结果 + /// 在运行 Windows XP 或更高版本的系统上,该函数将始终成功,因此永远不会返回零 + /// + /// + /// + [DllImport("Kernel32.dll")] + private static extern bool QueryPerformanceFrequency(out long lpFrequency); + + private long _startTime, _stopTime; + private readonly long _freq; + /// + /// 构造函数 + /// + /// + public Timer() + { + _startTime = 0; + _stopTime = 0; + + if (!QueryPerformanceFrequency(out _freq)) + throw new Win32Exception("不支持高性能计数器"); + } + + /// + /// 开始计时器 + /// + public void Start() + { + Thread.Sleep(0); + QueryPerformanceCounter(out _startTime); + } + + /// + /// 停止计时器 + /// + public void Stop() + { + QueryPerformanceCounter(out _stopTime); + Second = (double)(_stopTime - _startTime) / _freq; + } + + // 返回计时器经过时间 + /// + /// 秒 + /// + public double Second { get; private set; } + + /// + /// 毫秒 + /// + public double Millisecond => Second * 1000.0; + /// + /// 微秒 + /// + public double Microsecond => Second * 1000000.0; + /// + /// 纳秒 + /// + public double Nanosecond => Second * 1000000000.0; + /// + /// 计算执行委托的时间 + /// + /// 要执行的委托 + /// 时间单位 + /// 执行委托的时间 + public static double RunTime(Action action, + TimeEnum timeEnum = TimeEnum.Millisecond) + { + var nanoSecond = new Timer(); + nanoSecond.Start(); + action(); + nanoSecond.Stop(); + + var time = timeEnum switch + { + TimeEnum.Second => nanoSecond.Second, + TimeEnum.Millisecond => nanoSecond.Millisecond, + TimeEnum.Microsecond => nanoSecond.Microsecond, + TimeEnum.Nanosecond => nanoSecond.Nanosecond, + _ => 0.0 + }; + //string timeNameZn = ""; + //switch (timeEnum) + //{ + // case TimeEnum.Second: + // timeNameZn = " 秒"; + // break; + // case TimeEnum.Millisecond: + // timeNameZn = " 毫秒"; + // break; + // case TimeEnum.Microsecond: + // timeNameZn = " 微秒"; + // break; + // case TimeEnum.Nanosecond: + // timeNameZn = " 纳秒"; + // break; + //} + return time; + } +} \ No newline at end of file diff --git a/Test/Tools.cs b/Test/Tools.cs new file mode 100644 index 0000000..cff5937 --- /dev/null +++ b/Test/Tools.cs @@ -0,0 +1,74 @@ +namespace Test; + +public static class Tools +{ + + /// + /// 计时器 + /// + [System.Diagnostics.DebuggerStepThrough] + public static void TestTimes2(int count, string message, Action action) + { + System.Diagnostics.Stopwatch watch = new(); + watch.Start(); // 开始监视代码运行时间 + for (var i = 0; i < count; i++) + action.Invoke();// 需要测试的代码 + watch.Stop(); // 停止监视 + var timespan = watch.Elapsed; // 获取当前实例测量得出的总时间 + var time = timespan.TotalMilliseconds; + var name = "毫秒"; + if (timespan.TotalMilliseconds > 1000) + { + time = timespan.TotalSeconds; + name = "秒"; + } + Env.Print($"{message} 代码执行 {count} 次的时间:{time} ({name})"); // 总毫秒数 + } + + /// + /// 计时器 + /// + [System.Diagnostics.DebuggerStepThrough] + public static void TestTimes3(int count, string message, Action action) + { + System.Diagnostics.Stopwatch watch = new(); + watch.Start(); // 开始监视代码运行时间 + for (var i = 0; i < count; i++) + action.Invoke(i);// 需要测试的代码 + watch.Stop(); // 停止监视 + var timespan = watch.Elapsed; // 获取当前实例测量得出的总时间 + var time = timespan.TotalMilliseconds; + var name = "毫秒"; + if (timespan.TotalMilliseconds > 1000) + { + time = timespan.TotalSeconds; + name = "秒"; + } + Env.Print($"{message} 代码执行 {count} 次的时间:{time} ({name})"); // 总毫秒数 + } + + + + /// + /// 纳秒计时器 + /// + [System.Diagnostics.DebuggerStepThrough] + public static void TestTimes(int count, string message, Action action, + Timer.TimeEnum timeEnum = Timer.TimeEnum.Millisecond) + { + var time = Timer.RunTime(() => { + for (var i = 0; i < count; i++) + action.Invoke(); + }, timeEnum); + + var timeNameZn = timeEnum switch + { + Timer.TimeEnum.Millisecond => " 毫秒", + Timer.TimeEnum.Microsecond => " 微秒", + Timer.TimeEnum.Nanosecond => " 纳秒", + _ => " 秒" + }; + + Env.Print($"{message} 代码执行 {count} 次的时间:{time} ({timeNameZn})"); + } +} \ No newline at end of file -- Gitee From f3e0171a33a481ac0ab3bffae8bc951f293a69c2 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sat, 23 Mar 2024 12:09:26 +0800 Subject: [PATCH 259/453] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E5=90=8D=E4=B8=BA=E4=BC=97=E6=89=80=E5=91=A8=E7=9F=A5=E7=9A=84?= =?UTF-8?q?=E5=90=8D=E5=AD=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IFoxCAD.Cad/ExtensionMethod/Entity/BlockReferenceEx.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/IFoxCAD.Cad/ExtensionMethod/Entity/BlockReferenceEx.cs b/IFoxCAD.Cad/ExtensionMethod/Entity/BlockReferenceEx.cs index 325cd12..5a6f0b9 100644 --- a/IFoxCAD.Cad/ExtensionMethod/Entity/BlockReferenceEx.cs +++ b/IFoxCAD.Cad/ExtensionMethod/Entity/BlockReferenceEx.cs @@ -65,13 +65,14 @@ public static void ClipBlockRef(this BlockReference brf, Point3d pt1, Point3d pt /// /// 更新动态块属性值 /// - public static void ChangeDynamicBlockProperty(this BlockReference blockReference, + public static void ChangeBlockProperty(this BlockReference blockReference, Dictionary propertyNameValues) { using (blockReference.ForWrite()) { foreach (DynamicBlockReferenceProperty item in blockReference.DynamicBlockReferencePropertyCollection) { + // TODO 这里太烂了,应该判断类型 if (propertyNameValues.TryGetValue(item.PropertyName, out var value)) { item.Value = value; -- Gitee From a93ec767cd21ecd68940acee2df34be92080100d Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sun, 24 Mar 2024 08:59:51 +0800 Subject: [PATCH 260/453] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E8=A3=81=E5=89=AA?= =?UTF-8?q?=E5=9D=97=E7=9A=84=E6=96=B9=E6=B3=95=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IFoxCAD.Cad/ExtensionMethod/Entity/BlockReferenceEx.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/IFoxCAD.Cad/ExtensionMethod/Entity/BlockReferenceEx.cs b/IFoxCAD.Cad/ExtensionMethod/Entity/BlockReferenceEx.cs index 5a6f0b9..7284569 100644 --- a/IFoxCAD.Cad/ExtensionMethod/Entity/BlockReferenceEx.cs +++ b/IFoxCAD.Cad/ExtensionMethod/Entity/BlockReferenceEx.cs @@ -15,7 +15,7 @@ public static class BlockReferenceEx ///
/// 块参照 /// 裁剪多边形点表 - public static void ClipBlockRef(this BlockReference brf, IEnumerable pt3ds) + public static void XClip(this BlockReference brf, IEnumerable pt3ds) { var mat = brf.BlockTransform.Inverse(); var pts = @@ -36,7 +36,7 @@ public static void ClipBlockRef(this BlockReference brf, IEnumerable pt /// 块参照 /// 第一角点 /// 第二角点 - public static void ClipBlockRef(this BlockReference brf, Point3d pt1, Point3d pt2) + public static void XClip(this BlockReference brf, Point3d pt1, Point3d pt2) { var mat = brf.BlockTransform.Inverse(); pt1 = pt1.TransformBy(mat); -- Gitee From 0daf1ff54c6cfd3b8192ce571ba356f57180d38b Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sun, 24 Mar 2024 09:00:26 +0800 Subject: [PATCH 261/453] =?UTF-8?q?=E6=A0=BC=E5=BC=8F=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IFoxCAD.Cad/ExtensionMethod/DBObjectEx.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/IFoxCAD.Cad/ExtensionMethod/DBObjectEx.cs b/IFoxCAD.Cad/ExtensionMethod/DBObjectEx.cs index f99b1b1..8cb764a 100644 --- a/IFoxCAD.Cad/ExtensionMethod/DBObjectEx.cs +++ b/IFoxCAD.Cad/ExtensionMethod/DBObjectEx.cs @@ -5,7 +5,6 @@ /// public static class DBObjectEx { - #region Linq /// -- Gitee From 0b8d8718f27334aa80234e9857747fa9944ca744 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sun, 24 Mar 2024 09:01:17 +0800 Subject: [PATCH 262/453] =?UTF-8?q?=E4=BD=BF=E7=94=A8=E6=98=BE=E7=A4=BApri?= =?UTF-8?q?vate?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IFoxCAD.Cad/ExtensionMethod/Geomerty/PointEx.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/IFoxCAD.Cad/ExtensionMethod/Geomerty/PointEx.cs b/IFoxCAD.Cad/ExtensionMethod/Geomerty/PointEx.cs index 7b06d90..701a8ba 100644 --- a/IFoxCAD.Cad/ExtensionMethod/Geomerty/PointEx.cs +++ b/IFoxCAD.Cad/ExtensionMethod/Geomerty/PointEx.cs @@ -24,7 +24,7 @@ public static string GetHashString(this Point3d pt, int xyz = 3, int decimalReta } // 为了频繁触发所以弄个缓存 - static Plane? _planeCache; + private static Plane? _planeCache; /// /// 两点计算弧度范围0到2Pi -- Gitee From 3da469b0ba5c045eec7ff901afa0daab85500d30 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sun, 24 Mar 2024 09:05:05 +0800 Subject: [PATCH 263/453] =?UTF-8?q?=E6=B7=BB=E5=8A=A0Point.OrthoProject?= =?UTF-8?q?=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IFoxCAD.Cad/ExtensionMethod/Geomerty/PointEx.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/IFoxCAD.Cad/ExtensionMethod/Geomerty/PointEx.cs b/IFoxCAD.Cad/ExtensionMethod/Geomerty/PointEx.cs index 701a8ba..3244224 100644 --- a/IFoxCAD.Cad/ExtensionMethod/Geomerty/PointEx.cs +++ b/IFoxCAD.Cad/ExtensionMethod/Geomerty/PointEx.cs @@ -120,6 +120,16 @@ public static Point3d Point3d(this Point2d pt, double z = 0) return new(pt.X, pt.Y, z); } + /// + /// 投影到指定Z值 + /// + /// 点 + /// 新z值 + /// 投影后的坐标 + public static Point3d OrthoProject(this Point3d pt, double z) + { + return new Point3d(pt.X, pt.Y, z); + } /// /// 根据世界坐标计算用户坐标 -- Gitee From 2d4c10499d466bd30e3a78087de86ca4b9723bb5 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sun, 24 Mar 2024 09:09:58 +0800 Subject: [PATCH 264/453] =?UTF-8?q?=E5=AE=8C=E5=96=84=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E5=8A=A8=E6=80=81=E5=9D=97=E5=8F=82=E6=95=B0=E5=80=BC=E6=96=B9?= =?UTF-8?q?=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Entity/BlockReferenceEx.cs | 112 ++++++++++++------ 1 file changed, 78 insertions(+), 34 deletions(-) diff --git a/IFoxCAD.Cad/ExtensionMethod/Entity/BlockReferenceEx.cs b/IFoxCAD.Cad/ExtensionMethod/Entity/BlockReferenceEx.cs index 7284569..7a4e91b 100644 --- a/IFoxCAD.Cad/ExtensionMethod/Entity/BlockReferenceEx.cs +++ b/IFoxCAD.Cad/ExtensionMethod/Entity/BlockReferenceEx.cs @@ -63,26 +63,69 @@ public static void XClip(this BlockReference brf, Point3d pt1, Point3d pt2) #region 属性 /// - /// 更新动态块属性值 + /// 更新动态块参数值 /// - public static void ChangeBlockProperty(this BlockReference blockReference, - Dictionary propertyNameValues) + public static bool ChangeBlockProperty(this BlockReference blockReference, + Dictionary propertyNameValues) { + if (!blockReference.IsDynamicBlock) + return false; using (blockReference.ForWrite()) { foreach (DynamicBlockReferenceProperty item in blockReference.DynamicBlockReferencePropertyCollection) { - // TODO 这里太烂了,应该判断类型 if (propertyNameValues.TryGetValue(item.PropertyName, out var value)) { - item.Value = value; + item.Value = item.PropertyTypeCode switch + { + 1 => Convert.ToDouble(value), + 2 => Convert.ToInt32(value), + 3 => Convert.ToInt16(value), + 4 => Convert.ToInt16(value), + 5 => Convert.ToString(value), + 13 => Convert.ToInt64(value), + _ => value, + }; } } } + + return true; + } + + /// + /// 更新动态块参数值 + /// + public static bool ChangeBlockProperty(this BlockReference blockReference, + string propName, object value) + { + if (!blockReference.IsDynamicBlock) + return false; + using (blockReference.ForWrite()) + { + foreach (DynamicBlockReferenceProperty item in blockReference.DynamicBlockReferencePropertyCollection) + { + if (item.PropertyName != propName) + continue; + item.Value = item.PropertyTypeCode switch + { + 1 => Convert.ToDouble(value), + 2 => Convert.ToInt32(value), + 3 => Convert.ToInt16(value), + 4 => Convert.ToInt16(value), + 5 => Convert.ToString(value), + 13 => Convert.ToInt64(value), + _ => value, + }; + break; + } + } + + return true; } /// - /// 更新普通块的属性值 + /// 更新属性块的属性值 /// public static void ChangeBlockAttribute(this BlockReference blockReference, Dictionary propertyNameValues) { @@ -111,34 +154,6 @@ public static void ChangeBlockAttribute(this BlockReference blockReference, Dict } } - /// - /// 获取嵌套块的位置(wcs) - /// - /// 父块 - /// 子块名 - /// 子块的位置 - /// - public static Point3d? GetNestedBlockPosition(this BlockReference parentBlockRef, string nestedBlockName) - { - var tr = DBTrans.GetTopTransaction(parentBlockRef.Database); - - var btr = tr.GetObject(parentBlockRef.BlockTableRecord); - if (btr == null) return null; - foreach (var id in btr) - { - if (id.ObjectClass.Name == "AcDbBlockReference") - { - var nestedBlockRef = tr.GetObject(id); - if (nestedBlockRef?.Name == nestedBlockName) - { - return nestedBlockRef.Position.TransformBy(parentBlockRef.BlockTransform); - } - } - } - - return null; - } - /// /// 获取普通块参照的属性集合 /// @@ -181,6 +196,35 @@ public static string GetBlockName(this BlockReference blk) return blk.Name; } + + /// + /// 获取嵌套块的位置(wcs) + /// + /// 父块 + /// 子块名 + /// 子块的位置 + /// + public static Point3d? GetNestedBlockPosition(this BlockReference parentBlockRef, string nestedBlockName) + { + var tr = DBTrans.GetTopTransaction(parentBlockRef.Database); + + var btr = tr.GetObject(parentBlockRef.BlockTableRecord); + if (btr == null) return null; + foreach (var id in btr) + { + if (id.ObjectClass.Name == "AcDbBlockReference") + { + var nestedBlockRef = tr.GetObject(id); + if (nestedBlockRef?.Name == nestedBlockName) + { + return nestedBlockRef.Position.TransformBy(parentBlockRef.BlockTransform); + } + } + } + + return null; + } + /// /// 遍历块内 /// -- Gitee From f5cb756acb6c70cdaa277afee605acefebf0e534 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sun, 24 Mar 2024 09:19:10 +0800 Subject: [PATCH 265/453] =?UTF-8?q?=E8=A7=84=E8=8C=83=E5=91=BD=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IFoxCAD.Cad/ExtensionMethod/DBDictionaryEx.cs | 53 +++++++++---------- IFoxCAD.Cad/ResultData/XRecordDataList.cs | 2 +- 2 files changed, 25 insertions(+), 30 deletions(-) diff --git a/IFoxCAD.Cad/ExtensionMethod/DBDictionaryEx.cs b/IFoxCAD.Cad/ExtensionMethod/DBDictionaryEx.cs index 0f735bc..f3912ac 100644 --- a/IFoxCAD.Cad/ExtensionMethod/DBDictionaryEx.cs +++ b/IFoxCAD.Cad/ExtensionMethod/DBDictionaryEx.cs @@ -5,20 +5,22 @@ /// public static class DBDictionaryEx { + #region Get Set + /// /// 获取字典里的全部对象 /// /// 对象类型的泛型 /// 字典 /// 对象迭代器 - [System.Diagnostics.DebuggerStepThrough] + [DebuggerStepThrough] public static IEnumerable GetAllObjects(this DBDictionary dict) where T : DBObject { var tr = DBTrans.GetTopTransaction(dict.Database); foreach (var e in dict) { - if (tr.GetObject(e.Value) is T tobj) - yield return tobj; + if (tr.GetObject(e.Value) is T tObj) + yield return tObj; } } @@ -123,6 +125,8 @@ public static ObjectId SetData(this DBDictionary dict, string key, T newValue } } + #endregion + #region XRecord /// @@ -133,7 +137,12 @@ public static ObjectId SetData(this DBDictionary dict, string key, T newValue /// 扩展数据 public static XRecordDataList? GetXRecord(this DBDictionary dict, string key) { - return dict.GetData(key) is Xrecord xr ? xr.Data : null; + if (dict.GetData(key) is Xrecord { Data: not null } xr) + { + return xr.Data; + } + + return null; } /// @@ -188,15 +197,15 @@ public static DataTable CreateDataTable(Dictionary colTypes, o foreach (var t in colTypes) table.AppendColumn(t.Value, t.Key); - var ncol = colTypes.Count; - var types = new CellType[ncol]; + var nCol = colTypes.Count; + var types = new CellType[nCol]; colTypes.Values.CopyTo(types, 0); - var nrow = content.GetLength(0); - for (int i = 0; i < nrow; i++) + var nRow = content.GetLength(0); + for (int i = 0; i < nRow; i++) { DataCellCollection row = new(); - for (int j = 0; j < ncol; j++) + for (int j = 0; j < nCol; j++) { var cell = new DataCell(); cell.SetValue(types[j], content[i, j]); @@ -280,7 +289,7 @@ public static void SetValue(this DataCell cell, CellType type, object value) bool createSubDictionary, IEnumerable dictNames) { - DBDictionary? newdict = null; + DBDictionary? newDict = null; if (createSubDictionary) { @@ -291,14 +300,14 @@ public static void SetValue(this DataCell cell, CellType type, object value) { if (dict.Contains(name)) { - newdict = dict.GetData(name) as DBDictionary; + newDict = dict.GetData(name) as DBDictionary; } else { DBDictionary subDict = new(); dict.SetData(name, subDict); - newdict = subDict; - newdict.TreatElementsAsHard = true; + newDict = subDict; + newDict.TreatElementsAsHard = true; } } } @@ -307,29 +316,15 @@ public static void SetValue(this DataCell cell, CellType type, object value) foreach (string name in dictNames) { if (dict.Contains(name)) - newdict = dict.GetData(name); + newDict = dict.GetData(name); else return null; } } - return newdict; + return newDict; } - - ///// - ///// 获取对象扩展字典的子字典 - ///// - ///// 对象 - ///// 事务 - ///// 是否创建子字典 - ///// 键值列表 - ///// 字典 - // public static DBDictionary GetSubDictionary(this DBObject obj, bool createSubDictionary, params string[] dictNames) - // { - // return obj.GetXDictionary().GetSubDictionary(createSubDictionary, dictNames); - // } - #endregion #region 组字典 diff --git a/IFoxCAD.Cad/ResultData/XRecordDataList.cs b/IFoxCAD.Cad/ResultData/XRecordDataList.cs index 3d577c7..e36eb3e 100644 --- a/IFoxCAD.Cad/ResultData/XRecordDataList.cs +++ b/IFoxCAD.Cad/ResultData/XRecordDataList.cs @@ -47,7 +47,7 @@ public void Add(DxfCode code, object obj) /// ResultBuffer 隐式转换到 XRecordDataList /// /// ResultBuffer 实例 - public static implicit operator XRecordDataList(ResultBuffer? buffer) => new(buffer?.AsArray()??[]); + public static implicit operator XRecordDataList(ResultBuffer buffer) => new(buffer.AsArray()); /// /// XRecordDataList 隐式转换到 TypedValue 数组 /// -- Gitee From edbafe1cdc062bfcdaffcb1d29ec9bbee9b16c42 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sun, 24 Mar 2024 10:59:16 +0800 Subject: [PATCH 266/453] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=88=9D=E5=A7=8B?= =?UTF-8?q?=E5=8C=96=E6=93=8D=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IFoxCAD.Cad/Initialize/AcadEMR.cs | 151 +++++++++++++++++++++++++ IFoxCAD.Cad/Initialize/AssemInfo.cs | 99 ++++++++++++++++ IFoxCAD.Cad/Initialize/AutoReg.cs | 88 ++++++++++++++ IFoxCAD.Cad/Initialize/CheckFactory.cs | 54 +++++++++ 4 files changed, 392 insertions(+) create mode 100644 IFoxCAD.Cad/Initialize/AcadEMR.cs create mode 100644 IFoxCAD.Cad/Initialize/AssemInfo.cs create mode 100644 IFoxCAD.Cad/Initialize/AutoReg.cs create mode 100644 IFoxCAD.Cad/Initialize/CheckFactory.cs diff --git a/IFoxCAD.Cad/Initialize/AcadEMR.cs b/IFoxCAD.Cad/Initialize/AcadEMR.cs new file mode 100644 index 0000000..c4db286 --- /dev/null +++ b/IFoxCAD.Cad/Initialize/AcadEMR.cs @@ -0,0 +1,151 @@ +#if true +namespace IFoxCAD.Cad; + +// 作者: [VB.net]福萝卜 莱昂纳多·胖子 +// Email:oneeshine@163.com +// QQ: 461884072 +// 测试 2006-2019+ + +/// +/// 去教育版 +/// +/// +internal class AcadEMR +{ + // /// + // /// 释放库 + // /// + // /// 句柄 + // /// + // [DllImport("kernel32.dll", CharSet = CharSet.Auto)] + // static extern IntPtr FreeLibrary(IntPtr loadLibraryIntPtr); + + /// + /// 获取一个应用程序或dll的模块句柄,要求已经载入 + /// + /// + /// + [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] + static extern IntPtr GetModuleHandle(string name); + + /// + /// 获取要引入的函数,将符号名或标识号转换为DLL内部地址 + /// + /// exe/dll句柄 + /// 接口名 + /// + [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true)] + static extern IntPtr GetProcAddress(IntPtr hModule, string procName); + + /// + /// 虚拟保护 + /// + /// + /// + /// + /// + /// + [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] + // ReSharper disable once IdentifierTypo + static extern bool VirtualProtect(IntPtr lpAddress, IntPtr dwSize, uint flNewProtect, ref uint lpflOldProtect); + + + /// + /// 移除教育版 + /// + /// 打印出错信息 + public static void Remove(bool echoes = false) + { + var dllName = Env.GetAcapVersionDll(); + var moduleHandle = GetModuleHandle(dllName); + if (moduleHandle == IntPtr.Zero) + { + if (echoes) + Env.Printl(typeof(AcadEMR).FullName + "." + nameof(Remove) + "找不到模块:" + dllName); + return; + } + + string funcName = Encoding.Unicode.GetString(new byte[] { 63 }); + if (IntPtr.Size == 4) + funcName += "isEMR@AcDbDatabase@@QBE_NXZ"; + else + funcName += "isEMR@AcDbDatabase@@QEBA_NXZ"; + + var funcAddress = GetProcAddress(moduleHandle, funcName); + if (funcAddress == IntPtr.Zero) + { + if (echoes) + Env.Printl("无法找指定函数:" + funcName); + return; + } + + var ptr = IntPtr.Size == 4 + ? new IntPtr(funcAddress.ToInt32() + 3) + : new IntPtr(funcAddress.ToInt64() + 4); + + if (!CheckFunc(ref ptr, 51, 2)) // 08 通过此处 + if (echoes) + Env.Printl("无法验证函数体:0x33"); + var destPtr = ptr; + + if (!CheckFunc(ref ptr, 57, 6)) // 08 无法通过此处,所以只是打印提示 + if (echoes) + Env.Printl("无法验证函数体:0x39"); + if (!CheckFunc(ref ptr, 15, 2)) // 08 无法通过此处,所以只是打印提示 + if (echoes) + Env.Printl("无法验证函数体:0x0F"); + + uint flag = default; + // ReSharper disable once IdentifierTypo + uint tccc = default; + + IntPtr ip100 = new(100); + if (!VirtualProtect(destPtr, ip100, 64, ref flag)) // 修改内存权限 + { + if (echoes) + Env.Printl("内存模式修改失败!"); + return; + } + + Marshal.WriteByte(destPtr, 137); + VirtualProtect(destPtr, ip100, flag, ref tccc); // 恢复内存权限 + } + + /// + /// 验证函数体 + /// + /// + /// + /// + /// + static bool CheckFunc(ref IntPtr address, byte val, int len) + { + if (address.ToInt64() > 0) + { + if (Marshal.ReadByte(address) == 233) + { + if (IntPtr.Size == 4) + { + var pass = Marshal.ReadInt32(new IntPtr(address.ToInt32() + 1)); + address = new IntPtr(address.ToInt32() + pass + 5); + } + else + { + var pass = Marshal.ReadInt64(new IntPtr(address.ToInt64() + 1)); + address = new IntPtr(address.ToInt64() + pass + 5); + } + } + + if (address.ToInt64() > 0 && Marshal.ReadByte(address) == val) + { + address = IntPtr.Size == 4 + ? new IntPtr(address.ToInt32() + len) + : new IntPtr(address.ToInt64() + len); + return true; + } + } + + return false; + } +} +#endif \ No newline at end of file diff --git a/IFoxCAD.Cad/Initialize/AssemInfo.cs b/IFoxCAD.Cad/Initialize/AssemInfo.cs new file mode 100644 index 0000000..e1ee17d --- /dev/null +++ b/IFoxCAD.Cad/Initialize/AssemInfo.cs @@ -0,0 +1,99 @@ +namespace IFoxCAD.Cad; + +/// +/// 程序集信息 +/// +[Serializable] +public struct AssemInfo +{ + public AssemInfo(Assembly assembly) + { + Loader = assembly.Location; + Fullname = assembly.FullName; + Name = assembly.GetName().Name; + LoadType = AssemLoadType.Starting; + } + + /// + /// 注册名 + /// + public string Name = ""; + + /// + /// 程序集全名 + /// + public string Fullname = ""; + + /// + /// 程序集路径 + /// + public string Loader = ""; + + /// + /// 加载方式 + /// + public AssemLoadType LoadType = AssemLoadType.Starting; + + /// + /// 程序集说明 + /// + public string Description = ""; +} + +/// +/// 程序集加载类型 +/// +public enum AssemLoadType +{ + /// + /// 启动 + /// + Starting = 2, + + /// + /// 随命令 + /// + ByCommand = 12, + + /// + /// 无效 + /// + Disabled = 20 +} + +/// +/// 注册中心配置信息 +/// +[Flags] +public enum AutoRegConfig +{ + /// + /// 不进行任何操作 + /// + Undefined = 0, + + /// + /// 注册表 + /// + Regedit = 1, + + /// + /// 反射特性 + /// + ReflectionAttribute = 2, + + /// + /// 反射接口 + /// + ReflectionInterface = 4, + + /// + /// 移除教育版 + /// + RemoveEMR = 8, + + /// + /// 全部 + /// + All = Regedit | ReflectionAttribute | ReflectionInterface | RemoveEMR, +} \ No newline at end of file diff --git a/IFoxCAD.Cad/Initialize/AutoReg.cs b/IFoxCAD.Cad/Initialize/AutoReg.cs new file mode 100644 index 0000000..2e8733f --- /dev/null +++ b/IFoxCAD.Cad/Initialize/AutoReg.cs @@ -0,0 +1,88 @@ +namespace IFoxCAD.Cad; + +/// +/// 自动加载辅助类 +/// +public static class AutoReg +{ + /// + /// 获取自动加载注册表位置节点 + /// + /// 注册表节点 + public static RegistryKey? GetAcAppKey() + { + var key = HostApplicationServices.Current.UserRegistryProductRootKey; + var acKey = Registry.CurrentUser.OpenSubKey(key, true); + return acKey?.CreateSubKey("Applications"); + } + + /// + /// 是否已经自动加载 + /// + /// 程序集信息 + /// 已经设置返回true,反之返回false + public static bool SearchForReg(AssemInfo info) + { + if (GetAcAppKey() is not { } appKey || appKey.SubKeyCount == 0) + return false; + + var regApps = appKey.GetSubKeyNames(); + if (!regApps.Contains(info.Name)) + return false; + // 20220409 bug:文件名相同,路径不同,需要判断路径 + var subKey = appKey.OpenSubKey(info.Name); + return string.Equals(subKey?.GetValue("LOADER")?.ToString(), info.Loader, StringComparison.CurrentCultureIgnoreCase); + } + + /// + /// 在注册表写入自动加载的程序集信息 + /// + /// 程序集信息 + public static void RegApp(AssemInfo info) + { + using var appKey = GetAcAppKey(); + var rk = appKey?.CreateSubKey(info.Name); + rk?.SetValue("DESCRIPTION", info.Fullname, RegistryValueKind.String); + rk?.SetValue("LOADCTRLS", info.LoadType, RegistryValueKind.DWord); + rk?.SetValue("LOADER", info.Loader, RegistryValueKind.String); + rk?.SetValue("MANAGED", 1, RegistryValueKind.DWord); + appKey?.Close(); + } + + /// + /// 在注册表写入自动加载的程序集信息 + /// + /// 程序集 + public static void RegApp(Assembly? assembly = null) + { + assembly ??= Assembly.GetCallingAssembly(); + var info = new AssemInfo(assembly); + RegApp(info); + } + + /// + /// 卸载注册表信息 + /// + public static bool UnRegApp(AssemInfo info) + { + using var appKey = GetAcAppKey(); + if (appKey is { SubKeyCount: 0 }) + return false; + + var regApps = appKey?.GetSubKeyNames(); + if (regApps != null && !regApps.Contains(info.Name)) return false; + appKey?.DeleteSubKey(info.Name, false); + return true; + } + + /// + /// 卸载注册表信息 + /// + /// 程序集 + public static void UnRegApp(Assembly? assembly = null) + { + assembly ??= Assembly.GetCallingAssembly(); + var info = new AssemInfo(assembly); + UnRegApp(info); + } +} \ No newline at end of file diff --git a/IFoxCAD.Cad/Initialize/CheckFactory.cs b/IFoxCAD.Cad/Initialize/CheckFactory.cs new file mode 100644 index 0000000..ab326b0 --- /dev/null +++ b/IFoxCAD.Cad/Initialize/CheckFactory.cs @@ -0,0 +1,54 @@ +#if DEBUG +namespace IFoxCAD.Cad; + +/// +/// 命令检查类 +/// +public static class CheckFactory +{ + /* + * 平时command命令的globalName如果重复,加载时会报错 + * 但是并不会告诉你是哪里错了,通常需要花大量时间来查找 + * 将此函数添加在IExtensionApplication.Initialize()函数开头 + * 虽然还会报错,但是至少能知道哪个类下哪个方法导致的报错 + * 聊胜于无吧 + * 2023-05-16 by DYH + */ + + /// + /// 检查Command命令重复 + /// + public static void CheckDuplicateCommand(Assembly? assembly = null) + { + var dic = new Dictionary>(); + assembly ??= Assembly.GetCallingAssembly(); + // 反射所有的公共类型 + var typeArray = assembly.GetExportedTypes(); + foreach (var type in typeArray) + { + if (!type.IsPublic) + continue; + foreach (var method in type.GetMethods()) + { + if (!method.IsPublic) + continue; + if (method.GetCustomAttribute() is not { } att) + continue; + if (!dic.ContainsKey(att.GlobalName)) + { + dic.Add(att.GlobalName, new()); + } + + dic[att.GlobalName].Add(type.Name + "." + method.Name); + } + } + + var strings = dic + .Where(o => o.Value.Count() > 1) + .Select(o => o.Key + "命令重复,在类" + string.Join("和", o.Value) + "中"); + var str = string.Join(Environment.NewLine, strings); + if (!string.IsNullOrEmpty(str)) + System.Windows.Forms.MessageBox.Show(str, @"错误:重复命令!"); + } +} +#endif \ No newline at end of file -- Gitee From 6f338f132e021c2f1d8258771ca5a3f8fefcff8e Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sun, 24 Mar 2024 10:59:30 +0800 Subject: [PATCH 267/453] =?UTF-8?q?=E6=B7=BB=E5=8A=A0jig=E6=93=8D=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IFoxCAD.Cad/ExtensionMethod/Jig/JigEx.cs | 440 ++++++++++++++++++ .../ExtensionMethod/Jig/JigExTransient.cs | 183 ++++++++ 2 files changed, 623 insertions(+) create mode 100644 IFoxCAD.Cad/ExtensionMethod/Jig/JigEx.cs create mode 100644 IFoxCAD.Cad/ExtensionMethod/Jig/JigExTransient.cs diff --git a/IFoxCAD.Cad/ExtensionMethod/Jig/JigEx.cs b/IFoxCAD.Cad/ExtensionMethod/Jig/JigEx.cs new file mode 100644 index 0000000..0d451d3 --- /dev/null +++ b/IFoxCAD.Cad/ExtensionMethod/Jig/JigEx.cs @@ -0,0 +1,440 @@ +namespace IFoxCAD.Cad; + +/* 封装jig + * 20220726 隐藏事件,利用函数进行数据库图元重绘 + * 20220710 修改SetOption()的空格结束,并添加例子到IFox + * 20220503 cad22需要防止刷新过程中更改队列,是因为允许函数重入导致,08不会有. + * 20220326 重绘图元的函数用错了,现在修正过来 + * 20211216 加入块表时候做一个差集,剔除临时图元 + * 20211209 补充正交变量设置和回收设置 + * 作者: 惊惊⎛⎝◕⏝⏝◕。⎠⎞ ⎛⎝≥⏝⏝0⎠⎞ ⎛⎝⓿⏝⏝⓿。⎠⎞ ⎛⎝≥⏝⏝≤⎠⎞ + * 博客: https://www.cnblogs.com/JJBox/p/15650770.html + */ +/// +/// 重绘事件 +/// +/// +public delegate void WorldDrawEvent(WorldDraw draw); + +/// +/// jig扩展类 +/// +public class JigEx : DrawJig, IDisposable +{ + #region 成员 + + /// + /// 事件:亮显/暗显会被刷新冲刷掉,所以这个事件用于补充非刷新的工作 + /// + event WorldDrawEvent? WorldDrawEvent; + + /// + /// 最后的鼠标点,用来确认长度 + /// + public Point3d MousePointWcsLast; + + /// + /// 最后的图元,用来生成 + /// + public Entity[] Entitys => _drawEntitys.ToArray(); + + + readonly Action>? _mouseAction; + readonly Tolerance _tolerance; // 容差 + + readonly Queue _drawEntitys; // 重复生成的图元,放在这里刷新 + JigPromptPointOptions? _options; // jig鼠标配置 + private bool _worldDrawFlag; // 20220503 + + private bool _systemVariablesOrthomode; + bool SystemVariablesOrthomode // 正交修改还原 + { + get => _systemVariablesOrthomode; + set + { + if (Env.OrthoMode != value) + Env.OrthoMode = _systemVariablesOrthomode = value; + } + } + + #endregion + + #region 构造 + + /// + /// 在界面绘制图元 + /// + JigEx() + { + _drawEntitys = new(); + DimensionEntitys = new(); + } + + /// + /// 在界面绘制图元 + /// + /// + /// 用来频繁执行的回调:
+ /// 鼠标点;
+ /// 加入新建的图元,鼠标采样期间会Dispose图元的;
+ /// 所以已经在数据库图元利用事件加入,不要在此加入;
+ /// + /// 鼠标移动的容差 + public JigEx(Action>? action = null, double tolerance = 1e-6) : this() + { + _mouseAction = action; + _tolerance = new(tolerance, tolerance); + } + + #endregion + + /// + /// 因为是worldDraw触发sampler不是Sample触发worldDraw,所以要记一次上次的状态 + /// + private static bool lastIsKw; + + #region 重写 + + /// + /// 鼠标采样器 + /// + /// + /// 返回状态:令频繁刷新结束 + protected override SamplerStatus Sampler(JigPrompts prompts) + { + if (_worldDrawFlag) + return SamplerStatus.NoChange; // OK的时候拖动鼠标与否都不出现图元 + if (_options is null) + throw new NullReferenceException(nameof(_options)); + var pro = prompts.AcquirePoint(_options); + if (pro.Status != PromptStatus.OK && pro.Status != PromptStatus.Keyword) + return SamplerStatus.Cancel; + // 记上次的状态,因为马上要还原 + bool isOk = !lastIsKw; + lastIsKw = pro.Status == PromptStatus.Keyword; + + // 上次鼠标点不同(一定要这句,不然图元刷新太快会看到奇怪的边线) + var mousePointWcs = pro.Value; + + // == 是比较类字段,但是最好转为哈希比较. + // IsEqualTo 是方形判断(仅加法),但是cad是距离. + // Distance 是圆形判断(会求平方根,使用了牛顿迭代), + // 大量数据(十万以上/频繁刷新)面前会显得非常慢. + if (isOk && mousePointWcs.IsEqualTo(MousePointWcsLast, _tolerance)) + { + return SamplerStatus.NoChange; + } + + // 上次循环的缓冲区图元清理,否则将会在vs输出遗忘 Dispose + while (_drawEntitys.Count > 0) + _drawEntitys.Dequeue().Dispose(); + + // 委托把容器扔出去接收新创建的图元,然后给重绘更新 + _mouseAction?.Invoke(mousePointWcs, _drawEntitys); + MousePointWcsLast = mousePointWcs; + + return SamplerStatus.OK; + } + + /// + /// 重绘已在数据库的图元 + /// + /// 0x01 此处不加入newEntity的,它们在构造函数的参数回调处加入,它们会进行频繁new和Dispose从而避免遗忘释放
+ /// 0x02 此处用于重绘已经在数据的图元
+ /// 0x03 此处用于图元亮显暗显,因为会被重绘冲刷掉所以独立出来不重绘,它们也往往已经存在数据库的 + ///
+ ///
+ /// + /// newEntity只会存在一个图元队列中,而数据库图元可以分多个集合 + /// 例如: 集合A亮显时 集合B暗显/集合B亮显时 集合A暗显,所以我没有设计多个"数据库图元集合"存放,而是由用户在构造函数外自行创建 + /// + /// + public void DatabaseEntityDraw(WorldDrawEvent action) + { + WorldDrawEvent = action; + } + + /* WorldDraw 封装外的操作说明: + * 0x01 + * 我有一个业务是一次性生成四个方向的箭头,因为cad08缺少瞬时图元, + * 那么可以先提交一次事务,再开一个事务,把Entity传给jig,最后选择删除部分. + * 虽然这个是可行的方案,但是Entity穿越事务本身来说是非必要不使用的. + * 0x02 + * 四个箭头最近鼠标的亮显,其余淡显, + * 在jig使用淡显ent.Unhighlight和亮显ent.Highlight() + * 需要绕过重绘,否则重绘将导致图元频闪,令这两个操作失效, + * 此时需要自定义一个集合 EntityList (不使用本函数的_drawEntitys) + * 再将 EntityList 传给 WorldDrawEvent 事件,事件内实现亮显和淡显(事件已经利用 DatabaseEntityDraw函数进行提供). + * 0x03 + * draw.Geometry.Draw(_drawEntitys[i]); + * 此函数有问题,acad08克隆一份数组也可以用来刷新, + * 而arx上面的jig只能一次改一个,所以可以用此函数. + * 起因是此函数属于异步刷新, + * 同步上下文的刷新是 RawGeometry + * 0x04 + * cad22测试出现,08不会, + * draw.RawGeometry.Draw(ent);会跳到 Sampler(),所以设置 _worldDrawFlag + * 但是禁止重绘重入的话(令图元不频繁重绘),那么鼠标停着的时候就看不见图元, + * 所以只能重绘结束的时候才允许鼠标采集,采集过程的时候不会触发重绘, + * 这样才可以保证容器在重绘中不被更改. + */ + /// + /// 重绘图形 + /// + protected override bool WorldDraw(WorldDraw draw) + { + _worldDrawFlag = true; + WorldDrawEvent?.Invoke(draw); + _drawEntitys.ForEach(ent => + { +#if zcad + draw.Geometry.Draw(ent); +#else + draw.RawGeometry.Draw(ent); +#endif + }); + _worldDrawFlag = false; + return true; + } + + #endregion + + #region 方法 + + /// + /// 鼠标配置:基点 + /// + /// 基点 + /// 光标绑定 + /// 提示信息 + /// 正交开关 + public JigPromptPointOptions SetOptions(Point3d basePoint, + CursorType cursorType = CursorType.RubberBand, + string msg = "点选第二点", + bool orthomode = false) + { + if (orthomode) + SystemVariablesOrthomode = true; + + _options = JigPointOptions(); + _options.Message = Environment.NewLine + msg; + _options.Cursor = cursorType; // 光标绑定 + _options.UseBasePoint = true; // 基点打开 + _options.BasePoint = basePoint; // 基点设定 + return _options; + } + + /// + /// 鼠标配置:提示信息,关键字 + /// + /// 信息 + /// 关键字 + /// 正交开关 + /// + public JigPromptPointOptions SetOptions(string msg, + Dictionary? keywords = null, + bool orthomode = false) + { + if (orthomode) + SystemVariablesOrthomode = true; + + _options = JigPointOptions(); + _options.Message = Environment.NewLine + msg; + + + if (keywords != null) + foreach (var item in keywords) + _options.Keywords.Add(item.Key, item.Key, item.Value); + + // 因为默认配置函数导致此处空格触发是无效的, + // 但是用户如果想触发,就需要在外部减去默认UserInputControls配置 + // 要放最后,才能优先触发其他关键字 + + + // 外部设置减去配置 + // _options.UserInputControls = + // _options.UserInputControls + // ^ UserInputControls.NullResponseAccepted // 输入了鼠标右键,结束jig + // ^ UserInputControls.AnyBlankTerminatesInput; // 空格或回车,结束jig; + return _options; + } + + /// + /// 鼠标配置:自定义 + /// + /// + /// 正交开关 + public void SetOptions(Action action, bool orthomode = false) + { + if (orthomode) + SystemVariablesOrthomode = true; + + _options = new JigPromptPointOptions(); + action.Invoke(_options); + } + + /// + /// 执行 + /// + /// + public PromptResult Drag() + { + // jig功能必然是当前前台文档,所以封装内部更好调用 + var dm = Acap.DocumentManager; + var doc = dm.MdiActiveDocument; + var ed = doc.Editor; + var dr = ed.Drag(this); + + if (SystemVariablesOrthomode) + SystemVariablesOrthomode = !SystemVariablesOrthomode; + return dr; + } + + /// + /// 最后一次的图元加入数据库 + /// + /// 加入此空间 + /// 不生成的图元用于排除,例如刷新时候的提示文字 + /// 加入数据库的id集合 + public IEnumerable? AddEntityToMsPs(BlockTableRecord btrOfAddEntitySpace, + IEnumerable? removeEntity = null) + { + // 内部用 _drawEntitys 外部用 Entitys,减少一层转换 + if (_drawEntitys.Count == 0) + return null; + + IEnumerable es = _drawEntitys; + if (removeEntity != null) + es = es.Except(removeEntity); // 差集 + + return btrOfAddEntitySpace.AddEntity(es); + } + + + #region 配置 + + /// + /// 用户输入控制默认配置 + /// 令jig.Drag().Status == + /// + /// + static JigPromptPointOptions JigPointOptions() + { + return new JigPromptPointOptions() + { + UserInputControls = + UserInputControls.GovernedByUCSDetect // 由UCS探测用 + | UserInputControls.Accept3dCoordinates // 接受三维坐标 + | UserInputControls.NullResponseAccepted // 输入了鼠标右键,结束jig + | UserInputControls.AnyBlankTerminatesInput // 空格或回车,结束jig; + }; + } + + /// + /// 空格默认是, + /// 将它设置为 + /// + public void SetSpaceIsKeyword() + { + var opt = _options; + ArgumentNullEx.ThrowIfNull(opt); + if ((opt.UserInputControls & UserInputControls.NullResponseAccepted) == UserInputControls.NullResponseAccepted) + opt.UserInputControls ^= UserInputControls.NullResponseAccepted; // 输入了鼠标右键,结束jig + if ((opt.UserInputControls & UserInputControls.AnyBlankTerminatesInput) == UserInputControls.AnyBlankTerminatesInput) + opt.UserInputControls ^= UserInputControls.AnyBlankTerminatesInput; // 空格或回车,结束jig + } + + #endregion + + #region 注释数据 + + /// + /// 注释数据,可以在缩放的时候不受影响 + /// + public DynamicDimensionDataCollection DimensionEntitys { get; set; } + + /// + /// 重写注释数据 + /// + /// + /// + protected override DynamicDimensionDataCollection GetDynamicDimensionData(double dimScale) + { + base.GetDynamicDimensionData(dimScale); + return DimensionEntitys; + } + + #endregion + + #endregion + + #region IDisposable接口相关函数 + + /// + /// + /// + public bool IsDisposed { get; private set; } + + /// + /// 手动调用释放 + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// 析构函数调用释放 + /// + ~JigEx() + { + Dispose(false); + } + + /// + /// + /// + /// + protected virtual void Dispose(bool disposing) + { + // 不重复释放,并设置已经释放 + if (IsDisposed) + return; + IsDisposed = true; + if (disposing) + { + // 最后一次的图元如果没有加入数据库,就在此销毁,所以JigEx调用的时候加using + _drawEntitys.ForEach(ent => + { + if (ent.Database == null && !ent.IsDisposed) + ent.Dispose(); + }); + } + + _drawEntitys.Clear(); + } + + #endregion + + // 此处无测试 + // protected override void ViewportDraw(ViewportDraw draw) + // { + // base.ViewportDraw(draw); + // } +} + +#if false +| UserInputControls.DoNotEchoCancelForCtrlC // 不要取消CtrlC的回音 +| UserInputControls.DoNotUpdateLastPoint // 不要更新最后一点 +| UserInputControls.NoDwgLimitsChecking // 没有Dwg限制检查 +| UserInputControls.NoZeroResponseAccepted // 接受非零响应 +| UserInputControls.NoNegativeResponseAccepted // 不否定回复已被接受 +| UserInputControls.Accept3dCoordinates // 返回点的三维坐标,是转换坐标系了? +| UserInputControls.AcceptMouseUpAsPoint // 接受释放按键时的点而不是按下时 + +| UserInputControls.InitialBlankTerminatesInput // 初始 空格或回车,结束jig +| UserInputControls.AcceptOtherInputString // 接受其他输入字符串 +| UserInputControls.NoZDirectionOrtho // 无方向正射,直接输入数字时以基点到当前点作为方向 +| UserInputControls.UseBasePointElevation // 使用基点高程,基点的Z高度探测 +#endif \ No newline at end of file diff --git a/IFoxCAD.Cad/ExtensionMethod/Jig/JigExTransient.cs b/IFoxCAD.Cad/ExtensionMethod/Jig/JigExTransient.cs new file mode 100644 index 0000000..2c00e1b --- /dev/null +++ b/IFoxCAD.Cad/ExtensionMethod/Jig/JigExTransient.cs @@ -0,0 +1,183 @@ +namespace IFoxCAD.Cad; + +/// +/// 瞬态容器 +/// +public class JigExTransient : IDisposable +{ + #region 私有字段 + + // 整数集,暂时不知道有什么意义 + readonly IntegerCollection _integerCollection; + + // 维护集合 + readonly HashSet _drawableSet; + readonly TransientManager _manager; + + #endregion + + #region 公开属性 + + /// + /// 图元集合 + /// + public Entity[] Entities => _drawableSet.OfType().ToArray(); + + /// + /// 对象集合 + /// + public Drawable[] Drawables => _drawableSet.ToArray(); + + /// + /// 数量 + /// + public int Count => _drawableSet.Count; + + #endregion + + #region 构造函数 + + /// + /// 瞬态容器 + /// + public JigExTransient() + { + _integerCollection = new(); + _drawableSet = new(); + _manager = TransientManager.CurrentTransientManager; + } + + #endregion + + #region 方法 + + /// + /// 判断瞬态容器里是否含有对象 + /// + /// 对象 + /// 含有返回true + public bool Contains(Drawable drawable) + { + return _drawableSet.Contains(drawable); + } + + /// + /// 向瞬态容器中添加对象 + /// + /// 图元 + /// 绘图模式 + public void Add(Drawable drawable, TransientDrawingMode tdm = TransientDrawingMode.Main) + { + if (_drawableSet.Add(drawable)) + { + _manager.AddTransient(drawable, tdm, 128, _integerCollection); + } + } + + + /// + /// 从瞬态容器中移除图元 + /// + /// 已经加入瞬态容器的图元 + public void Remove(Drawable drawable) + { + if (!Contains(drawable)) + return; + _manager.EraseTransient(drawable, _integerCollection); + _drawableSet.Remove(drawable); + } + + /// + /// 清空瞬态容器并移除图元显示 + /// + public void Clear() + { + foreach (var drawable in _drawableSet) + { + _manager.EraseTransient(drawable, _integerCollection); + } + + _drawableSet.Clear(); + } + + /// + /// 清空瞬态容器并移除图元显示 + /// + public void ClearAndDispose() + { + foreach (var drawable in _drawableSet) + { + _manager.EraseTransient(drawable, _integerCollection); + if (!drawable.IsDisposed) + drawable.Dispose(); + } + + _drawableSet.Clear(); + } + + + /// + /// 更新单个显示 + /// + /// 已经加入瞬态容器的图元 + public void Update(Drawable drawable) + { + if (!Contains(drawable)) + return; + _manager.UpdateTransient(drawable, _integerCollection); + } + + /// + /// 更新全部显示 + /// + public void UpdateAll() + { + foreach (var drawable in _drawableSet) + Update(drawable); + } + + #endregion + + #region IDisposable接口相关函数 + + /// + /// 是否注销 + /// + public bool IsDisposed { get; private set; } + + /// + /// 手动释放 + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// 析构函数调用释放 + /// + ~JigExTransient() + { + Dispose(false); + } + + /// + /// 销毁瞬态容器 + /// + protected virtual void Dispose(bool disposing) + { + if (IsDisposed) + return; + IsDisposed = true; + + if (disposing) + { + ClearAndDispose(); // 清空瞬态容器并移除对象在图纸上的显示 + } + + _drawableSet.Clear(); + } + + #endregion +} \ No newline at end of file -- Gitee From 59f7f477ece556d9c6e4d2135ff6dc7d2f5e9c99 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sun, 24 Mar 2024 11:03:10 +0800 Subject: [PATCH 268/453] =?UTF-8?q?rider=E7=94=A8=E6=88=B7=E8=AF=8D?= =?UTF-8?q?=E5=85=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IFoxCAD.sln.DotSettings | 2 ++ 1 file changed, 2 insertions(+) diff --git a/IFoxCAD.sln.DotSettings b/IFoxCAD.sln.DotSettings index 62845c2..35967cc 100644 --- a/IFoxCAD.sln.DotSettings +++ b/IFoxCAD.sln.DotSettings @@ -6,12 +6,14 @@ True True True + True True True True True True True + True True True True \ No newline at end of file -- Gitee From 467a72318771a60a46ed543979d66d8e4c0a0612 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sun, 24 Mar 2024 11:04:04 +0800 Subject: [PATCH 269/453] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IFoxCAD.Cad/Initialize/AutoReg.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/IFoxCAD.Cad/Initialize/AutoReg.cs b/IFoxCAD.Cad/Initialize/AutoReg.cs index 2e8733f..b84d3f3 100644 --- a/IFoxCAD.Cad/Initialize/AutoReg.cs +++ b/IFoxCAD.Cad/Initialize/AutoReg.cs @@ -29,7 +29,7 @@ public static bool SearchForReg(AssemInfo info) var regApps = appKey.GetSubKeyNames(); if (!regApps.Contains(info.Name)) return false; - // 20220409 bug:文件名相同,路径不同,需要判断路径 + // 20220409 文件名相同,路径不同,需要判断路径 var subKey = appKey.OpenSubKey(info.Name); return string.Equals(subKey?.GetValue("LOADER")?.ToString(), info.Loader, StringComparison.CurrentCultureIgnoreCase); } -- Gitee From 1d708e6560280dae1e2f8ae724eb2ff00d6aa87d Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sun, 24 Mar 2024 11:18:43 +0800 Subject: [PATCH 270/453] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=88=9D=E5=A7=8B?= =?UTF-8?q?=E5=8C=96=E5=86=85=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IFoxCAD.Cad/Basal/General/DebugHelper.cs | 32 ++ IFoxCAD.Cad/Initialize/AutoRegAssem.cs | 109 ++++++ IFoxCAD.Cad/Initialize/IAutoGo.cs | 407 +++++++++++++++++++++ IFoxCAD.Cad/Initialize/MethodInfoHelper.cs | 64 ++++ IFoxCAD.sln.DotSettings | 3 +- 5 files changed, 614 insertions(+), 1 deletion(-) create mode 100644 IFoxCAD.Cad/Basal/General/DebugHelper.cs create mode 100644 IFoxCAD.Cad/Initialize/AutoRegAssem.cs create mode 100644 IFoxCAD.Cad/Initialize/IAutoGo.cs create mode 100644 IFoxCAD.Cad/Initialize/MethodInfoHelper.cs diff --git a/IFoxCAD.Cad/Basal/General/DebugHelper.cs b/IFoxCAD.Cad/Basal/General/DebugHelper.cs new file mode 100644 index 0000000..cadff7e --- /dev/null +++ b/IFoxCAD.Cad/Basal/General/DebugHelper.cs @@ -0,0 +1,32 @@ +namespace IFoxCAD.Basal; +/// +/// 调试工具 +/// +public static class DebugEx +{ + /// + /// cad命令切换: DebugEx + /// + /// 打印信息 + /// 打印时间 + [DebuggerHidden] + public static void Printl(object message, bool time = true) + { + var flag = Environment.GetEnvironmentVariable("debugx", EnvironmentVariableTarget.User); + if (flag is null or "0") + return; + + if (time) + //message = $"{DateTime.Now.ToLongDateString() + DateTime.Now.TimeOfDay}\n" + + message = $"{DateTime.Now.TimeOfDay} ThreadId:{Environment.CurrentManagedThreadId}\n" + + $"\t\t{message}"; + + //System.Diagnostics.Debug.Indent(); +#if DEBUG + Debug.WriteLine(message); +#else + System.Diagnostics.Trace.WriteLine(message); +#endif + //System.Diagnostics.Debug.Unindent(); + } +} \ No newline at end of file diff --git a/IFoxCAD.Cad/Initialize/AutoRegAssem.cs b/IFoxCAD.Cad/Initialize/AutoRegAssem.cs new file mode 100644 index 0000000..5431ecb --- /dev/null +++ b/IFoxCAD.Cad/Initialize/AutoRegAssem.cs @@ -0,0 +1,109 @@ +namespace IFoxCAD.Cad; + +/// +/// 注册中心 +/// +/// 初始化程序集信息写入注册表并反射特性和接口
+/// 启动cad后的执行顺序为:
+/// 1:程序集配置中心构造函数
+/// 2:特性..(多个)
+/// 3:接口..(多个)
+///
+///
+public abstract class AutoRegAssem : IExtensionApplication +{ + #region 字段 + + private readonly AutoReflection? _autoRef; + + #endregion + + #region 静态方法 + + /// + /// 程序集的路径 + /// + public static FileInfo Location => new(Assembly.GetCallingAssembly().Location); + + /// + /// 程序集的目录 + /// + public static DirectoryInfo? CurrDirectory => Location.Directory; + + /// + /// 获取程序集的目录 + /// + /// 程序集 + /// 路径对象 + public static DirectoryInfo? GetDirectory(Assembly? assem) + { + ArgumentNullEx.ThrowIfNull(assem); + return new FileInfo(assem.Location).Directory; + } + + #endregion + + #region 构造函数 + + /// + /// 注册中心 + /// + /// 配置项目 + protected AutoRegAssem(AutoRegConfig autoRegConfig) + { + var assem = Assembly.GetCallingAssembly(); + var info = new AssemInfo + { + Loader = assem.Location, + Fullname = assem.FullName, + Name = assem.GetName().Name, + LoadType = AssemLoadType.Starting + }; + + if ((autoRegConfig & AutoRegConfig.Regedit) == AutoRegConfig.Regedit) + { + if (!AutoReg.SearchForReg(info)) + AutoReg.RegApp(info); + } + + if ((autoRegConfig & AutoRegConfig.RemoveEMR) == AutoRegConfig.RemoveEMR) + AcadEMR.Remove(); + + // 实例化了 AutoClass 之后会自动执行 IFoxAutoGo 接口下面的类, + // 以及自动执行特性 [IFoxInitialize] + // 类库用户不在此处进行其他代码,而是实现特性 + if ((autoRegConfig & AutoRegConfig.ReflectionInterface) != AutoRegConfig.ReflectionInterface && + (autoRegConfig & AutoRegConfig.ReflectionAttribute) != AutoRegConfig.ReflectionAttribute) return; + _autoRef = new AutoReflection(info.Name, autoRegConfig); + _autoRef.Initialize(); + } + + #endregion + + #region RegApp + + // 这里的是不会自动执行的 + /// + /// + /// + public void Initialize() + { + } + + /// + /// + /// + public void Terminate() + { + } + + /// + /// + /// + ~AutoRegAssem() + { + _autoRef?.Terminate(); + } + + #endregion RegApp +} \ No newline at end of file diff --git a/IFoxCAD.Cad/Initialize/IAutoGo.cs b/IFoxCAD.Cad/Initialize/IAutoGo.cs new file mode 100644 index 0000000..e9608be --- /dev/null +++ b/IFoxCAD.Cad/Initialize/IAutoGo.cs @@ -0,0 +1,407 @@ +namespace IFoxCAD.Cad; + +using System.Diagnostics; + +/// +/// 加载时优先级 +/// +[Flags] +public enum Sequence : byte +{ + /// + /// 最先 + /// + First, + + /// + /// 最后 + /// + Last, +} + +/// +/// 加载时自动执行接口 +/// +public interface IFoxAutoGo +{ + /// + /// 控制加载顺序 + /// + /// + Sequence SequenceId(); + + /// + /// 关闭cad的时候会自动执行 + /// + void Terminate(); + + /// + /// 打开cad的时候会自动执行 + /// + void Initialize(); +} + +/// +/// 加载时自动执行特性 +/// +/// +/// 用于初始化和结束回收 +/// +/// 优先级 +/// 用于初始化;用于结束回收 +[AttributeUsage(AttributeTargets.Method)] +// ReSharper disable once InconsistentNaming +// ReSharper disable once ClassNeverInstantiated.Global +public class IFoxInitializeAttribute(Sequence sequence = Sequence.Last, bool isInitialize = true) : Attribute +{ + /// + /// 优先级 + /// + internal readonly Sequence SequenceId = sequence; + + /// + /// 用于初始化;用于结束回收 + /// + internal readonly bool IsInitialize = isInitialize; +} + +// 为了解决IExtensionApplication在一个dll内无法多次实现接口的关系 +// 所以在这里反射加载所有的 IAutoGo ,以达到能分开写"启动运行"函数的目的 +/// +/// 执行此方法 +/// +/// +/// +/// 已经创建的对象 +internal class RunClass(MethodInfo method, Sequence sequence, object? instance = null) +{ + public Sequence Sequence { get; } = sequence; + + /// + /// 运行方法 + /// + public void Run() + { + method.Invoke(ref instance); + } +} + +/// +/// 此类作为加载后cad自动运行接口的一部分,用于反射特性和接口 +/// +/// 启动cad后的执行顺序为:
+/// 1:特性..(多个)
+/// 2:接口..(多个) +///
+///
+/// +/// 反射执行 +/// +/// 1.特性:
+/// 2.接口: +///
+///
+/// 约束在此dll进行加速 +/// +public class AutoReflection(string dllName, AutoRegConfig configInfo) +{ + private static List _initializeList = []; // 储存方法用于初始化 + private static List _terminateList = []; // 储存方法用于结束释放 + + readonly string _dllName = dllName; + readonly AutoRegConfig _autoRegConfig = configInfo; + + /// + /// 启动cad的时候会自动执行 + /// + public void Initialize() + { + try + { + // 收集特性,包括启动时和关闭时 + if ((_autoRegConfig & AutoRegConfig.ReflectionAttribute) == AutoRegConfig.ReflectionAttribute) + GetAttributeFunctions(_initializeList, _terminateList); + + if ((_autoRegConfig & AutoRegConfig.ReflectionInterface) == AutoRegConfig.ReflectionInterface) + { + GetInterfaceFunctions(_initializeList, nameof(Initialize), _terminateList, nameof(Terminate)); + } + + if (_initializeList.Count <= 0) return; + // 按照 SequenceId 排序_升序 + _initializeList = _initializeList.OrderBy(runClass => runClass.Sequence).ToList(); + RunFunctions(_initializeList); + } + catch + { + Debugger.Break(); + } + } + + /// + /// 关闭cad的时候会自动执行 + /// + public void Terminate() + { + try + { + //if ((_autoRegConfig & AutoRegConfig.ReflectionInterface) == AutoRegConfig.ReflectionInterface) + // GetInterfaceFunctions(_TerminateList, nameof(Terminate)); + + if (_terminateList.Count <= 0) return; + // 按照 SequenceId 排序_降序 + _terminateList = [.. _terminateList.OrderByDescending(runClass => runClass.Sequence)]; + RunFunctions(_terminateList); + } + catch (Exception e) + { + Env.Printl(e.Message); + Debugger.Break(); + } + } + + /// + /// 遍历程序域下所有类型 + /// + /// 输出每个成员执行 + /// 过滤此dll,不含后缀 + public static void AppDomainGetTypes(Action action, string? dllNameWithoutExtension = null) + { +#if DEBUG + var error = 0; +#endif + try + { + var assemblies = AppDomain.CurrentDomain.GetAssemblies(); + + // cad2021出现如下报错 + // System.NotSupportedException:动态程序集中不支持已调用的成员 + // assemblies = assemblies.Where(p => !p.IsDynamic).ToArray();// 这个要容器类型转换 + assemblies = Array.FindAll(assemblies, p => !p.IsDynamic); + + // 主程序域 + foreach (var assembly in assemblies) + { + // 获取类型集合,反射时候还依赖其他的dll就会这个错误 + // 此通讯库要跳过,否则会报错. + var location = Path.GetFileNameWithoutExtension(assembly.Location); + if (dllNameWithoutExtension != null && location != dllNameWithoutExtension) + continue; + if (location == "AcInfoCenterConn") // 通讯库 + continue; + + Type[]? types; + try + { + types = assembly.GetTypes(); + } + catch (ReflectionTypeLoadException) + { + continue; + } + + foreach (var type in types) + { + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract + if (type is not null) + { +#if DEBUG + ++error; +#endif + action.Invoke(type); + } + } + } + } +#if DEBUG + catch (Exception e) + { + DebugEx.Printl($"出错:{nameof(AppDomainGetTypes)};计数{error};错误信息:{e.Message}"); + Debugger.Break(); +#else + catch + { +#endif + } + } + + /// + /// 收集接口下的函数 + /// + /// + /// + /// + /// + void GetInterfaceFunctions(List initializes, string initializeName, + List terminates, string terminateName) + { + AppDomainGetTypes(type => + { + // 接口的静态类屏蔽,继承接口无法使用静态类,因此跳过 + if (type.IsAbstract) + return; + + var ints = type.GetInterfaces(); + foreach (var t in ints) + { + if (t.Name != nameof(IFoxAutoGo)) + continue; + + Sequence? sequence = null; + MethodInfo? initialize = null; + MethodInfo? terminate = null; + object? instance = null; + + var methods = type.GetMethods(); + foreach (var method in methods) + { + // 接口的静态方法屏蔽,继承的方法也不可能是静态的,因此跳过 + if (method.IsAbstract) + continue; + + if (method.Name == nameof(IFoxAutoGo.SequenceId)) + { + // 避免触发两次构造函数,所以这里需要ref构造的对象出来 + var obj = method.Invoke(ref instance); + if (obj is not null) + sequence = (Sequence)obj; + continue; + } + + if (method.Name == initializeName) + { + initialize = method; + continue; + } + + if (method.Name == terminateName) + { + terminate = method; + continue; + } + + if (sequence is not null && initialize is not null && terminate is not null) + break; + } + + // 避免在terminate释放的时候去再次构造,所以需要一次性收集 + // 若是释放的时候去再次构造: + // 0x01 initialize构造的字段拥有的资源就处于系统释放了,这是不合理的 + // 0x02 同时也发生了,为了释放而去构造这个操作 + var seq = sequence ?? Sequence.Last; + if (initialize is not null) + initializes.Add(new(initialize, seq, instance)); + if (terminate is not null) + terminates.Add(new(terminate, seq, instance)); + break; + } + }, _dllName); + } + + /// + /// 收集特性下的函数 + /// + void GetAttributeFunctions(List initializes, + List terminates) + { + AppDomainGetTypes(type => + { + if (!type.IsClass) + return; + + // 特性的静态类不屏蔽 + //if (type.IsAbstract) + // return; + + var methods = type.GetMethods(); + foreach (var method in methods) + { + // 特性的静态方法不屏蔽 + //if (method.IsAbstract) + // continue; + + var attr = method.GetCustomAttributes(true); + foreach (var t in attr) + { + if (t is IFoxInitializeAttribute jjAtt) + { + var runClass = new RunClass(method, jjAtt.SequenceId); + if (jjAtt.IsInitialize) + initializes.Add(runClass); + else + terminates.Add(runClass); + break; + } + } + } + }, _dllName); + } + + /// + /// 执行收集到的函数 + /// + static void RunFunctions(List runClassList) + { + foreach (var t in runClassList) + t.Run(); + + runClassList.Clear(); + } + +#if Debug + /// + /// 检查当前程序域重复出现命令, + /// 当出现重复时候将引起断点 + /// + public static void DebugCheckCmdRecurrence() + { + HashSet keys = new(); + + // 本dll中存在冲突命令,此时cad自动接口可以运行,但是加载命令之后会报错,因此利用断点告诉程序员 + AutoReflection.AppDomainGetTypes(type => { + var mets = type.GetMethods(); + for (int ii = 0; ii < mets.Length; ii++) + { + var method = mets[ii]; + var attr = method.GetCustomAttributes(true); + for (int jj = 0; jj < attr.Length; jj++) + if (attr[jj] is CommandMethodAttribute att) + { + if (keys.Contains(att.GlobalName)) + Debugger.Break(); + keys.Add(att.GlobalName); + } + } + }, Assembly.GetCallingAssembly().GetName().Name); + + // 其他dll中存在冲突命令,此时会覆盖命令,友好的提示程序员 + keys.Clear(); + HashSet msgMod = new(); + AutoReflection.AppDomainGetTypes(type => { + var mets = type.GetMethods(); + for (int ii = 0; ii < mets.Length; ii++) + { + var method = mets[ii]; + var attr = method.GetCustomAttributes(true); + for (int jj = 0; jj < attr.Length; jj++) + if (attr[jj] is CommandMethodAttribute att) + { + if (keys.Contains(att.GlobalName)) + msgMod.Add(att.GlobalName); + keys.Add(att.GlobalName); + } + } + }); + var sb = new StringBuilder(); + foreach (string key in msgMod) + sb.AppendLine(key); + if (sb.Length != 0) + { + Env.Printl("当前cad环境加载的多个DLL中存在重复命令将被覆盖:"); + Env.Printl("{"); + Env.Printl(sb.ToString()); + Env.Printl("}"); + } + } +#endif +} \ No newline at end of file diff --git a/IFoxCAD.Cad/Initialize/MethodInfoHelper.cs b/IFoxCAD.Cad/Initialize/MethodInfoHelper.cs new file mode 100644 index 0000000..2da1d70 --- /dev/null +++ b/IFoxCAD.Cad/Initialize/MethodInfoHelper.cs @@ -0,0 +1,64 @@ +namespace IFoxCAD.Cad; + +internal static class MethodInfoHelper +{ +#if cache + private static readonly Dictionary methodDic = new(); +#endif + + /// + /// 执行函数 + /// + /// 函数 + /// 已经外部创建的对象,为空则此处创建 + public static object? Invoke(this MethodInfo methodInfo, ref object? instance) + { + ArgumentNullEx.ThrowIfNull(methodInfo); + object? result = null; + if (methodInfo.IsStatic) + { + // 新函数指针进入此处 + // 参数数量一定要匹配,为null则参数个数不同导致报错, + // 参数为string[],则可以传入object[]代替,其他参数是否还可以实现默认构造? + var args = new List(); + var paramInfos = methodInfo.GetParameters(); + for (var i = 0; i < paramInfos.Length; i++) + args.Add(null!); + result = methodInfo.Invoke(null, args.ToArray()); // 静态调用 + } + else + { +#if cache + // 原命令的函数指针进入此处 + // object instance; + if (methodDic.ContainsKey(methodInfo)) + instance = methodDic[methodInfo]; +#endif + if (instance == null) + { + var refType = methodInfo.ReflectedType; + if (refType == null) + return null; + + var fullName = refType.FullName; // 命名空间+类 + if (fullName == null) + return null; + + var type = refType.Assembly.GetType(fullName); + if (type == null) + return null; + + instance = Activator.CreateInstance(type); // 构造类 +#if cache + if (!type.IsAbstract)// 无法创建抽象类成员 + methodDic.Add(methodInfo, instance); +#endif + } + + if (instance != null) + result = methodInfo.Invoke(instance, null); // 非静态,调用实例化方法 + } + + return result; + } +} \ No newline at end of file diff --git a/IFoxCAD.sln.DotSettings b/IFoxCAD.sln.DotSettings index 35967cc..916f197 100644 --- a/IFoxCAD.sln.DotSettings +++ b/IFoxCAD.sln.DotSettings @@ -16,4 +16,5 @@ True True True - True \ No newline at end of file + True + True \ No newline at end of file -- Gitee From 4374030f62660ebf1041f5905d349b97e6eee8ed Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 28 Mar 2024 23:04:30 +0800 Subject: [PATCH 271/453] =?UTF-8?q?=E8=A1=A5=E5=85=85=E5=BF=85=E9=A1=BB?= =?UTF-8?q?=E7=9A=84=E6=89=A9=E5=B1=95=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IFoxCAD.Cad/Basal/General/ArrayEx.cs | 58 + IFoxCAD.Cad/Basal/General/EnumEx.cs | 111 ++ IFoxCAD.Cad/Basal/General/LinqEx.cs | 327 +++++ IFoxCAD.Cad/Basal/General/LoopList.cs | 745 +++++++++++ IFoxCAD.Cad/Basal/Win/SystemEx.cs | 27 + IFoxCAD.Cad/Basal/Win/Win32Api.cs | 32 + IFoxCAD.Cad/ExtensionMethod/EditorEx.cs | 1169 +++++++++++++++++ .../ExtensionMethod/Entity/PolylineEx.cs | 163 +++ IFoxCAD.Cad/ExtensionMethod/Enums.cs | 202 +++ .../ExtensionMethod/Geomerty/GeometryEx.cs | 676 ++++++++++ .../ExtensionMethod/Geomerty/PointEx.cs | 81 ++ IFoxCAD.Cad/ExtensionMethod/SelectionSetEx.cs | 114 ++ IFoxCAD.Cad/ExtensionMethod/SymbolTableEx.cs | 368 ++++++ IFoxCAD.Cad/ExtensionMethod/TangentEx.cs | 24 + IFoxCAD.Cad/ExtensionMethod/WindowEx.cs | 86 ++ IFoxCAD.Cad/IFoxCAD.Cad.csproj | 4 + IFoxCAD.Cad/ResultData/LispList.cs | 194 +++ IFoxCAD.Cad/Runtime/IdleNoCommandAction.cs | 69 + IFoxCAD.Cad/SelectionFilter/OpComp.cs | 76 ++ IFoxCAD.Cad/SelectionFilter/OpEqual.cs | 83 ++ IFoxCAD.Cad/SelectionFilter/OpFilter.cs | 341 +++++ IFoxCAD.Cad/SelectionFilter/OpList.cs | 160 +++ IFoxCAD.Cad/SelectionFilter/OpLogi.cs | 121 ++ 23 files changed, 5231 insertions(+) create mode 100644 IFoxCAD.Cad/Basal/General/ArrayEx.cs create mode 100644 IFoxCAD.Cad/Basal/General/EnumEx.cs create mode 100644 IFoxCAD.Cad/Basal/General/LinqEx.cs create mode 100644 IFoxCAD.Cad/Basal/General/LoopList.cs create mode 100644 IFoxCAD.Cad/Basal/Win/SystemEx.cs create mode 100644 IFoxCAD.Cad/Basal/Win/Win32Api.cs create mode 100644 IFoxCAD.Cad/ExtensionMethod/EditorEx.cs create mode 100644 IFoxCAD.Cad/ExtensionMethod/Entity/PolylineEx.cs create mode 100644 IFoxCAD.Cad/ExtensionMethod/Enums.cs create mode 100644 IFoxCAD.Cad/ExtensionMethod/Geomerty/GeometryEx.cs create mode 100644 IFoxCAD.Cad/ExtensionMethod/SelectionSetEx.cs create mode 100644 IFoxCAD.Cad/ExtensionMethod/SymbolTableEx.cs create mode 100644 IFoxCAD.Cad/ExtensionMethod/TangentEx.cs create mode 100644 IFoxCAD.Cad/ExtensionMethod/WindowEx.cs create mode 100644 IFoxCAD.Cad/ResultData/LispList.cs create mode 100644 IFoxCAD.Cad/Runtime/IdleNoCommandAction.cs create mode 100644 IFoxCAD.Cad/SelectionFilter/OpComp.cs create mode 100644 IFoxCAD.Cad/SelectionFilter/OpEqual.cs create mode 100644 IFoxCAD.Cad/SelectionFilter/OpFilter.cs create mode 100644 IFoxCAD.Cad/SelectionFilter/OpList.cs create mode 100644 IFoxCAD.Cad/SelectionFilter/OpLogi.cs diff --git a/IFoxCAD.Cad/Basal/General/ArrayEx.cs b/IFoxCAD.Cad/Basal/General/ArrayEx.cs new file mode 100644 index 0000000..36bf8e7 --- /dev/null +++ b/IFoxCAD.Cad/Basal/General/ArrayEx.cs @@ -0,0 +1,58 @@ +namespace IFoxCAD.Basal; + +/* + * 由于linq的函数大部分带有状态机,而cad是一个单机程序, + * 使用状态机会变得缓慢,因此我们设计的时候着重于时间优化, + * 本工具类在着重于数组遍历时候替代linq + */ +/// +/// 数组扩展类 +/// +public static class ArrayEx +{ + /// + /// 合并数组 + /// + /// + /// + public static T[] Combine2(this T[] a, T[] b) + { + var c = new T[a.Length + b.Length]; + Array.Copy(a, 0, c, 0, a.Length); + Array.Copy(b, 0, c, a.Length, b.Length); + return c; + } + + /// + /// 一维数组按规则消除
+ /// 本例适用于数值类型比较,特定规则比较
+ /// 如果是哈希比较,建议更改为: + /// set = new(); + /// foreach (var item in listInOut) + /// set.Add(item); + /// ]]> + ///
+ /// + /// 传入有重复成员的数组,原数组修改 + /// + /// 传出参数1:数组开头
+ /// 传出参数2:数组结尾
+ /// 返回值比较结尾为就移除
+ /// + [DebuggerStepThrough] + public static void Deduplication(List lst, Func func) + { + // 头和尾比较,满足条件移除尾巴 + for (var i = 0; i < lst.Count; i++) + { + var first = lst[i]; + for (var j = lst.Count - 1; j > i/*符号是 >= 而且是i*/; j--) + { + var last = lst[j]; + if (func(first, last)) + lst.RemoveAt(j); + } + } + } +} \ No newline at end of file diff --git a/IFoxCAD.Cad/Basal/General/EnumEx.cs b/IFoxCAD.Cad/Basal/General/EnumEx.cs new file mode 100644 index 0000000..34a81ef --- /dev/null +++ b/IFoxCAD.Cad/Basal/General/EnumEx.cs @@ -0,0 +1,111 @@ +namespace IFoxCAD.Basal; + +/// +/// 枚举扩展 +/// +public static class EnumEx +{ + /// + /// 清理缓存 + /// + public static void CleanCache() + { + Cache.Clear(); + } + + // (类型完整名,描述组合) + private static readonly Dictionary> Cache = []; + + /// + /// 打印枚举的特性注释内容 + /// + /// 枚举 + /// + /// 注释内容 + public static HashSet? GetAttribute(this Enum e, bool noDescrToString = true) + where T : DescriptionAttribute + { + var eType = e.GetType(); + var eFullName = eType.FullName + "." + e; + + if (Cache.TryGetValue(eFullName, out var attribute1)) + return attribute1; + + var fieldInfo = eType.GetField(Enum.GetName(eType, e)); + if (fieldInfo == null) + return null!; + + // 注释存放的容器 + HashSet nodes = new(); + if (Attribute.GetCustomAttribute(fieldInfo, typeof(T)) is T attribute) + { + nodes.Add(attribute.Description); + Cache.Add(eFullName, nodes); + return nodes; + } + + // 通常到这里的就是 ALL = A | B | C + // 遍历所有的枚举,组合每个注释 + List enumHas = []; + enumHas.AddRange(Enum.GetValues(eType).Cast().Where(em => + (e.GetHashCode() & em.GetHashCode()) == em.GetHashCode() && e.GetHashCode() != em.GetHashCode())); + + // 遍历这个枚举类型,获取枚举按位包含的成员 + + + // 采取的行为是:注释的行为是特殊的,就按照注释的,否则,遍历子元素提取注释 + // 大的在前面才能判断是否按位包含后面的,后面的就是要移除的 + enumHas = [.. enumHas.OrderByDescending(a => a.GetHashCode())]; + ArrayEx.Deduplication(enumHas, (a, b) => (a.GetHashCode() & b.GetHashCode()) == b.GetHashCode()); + + // 逆序仅仅为排序后处理,不一定和书写顺序一样,尤其是递归可能存在重复的元素 + for (var i = enumHas.Count - 1; i >= 0; i--) + { + var atts = GetAttribute(enumHas[i], noDescrToString);// 递归 + if (atts == null) + continue; + foreach (var item in atts) + nodes.Add(item); + } + + if (nodes.Count == 0 && noDescrToString) + nodes.Add(e.ToString()); + + Cache.Add(eFullName, nodes); + return nodes; + } + + /// + /// 打印枚举的特性注释内容 + /// + public static string? PrintNote(this Enum e, bool noDescToString = true) + { + var hash = GetAttribute(e, noDescToString); + return hash == null ? null : string.Join("|", [.. hash]); + } + + /// + /// 获取枚举的描述内容 + /// + /// 不按位运算的情况下,直接获取比较快捷 + /// + /// + public static string GetDescription(this Enum e) + { + return GetDescription(e.GetType(), e.ToString()); + } + + /// + /// 获取字段的描述内容 + /// + /// + /// + /// + public static string GetDescription(this Type type, string field) + { + var memberInfo = type.GetMember(field); + var attributes = memberInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false); + // 如果没有定义描述,就把当前枚举值的对应名称返回 + return attributes.Length != 1 ? field : ((DescriptionAttribute)attributes.Single()).Description; + } +} \ No newline at end of file diff --git a/IFoxCAD.Cad/Basal/General/LinqEx.cs b/IFoxCAD.Cad/Basal/General/LinqEx.cs new file mode 100644 index 0000000..746bacf --- /dev/null +++ b/IFoxCAD.Cad/Basal/General/LinqEx.cs @@ -0,0 +1,327 @@ +namespace IFoxCAD.Basal; + +/// +/// linq 扩展类 +/// +public static class LinqEx +{ + #region FindByMax + + /// + /// 按转换函数找出序列中最大键值的对应值 + /// + /// + /// + /// 序列 + /// 转换函数 + /// 最大键值的对应值 + public static TValue FindByMax(this IEnumerable source, Func func) + where TKey : IComparable + { + using var itr = source.GetEnumerator(); + if (!itr.MoveNext()) + throw new ArgumentNullException(nameof(source), "对象为 null"); + + var value = itr.Current; + var key = func(value); + + while (itr.MoveNext()) + { + var tKey = func(itr.Current); + if (tKey.CompareTo(key) <= 0) continue; + key = tKey; + value = itr.Current; + } + return value; + } + + /// + /// 按转换函数找出序列中最大键值的对应值 + /// + /// + /// + /// 序列 + /// 对应的最大键值 + /// 转换函数 + /// 最大键值的对应值 + public static TValue FindByMax(this IEnumerable source, out TKey maxResult, Func func) + where TKey : IComparable + { + using var itr = source.GetEnumerator(); + if (!itr.MoveNext()) + throw new ArgumentNullException(nameof(source), "对象为 null"); + + var value = itr.Current; + var key = func(value); + + while (itr.MoveNext()) + { + var tKey = func(itr.Current); + if (tKey.CompareTo(key) <= 0) continue; + key = tKey; + value = itr.Current; + } + maxResult = key; + return value; + } + + /// + /// 按比较器找出序列中最大键值的对应值 + /// + /// + /// 序列 + /// 比较器 + /// 最大键值的对应值 + public static TValue FindByMax(this IEnumerable source, Comparison comparison) + { + using var itr = source.GetEnumerator(); + if (!itr.MoveNext()) + throw new ArgumentNullException(nameof(source), "对象为 null"); + + var value = itr.Current; + + while (itr.MoveNext()) + { + if (comparison(itr.Current, value) > 0) + value = itr.Current; + } + return value; + } + + #endregion FindByMax + + #region FindByMin + + /// + /// 按转换函数找出序列中最小键值的对应值 + /// + /// + /// + /// 序列 + /// 对应的最小键值 + /// 转换函数 + /// 最小键值的对应值 + public static TValue FindByMin(this IEnumerable source, out TKey minKey, Func func) + where TKey : IComparable + { + using var itr = source.GetEnumerator(); + if (!itr.MoveNext()) + throw new ArgumentNullException(nameof(source), "对象为 null"); + + var value = itr.Current; + var key = func(value); + + while (itr.MoveNext()) + { + var tKey = func(itr.Current); + if (tKey.CompareTo(key) >= 0) continue; + key = tKey; + value = itr.Current; + } + minKey = key; + return value; + } + + /// + /// 按转换函数找出序列中最小键值的对应值 + /// + /// + /// + /// 序列 + /// 转换函数 + /// 最小键值的对应值 + public static TValue FindByMin(this IEnumerable source, Func func) + where TKey : IComparable + { + using var itr = source.GetEnumerator(); + if (!itr.MoveNext()) + throw new ArgumentNullException(nameof(source), "对象为 null"); + + var value = itr.Current; + var key = func(value); + + while (itr.MoveNext()) + { + var tKey = func(itr.Current); + if (tKey.CompareTo(key) >= 0) continue; + key = tKey; + value = itr.Current; + } + return value; + } + + /// + /// 按比较器找出序列中最小键值的对应值 + /// + /// + /// 序列 + /// 比较器 + /// 最小键值的对应值 + public static TValue FindByMin(this IEnumerable source, Comparison comparison) + { + using var itr = source.GetEnumerator(); + if (!itr.MoveNext()) + throw new ArgumentNullException(nameof(source), "对象为 null"); + + var value = itr.Current; + + while (itr.MoveNext()) + { + if (comparison(itr.Current, value) < 0) + value = itr.Current; + } + return value; + } + + #endregion FindByMin + + #region FindByExt + + /// + /// 按转换函数找出序列中最(小/大)键值的对应值 + /// + /// + /// + /// 序列 + /// 转换函数 + /// 最(小/大)键值的对应值 + public static TValue[] FindByExt(this IEnumerable source, Func func) + where TKey : IComparable + { + using var itr = source.GetEnumerator(); + if (!itr.MoveNext()) + throw new ArgumentNullException(nameof(source), "对象为 null"); + + var values = new TValue[2]; + values[0] = values[1] = itr.Current; + + var keys = new TKey[2]; + keys[0] = keys[1] = func(itr.Current); + + while (itr.MoveNext()) + { + var tKey = func(itr.Current); + if (tKey.CompareTo(keys[0]) < 0) + { + keys[0] = tKey; + values[0] = itr.Current; + } + else if (tKey.CompareTo(keys[1]) > 0) + { + keys[1] = tKey; + values[1] = itr.Current; + } + } + return values; + } + + /// + /// 按比较器找出序列中最(小/大)键值的对应值 + /// + /// + /// 序列 + /// 比较器 + /// 最(小/大)键值的对应值 + public static TValue[] FindByExt(this IEnumerable source, Comparison comparison) + { + using var itr = source.GetEnumerator(); + if (!itr.MoveNext()) + throw new ArgumentNullException(nameof(source), "对象为 null"); + + var values = new TValue[2]; + values[0] = values[1] = itr.Current; + + while (itr.MoveNext()) + { + if (comparison(itr.Current, values[0]) < 0) + values[0] = itr.Current; + else if (comparison(itr.Current, values[1]) > 0) + values[1] = itr.Current; + } + return values; + } + + /// + /// 按转换函数找出序列中最(小/大)键值的对应键值 + /// + /// + /// + /// 序列 + /// 转换函数 + /// 最(小/大)键值 + public static TKey[] FindExt(this IEnumerable source, Func func) + where TKey : IComparable + { + using var itr = source.GetEnumerator(); + if (!itr.MoveNext()) + throw new ArgumentNullException(nameof(source), "对象为 null"); + + var keys = new TKey[2]; + keys[0] = keys[1] = func(itr.Current); + + while (itr.MoveNext()) + { + var tKey = func(itr.Current); + if (tKey.CompareTo(keys[0]) < 0) + keys[0] = tKey; + else if (tKey.CompareTo(keys[1]) > 0) + keys[1] = tKey; + } + return keys; + } + + #endregion FindByExt + + #region Order + + /// + /// 自定义的比较泛型类 + /// + /// 泛型 + private class SpecComparer : IComparer + { + private readonly Comparison _comp; + + internal SpecComparer(Comparison comp) + { + _comp = comp; + } + + #region IComparer 成员 + public int Compare(T x, T y) + { + return _comp(x, y); + } + #endregion IComparer 成员 + } + + /// + /// 使用指定的比较器将序列按升序排序 + /// + /// 输入泛型 + /// 输出泛型 + /// 序列 + /// 用于从元素中提取键的函数 + /// 比较器 + /// 排序的序列 + public static IOrderedEnumerable OrderBy(this IEnumerable source, Func keySelector, Comparison comparison) + { + return source.OrderBy(keySelector, new SpecComparer(comparison)); + } + + /// + /// 使用指定的比较器将其后的序列按升序排序 + /// + /// 输入泛型 + /// 输出泛型 + /// 序列 + /// 用于从元素中提取键的函数 + /// 比较器 + /// 排序的序列 + public static IOrderedEnumerable ThenBy(this IOrderedEnumerable source, Func keySelector, Comparison comparison) + { + return source.ThenBy(keySelector, new SpecComparer(comparison)); + } + + #endregion Order +} diff --git a/IFoxCAD.Cad/Basal/General/LoopList.cs b/IFoxCAD.Cad/Basal/General/LoopList.cs new file mode 100644 index 0000000..da1e258 --- /dev/null +++ b/IFoxCAD.Cad/Basal/General/LoopList.cs @@ -0,0 +1,745 @@ +namespace IFoxCAD.Basal; + +#line hidden // 调试的时候跳过它 + +/// +/// 环链表节点 +/// +/// +public class LoopListNode +{ + #region 成员 + /// + /// 取值 + /// + public T Value; + + /// + /// 上一个节点 + /// + public LoopListNode? Previous { internal set; get; } + + /// + /// 下一个节点 + /// + public LoopListNode? Next { internal set; get; } + + /// + /// 环链表序列 + /// + public LoopList? List { internal set; get; } + #endregion + + #region 构造 + /// + /// 环链表节点构造函数 + /// + /// 节点值 + /// 环链表 + public LoopListNode(T value, LoopList ts) + { + Value = value; + List = ts; + } + + /// + /// 获取当前节点的临近节点 + /// + /// 搜索方向标志,为向前搜索,为向后搜索 + /// + public LoopListNode? GetNext(bool forward) + { + return forward ? Next : Previous; + } + #endregion + + #region 方法 + /// + /// 无效化成员 + /// + internal void Invalidate() + { + List = null; + Next = null; + Previous = null; + } + #endregion +} + +/// +/// 环链表 +/// +/// +public class LoopList : IEnumerable, IFormattable +{ + #region 成员 + + /// + /// 节点数 + /// + public int Count { get; private set; } + + /// + /// 首节点 + /// + public LoopListNode? First { get; private set; } + + /// + /// 尾节点 + /// + public LoopListNode? Last => First?.Previous; + + + + + #endregion + + #region 构造 + + /// + /// 默认构造函数 + /// + public LoopList() { } + + /// + /// 环链表构造函数 + /// + /// 节点迭代器 + [DebuggerStepThrough] + public LoopList(IEnumerable values) + { + using var ge = values.GetEnumerator(); + while (ge.MoveNext()) + Add(ge.Current); + } + + #endregion + + #region 方法 + + /// + /// 设置首节点 + /// + /// 节点 + /// + public bool SetFirst(LoopListNode node) + { + if (!Contains(node)) + return false; + + First = node; + return true; + } + + /// + /// 交换两个节点的值 + /// + /// 第一个节点 + /// 第二个节点 + public void Swap(LoopListNode node1, LoopListNode node2) + { + (node2.Value, node1.Value) = (node1.Value, node2.Value); + } + + /// + /// 链内翻转 + /// + public void Reverse() + { + var first = First; + if (first is null) + return; + var last = Last; + for (int i = 0; i < Count / 2; i++) + { + Swap(first!, last!); + first = first!.Next; + last = last!.Previous; + } + } + + /// + /// 清理 + /// + public void Clear() + { + // 移除头部,表示链表再也无法遍历得到 + First = null; + Count = 0; + } + + /// + /// 从头遍历_非迭代器(此处和通用ForEach冲突,所以内部用) + /// + /// + void ForEach(Func, bool> action) + { + var node = First; + if (node is null) + return; + for (int i = 0; i < Count; i++) + { + if (action(node!)) + break; + node = node!.Next; + } + } + + /// + /// 从头遍历_非迭代器(扔出计数) + /// + /// + public void For(Func, bool> action) + { + var node = First; + if (node is null) + return; + for (int i = 0; i < Count; i++) + { + if (action(i, node!)) + break; + node = node!.Next; + } + } + + #region Contains + + /// + /// 是否包含节点 + /// + /// + /// + public bool Contains(LoopListNode node) + { + return node.List == this; + } + + /// + /// 是否包含值 + /// + /// + /// + public bool Contains(T value) + { + var result = false; + ForEach(node => { + if (!node.Value!.Equals(value)) return false; + result = true; + return true; + }); + return result; + } + + /// + /// 查找第一个出现的节点 + /// + /// + /// + public LoopListNode? Find(T value) + { + // LoopListNode result = null; + // ForEach(node => + // { + // if (node.Value.Equals(t2)) + // { + // result = node; + // return true; + // } + // return false; + // }); + // return result; + + LoopListNode? node = First; + var c = EqualityComparer.Default; + if (node is not null) + { + if (value is not null) + { + do + { + if (c.Equals(node!.Value, value)) + return node; + node = node.Next; + } while (node != First); + } + else + { + do + { + if (node!.Value is null) + return node; + node = node.Next; + } while (node != First); + } + } + return null; + } + + /// + /// 查找所有出现的节点 + /// + /// + /// + public IEnumerable>? Finds(T value) + { + var node = First; + if (node is null) + return null; + + List> result = new(); + var c = EqualityComparer.Default; + if (value is not null) + { + do + { + if (c.Equals(node!.Value, value)) + result.Add(node); + node = node.Next; + } while (node != First); + } + else + { + do + { + if (node!.Value is null) + result.Add(node); + node = node.Next; + } while (node != First); + } + return result; + } + + /// + /// 获取节点 + /// + /// + /// + public LoopListNode? GetNode(Func func) + { + LoopListNode? result = null; + ForEach(node => { + if (func(node.Value)) + { + result = node; + return true; + } + return false; + }); + return result; + } + + #endregion + + #region Add + + /// + /// 在首节点之前插入节点,并设置新节点为首节点 + /// + /// + /// + public LoopListNode AddFirst(T value) + { + var node = new LoopListNode(value, this); + + if (Count == 0) + { + First = node; + First.Previous = First.Next = node; + } + else + { + LoopListNode last = Last!; + First!.Previous = last.Next = node; + node.Next = First; + node.Previous = last; + First = node; + } + Count++; + return First; + } + + /// + /// 在尾节点之后插入节点,并设置新节点为尾节点 + /// + /// + /// + public LoopListNode Add(T value) + { + var node = new LoopListNode(value, this); + + if (Count == 0) + { + First = node; + First.Previous = First.Next = node; + } + else + { + var last = First!.Previous!; + First.Previous = last.Next = node; + node.Next = First; + node.Previous = last; + } + Count++; + return Last!; + } + + /// + /// 在尾节点之后插入节点,并设置新节点为尾节点_此函数仅为与LinkedList同名方法 + /// + /// + /// + [DebuggerStepThrough] + public LoopListNode AddLast(T value) + { + return Add(value); + } + + /// + /// 容器内容全部加入到末尾 + /// + /// + [DebuggerStepThrough] + public void AddRange(IEnumerable list) + { + using var ge = list.GetEnumerator(); + while (ge.MoveNext()) + Add(ge.Current); + } + + /// + /// 前面增加节点 + /// + /// + /// + /// + public LoopListNode AddBefore(LoopListNode node, T value) + { + if (node == First) + return AddFirst(value); + + var tNode = new LoopListNode(value, this); + node.Previous!.Next = tNode; + tNode.Previous = node.Previous; + node.Previous = tNode; + tNode.Next = node; + Count++; + return tNode; + } + + /// + /// 后面增加节点 + /// + /// + /// + /// + public LoopListNode AddAfter(LoopListNode node, T value) + { + var tNode = new LoopListNode(value, this); + node.Next!.Previous = tNode; + tNode.Next = node.Next; + node.Next = tNode; + tNode.Previous = node; + Count++; + return tNode; + } + + #endregion + + #region Remove + + /// + /// 删除首节点 + /// + /// + public bool RemoveFirst() + { + switch (Count) + { + case 0: + return false; + + case 1: + First = null; + break; + + default: + LoopListNode last = Last!; + First = First!.Next; + First!.Previous = last; + last.Next = First; + break; + } + Count--; + return true; + } + + /// + /// 删除尾节点 + /// + /// + public bool RemoveLast() + { + switch (Count) + { + case 0: + return false; + + case 1: + First = null; + break; + + default: + LoopListNode last = Last!.Previous!; + last.Next = First; + First!.Previous = last; + break; + } + Count--; + return true; + } + + /// + /// 删除此参数节点(唯一) + /// + /// 指定节点 + /// + public bool Remove(LoopListNode node) + { + if (!Contains(node)) + return false; + InternalRemove(node); + return true; + } + + /// + /// 删除含有此参数节点(所有) + /// + /// 将移除所有含有此值 + /// + public bool Remove(T value) + { + var lst = Finds(value); + if (lst is null) + return false; + + using var ge = lst.GetEnumerator(); + while (ge.MoveNext()) + if (ge.Current != null) + InternalRemove(ge.Current); + return true; + } + + /// + /// 删除节点_内部调用 + /// + /// 此值肯定存在当前链表 + /// + void InternalRemove(LoopListNode node) + { + if (Count == 1 || node == First) + { + RemoveFirst();// 此处会减数字 + } + else + { + node.Next!.Previous = node.Previous; + node.Previous!.Next = node.Next; + Count--; + } + node.Invalidate(); + } + + #endregion + + #region LinkTo + + /// + /// 链接两节点,并去除这两个节点间的所有节点 + /// + /// + /// + public void LinkTo(LoopListNode from, LoopListNode to) + { + if (from != to && Contains(from) && Contains(to)) + { + LoopListNode node = from.Next!; + bool isFirstChanged = false; + int number = 0; + + while (node != to) + { + if (node == First) + isFirstChanged = true; + + node = node.Next!; + number++; + } + + from.Next = to; + to.Previous = from; + + if (number > 0 && isFirstChanged) + First = to; + + Count -= number; + } + } + + /// + /// 链接两节点,并去除这两个节点间的所有节点 + /// + /// + /// + /// + public void LinkTo(LoopListNode from, LoopListNode to, int number) + { + if (from != to && Contains(from) && Contains(to)) + { + from.Next = to; + to.Previous = from; + First = to; + Count -= number; + } + } + + /// + /// 链接两节点,并去除这两个节点间的所有节点 + /// + /// + /// + /// + /// + public void LinkTo(LoopListNode from, LoopListNode to, int number, bool isFirstChanged) + { + if (from != to && Contains(from) && Contains(to)) + { + from.Next = to; + to.Previous = from; + if (isFirstChanged) + First = to; + Count -= number; + } + } + + #endregion + + #endregion + + #region IEnumerable + + /// + /// 获取节点的查询器 + /// + /// + /// + [DebuggerStepThrough] + public IEnumerable> GetNodes(LoopListNode from) + { + var node = from; + for (int i = 0; i < Count; i++) + { + yield return node!; + node = node!.Next; + } + } + + /// + /// 获取节点的查询器 + /// + /// + [DebuggerStepThrough] + public IEnumerable> GetNodes() + { + LoopListNode node = First!; + for (int i = 0; i < Count; i++) + { + yield return node!; + node = node.Next!; + } + } + + /// + /// 获取节点值的查询器 + /// + /// + [DebuggerStepThrough] + public IEnumerator GetEnumerator() + { + LoopListNode node = First!; + for (int i = 0; i < Count; i++) + { + yield return node!.Value; + node = node.Next!; + } + } + + [DebuggerStepThrough] + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + #region IEnumerable 成员 + + [DebuggerStepThrough] + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + #endregion IEnumerable 成员 + + #endregion + + #region IFormattable + /// + /// 转换为字符串_格式化实现 + /// + /// + /// + /// + string IFormattable.ToString(string? format, IFormatProvider? formatProvider) + { + return ToString(format, formatProvider); + } + + /// + /// 转换为字符串_无参调用 + /// + /// + public override string ToString() + { + return ToString(null); + } + + /// + /// 转换为字符串_有参调用 + /// + /// + public string ToString(string? format, IFormatProvider? formatProvider = null) + { + var s = new StringBuilder(); + s.Append($"Count = {Count};"); + if (format is not null) return s.ToString(); + s.Append("{ "); + foreach (var value in this) + s.Append($"{value} "); + s.Append(" }"); + return s.ToString(); + } + #endregion + + #region ICloneable + /* 山人说无法分辨ICloneable接口是深浅克隆, + * 因此不要在泛型模板实现克隆函数, + * 让用户自己来 new(xx)实现浅克隆,所以也不提供Clone()了 + * + * 因此约定了:CopyTo(T,index)是深克隆;MemberwiseClone()是浅克隆; + * public object Clone() + * { + * var lst = new LoopList>(); + * ForEach(node => { + * lst.Add(node); + * return false; + * }); + * return lst; + * } + */ + #endregion +} + +#line default \ No newline at end of file diff --git a/IFoxCAD.Cad/Basal/Win/SystemEx.cs b/IFoxCAD.Cad/Basal/Win/SystemEx.cs new file mode 100644 index 0000000..3ca3314 --- /dev/null +++ b/IFoxCAD.Cad/Basal/Win/SystemEx.cs @@ -0,0 +1,27 @@ +namespace IFoxCAD.Cad.Basal.Win; + +public class SystemEx +{ + + + /// + /// 关闭进程 + /// + /// 进程名 + /// + public static bool CloseProc(string procName) + { + var result = false; + + foreach (var thisProc in Process.GetProcesses()) + { + var tempName = thisProc.ProcessName; + if (tempName != procName) + continue; + thisProc.Kill(); //当发送关闭窗口命令无效时强行结束进程 + result = true; + } + + return result; + } +} \ No newline at end of file diff --git a/IFoxCAD.Cad/Basal/Win/Win32Api.cs b/IFoxCAD.Cad/Basal/Win/Win32Api.cs new file mode 100644 index 0000000..e3973dc --- /dev/null +++ b/IFoxCAD.Cad/Basal/Win/Win32Api.cs @@ -0,0 +1,32 @@ +namespace IFoxCAD.Basal; + +public static class Win32Api +{ + #region Win32 + + /// + /// 查找窗口 + /// + /// + /// + /// + [DllImport("user32.dll", SetLastError = true)] + public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); + + [DllImport("user32.dll", CharSet = CharSet.Auto)] + public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam); + + /// + /// 关闭窗口 + /// + /// + public static void CloseWindow(IntPtr hWnd) + { + SendMessage(hWnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero); + } + + // 定义 WM_CLOSE 消息 + const UInt32 WM_CLOSE = 0x0010; + + #endregion +} \ No newline at end of file diff --git a/IFoxCAD.Cad/ExtensionMethod/EditorEx.cs b/IFoxCAD.Cad/ExtensionMethod/EditorEx.cs new file mode 100644 index 0000000..ad36df9 --- /dev/null +++ b/IFoxCAD.Cad/ExtensionMethod/EditorEx.cs @@ -0,0 +1,1169 @@ +namespace IFoxCAD.Cad; + +/// +/// 命令行扩展类 +/// +public static class EditorEx +{ + #region 选择集 + /// + /// 选择穿过一个点的对象 + /// + /// 命令行对象 + /// 点 + /// 过滤器 + /// 选择集结果类 + public static PromptSelectionResult SelectAtPoint(this Editor editor, Point3d point, + SelectionFilter? filter = default) + { + return editor.SelectCrossingWindow(point, point, filter); + } + + /// + /// 根据线宽创建图层选择集 + /// + /// 命令行对象 + /// 线宽 + /// 图层选择集 + public static SelectionSet SelectByLineWeight(this Editor editor, LineWeight lineWeight) + { + OpFilter filter = new OpEqual(370, lineWeight); + + var lays = + DBTrans.Top.LayerTable + .GetRecords() + .Where(ltr => ltr.LineWeight == lineWeight) + .Select(ltr => ltr.Name) + .ToArray(); + + if (lays.Length > 0) + { + filter = + new OpOr + { + filter, + new OpAnd + { + { 8, string.Join(",", lays) }, + { 370, LineWeight.ByLayer } + } + }; + } + + var res = editor.SelectAll(filter); + return res.Value; + } + + /// + /// 选择集 + /// + /// 命令行对象 + /// 模式 + /// 过滤器 + /// 消息 + /// + /// 关键字和回调函数 + /// 不用使用下列关键字 "Window/Last/Crossing/BOX/ALL/Fence/WPolygon/CPolygon/Group/Add/Remove/Multiple/Previous/Undo/AUto/Single" + /// + /// + public static PromptSelectionResult SSGet(this Editor editor, + string? mode = null, + SelectionFilter? filter = null, + (string add, string remove)? messages = null, + Dictionary? keywords = null) + { + PromptSelectionOptions pso = new(); + if (mode is not null) + { + mode = mode.ToUpper(); + pso.SinglePickInSpace = mode.Contains(":A"); + pso.RejectObjectsFromNonCurrentSpace = mode.Contains(":C"); + pso.AllowDuplicates = mode.Contains(":D"); + pso.SelectEverythingInAperture = mode.Contains(":E"); + pso.RejectObjectsOnLockedLayers = mode.Contains(":L"); + pso.PrepareOptionalDetails = mode.Contains(":N"); + pso.SingleOnly = mode.Contains(":S"); + pso.RejectPaperspaceViewport = mode.Contains(":V"); + pso.AllowSubSelections = mode.Contains("-A"); + pso.ForceSubSelections = mode.Contains("-F"); + } + if (messages is not null) + { + pso.MessageForAdding = messages.Value.add; + pso.MessageForRemoval = messages.Value.remove; + } + + if (keywords is not null) + { + foreach (var keyword in keywords.Keys) + pso.Keywords.Add(keyword); + if (pso.MessageForRemoval is null) + pso.MessageForAdding = "选择对象"; + + var str = keywords.Keys.Select(key => { + keywords.TryGetValue(key, out (string, Action) value); + return $"{value.Item1}({key})"; + }); + + + pso.MessageForAdding += $" [{string.Join("/", str)}]"; + pso.KeywordInput += (_, e) => { + if (keywords.TryGetValue(e.Input, out var value)) + value.Item2.Invoke(); + }; + } + + var ss = filter is not null ? editor.GetSelection(pso, filter) : editor.GetSelection(pso); + return ss; + } + + + /* + * // 定义选择集选项 + * var pso = new PromptSelectionOptions + * { + * AllowDuplicates = false, // 重复选择 + * }; + * + * // getai遍历全图选择块有用到 + * var dic = new Dictionary() { + * { "Z,全部同名", ()=> { + * getai = BlockHelper.EnumAttIdentical.AllBlockName; + * SendEsc.Esc(); + * }}, + * { "X,动态块显示", ()=> { + * getai = BlockHelper.EnumAttIdentical.Display; + * }}, + * { "V,属性值-默认", ()=> { + * getai = BlockHelper.EnumAttIdentical.DisplayAndTagText; + * }}, + * // 允许以下操作,相同的会加入前面的 + * // { "V,属性值-默认|X,啊啊啊啊", ()=> { + * + * // }}, + * }; + * pso.SsgetAddKeys(dic); + * + * // 创建选择集过滤器,只选择块对象 + * var filList = new TypedValue[] { new TypedValue((int)DxfCode.Start, "INSERT") }; + * var filter = new SelectionFilter(filList); + * ssPsr = ed.GetSelection(pso, filter); + */ + + /// + /// 添加选择集关键字和回调 + /// + /// 选择集配置 + /// 关键字,回调委托 + /// + public static void SsgetAddKeys(this PromptSelectionOptions pso, + Dictionary dicActions) + { + Dictionary tmp = new(); + // 后缀名的|号切割,移除掉,组合成新的加入tmp + for (int i = dicActions.Count - 1; i >= 0; i--) + { + var pair = dicActions.ElementAt(i); + var key = pair.Key; + var keySp = key.Split('|'); + if (keySp.Length < 2) + continue; + + for (int j = 0; j < keySp.Length; j++) + { + var item = keySp[j]; + // 防止多个后缀通过|符越过词典约束同名 + // 后缀(key)含有,而且Action(value)不同,就把Action(value)累加到后面. + if (dicActions.TryGetValue(item, out Action value)) + { + if (dicActions[item] != dicActions[key]) + dicActions[item] += dicActions[key]; + } + else + tmp.Add(item, value); + } + dicActions.Remove(key); + } + + foreach (var item in tmp) + dicActions.Add(item.Key, item.Value); + + // 去除关键字重复的,把重复的执行动作移动到前面 + for (int i = 0; i < dicActions.Count; i++) + { + var pair1 = dicActions.ElementAt(i); + var key1 = pair1.Key; + + for (int j = dicActions.Count - 1; j > i; j--) + { + var pair2 = dicActions.ElementAt(j); + var key2 = pair2.Key; + + if (key1.Split(',')[0] == key2.Split(',')[0]) + { + if (dicActions[key1] != dicActions[key2]) + dicActions[key1] += dicActions[key2]; + dicActions.Remove(key2); + } + } + } + + foreach (var item in dicActions) + { + var keySplitS = item.Key.Split(new string[] { ",", "|" }, StringSplitOptions.RemoveEmptyEntries); + for (int i = 0; i < keySplitS.Length; i += 2) + pso.Keywords.Add(keySplitS[i], keySplitS[i], + keySplitS[i + 1] + "(" + keySplitS[i] + ")"); + } + + // 回调的时候我想用Dict的O(1)索引, + // 但是此函数内进行new Dictionary() 在函数栈释放的时候,它被释放掉了. + // 因此 dicActions 参数的生命周期 + tmp = new(dicActions); + dicActions.Clear(); + foreach (var item in tmp) + dicActions.Add(item.Key.Split(',')[0], item.Value); + + var keyWords = pso.Keywords; + // 从选择集命令中显示关键字 + pso.MessageForAdding = keyWords.GetDisplayString(true); + // 关键字回调事件 ssget关键字 + pso.KeywordInput += (_, e) => { + dicActions[e.Input].Invoke(); + }; + } + + + + + + + // #region 即时选择样板 + // /// + // /// 即时选择,框选更新关键字 + // /// + // public static void SelectTest() + // { + // Env.Editor.WriteMessage("\n[白嫖工具]--测试"); + // // 激活选中事件 + // Env.Editor.SelectionAdded += SelectTest_SelectionAdded; + // // 初始化坐标系 + // Env.Editor.CurrentUserCoordinateSystem = Matrix3d.Identity; + + // // 创建过滤器 + // var sf = new OpEqual(0, "arc"); + // var pso = new PromptSelectionOptions + // { + // MessageForAdding = "\n请选择对象:" + // }; + + // pso.Keywords.Add("Z"); + // pso.Keywords.Add("X"); + // pso.Keywords.Add("Q"); + // // 注册关键字 + // pso.KeywordInput += SelectTest_KeywordInput; + // try + // { + // // 用户选择 + // var psr = Env.Editor.GetSelection(pso, sf); + // // 处理代码 + + + // } + // catch (Exception ex)// 捕获关键字 + // { + // if (ex.Message == "XuError") + // { + // // 关闭关键字事件 + // pso.KeywordInput -= SelectTest_KeywordInput; + // // 关闭选中事件 + // Env.Editor.SelectionAdded -= SelectTest_SelectionAdded; + // // 重新调用自身 + // ZengLiangYuanJiao(); + // } + // } + // // 关闭关键字事件 + // pso.KeywordInput -= SelectTest_KeywordInput; + // // 关闭选中事件 + // Env.Editor.SelectionAdded -= SelectTest_SelectionAdded; + // } + + // /// + // /// 即时选择 + // /// + // /// + // /// + // private static void SelectTest_SelectionAdded(object sender, SelectionAddedEventArgs e) + // { + // // 关闭选中事件 + // Env.Editor.SelectionAdded -= SelectTest_SelectionAdded; + // using (var tr = new DBTrans()) + // { + // // 处理代码 + // for (int i = 0; i < e.AddedObjects.Count; i++) + // { + // // 处理完移除已处理的对象 + // e.Remove(i); + // } + // } + // // 激活选中事件 + // Env.Editor.SelectionAdded += SelectTest_SelectionAdded; + // } + + // /// + // /// 关键字响应 + // /// + // /// + // /// + // private static void SelectTest_KeywordInput(object sender, SelectionTextInputEventArgs e) + // { + // // 获取关键字 + // switch (e.Input) + // { + // case "Z": + // break; + // case "X": + // break; + + // case "Q": + // break; + // } + // // 抛出异常,用于更新提示信息 + // throw new ArgumentException("XuError"); + // } + // #endregion + #endregion + + #region Info + + /// + /// 带错误提示对话框的打印信息函数 + /// + /// 带格式项的字符串 + /// 指定格式化的对象数组 + public static void StreamMessage(string format, params object[] args) + { + StreamMessage(string.Format(format, args)); + } + + /// + /// 带错误提示对话框的打印信息函数 + /// + /// 打印信息 + public static void StreamMessage(string message) + { + try + { + if (HasEditor()) + WriteMessage(message); + else + InfoMessageBox(message); + } + catch (Exception ex) + { + Message(ex); + } + } + + /// + /// 异常信息对话框 + /// + /// 异常 + public static void Message(Exception ex) + { + try + { + System.Windows.Forms.MessageBox.Show( + ex.ToString(), + "Error", + System.Windows.Forms.MessageBoxButtons.OK, + System.Windows.Forms.MessageBoxIcon.Error); + } + catch + { + // ignored + } + } + + /// + /// 提示信息对话框 + /// + /// 对话框的标题 + /// 对话框文本 + public static void InfoMessageBox(string caption, string message) + { + try + { + System.Windows.Forms.MessageBox.Show( + message, + caption, + System.Windows.Forms.MessageBoxButtons.OK, + System.Windows.Forms.MessageBoxIcon.Information); + } + catch (Exception ex) + { + Message(ex); + } + } + + /// + /// 提示信息对话框 + /// + /// 对话框的标题 + /// 带格式化项的对话框文本 + /// 指定格式化的对象数组 + public static void InfoMessageBox(string caption, string format, params object[] args) + { + InfoMessageBox(caption, string.Format(format, args)); + } + + /// + /// 提示信息对话框,默认标题为NFox.Cad + /// + /// 对话框文本 + public static void InfoMessageBox(string message) + { + InfoMessageBox("NFox.Cad", message); + } + + /// + /// 提示信息对话框 + /// + /// 带格式化项的对话框文本 + /// 指定格式化的对象数组 + public static void InfoMessageBox(string format, params object[] args) + { + InfoMessageBox(string.Format(format, args)); + } + + /// + /// 命令行打印字符串 + /// + /// 字符串 + public static void WriteMessage(string message) + { + try + { + if (Acceptable()) + Acap.DocumentManager.MdiActiveDocument.Editor.WriteMessage("\n" + message); + } + catch (Exception ex) + { + Message(ex); + } + } + + /// + /// 命令行打印字符串 + /// + /// 带格式化项的文本 + /// 指定格式化的对象数组 + public static void WriteMessage(string format, params object[] args) + { + WriteMessage(string.Format(format, args)); + } + + /// + /// 判断是否有活动的编辑器对象 + /// + /// 有,没有 + public static bool HasEditor() + { + return Acap.DocumentManager.MdiActiveDocument is not null + && Acap.DocumentManager.Count != 0 + && Acap.DocumentManager.MdiActiveDocument.Editor is not null; + } + + /// + /// 判断是否可以打印字符串 + /// + /// 可以打印,不可以打印 + public static bool Acceptable() + { + return HasEditor() + && !Acap.DocumentManager.MdiActiveDocument.Editor.IsDragging; + } + + #endregion Info + + #region 画矢量线 + + /// + /// 根据点表返回矢量线的列表 + /// + /// 点表 + /// 是否闭合, 为闭合, 为不闭合 + /// + public static List GetLines(IEnumerable pnts, bool isClosed) + { + using var itor = pnts.GetEnumerator(); + if (!itor.MoveNext()) + return new List(); + + List values = new(); + + TypedValue tvFirst = new((int)LispDataType.Point2d, itor.Current); + TypedValue tv1; + TypedValue tv2 = tvFirst; + + while (itor.MoveNext()) + { + tv1 = tv2; + tv2 = new TypedValue((int)LispDataType.Point2d, itor.Current); + values.Add(tv1); + values.Add(tv2); + } + + if (isClosed) + { + values.Add(tv2); + values.Add(tvFirst); + } + + return values; + } + + /// + /// 画矢量线 + /// + /// 编辑器对象 + /// 点表 + /// 颜色码 + /// 是否闭合, 为闭合, 为不闭合 + public static void DrawVectors(this Editor editor, IEnumerable pnts, short colorIndex, bool isClosed) + { + var rlst = + new LispList { { LispDataType.Int16, colorIndex } }; + rlst.AddRange(GetLines(pnts, isClosed)); + editor.DrawVectors(new(rlst.ToArray()), Matrix3d.Identity); + } + + /// + /// 画矢量线 + /// + /// 编辑器对象 + /// 点表 + /// 颜色码 + public static void DrawVectors(this Editor editor, IEnumerable pnts, short colorIndex) + { + editor.DrawVectors(pnts, colorIndex, false); + } + + /// + /// 用矢量线画近似圆(正多边形) + /// + /// 编辑器对象 + /// 点表 + /// 颜色码 + /// 半径 + /// 多边形边的个数 + public static void DrawCircles(this Editor editor, IEnumerable pnts, short colorIndex, double radius, int numEdges) + { + var rlst = + new LispList { { LispDataType.Int16, colorIndex } }; + + foreach (Point2d pnt in pnts) + { + Vector2d vec = Vector2d.XAxis * radius; + double angle = Math.PI * 2 / numEdges; + + List tpnts = [pnt + vec]; + for (int i = 1; i < numEdges; i++) + { + tpnts.Add(pnt + vec.RotateBy(angle * i)); + } + + rlst.AddRange(GetLines(tpnts, true)); + } + editor.DrawVectors(new(rlst.ToArray()), editor.CurrentUserCoordinateSystem); + } + + /// + /// 用矢量线画近似圆(正多边形) + /// + /// 编辑器对象 + /// 点 + /// 颜色码 + /// 半径 + /// 多边形边的个数 + public static void DrawCircle(this Editor editor, Point2d pnt, short colorIndex, double radius, int numEdges) + { + Vector2d vec = Vector2d.XAxis * radius; + double angle = Math.PI * 2 / numEdges; + + List pnts = [pnt + vec]; + for (int i = 1; i < numEdges; i++) + pnts.Add(pnt + vec.RotateBy(angle * i)); + + editor.DrawVectors(pnts, colorIndex, true); + } + /// + /// 根据点表绘制矢量线段(每两点为一条线段的起始点和终止点) + /// + /// 用户交互对象 + /// 点表 + /// CAD颜色索引;默认:1为红色 + /// 是否高亮显示;为高亮显示,默认:为不高亮显示 + public static void DrawLineVectors(this Editor editor, IEnumerable points, int colorIndex = 1, + bool drawHighlighted = false) + { + Point3d endPoint1, endPoint2; + using var itor = points.GetEnumerator(); + while (itor.MoveNext()) + { + endPoint1 = itor.Current; + if (!itor.MoveNext()) return; + endPoint2 = itor.Current; + editor.DrawVector(endPoint1, endPoint2, colorIndex, drawHighlighted); + } + } + /// + /// 根据点表绘制首尾相连的矢量 + /// + /// 用户交互对象 + /// 点表 + /// CAD颜色索引;默认:1为红色 + /// 是否闭合; 为闭合,默认: 为不闭合 + /// 是否高亮显示;为高亮显示,默认:为不高亮显示 + public static void DrawEndToEndVectors(this Editor editor, IEnumerable points, int colorIndex = 1, + bool isclose = false, bool drawHighlighted = false) + { + using var itor = points.GetEnumerator(); + if (!points.Any() || !itor.MoveNext()) return; + Point3d endPoint1 = itor.Current, endPoint2 = new(), firstEndPoint = endPoint1; + while (itor.MoveNext()) + { + endPoint2 = itor.Current; + editor.DrawVector(endPoint1, endPoint2, colorIndex, drawHighlighted); + endPoint1 = endPoint2; + } + if (isclose) + editor.DrawVector(endPoint2, firstEndPoint, colorIndex, drawHighlighted); + } + #endregion + + #region 矩阵 + + /// + /// 获取UCS到WCS的矩阵 + /// + /// 命令行对象 + /// 变换矩阵 + public static Matrix3d GetMatrixFromUcsToWcs(this Editor editor) + { + return editor.CurrentUserCoordinateSystem; + } + + /// + /// 获取WCS到UCS的矩阵 + /// + /// 命令行对象 + /// 变换矩阵 + public static Matrix3d GetMatrixFromWcsToUcs(this Editor editor) + { + return editor.CurrentUserCoordinateSystem.Inverse(); + } + + /// + /// 获取MDCS(模型空间)到WCS的矩阵 + /// + /// 命令行对象 + /// 变换矩阵 + public static Matrix3d GetMatrixFromMDcsToWcs(this Editor editor) + { + using var vtr = editor.GetCurrentView(); + var mat = Matrix3d.PlaneToWorld(vtr.ViewDirection); + mat = Matrix3d.Displacement(vtr.Target - Point3d.Origin) * mat; + return Matrix3d.Rotation(-vtr.ViewTwist, vtr.ViewDirection, vtr.Target) * mat; + } + + /// + /// 获取WCS到MDCS(模型空间)的矩阵 + /// + /// 命令行对象 + /// 变换矩阵 + public static Matrix3d GetMatrixFromWcsToMDcs(this Editor editor) + { + return editor.GetMatrixFromMDcsToWcs().Inverse(); + } + + /// + /// 获取MDCS(模型空间)到PDCS(图纸空间)的矩阵 + /// + /// 命令行对象 + /// 变换矩阵 + public static Matrix3d GetMatrixFromMDcsToPDcs(this Editor editor) + { + if ((short)Env.GetVar("TILEMODE") == 1) + throw new ArgumentException("TILEMODE == 1..Espace papier uniquement"); + + Matrix3d mat = Matrix3d.Identity; + //using DBTrans tr = new(); + var tr = DBTrans.GetTopTransaction(editor.Document.Database); + var vp = tr.GetObject(editor.CurrentViewportObjectId); + if (vp == null) + return mat; + + if (vp.Number == 1) + { + try + { + editor.SwitchToModelSpace(); + vp = tr.GetObject(editor.CurrentViewportObjectId); + editor.SwitchToPaperSpace(); + } + catch + { + throw new Exception("Aucun fenêtre active...ErrorStatus.InvalidInput"); + } + } + if (vp == null) + return mat; + + Point3d vCtr = new(vp.ViewCenter.X, vp.ViewCenter.Y, 0.0); + mat = Matrix3d.Displacement(vCtr.GetAsVector().Negate()); + mat = Matrix3d.Displacement(vp.CenterPoint.GetAsVector()) * mat; + mat = Matrix3d.Scaling(vp.CustomScale, vp.CenterPoint) * mat; + return mat; + } + + /// + /// 获取PDCS(图纸空间)到MDCS(模型空间)的矩阵 + /// + /// 命令行对象 + /// 变换矩阵 + public static Matrix3d GetMatrixFromPDcsToMDcs(this Editor editor) + { + return editor.GetMatrixFromMDcsToPDcs().Inverse(); + } + + /// + /// 获取变换矩阵 + /// + /// 命令行对象 + /// 源坐标系 + /// 目标坐标系 + /// 变换矩阵 + public static Matrix3d GetMatrix(this Editor editor, CoordinateSystemCode from, CoordinateSystemCode to) + { + return (from, to) switch + { + (CoordinateSystemCode.Wcs, CoordinateSystemCode.Ucs) => editor.GetMatrixFromWcsToUcs(), + (CoordinateSystemCode.Wcs, CoordinateSystemCode.MDcs) => editor.GetMatrixFromWcsToMDcs(), + (CoordinateSystemCode.Ucs, CoordinateSystemCode.Wcs) => editor.GetMatrixFromUcsToWcs(), + (CoordinateSystemCode.Ucs, CoordinateSystemCode.MDcs) => editor.GetMatrixFromUcsToWcs() * editor.GetMatrixFromWcsToMDcs(), + (CoordinateSystemCode.MDcs, CoordinateSystemCode.Wcs) => editor.GetMatrixFromMDcsToWcs(), + (CoordinateSystemCode.MDcs, CoordinateSystemCode.Ucs) => editor.GetMatrixFromMDcsToWcs() * editor.GetMatrixFromWcsToUcs(), + (CoordinateSystemCode.MDcs, CoordinateSystemCode.PDcs) => editor.GetMatrixFromMDcsToPDcs(), + (CoordinateSystemCode.PDcs, CoordinateSystemCode.MDcs) => editor.GetMatrixFromPDcsToMDcs(), + (CoordinateSystemCode.PDcs, CoordinateSystemCode.Wcs or CoordinateSystemCode.Ucs) + or (CoordinateSystemCode.Wcs or CoordinateSystemCode.Ucs, CoordinateSystemCode.PDcs) => throw new Exception("To be used only with DCS...ErrorStatus.InvalidInput"), + (_, _) => Matrix3d.Identity + }; + } + + #endregion + + #region 缩放 + + // todo 暂时先屏蔽这个又臭又长的代码,待搞明白为什么都这么写之后再说 +#if false + /// + /// 缩放窗口范围 + /// + /// 命令行对象 + /// 窗口左下点 + /// 窗口右上点 + public static void ZoomWindow(this Editor ed, Point3d minPoint, Point3d maxPoint) + { + ViewTableRecord vtr = new(); + vtr.CopyFrom(ed.GetCurrentView()); + + var oldpnts = new Point3d[] { minPoint, maxPoint }; + var pnts = new Point3d[8]; + var dpnts = new Point3d[8]; + + var mat = ed.GetMatrixFromWcsToMDcs(); + for (int i = 0; i < 2; i++) + for (int j = 0; j < 2; j++) + for (int k = 0; k < 2; k++) + { + int n = i * 4 + j * 2 + k; + pnts[n] = new Point3d(oldpnts[i][0], oldpnts[j][1], oldpnts[k][2]); + dpnts[n] = pnts[n].TransformBy(mat); + } + + double xmin, xmax, ymin, ymax; + xmin = xmax = dpnts[0][0]; + ymin = ymax = dpnts[0][1]; + for (int i = 1; i < 8; i++) + { + xmin = Math.Min(xmin, dpnts[i][0]); + xmax = Math.Max(xmax, dpnts[i][0]); + ymin = Math.Min(ymin, dpnts[i][1]); + ymax = Math.Max(ymax, dpnts[i][1]); + } + + vtr.Width = xmax - xmin; + vtr.Height = ymax - ymin; + vtr.CenterPoint = (dpnts[0] + (dpnts[7] - dpnts[0]) / 2) + .Convert2d(Curve2dEx._planeCache); + + ed.SetCurrentView(vtr); + //ed.Regen(); + } +#endif + + /// + /// 缩放窗口范围 + /// + /// 命令行对象 + /// 窗口范围点 + public static void ZoomWindow(this Editor ed, Extents3d ext) + { + ZoomWindow(ed, ext.MinPoint, ext.MaxPoint); + } + + /// + /// 按范围缩放 + /// + /// 命令行对象 + /// 中心点 + /// 窗口宽 + /// 窗口高 + public static void Zoom(this Editor ed, Point3d CenPt, double width, double height) + { + using ViewTableRecord view = ed.GetCurrentView(); + view.Width = width; + view.Height = height; + view.CenterPoint = new Point2d(CenPt.X, CenPt.Y); + ed.SetCurrentView(view);// 更新当前视图 + } + + /// + /// 缩放窗口范围 + /// + /// 命令行对象 + /// 第一点 + /// 对角点 + /// 偏移距离 + public static void ZoomWindow(this Editor ed, Point3d lpt, Point3d rpt, double offsetDist = 0.00) + { + Extents3d extents = new(); + extents.AddPoint(lpt); + extents.AddPoint(rpt); + rpt = extents.MaxPoint + new Vector3d(offsetDist, offsetDist, 0); + lpt = extents.MinPoint - new Vector3d(offsetDist, offsetDist, 0); + Vector3d ver = rpt - lpt; + ed.Zoom(lpt + ver / 2, ver.X, ver.Y); + } + + + /// + /// 获取有效的数据库范围 + /// + /// 数据库 + /// 容差值:图元包围盒会超过数据库边界,用此参数扩大边界 + /// + public static Extents3d? GetValidExtents3d(this Database db, double extention = 1e-6) + { + db.UpdateExt(true);// 更新当前模型空间的范围 + var ve = new Vector3d(extention, extention, extention); + // 数据库没有图元的时候,min是大,max是小,导致新建出错 + // 数据如下: + // min.X == 1E20 && min.Y == 1E20 && min.Z == 1E20 && + // max.X == -1E20 && max.Y == -1E20 && max.Z == -1E20) + var a = db.Extmin; + var b = db.Extmax; + if (a.X < b.X && a.Y < b.Y) + return new Extents3d(db.Extmin - ve, db.Extmax + ve); + + return null; + } + + /// + /// 动态缩放 + /// + /// 命令行对象 + /// 偏移距离 + public static void ZoomExtents(this Editor ed, double offsetDist = 0.00) + { + Database db = ed.Document.Database; + // db.UpdateExt(true); // GetValidExtents3d内提供了 + var dbExtent = db.GetValidExtents3d(); + if (dbExtent == null) + ed.ZoomWindow(Point3d.Origin, new Point3d(1, 1, 0), offsetDist); + else + ed.ZoomWindow(db.Extmin, db.Extmax, offsetDist); + } + + /// + /// 根据实体对象的范围显示视图 + /// + /// 命令行对象 + /// Entity对象 + /// 偏移距离 + public static void ZoomObject(this Editor ed, Entity ent, double offsetDist = 0.00) + { + Extents3d ext = ent.GeometricExtents; + ed.ZoomWindow(ext.MinPoint, ext.MaxPoint, offsetDist); + } + +#endregion + + #region Get交互类 + + /// + /// 获取Point + /// + /// 命令行对象 + /// 提示信息 + /// 提示使用的基点 + /// + public static PromptPointResult GetPoint(this Editor ed, string Message, Point3d BasePoint) + { + PromptPointOptions ptOp = new(Message) + { + BasePoint = BasePoint, + UseBasePoint = true + }; + return ed.GetPoint(ptOp); + } + + /// + /// 获取double值 + /// + /// 命令行对象 + /// 提示信息 + /// double默认值 + /// + public static PromptDoubleResult GetDouble(this Editor ed, string Message, double DefaultValue = 1.0) + { + PromptDoubleOptions douOp = new(Message) + { + DefaultValue = DefaultValue + }; + return ed.GetDouble(douOp); + } + + /// + /// 获取int值 + /// + /// 命令行对象 + /// 提示信息 + /// double默认值 + /// + public static PromptIntegerResult GetInteger(this Editor ed, string Message, int DefaultValue = 1) + { + PromptIntegerOptions douOp = new(Message) + { + DefaultValue = DefaultValue + }; + return ed.GetInteger(douOp); + } + + /// + /// 获取string值 + /// + /// 命令行对象 + /// 提示信息 + /// string默认值 + /// + public static PromptResult GetString(this Editor ed, string Message, string DefaultValue = "") + { + PromptStringOptions strOp = new(Message) + { + DefaultValue = DefaultValue + }; + return ed.GetString(strOp); + } + + #endregion + + #region 执行lisp + [DllImport("accore.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "acedInvoke")] + static extern int AcedInvoke(IntPtr args, out IntPtr result); + + + // 高版本此接口不能使用lisp(command "xx"),但是可以直接在自动运行接口上 + [DllImport("accore.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, + EntryPoint = "?acedEvaluateLisp@@YAHPEB_WAEAPEAUresbuf@@@Z")] + [System.Security.SuppressUnmanagedCodeSecurity]// 初始化默认值 + static extern int AcedEvaluateLisp(string lispLine, out IntPtr result); + + + [DllImport("accore.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ads_queueexpr")] + static extern int Ads_queueexpr(string strExpr); + /// + /// 执行lisp的方式枚举 + /// + [Flags] + public enum RunLispFlag : byte + { + /// + /// AdsQueueexpr + /// + AdsQueueexpr = 1, + /// + /// AcedEvaluateLisp + /// + AcedEvaluateLisp = 2, + /// + /// SendStringToExecute + /// + SendStringToExecute = 4, + } + + /* + * 测试命令: + * [CommandMethod(nameof(CmdTest_RunLisp))] + * public static void CmdTest_RunLisp() + * { + * var res = RunLisp("(setq abc 10)"); + * } + * 调用方式: + * (command "CmdTest_RunLisp1") + * bug说明: + * AcedEvaluateLisp 接口 + * 在高版本调用时候没有运行成功,使得 !abc 没有值 + * 在cad08成功,此bug与CommandFlags无关 + * 解决方案: + * 0x01 用异步接口,但是这样是显式调用了: + * (setq thisdrawing (vla-get-activedocument (vlax-get-acad-object)))(vla-SendCommand thisdrawing "CmdTest_RunLisp1 ") + * 0x02 使用 Ads_queueexpr 接口 + */ + /// + /// 发送lisp语句字符串到cad执行 + /// + /// 编辑器对象 + /// lisp语句 + /// 运行方式 + /// 缓冲结果,返回值 + public static ResultBuffer? RunLisp(this Editor ed, string lispCode, RunLispFlag flag = RunLispFlag.AdsQueueexpr) + { + if ((flag & RunLispFlag.AdsQueueexpr) == RunLispFlag.AdsQueueexpr) + { + // 这个在08/12发送lisp不会出错,但是发送bo命令出错了. + // 0x01 设置RunLispFlag特性为RunLispFlag.AcedEvaluateLisp即可同步执行 + // 0x02 自执行发送lisp都是异步,用来发送 含有(command)的lisp的 + _ = Ads_queueexpr(lispCode + "\n"); + } + if ((flag & RunLispFlag.AcedEvaluateLisp) == RunLispFlag.AcedEvaluateLisp) + { + _ = AcedEvaluateLisp(lispCode, out IntPtr rb); + if (rb != IntPtr.Zero) + return (ResultBuffer)DisposableWrapper.Create(typeof(ResultBuffer), rb, true); + } + if ((flag & RunLispFlag.SendStringToExecute) == RunLispFlag.SendStringToExecute) + { + var dm = Acap.DocumentManager; + var doc = dm.MdiActiveDocument; + doc?.SendStringToExecute(lispCode + "\n", false, false, false); + } + return null; + } + #endregion + + #region Export + /// + /// 输出WMF
+ /// 此函数不适用于后台 + ///
+ /// 命令行对象 + /// 保存文件 + /// 选择集的对象,为null时候手选 + /// 是否清空选择集 + /// + public static void ComExportWMF(this Editor editor, string saveFile, + ObjectId[]? ids = null, bool wmfSetDel = false) + { + if (string.IsNullOrWhiteSpace(saveFile)) + throw new ArgumentNullException(nameof(saveFile)); + if (File.Exists(saveFile)) + throw new FileFormatException("文件重复:" + saveFile); + + var dm = Acap.DocumentManager; + if (dm.Count == 0) + return; + + // 剔除后缀 + saveFile = Path.Combine(Path.GetDirectoryName(saveFile), Path.GetFileNameWithoutExtension(saveFile)); + // ActiveSelectionSet: + // 第一次执行会触发选择,再次重复命令执行的时候,它会无法再选择(即使清空选择集). + // 因此此处netAPI进行选择,它就能读取当前选择集缓冲区的对象 + if (ids == null || ids.Length == 0) + { + var psr = editor.SelectImplied();// 预选 + if (psr.Status != PromptStatus.OK) + psr = editor.GetSelection();// 手选 + if (psr.Status != PromptStatus.OK) + return; + ids = psr.Value.GetObjectIds(); + } + editor.SetImpliedSelection(ids); + +#if zcad + dynamic com = Acap.ZcadApplication; +#else + dynamic com = Acap.AcadApplication; +#endif + dynamic doc = com.ActiveDocument; + dynamic wmfSet = doc.ActiveSelectionSet; + // TODO 20221007 导出wmf的bug + // cad21 先net选择,再进行,此处再选择一次? + // cad21 调试期间无法选择性粘贴? + doc.Export(saveFile, "wmf", wmfSet); + if (wmfSetDel) + wmfSet.Delete(); + } + #endregion + + #region JigEx + /// + /// jig前的准备工作,使图元暗显 + /// + /// 命令栏 + /// 实体(已存在数据库中) + public static void PrepareForJig(this Editor ed, params Entity[] ents) + { + ed.PrepareForJig(ents.ToList()); + } + /// + /// jig前的准备工作,使图元暗显 + /// + /// 命令栏 + /// 实体(已存在数据库中) + public static void PrepareForJig(this Editor ed, IEnumerable ents) + { + var dic = new Dictionary(); + foreach (var ent in ents) + { + if (ent.IsNewObject) + continue; + dic.Add(ent, ent.ColorIndex); + ent.ColorIndex = 250; + ent.Draw(); + } + ed.Redraw(); + foreach (var kvp in dic) + { + kvp.Key.ColorIndex = kvp.Value; + } + } + #endregion + + #region Extension + + /// + /// 获取CAD鼠标当前位置坐标 + /// + /// 命令栏 + /// 坐标(可能为null) + public static Point3d? GetCurrentMouthPoint(this Editor ed) + { + return ed.RunLisp("(grread T)", RunLispFlag.AcedEvaluateLisp)?.AsArray() + .FirstOrDefault(tv => tv.TypeCode == 5009).Value as Point3d?; + } + + #endregion +} \ No newline at end of file diff --git a/IFoxCAD.Cad/ExtensionMethod/Entity/PolylineEx.cs b/IFoxCAD.Cad/ExtensionMethod/Entity/PolylineEx.cs new file mode 100644 index 0000000..55b57ee --- /dev/null +++ b/IFoxCAD.Cad/ExtensionMethod/Entity/PolylineEx.cs @@ -0,0 +1,163 @@ +namespace IFoxCAD.Cad; + +/// +/// 多段线扩展类 +/// +public static class PolylineEx +{ + #region 获取多段线端点 + + /// + /// 获取二维多段线的端点坐标 + /// + /// 二维多段线 + /// 端点坐标集合 + public static IEnumerable GetPoints(this Polyline2d pl2d) + { + var tr = DBTrans.GetTopTransaction(pl2d.Database); + foreach (ObjectId id in pl2d) + { + if (tr.GetObject(id) is Vertex2d vertex) + { + yield return vertex.Position; + } + } + } + + /// + /// 获取三维多段线的端点坐标 + /// + /// 三维多段线 + /// 端点坐标集合 + public static IEnumerable GetPoints(this Polyline3d pl3d) + { + var tr = DBTrans.GetTopTransaction(pl3d.Database); + foreach (ObjectId id in pl3d) + { + if (tr.GetObject(id) is PolylineVertex3d vertex) + yield return vertex.Position; + } + } + + /// + /// 获取多段线的端点坐标 + /// + /// 多段线 + /// 端点坐标集合 + public static List GetPoints(this Polyline pl) + { + return + Enumerable + .Range(0, pl.NumberOfVertices) + .Select(pl.GetPoint3dAt) + .ToList(); + } + + #endregion + + #region 创建多段线 + + /// + /// 根据点集创建多段线
+ /// 此多段线无默认全局宽度0,无圆弧段 + ///
+ /// 点集 + /// 多段线属性设置委托 + /// 多段线对象 + public static Polyline CreatePolyline(this IEnumerable points, Action? action = null) + { + Polyline pl = new(); + pl.SetDatabaseDefaults(); + points.ForEach((index, pt) => { pl.AddVertexAt(index, pt.Point2d(), 0, 0, 0); }); + action?.Invoke(pl); + return pl; + } + + /// + /// 根据点集创建多段线 + /// + /// 端点表,利用元组(Point3d pt, double bulge, double startWidth, double endWidth) + /// 轻多段线属性设置委托 + /// 轻多段线对象 + public static Polyline CreatePolyline( + this IEnumerable<(Point3d pt, double bulge, double startWidth, double endWidth)> pts, + Action? action = null) + { + Polyline pl = new(); + pl.SetDatabaseDefaults(); + + pts.ForEach((index, vertex) => + { + pl.AddVertexAt(index, vertex.pt.Point2d(), vertex.bulge, vertex.startWidth, vertex.endWidth); + }); + action?.Invoke(pl); + return pl; + } + + /// + /// 根据Extents3d创建多段线
+ /// 此多段线无默认全局宽度0,无圆弧段,标高为0 + ///
+ /// Extents3d + /// 多段线属性设置委托 + /// 多段线对象 + public static Polyline CreatePolyline(this Extents3d points, Action? action = null) + { + List pts = + [ + points.MinPoint.Point2d(), + new(points.MinPoint.X, points.MaxPoint.Y), + points.MaxPoint.Point2d(), + new(points.MaxPoint.X, points.MinPoint.Y) + ]; + + Polyline pl = new() { Closed = true }; + pl.SetDatabaseDefaults(); + pts.ForEach((index, pt) => { pl.AddVertexAt(index, pt, 0, 0, 0); }); + action?.Invoke(pl); + return pl; + } + + + /// + /// 点表生成多段线 + /// + /// 点表 + /// 线宽 + /// 是否闭合 + /// Polyline + public static Polyline CreatePolyline(this IEnumerable pointList, double plineWidth = 0, bool closed = false) + { + var pl = new Polyline(); + var enumerable = pointList.ToList(); + for (var i = 0; i < enumerable.Count; i++) + { + pl.AddVertexAt(i, enumerable.ElementAt(i), 0, plineWidth, plineWidth); + } + + pl.Closed = closed; + return pl; + } + + /// + /// 点表生成多段线 + /// + /// 点表 + /// 线宽 + /// 是否闭合 + /// Polyline + public static Polyline CreatePolyline(this IEnumerable pointList, double plineWidth = 0, bool closed = false) + { + var pl = new Polyline(); + var enumerable = pointList.ToList(); + for (var i = 0; i < enumerable.Count; i++) + { + pl.AddVertexAt(i, enumerable.ElementAt(i).Point2d(), 0, plineWidth, plineWidth); + } + + pl.Closed = closed; + return pl; + } + + #endregion +} \ No newline at end of file diff --git a/IFoxCAD.Cad/ExtensionMethod/Enums.cs b/IFoxCAD.Cad/ExtensionMethod/Enums.cs new file mode 100644 index 0000000..87f02c3 --- /dev/null +++ b/IFoxCAD.Cad/ExtensionMethod/Enums.cs @@ -0,0 +1,202 @@ +namespace IFoxCAD.Cad; + +/// +/// 参照路径转换 +/// +public enum PathConverterModes : byte +{ + /// + /// 相对路径 + /// + Relative, + /// + /// 绝对路径 + /// + Complete +} + +/// +/// 参照绑定 +/// +public enum XrefModes : byte +{ + /// + /// 卸载 + /// + Unload, + /// + /// 重载 + /// + Reload, + /// + /// 拆离 + /// + Detach, + /// + /// 绑定 + /// + Bind, +} +/// +/// 符号表模式 +/// +[Flags] +public enum SymModes : ushort +{ + /// + /// 块表 + /// + BlockTable = 1, + + /// + /// 图层表 + /// + LayerTable = 2, + /// + /// 文字样式表 + /// + TextStyleTable = 4, + /// + /// 注册应用程序表 + /// + RegAppTable = 8, + /// + /// 标注样式表 + /// + DimStyleTable = 16, + /// + /// 线型表 + /// + LinetypeTable = 32, + /// + /// 图层|字体|标注|线型|应用 + /// + Option1 = LayerTable | TextStyleTable | DimStyleTable | LinetypeTable | RegAppTable, + + /// + /// 用户坐标系表 + /// + UcsTable = 64, + /// + /// 视图表 + /// + ViewTable = 128, + /// + /// 视口表 + /// + ViewportTable = 256, + /// + /// 坐标|视口|视图 + /// + Option2 = UcsTable | ViewTable | ViewportTable, + + /// + /// 全部 + /// + All = BlockTable | Option1 | Option2 +} + + +/// +/// 坐标系类型枚举 +/// +public enum CoordinateSystemCode +{ + /// + /// 世界坐标系 + /// + Wcs = 0, + + /// + /// 用户坐标系 + /// + Ucs, + + /// + /// 模型空间坐标系 + /// + MDcs, + + /// + /// 图纸空间坐标系 + /// + PDcs +} + +/// +/// 方向的枚举 +/// +public enum OrientationType +{ + /// + /// 左转或逆时针 + /// + CounterClockWise, + /// + /// 右转或顺时针 + /// + ClockWise, + /// + /// 重合或平行 + /// + Parallel +} + +/// +/// 点与多边形的关系类型枚举 +/// +public enum PointOnRegionType +{ + /// + /// 多边形内部 + /// + Inside, + + /// + /// 多边形上 + /// + On, + + /// + /// 多边形外 + /// + Outside, + + /// + /// 错误 + /// + Error +} + + +/// +/// ttf字体枚举 +/// +public enum FontTTF +{ + /// + /// 宋体 + /// + [Description("宋体.ttf")] + 宋体, + /// + /// 仿宋 + /// + [Description("simfang.ttf")] + 仿宋, + /// + /// 仿宋GB2312 + /// + [Description("FSGB2312.ttf")] + 仿宋GB2312, + /// + /// Arial + /// + [Description("Arial.ttf")] + Arial, + /// + /// Romans + /// + [Description("Romans")] + Romans +} \ No newline at end of file diff --git a/IFoxCAD.Cad/ExtensionMethod/Geomerty/GeometryEx.cs b/IFoxCAD.Cad/ExtensionMethod/Geomerty/GeometryEx.cs new file mode 100644 index 0000000..3d7040f --- /dev/null +++ b/IFoxCAD.Cad/ExtensionMethod/Geomerty/GeometryEx.cs @@ -0,0 +1,676 @@ +namespace IFoxCAD.Cad; + +using System.Drawing; + +/// +/// 图形扩展类 +/// +public static class GeometryEx +{ + #region Point&Circle + + /// + /// 判断点与多边形的关系 + /// + /// 多边形顶点集合 + /// 点 + /// 点与多边形的关系 + public static PointOnRegionType PointOnRegion(this IEnumerable pts, Point2d pt) + { + // 遍历点集并生成首尾连接的多边形 + var ptlst = new LoopList(pts); + if (ptlst.Count < 3) + return PointOnRegionType.Error; + + List ls2ds = []; + foreach (var node in ptlst.GetNodes()) + { + ls2ds.Add(new LineSegment2d(node.Value, node.Next!.Value)); + } + var cc2d = new CompositeCurve2d(ls2ds.ToArray()); + + // 在多边形上? + if (cc2d.IsOn(pt)) + return PointOnRegionType.On; + + // 在最小包围矩形外? + var bb2d = cc2d.BoundBlock; + if (!bb2d.Contains(pt)) + return PointOnRegionType.Outside; + + // + bool flag = false; + foreach (var node in ptlst.GetNodes()) + { + var pt1 = node.Value; + var pt2 = node.Next!.Value; + if (pt.Y < pt1.Y && pt.Y < pt2.Y) + continue; + if (pt1.X < pt.X && pt2.X < pt.X) + continue; + Vector2d vec = pt2 - pt1; + double t = (pt.X - pt1.X) / vec.X; + double y = t * vec.Y + pt1.Y; + if (y < pt.Y && t >= 0 && t <= 1) + flag = !flag; + } + return + flag ? + PointOnRegionType.Inside : PointOnRegionType.Outside; + } + + /// + /// 判断点与多边形的关系 + /// + /// 多边形顶点集合 + /// 点 + /// 点与多边形的关系 + public static PointOnRegionType PointOnRegion(this IEnumerable pts, Point3d pt) + { + // 遍历点集并生成首尾连接的多边形 + var ptlst = new LoopList(pts); + if (ptlst.First!.Value == ptlst.Last!.Value) + ptlst.RemoveLast(); + if (ptlst.Count < 3) + return PointOnRegionType.Error; + + List ls3ds = []; + foreach (var node in ptlst.GetNodes()) + ls3ds.Add(new LineSegment3d(node.Value, node.Next!.Value)); + var cc3d = new CompositeCurve3d(ls3ds.ToArray()); + + // 在多边形上? + if (cc3d.IsOn(pt)) + return PointOnRegionType.On; + + // 在最小包围矩形外? + var bb2d = cc3d.BoundBlock; + if (!bb2d.Contains(pt)) + return PointOnRegionType.Outside; + + // + bool flag = false; + foreach (var node in ptlst.GetNodes()) + { + var pt1 = node.Value; + var pt2 = node.Next!.Value; + if (pt.Y < pt1.Y && pt.Y < pt2.Y) + continue; + if (pt1.X < pt.X && pt2.X < pt.X) + continue; + Vector3d vec = pt2 - pt1; + double t = (pt.X - pt1.X) / vec.X; + double y = t * vec.Y + pt1.Y; + if (y < pt.Y && t >= 0 && t <= 1) + flag = !flag; + } + return + flag ? + PointOnRegionType.Inside : PointOnRegionType.Outside; + } + + /// + /// 按两点返回最小包围圆 + /// + /// 基准点 + /// 基准点 + /// 输出圆上的点 + /// 解析类圆对象 + public static CircularArc2d GetMinCircle(Point2d pt1, Point2d pt2, out LoopList ptlst) + { + ptlst = new LoopList { pt1, pt2 }; + return + new CircularArc2d + ( + (pt1 + pt2.GetAsVector()) / 2, + pt1.GetDistanceTo(pt2) / 2 + ); + } + + /// + /// 按三点返回最小包围圆 + /// + /// 基准点 + /// 基准点 + /// 基准点 + /// 输出圆上的点 + /// 解析类圆对象 + public static CircularArc2d GetMinCircle(Point2d pt1, Point2d pt2, Point2d pt3, out LoopList ptlst) + { + ptlst = new LoopList { pt1, pt2, pt3 }; + + // 遍历各点与下一点的向量长度,找到距离最大的两个点 + LoopListNode maxNode = + ptlst.GetNodes().FindByMax + ( + out _, + node => node.Value.GetDistanceTo(node.Next!.Value) + ); + + // 以两点做最小包围圆 + CircularArc2d ca2d = + GetMinCircle(maxNode.Value, maxNode.Next!.Value, out LoopList tptlst); + + // 如果另一点属于该圆 + if (ca2d.IsIn(maxNode.Previous!.Value)) + { + // 返回 + ptlst = tptlst; + return ca2d; + } + // 否则按三点做圆 + // ptlst.SetFirst(maxNode); + ptlst = new LoopList { maxNode.Value, maxNode.Next.Value, maxNode.Previous.Value }; + ca2d = new CircularArc2d(pt1, pt2, pt3); + ca2d.SetAngles(0, Math.PI * 2); + return ca2d; + } + + /// + /// 按四点返回最小包围圆 + /// + /// 基准点 + /// 基准点 + /// 基准点 + /// 基准点 + /// 输出圆上的点 + /// 解析类圆对象 + public static CircularArc2d? GetMinCircle(Point2d pt1, Point2d pt2, Point2d pt3, Point2d pt4, out LoopList? ptlst) + { + var iniptlst = new LoopList() { pt1, pt2, pt3, pt4 }; + ptlst = null; + CircularArc2d? ca2d = null; + + // 遍历C43的组合,环链表的优势在这里 + foreach (var firstNode in iniptlst.GetNodes()) + { + // 获取各组合下三点的最小包围圆 + var secondNode = firstNode.Next; + var thirdNode = secondNode!.Next; + var tca2d = GetMinCircle(firstNode.Value, secondNode.Value, thirdNode!.Value, out LoopList tptlst); + + // 如果另一点属于该圆,并且半径小于当前值就把它做为候选解 + if (!tca2d.IsIn(firstNode.Previous!.Value)) + continue; + if (ca2d is null || tca2d.Radius < ca2d.Radius) + { + ca2d = tca2d; + ptlst = tptlst; + } + } + + // 返回直径最小的圆 + return ca2d; + } + + /// + /// 计算三点围成的有向面积 + /// + /// 基准点 + /// 第一点 + /// 第二点 + /// 三点围成的三角形的有向面积 + private static double CalArea(Point2d ptBase, Point2d pt1, Point2d pt2) + { + return (pt2 - ptBase).DotProduct((pt1 - ptBase).GetPerpendicularVector()) * 0.5; + } + /// + /// 计算三点围成的三角形的真实面积 + /// + /// 基准点 + /// 第一点 + /// 第二点 + /// 三点围成的三角形的真实面积 + public static double GetArea(this Point2d ptBase, Point2d pt1, Point2d pt2) + { + return Math.Abs(CalArea(ptBase, pt1, pt2)); + } + + /// + /// 判断三点是否为逆时针,也就是说判断三点是否为左转 + /// + /// 基点 + /// 第一点 + /// 第二点 + /// OrientationType 类型值 + public static OrientationType IsClockWise(this Point2d ptBase, Point2d pt1, Point2d pt2) + { + return CalArea(ptBase, pt1, pt2) switch + { + > 0 => OrientationType.CounterClockWise, + < 0 => OrientationType.ClockWise, + _ => OrientationType.Parallel + }; + } + + /// + /// 计算两个二维向量围成的平行四边形的有向面积 + /// + /// 基向量 + /// 向量 + /// 有向面积 + private static double CalArea(Vector2d vecBase, Vector2d vec) + { + return vec.DotProduct(vecBase.GetPerpendicularVector()) / 2; + } + + /// + /// 计算两个二维向量围成的平行四边形的真实面积 + /// + /// 基向量 + /// 向量 + /// 真实面积 + public static double GetArea(Vector2d vecBase, Vector2d vec) + { + return Math.Abs(CalArea(vecBase, vec)); + } + + /// + /// 判断两个二维向量是否左转 + /// + /// 基向量 + /// 向量 + /// OrientationType 类型值 + public static OrientationType IsClockWise(Vector2d vecBase, Vector2d vec) + { + return CalArea(vecBase, vec) switch + { + > 0 => OrientationType.CounterClockWise, + < 0 => OrientationType.ClockWise, + _ => OrientationType.Parallel + }; + } + + #region PointList + + /// + /// 计算点集的有向面积 + /// + /// 点集 + /// 有向面积 + private static double CalArea(IEnumerable pnts) + { + using var itor = pnts.GetEnumerator(); + if (!itor.MoveNext()) + throw new ArgumentNullException(nameof(pnts)); + var start = itor.Current; + var p2 = start; + double area = 0; + + while (itor.MoveNext()) + { + var p1 = p2; + p2 = itor.Current; + area += (p1.X * p2.Y - p2.X * p1.Y); + } + + area = (area + (p2.X * start.Y - start.X * p2.Y)) / 2.0; + return area; + } + /// + /// 计算点集的真实面积 + /// + /// 点集 + /// 面积 + public static double GetArea(this IEnumerable pnts) + { + return Math.Abs(CalArea(pnts)); + } + + /// + /// 判断点集的点序 + /// + /// 点集 + /// OrientationType 类型值 + public static OrientationType IsClockWise(this IEnumerable pnts) + { + return CalArea(pnts) switch + { + < 0 => OrientationType.ClockWise, + > 0 => OrientationType.CounterClockWise, + _ => OrientationType.Parallel + }; + } + + /// + /// 按点集返回最小包围圆 + /// + /// 点集 + /// 输出圆上的点 + /// 解析类圆对象 + public static CircularArc2d? GetMinCircle(this List pnts, out LoopList? ptlst) + { + // 点数较小时直接返回 + switch (pnts.Count) + { + case 0: + ptlst = null; + return null; + + case 1: + ptlst = new LoopList { pnts[0] }; + return new CircularArc2d(pnts[0], 0); + + case 2: + return GetMinCircle(pnts[0], pnts[1], out ptlst); + + case 3: + return GetMinCircle(pnts[0], pnts[1], pnts[2], out ptlst); + + case 4: + return GetMinCircle(pnts[0], pnts[1], pnts[2], pnts[3], out ptlst); + } + + // 按前三点计算最小包围圆 + var tpnts = new Point2d[4]; + pnts.CopyTo(0, tpnts, 0, 3); + var ca2d = GetMinCircle(tpnts[0], tpnts[1], tpnts[2], out ptlst); + + // 找到点集中距离圆心的最远点为第四点 + tpnts[3] = pnts.FindByMax(pnt => ca2d.Center.GetDistanceTo(pnt)); + + // 如果最远点属于圆结束 + while (!ca2d.IsIn(tpnts[3])) + { + // 如果最远点不属于圆,按此四点计算最小包围圆 + ca2d = GetMinCircle(tpnts[0], tpnts[1], tpnts[2], tpnts[3], out ptlst); + + // 将结果作为新的前三点 + if (ptlst!.Count == 3) + { + tpnts[2] = ptlst.Last!.Value; + } + else + { + // 第三点取另两点中距离圆心较远的点 + // 按算法中描述的任选其中一点的话,还是无法收敛...... + tpnts[2] = + tpnts.Except(ptlst) + .FindByMax(pnt => ca2d!.Center.GetDistanceTo(pnt)); + } + tpnts[0] = ptlst.First!.Value; + tpnts[1] = ptlst.First.Next!.Value; + + // 按此三点计算最小包围圆 + ca2d = GetMinCircle(tpnts[0], tpnts[1], tpnts[2], out ptlst); + + // 找到点集中圆心的最远点为第四点 + tpnts[3] = pnts.FindByMax(pnt => ca2d.Center.GetDistanceTo(pnt)); + } + + return ca2d; + } + + /// + /// 获取点集的凸包 + /// + /// 点集 + /// 凸包 + public static List ConvexHull(this List points) + { + if (points.Count <= 1) + return points; + + int n = points.Count, k = 0; + List H = new(new Point2d[2 * n]); + + points.Sort((a, b) => + a.X == b.X ? a.Y.CompareTo(b.Y) : a.X.CompareTo(b.X)); + + // Build lower hull + for (int i = 0; i < n; ++i) + { + while (k >= 2 && IsClockWise(H[k - 2], H[k - 1], points[i]) == OrientationType.CounterClockWise) + k--; + H[k++] = points[i]; + } + + // Build upper hull + for (int i = n - 2, t = k + 1; i >= 0; i--) + { + while (k >= t && IsClockWise(H[k - 2], H[k - 1], points[i]) == OrientationType.CounterClockWise) + k--; + H[k++] = points[i]; + } + return H.Take(k - 1).ToList(); + } + + + #endregion PointList + + #endregion Point&Circle + + #region Ucs + + /// + /// ucs到wcs的点变换 + /// + /// 点 + /// 变换后的点 + public static Point3d Ucs2Wcs(this Point3d point) + { + return point.TransformBy(Env.Editor.CurrentUserCoordinateSystem); + } + + /// + /// wcs到ucs的点变换 + /// + /// 点 + /// 变换后的点 + public static Point3d Wcs2Ucs(this Point3d point) + { + return point.TransformBy(Env.Editor.CurrentUserCoordinateSystem.Inverse()); + } + + /// + /// ucs到wcs的向量变换 + /// + /// 向量 + /// 变换后的向量 + public static Vector3d Ucs2Wcs(this Vector3d vec) + { + return vec.TransformBy(Env.Editor.CurrentUserCoordinateSystem); + } + + /// + /// wcs到ucs的向量变换 + /// + /// 向量 + /// 变换后的向量 + public static Vector3d Wcs2Ucs(this Vector3d vec) + { + return vec.TransformBy(Env.Editor.CurrentUserCoordinateSystem.Inverse()); + } + + /// + /// 模拟 trans 函数 + /// + /// 点 + /// 源坐标系 + /// 目标坐标系 + /// 变换后的点 + public static Point3d Trans(this Point3d point, CoordinateSystemCode from, CoordinateSystemCode to) + { + return Env.Editor.GetMatrix(from, to) * point; + } + + /// + /// 模拟 trans 函数 + /// + /// 向量 + /// 源坐标系 + /// 目标坐标系 + /// 变换后的向量 + public static Vector3d Trans(this Vector3d vec, CoordinateSystemCode from, CoordinateSystemCode to) + { + return vec.TransformBy(Env.Editor.GetMatrix(from, to)); + } + + /// + /// wcs到dcs的点变换 + /// + /// 点 + /// 是否为图纸空间 + /// 变换后的点 + public static Point3d Wcs2Dcs(this Point3d point, bool atPaperSpace) + { + return + Trans( + point, + CoordinateSystemCode.Wcs, atPaperSpace ? CoordinateSystemCode.PDcs : CoordinateSystemCode.MDcs + ); + } + + /// + /// wcs到dcs的向量变换 + /// + /// 向量 + /// 是否为图纸空间 + /// 变换后的向量 + public static Vector3d Wcs2Dcs(this Vector3d vec, bool atPaperSpace) + { + return + Trans( + vec, + CoordinateSystemCode.Wcs, atPaperSpace ? CoordinateSystemCode.PDcs : CoordinateSystemCode.MDcs + ); + } + + #endregion Ucs + + + /// + /// 返回不等比例变换矩阵 + /// + /// 基点 + /// x方向比例 + /// y方向比例 + /// z方向比例 + /// 三维矩阵 + public static Matrix3d GetScaleMatrix(this Point3d point, double x, double y, double z) + { + double[] matdata = new double[16]; + matdata[0] = x; + matdata[3] = point.X * (1 - x); + matdata[5] = y; + matdata[7] = point.Y * (1 - y); + matdata[10] = z; + matdata[11] = point.Z * (1 - z); + matdata[15] = 1; + return new(matdata); + } + + /// + /// 获取坐标范围的大小 + /// + /// 坐标范围 + /// 尺寸对象 + public static Size GetSize(this Extents3d ext) + { + int width = (int)Math.Floor(ext.MaxPoint.X - ext.MinPoint.X); + int height = (int)Math.Ceiling(ext.MaxPoint.Y - ext.MinPoint.Y); + return new(width, height); + } + + /// + /// 重绘 + /// + /// 图形界面几何 + /// 可绘制的对象列表 + public static void Draw(this Geometry geometry, IEnumerable drawables) + { + drawables.ForEach(d => geometry.Draw(d)); + } + /// + /// 重绘 + /// + /// 图形界面几何 + /// 可绘制的对象列表 + public static void Draw(this Geometry geometry, params Drawable[] drawables) + { + drawables.ForEach(d => geometry.Draw(d)); + } +} +/// +/// 向量扩展类 +/// +public static class VectorEx +{ + /// + /// 转换为2d向量 + /// + /// 3d向量 + /// 2d向量 + public static Vector2d Convert2d(this Vector3d vector3d) + { + return new Vector2d(vector3d.X, vector3d.Y); + } + + /// + /// 转换为3d向量 + /// + /// 2d向量 + /// z值 + /// 3d向量 + public static Vector3d Convert3d(this Vector2d vector2d, double z = 0) + { + return new Vector3d(vector2d.X, vector2d.Y, z); + } + /// + /// 2d叉乘 + /// + /// 向量a + /// 向量b + /// 叉乘值 + public static double Cross2d(this Vector3d a, Vector3d b) + { + return a.X * b.Y - b.X * a.Y; + } + /// + /// 2d叉乘 + /// + /// 向量a + /// 向量b + /// 叉乘值 + public static double Cross2d(this Vector2d a, Vector2d b) + { + return a.X * b.Y - b.X * a.Y; + } + /// + /// 向量Z值归零 + /// + /// 向量 + /// + public static Vector3d Z20(this Vector3d vector3d) + { + return new Vector3d(vector3d.X, vector3d.Y, 0); + } + /// + /// 向量在平面上的弧度 + /// + /// 向量 + /// 平面 + /// 弧度 + public static double AngleOnPlane(this Vector3d vector, Plane? plane = null) + { + return vector.AngleOnPlane(plane ?? PlaneEx.Z); + } +} +/// +/// 平面 +/// +public static class PlaneEx +{ + /// + /// X + /// + public static readonly Plane X = new (Point3d.Origin, Vector3d.XAxis); + /// + /// Y + /// + public static readonly Plane Y = new (Point3d.Origin, Vector3d.YAxis); + /// + /// Z + /// + public static readonly Plane Z = new (Point3d.Origin, Vector3d.ZAxis); +} \ No newline at end of file diff --git a/IFoxCAD.Cad/ExtensionMethod/Geomerty/PointEx.cs b/IFoxCAD.Cad/ExtensionMethod/Geomerty/PointEx.cs index 3244224..6cbc060 100644 --- a/IFoxCAD.Cad/ExtensionMethod/Geomerty/PointEx.cs +++ b/IFoxCAD.Cad/ExtensionMethod/Geomerty/PointEx.cs @@ -267,4 +267,85 @@ public static void End2End(this Point3dCollection ptCollection) } #endregion + + #region 包围盒 + + /// + /// 获取矩形4个3d角点(左下起,正方向) + /// + /// 包围盒 + /// z轴坐标 + /// 点表 + public static List GetRecPoint3ds(this Extents3d extents3d, double z = 0) + { + var xMin = extents3d.MinPoint.X; + var xMax = extents3d.MaxPoint.X; + var yMin = extents3d.MinPoint.Y; + var yMax = extents3d.MaxPoint.Y; + var pt1 = new Point3d(xMin, yMin, z); + var pt2 = new Point3d(xMax, yMin, z); + var pt3 = new Point3d(xMax, yMax, z); + var pt4 = new Point3d(xMin, yMax, z); + return [pt1, pt2, pt3, pt4]; + } + + /// + /// 获取矩形4个2d角点(左下起,正方向) + /// + /// 包围盒 + /// 点表 + public static List GetRecPoint2ds(this Extents3d extents3d) + { + var xMin = extents3d.MinPoint.X; + var xMax = extents3d.MaxPoint.X; + var yMin = extents3d.MinPoint.Y; + var yMax = extents3d.MaxPoint.Y; + var pt1 = new Point2d(xMin, yMin); + var pt2 = new Point2d(xMax, yMin); + var pt3 = new Point2d(xMax, yMax); + var pt4 = new Point2d(xMin, yMax); + return [pt1, pt2, pt3, pt4]; + } + + /// + /// 获取矩形4个角3d点(左下起,正方向) + /// + /// 角1 + /// 角2 + /// z轴坐标 + /// 点表 + public static List GetRecPoint3ds(this Point3d corner1, Point3d corner2, double z = 0) + { + var xMin = Math.Min(corner1.X, corner2.X); + var xMax = Math.Max(corner1.X, corner2.X); + var yMin = Math.Min(corner1.Y, corner2.Y); + var yMax = Math.Max(corner1.Y, corner2.Y); + var pt1 = new Point3d(xMin, yMin, z); + var pt2 = new Point3d(xMax, yMin, z); + var pt3 = new Point3d(xMax, yMax, z); + var pt4 = new Point3d(xMin, yMax, z); + return [pt1, pt2, pt3, pt4]; + } + + /// + /// 获取矩形4个角3d点(左下起,正方向) + /// + /// 角1 + /// 角2 + /// z轴坐标 + /// 点表 + public static List GetRecPoint2ds(this Point2d corner1, Point2d corner2, double z = 0) + { + var xMin = Math.Min(corner1.X, corner2.X); + var xMax = Math.Max(corner1.X, corner2.X); + var yMin = Math.Min(corner1.Y, corner2.Y); + var yMax = Math.Max(corner1.Y, corner2.Y); + var pt1 = new Point2d(xMin, yMin); + var pt2 = new Point2d(xMax, yMin); + var pt3 = new Point2d(xMax, yMax); + var pt4 = new Point2d(xMin, yMax); + return [pt1, pt2, pt3, pt4]; + } + + #endregion } \ No newline at end of file diff --git a/IFoxCAD.Cad/ExtensionMethod/SelectionSetEx.cs b/IFoxCAD.Cad/ExtensionMethod/SelectionSetEx.cs new file mode 100644 index 0000000..b4d22e4 --- /dev/null +++ b/IFoxCAD.Cad/ExtensionMethod/SelectionSetEx.cs @@ -0,0 +1,114 @@ +namespace IFoxCAD.Cad; + +/// +/// 选择集扩展类 +/// +public static class SelectionSetEx +{ + #region 获取对象id + + /// + /// 从选择集中获取对象id + /// + /// 图元类型 + /// 选择集 + /// 已选择的对象id集合 + [DebuggerStepThrough] + public static IEnumerable GetObjectIds(this SelectionSet ss) where T : Entity + { + var rxc = RXObject.GetClass(typeof(T)); + + return ss.GetObjectIds() + .Where(id => id.ObjectClass.IsDerivedFrom(rxc)); + } + + /// + /// 将选择集的对象按类型分组 + /// + /// 选择集 + /// 分组后的类型/对象id集合 + [DebuggerStepThrough] + public static IEnumerable> GetObjectIdGroup(this SelectionSet ss) + { + return ss.GetObjectIds() + .GroupBy(id => id.ObjectClass.DxfName); + } + + #endregion + + #region 获取实体对象 + + /// + /// 获取指定类型图元 + /// + /// 指定类型 + /// 选择集 + /// 打开模式 + /// 是否打开已删除对象,默认为不打开 + /// 是否打开锁定图层对象,默认为不打开 + /// 图元集合 + [DebuggerStepThrough] + public static IEnumerable GetEntities(this SelectionSet? ss, + OpenMode openMode = OpenMode.ForRead, + bool openErased = false, + bool openLockedLayer = false) where T : Entity + { + return ss?.GetObjectIds() + .Select(id => id.GetObject(openMode, openErased, openLockedLayer)) + .OfType() ?? []; + } + + #endregion + + #region ForEach + + /// + /// 遍历选择集 + /// + /// 指定图元类型 + /// 选择集 + /// 处理函数;(图元) + /// 打开模式 + /// 是否打开已删除对象,默认为不打开 + /// 是否打开锁定图层对象,默认为不打开 + [DebuggerStepThrough] + public static void ForEach(this SelectionSet ss, + Action action, + OpenMode openMode = OpenMode.ForRead, + bool openErased = false, + bool openLockedLayer = false) where T : Entity + { + ForEach(ss, (ent, _) => { action.Invoke(ent); }, openMode, openErased, openLockedLayer); + } + + /// + /// 遍历选择集 + /// + /// 指定图元类型 + /// 选择集 + /// 处理函数;(图元,终止方式) + /// 打开模式 + /// 是否打开已删除对象,默认为不打开 + /// 是否打开锁定图层对象,默认为不打开 + /// + [DebuggerStepThrough] + public static void ForEach(this SelectionSet ss, + Action action, + OpenMode openMode = OpenMode.ForRead, + bool openErased = false, + bool openLockedLayer = false) where T : Entity + { + ArgumentNullEx.ThrowIfNull(action); + + LoopState state = new(); + var ents = ss.GetEntities(openMode, openErased, openLockedLayer); + foreach (var ent in ents) + { + action.Invoke(ent, state); + if (!state.IsRun) + break; + } + } + + #endregion +} \ No newline at end of file diff --git a/IFoxCAD.Cad/ExtensionMethod/SymbolTableEx.cs b/IFoxCAD.Cad/ExtensionMethod/SymbolTableEx.cs new file mode 100644 index 0000000..0a70da6 --- /dev/null +++ b/IFoxCAD.Cad/ExtensionMethod/SymbolTableEx.cs @@ -0,0 +1,368 @@ +namespace IFoxCAD.Cad; + +/// +/// 符号表类扩展函数 +/// +public static class SymbolTableEx +{ + #region 图层表 + /// + /// 添加图层 + /// + /// 图层符号表 + /// 图层名 + /// 图层颜色 + /// 图层id + public static ObjectId Add(this SymbolTable table, string name, Color color) + { + return table.Add(name, lt => lt.Color = color); + } + /// + /// 添加图层 + /// + /// 图层符号表 + /// 图层名 + /// 图层颜色索引值 + /// 图层id + public static ObjectId Add(this SymbolTable table, string name, int colorIndex) + { + colorIndex %= 257;// 防止输入的颜色超出256 + colorIndex = Math.Abs(colorIndex);// 防止负数 + return table.Add(name, lt => lt.Color = Color.FromColorIndex(ColorMethod.ByColor, (short)colorIndex)); + } + /// + /// 更改图层名 + /// + /// 图层符号表 + /// 旧图层名 + /// 新图层名 + public static ObjectId Rename(this SymbolTable table, string oldName, string newName) + { + if (!table.Has(oldName)) + return ObjectId.Null; + + table.Change(oldName, layer => { + layer.Name = newName; + }); + return table[newName]; + } + /// + /// 删除图层 + /// + /// 层表 + /// 图层名 + /// 成功返回 ,失败返回 + public static bool Delete(this SymbolTable table, string name) + { + if (name == "0" || name == "Defpoints" || !table.Has(name) || table[name] == table.Database.Clayer) + return false; + + table.CurrentSymbolTable.GenerateUsageData(); + var ltr = table.GetRecord(name); + if (ltr is null) + return false; + + if (ltr.IsUsed) + return false; + using (ltr.ForWrite()) + ltr.Erase(); + return true; + } + #endregion + + #region 块表 + /// + /// 添加块定义 + /// + /// 块表 + /// 块名 + /// 对所添加块表的委托n + /// 添加图元的委托 + /// 添加属性定义的委托 + /// 块定义id + /// TODO: 需要测试匿名块等特殊的块是否能定义 + public static ObjectId Add(this SymbolTable table, + string name, + Action? action = null, + Func>? ents = null, + Func>? attdef = null) + { + return table.Add(name, btr => { + action?.Invoke(btr); + + var entsres = ents?.Invoke(); + if (entsres is not null) + btr.AddEntity(entsres); + + var adddefres = attdef?.Invoke(); + if (adddefres is not null) + btr.AddEntity(adddefres); + }); + } + /// + /// 添加块定义 + /// + /// 块表 + /// 块名 + /// 图元 + /// 属性定义 + /// + public static ObjectId Add(this SymbolTable table, + string name, + IEnumerable? ents = null, + IEnumerable? attdef = null) + { + return table.Add(name, btr => { + if (ents is not null) + btr.AddEntity(ents); + if (attdef is not null) + btr.AddEntity(attdef); + }); + } + + /// + /// 添加块定义 + /// + /// 块表 + /// 块名 + /// 图元(包括属性) + /// + public static ObjectId Add(this SymbolTable table, string name, params Entity[] ents) + { + return table.Add(name, null, () => ents); + } + + /// + /// 添加属性到块定义 + /// + /// 块表 + /// 块定义id + /// 属性列表 + public static void AddAttsToBlocks(this SymbolTable table, + ObjectId id, + List atts) + { + List attTags = []; + table.Change(id, btr => + { + btr.GetEntities() + .ForEach(def => attTags.Add(def.Tag.ToUpper())); + + foreach (var t in atts.Where(t => !attTags.Contains(t.Tag.ToUpper()))) + btr.AddEntity(t); + }); + } + /// + /// 添加属性到块定义 + /// + /// 块表 + /// 块定义名字 + /// 属性列表 + public static void AddAttsToBlocks(this SymbolTable table, + string name, + List atts) + { + List attTags = []; + table.Change(name, btr => + { + btr.GetEntities() + .ForEach(def => attTags.Add(def.Tag.ToUpper())); + + foreach (var t in atts.Where(t => !attTags.Contains(t.Tag.ToUpper()))) + btr.AddEntity(t); + }); + } + + /// + /// 从文件中获取块定义 + /// + /// 块表 + /// 文件名 + /// 是否覆盖 + /// 块定义Id + public static ObjectId GetBlockFrom(this SymbolTable table, string fileName, bool over) + { + + var blkdefname = SymbolUtilityServices.GetSymbolNameFromPathName(fileName, "dwg"); +#if acad + blkdefname = SymbolUtilityServices.RepairSymbolName(blkdefname, false); +#endif + var id = table[blkdefname]; + var has = id != ObjectId.Null; + + /* 每次看这里都要反应一阵 + 如果已经有这个id,并且要覆盖,或者没有这个id就执行下面的语句,不然就直接返回id + 其实就是如果有这个id,并且不覆盖,就直接返回,其他的情况都需要重新插入 + 所以原代码可以修改 + if (has && over || !has) + { + using Database db = new(false, true); + db.ReadDwgFile(fileName, FileShare.Read, true, null); + db.CloseInput(true); + id = table.Database.Insert(BlockTableRecord.ModelSpace, blkdefname, db, false); + + return id; + } */ + + if (has is true && over is false) + { + return id; + } + using Database db = new(false, true); + db.ReadDwgFile(fileName, FileShare.Read, true, null); + db.CloseInput(true); + id = table.Database.Insert(BlockTableRecord.ModelSpace, blkdefname, db, false); + return id; + } + + + + /// + /// 从文件中获取块定义 + /// + /// 块表 + /// 文件名 + /// 块定义名 + /// 是否覆盖 + /// 块定义Id + public static ObjectId GetBlockFrom(this SymbolTable table, + string fileName, + string blockName, + bool over) + { + return table.GetRecordFrom(t => t.BlockTable, fileName, blockName, over); + } + #endregion + + + #region 线型表 + /// + /// 添加线型 + /// + /// 线型表 + /// 线型名 + /// 线型说明 + /// 线型长度 + /// 笔画长度数组 + /// 线型id + public static ObjectId Add(this SymbolTable table, string name, string description, double length, double[] dash) + { + return table.Add( + name, + ltt => { + ltt.AsciiDescription = description; + ltt.PatternLength = length; // 线型的总长度 + ltt.NumDashes = dash.Length; // 组成线型的笔画数目 + for (int i = 0; i < dash.Length; i++) + { + ltt.SetDashLengthAt(i, dash[i]); + } + // ltt.SetDashLengthAt(0, 0.5); // 0.5个单位的划线 + // ltt.SetDashLengthAt(1, -0.25); // 0.25个单位的空格 + // ltt.SetDashLengthAt(2, 0); // 一个点 + // ltt.SetDashLengthAt(3, -0.25); // 0.25个单位的空格 + } + ); + } + #endregion + + #region 文字样式表 + /// + /// 添加文字样式记录 + /// + /// 文字样式表 + /// 文字样式名 + /// 字体名 + /// 宽度比例 + /// 文字样式Id + public static ObjectId Add(this SymbolTable table, + string textStyleName, + string font, + double xscale = 1.0) + { + return + table.Add( + textStyleName, + tstr => { + tstr.Name = textStyleName; + tstr.FileName = font; + tstr.XScale = xscale; + }); + } + /// + /// 添加文字样式记录 + /// + /// 文字样式表 + /// 文字样式名 + /// 字体名枚举 + /// 宽度比例 + /// 文字样式Id + public static ObjectId Add(this SymbolTable table, + string textStyleName, + FontTTF fontTTF, + double xscale = 1.0) + { + return table.Add(textStyleName, fontTTF.GetDescription(), xscale); + } + + /// + ///

添加文字样式记录,如果存在就默认强制替换

+ /// 此函数为了 而设 + ///
+ /// 文字样式表 + /// 文字样式名 + /// 字体名 + /// 大字体名 + /// 宽度比例 + /// 高度 + /// 是否强制替换 + /// 文字样式Id + public static ObjectId AddWithChange(this SymbolTable table, + string textStyleName, + string smallFont, + string bigFont = "", + double xScale = 1, + double height = 0, + bool forceChange = true) + { + if (forceChange && table.Has(textStyleName)) + { + table.Change(textStyleName, ttr => { + ttr.FileName = smallFont; + ttr.XScale = xScale; + ttr.TextSize = height; + if (bigFont != string.Empty) + ttr.BigFontFileName = bigFont; + }); + return table[textStyleName]; + } + return table.Add(textStyleName, ttr => { + ttr.FileName = smallFont; + ttr.XScale = xScale; + ttr.TextSize = height; + }); + } + + + #endregion + + #region 注册应用程序表 + + #endregion + + #region 标注样式表 + + #endregion + + #region 用户坐标系表 + + #endregion + + #region 视图表 + + #endregion + + #region 视口表 + + #endregion +} diff --git a/IFoxCAD.Cad/ExtensionMethod/TangentEx.cs b/IFoxCAD.Cad/ExtensionMethod/TangentEx.cs new file mode 100644 index 0000000..cc986b9 --- /dev/null +++ b/IFoxCAD.Cad/ExtensionMethod/TangentEx.cs @@ -0,0 +1,24 @@ +namespace IFoxCAD.Cad; + +/// +/// 天正接口 +/// +public static class TangentEx +{ + #region 获取天正比例 + + /// + /// 获取天正绘图比例 + /// + /// + public static double TgetPscale() + { + return DocGetPScale(); + } + + [DllImport("tch_kernal.arx", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, + EntryPoint = "?DocGetPScale@@YANXZ")] + private static extern double DocGetPScale(); + + #endregion +} \ No newline at end of file diff --git a/IFoxCAD.Cad/ExtensionMethod/WindowEx.cs b/IFoxCAD.Cad/ExtensionMethod/WindowEx.cs new file mode 100644 index 0000000..92c3fe5 --- /dev/null +++ b/IFoxCAD.Cad/ExtensionMethod/WindowEx.cs @@ -0,0 +1,86 @@ +using System.Drawing; +using System.Windows.Forms; +using Window = System.Windows.Window; + +namespace IFoxCAD.Cad; + +public static class WindowEx +{ + public static void AddEscQuit(this Window window) + { + window.KeyDown -= Window_KeyDown_Esc; + window.KeyDown += Window_KeyDown_Esc; + window.Closed -= WindowOnClosed; + window.Closed += WindowOnClosed; + } + + /// + /// 关闭时减掉事件 + /// + /// + /// + private static void WindowOnClosed(object sender, EventArgs e) + { + if (sender is not Window window) + return; + window.KeyDown -= Window_KeyDown_Esc; + window.Closed -= WindowOnClosed; + } + + private static void Window_KeyDown_Esc(object sender, System.Windows.Input.KeyEventArgs e) + { + if (e.Key != Key.Escape + || sender is not Window { IsLoaded: true, IsActive: true } window) + return; + + // 判断没有按住ctrl或shift或alt才执行 + var keys = Control.ModifierKeys; + if ((keys & Keys.Control) != 0 + || (keys & Keys.Shift) != 0 + || (keys & Keys.Alt) != 0) + return; + window.Close(); + } + + public static bool IsModel(this Window window) + { + return (bool)(typeof(Window) + .GetField("_showingAsDialog", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(window) ?? false); + } + + /// + /// 获取屏幕分辨率 + /// + /// 窗口句柄 + /// 屏幕尺寸 + public static Size GetScreenResolutionFromWindowHandle(IntPtr windowHandle) + { + var screen = Screen.FromHandle(windowHandle); + return new Size(screen.Bounds.Width, screen.Bounds.Height); + } + + /// + /// 通过分辨率设置面板尺寸 + /// + /// 侧栏 + /// 宽度 + /// 高度 + public static void SetSizeByScreenResolution(this PaletteSet paletteSet, int width, int height) + { + var size = GetScreenResolutionFromWindowHandle(Acap.MainWindow.Handle); + var scale = size.Height * 1d / 1080; + var newWidth = Convert.ToInt32(width * scale); + if (newWidth > size.Width) + newWidth = size.Width; + var newHeight = Convert.ToInt32(height * scale); + if (newHeight > size.Height) + newHeight = size.Height; + paletteSet.SetSize(new Size(newWidth, newHeight)); + } + + public static double GetScreenScale() + { + var scale = Graphics.FromHwnd(IntPtr.Zero).DpiX / 96.0f; + return scale; + } +} \ No newline at end of file diff --git a/IFoxCAD.Cad/IFoxCAD.Cad.csproj b/IFoxCAD.Cad/IFoxCAD.Cad.csproj index 24e8653..29ebc51 100644 --- a/IFoxCAD.Cad/IFoxCAD.Cad.csproj +++ b/IFoxCAD.Cad/IFoxCAD.Cad.csproj @@ -7,6 +7,7 @@ x64 IFoxCAD.Cad true + true @@ -30,4 +31,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/IFoxCAD.Cad/ResultData/LispList.cs b/IFoxCAD.Cad/ResultData/LispList.cs new file mode 100644 index 0000000..b097d9d --- /dev/null +++ b/IFoxCAD.Cad/ResultData/LispList.cs @@ -0,0 +1,194 @@ +namespace IFoxCAD.Cad; + +/// +/// lisp数据封装类 +/// +public class LispList : TypedValueList +{ + #region 构造函数 + /// + /// 默认构造函数 + /// + public LispList() { } + + /// + /// 构造函数 + /// + /// TypedValue 迭代器 + public LispList(IEnumerable values) : base(values) { } + #endregion + + #region 重写 + /// + /// lisp 列表的值 + /// + protected virtual List Value + { + get + { + var value = new List + { + new TypedValue((int)LispDataType.ListBegin,-1), + new TypedValue((int)LispDataType.ListEnd,-1) + }; + value.InsertRange(1, this); + return value; + } + } + #endregion + + #region 添加数据 + /// + /// 添加数据 + /// + /// 组码 + /// 组码值 + public override void Add(int code, object? obj) + { + if (code < 5000) + throw new Exception("传入的组码值不是 lisp数据 有效范围!"); + + Add(new TypedValue(code, obj)); + } + + /// + /// 添加数据 + /// + /// dxfcode枚举值 + /// 组码值 + public void Add(LispDataType code, object? obj) + { + Add((int)code, obj); + } + /// + /// 添加数据,参数为true时添加 lisp 中的 T,false时添加 lisp 中的 nil + /// + /// bool 型的数据 + public void Add(bool value) + { + if (value) + { + Add(LispDataType.T_atom, true); + } + else + { + Add(LispDataType.Nil, null); + } + } + /// + /// 添加字符串 + /// + /// 字符串 + public void Add(string value) + { + Add(LispDataType.Text, value); + } + /// + /// 添加短整型数 + /// + /// 短整型数 + public void Add(short value) + { + Add(LispDataType.Int16, value); + } + /// + /// 添加整型数 + /// + /// 整型数 + public void Add(int value) + { + Add(LispDataType.Int32, value); + } + /// + /// 添加浮点数 + /// + /// 浮点数 + public void Add(double value) + { + Add(LispDataType.Double, value); + } + /// + /// 添加对象id + /// + /// 对象id + public void Add(ObjectId value) + { + Add(LispDataType.ObjectId, value); + } + /// + /// 添加选择集 + /// + /// 选择集 + public void Add(SelectionSet value) + { + Add(LispDataType.SelectionSet, value); + } + /// + /// 添加二维点 + /// + /// 二维点 + public void Add(Point2d value) + { + Add(LispDataType.Point2d, value); + } + /// + /// 添加三维点 + /// + /// 三维点 + public void Add(Point3d value) + { + Add(LispDataType.Point3d, value); + } + /// + /// 添加二维点 + /// + /// X + /// Y + public void Add(double x, double y) + { + Add(LispDataType.Point2d, new Point2d(x, y)); + } + /// + /// 添加三维点 + /// + /// X + /// Y + /// Z + public void Add(double x, double y, double z) + { + Add(LispDataType.Point3d, new Point3d(x, y, z)); + } + /// + /// 添加列表 + /// + /// lisp 列表 + public void Add(LispList value) + { + this.AddRange(value.Value); + } + + #endregion + + #region 转换器 + /// + /// ResultBuffer 隐式转换到 LispList + /// + /// ResultBuffer 实例 + public static implicit operator LispList(ResultBuffer buffer) => new(buffer.AsArray()); + /// + /// LispList 隐式转换到 TypedValue 数组 + /// + /// TypedValueList 实例 + public static implicit operator TypedValue[](LispList values) => values.Value.ToArray(); + /// + /// LispList 隐式转换到 ResultBuffer + /// + /// TypedValueList 实例,要using + public static implicit operator ResultBuffer(LispList values) => new(values.Value.ToArray()); + /// + /// TypedValue 数组隐式转换到 LispList + /// + /// TypedValue 数组 + public static implicit operator LispList(TypedValue[] values) => new(values); + #endregion +} \ No newline at end of file diff --git a/IFoxCAD.Cad/Runtime/IdleNoCommandAction.cs b/IFoxCAD.Cad/Runtime/IdleNoCommandAction.cs new file mode 100644 index 0000000..093eae6 --- /dev/null +++ b/IFoxCAD.Cad/Runtime/IdleNoCommandAction.cs @@ -0,0 +1,69 @@ +namespace IFoxCAD.Cad; + +/// +/// 空闲且无命令时执行 +/// by DYH +/// 20231230 +/// +public static class IdleNoCmdAction +{ + private const string CmdActiveName = "CMDACTIVE"; + + /// + /// 是否已经加载 + /// + private static bool alreadyLoad = false; + + /// + /// 委托列表 + /// + private static readonly Queue _actions = new(); + + /// + /// 未处理的委托数量 + /// + public static int Count => _actions.Count; + + /// + /// 添加空闲执行委托 + /// + /// 委托 + public static void Add(Action action) + { + _actions.Enqueue(action); + if (!alreadyLoad) + { + Acap.Idle -= Acap_Idle; + Acap.Idle += Acap_Idle; + alreadyLoad = true; + } + } + + /// + /// 空闲处理事件 + /// + /// Acap + /// 事件参数 + private static void Acap_Idle(object sender, EventArgs e) + { + if (Count == 0) + { + alreadyLoad = false; + Acap.Idle -= Acap_Idle; + return; + } + // 判断是否有活动的命令 + if (Convert.ToBoolean(Acap.GetSystemVariable(CmdActiveName))) + return; + try + { + // 执行委托 + _actions.Dequeue()?.Invoke(); + } + catch + { + // 不进行操作 + } + System.Windows.Forms.Cursor.Position = System.Windows.Forms.Cursor.Position; + } +} \ No newline at end of file diff --git a/IFoxCAD.Cad/SelectionFilter/OpComp.cs b/IFoxCAD.Cad/SelectionFilter/OpComp.cs new file mode 100644 index 0000000..050c122 --- /dev/null +++ b/IFoxCAD.Cad/SelectionFilter/OpComp.cs @@ -0,0 +1,76 @@ +namespace IFoxCAD.Cad; + +/// +/// 比较运算符类 +/// +public class OpComp : OpEqual +{ + /// + /// 比较运算符,如: + /// "<=" + /// 以及合并比较运算符: + /// "<=,<=,=" + /// + public string Content { get; } + + /// + /// 符号名 + /// + public override string Name => "Comp"; + + /// + /// 比较运算符类构造函数 + /// + /// 运算符 + /// 数据 + public OpComp(string content, TypedValue value) + : base(value) + { + Content = content; + } + + /// + /// 比较运算符类构造函数 + /// + /// 运算符 + /// 组码 + public OpComp(string content, int code) + : base(code) + { + Content = content; + } + + /// + /// 比较运算符类构造函数 + /// + /// 运算符 + /// 组码 + /// 组码值 + public OpComp(string content, int code, object value) + : base(code, value) + { + Content = content; + } + + /// + /// 比较运算符类构造函数 + /// + /// 运算符 + /// 组码 + /// 组码值 + public OpComp(string content, DxfCode code, object value) + : base(code, value) + { + Content = content; + } + + /// + /// 获取过滤器数据迭代器 + /// + /// TypedValue迭代器 + public override IEnumerable GetValues() + { + yield return new TypedValue(-4, Content); + yield return Value; + } +} \ No newline at end of file diff --git a/IFoxCAD.Cad/SelectionFilter/OpEqual.cs b/IFoxCAD.Cad/SelectionFilter/OpEqual.cs new file mode 100644 index 0000000..e23e286 --- /dev/null +++ b/IFoxCAD.Cad/SelectionFilter/OpEqual.cs @@ -0,0 +1,83 @@ +namespace IFoxCAD.Cad; + +/// +/// 相等运算符类 +/// +public class OpEqual : OpFilter +{ + /// + /// 组码与匹配值的TypedValue类型值 + /// + public TypedValue Value { get; private set; } + + /// + /// 符号名 + /// + public override string Name => "Equal"; + + /// + /// 相等运算符类构造函数 + /// + /// 组码 + public OpEqual(int code) + { + Value = new TypedValue(code); + } + + /// + /// 相等运算符类构造函数 + /// + /// 组码 + /// 组码值 + public OpEqual(int code, object value) + { + Value = new TypedValue(code, value); + } + + /// + /// 相等运算符类构造函数 + /// + /// 组码 + /// 组码值 + public OpEqual(DxfCode code, object value) + { + Value = new TypedValue((int)code, value); + } + + /// + /// 相等运算符类构造函数 + /// + /// 组码与组码值的TypedValue类型值 + internal OpEqual(TypedValue value) + { + Value = value; + } + + /// + /// 过滤器数据迭代器 + /// + /// TypedValue迭代器 + public override IEnumerable GetValues() + { + yield return Value; + } + + /// + /// 设置数据 + /// + /// 组码值 + public void SetValue(object value) + { + Value = new TypedValue(Value.TypeCode, value); + } + + /// + /// 设置数据 + /// + /// 组码 + /// 组码值 + public void SetValue(int code, object value) + { + Value = new TypedValue(code, value); + } +} diff --git a/IFoxCAD.Cad/SelectionFilter/OpFilter.cs b/IFoxCAD.Cad/SelectionFilter/OpFilter.cs new file mode 100644 index 0000000..7eb495d --- /dev/null +++ b/IFoxCAD.Cad/SelectionFilter/OpFilter.cs @@ -0,0 +1,341 @@ +namespace IFoxCAD.Cad; + +/// +/// 选择集过滤器抽象类 +/// +public abstract class OpFilter +{ + /// + /// 过滤器的名字 + /// + public abstract string Name { get; } + + /// + /// 只读属性,表示这个过滤器取反 + /// + public OpFilter Not => new OpNot(this); + + /// + /// 获取TypedValue类型的值的迭代器的抽象方法,子类必须重写 + /// + /// TypedValue迭代器 + public abstract IEnumerable GetValues(); + + /// + /// 非操作符,返回的是OpFilter类型变量的 属性 + /// + /// OpFilter类型变量 + /// OpFilter对象 + public static OpFilter operator !(OpFilter item) + { + return item.Not; + } + + /// + /// 过滤器值转换为 TypedValue 类型数组 + /// + /// TypedValue数组 + public TypedValue[] ToArray() + { + return GetValues().ToArray(); + } + + /// + /// 隐式类型转换,将自定义的过滤器转换为 Autocad 认识的选择集过滤器 + /// + /// 过滤器对象 + /// + /// 选择集过滤器. + /// + public static implicit operator SelectionFilter(OpFilter item) + { + return new SelectionFilter(item.ToArray()); + } + + /// + /// 转换为字符串 + /// + /// 字符串 + public override string ToString() + { + var sb = new StringBuilder(); + foreach (var value in GetValues()) + sb.Append(value); + return sb.ToString(); + } + + /// + /// 构建过滤器 + /// + /// + /// 举两个利用构建函数创建选择集过滤的例子 + /// + /// !(e.Dxf(0) == "line" & e.Dxf(8) == "0") + /// | e.Dxf(0) != "circle" & e.Dxf(8) == "2" & e.Dxf(10) >= p); + /// + /// 例子2: + /// var f2 = OpFilter.Build( + /// e => e.Or( + /// !e.And(e.Dxf(0) == "line", e.Dxf(8) == "0"), + /// e.And(e.Dxf(0) != "circle", e.Dxf(8) == "2", + /// e.Dxf(10) <= new Point3d(10, 10, 0)))); + /// ]]> + /// + /// 构建过滤器的函数委托 + /// 过滤器 + public static OpFilter Build(Func func) + { + return func(new Op()).Filter!; + } + + #region Operator + + /// + /// 过滤器操作符类 + /// + public class Op + { + /// + /// 过滤器属性 + /// + internal OpFilter? Filter { get; private set; } + + internal Op() { } + + private Op(OpFilter filter) + { + Filter = filter; + } + + /// + /// AND 操作符 + /// + /// 操作符类型的可变参数 + /// Op对象 +#pragma warning disable CA1822 // 将成员标记为 static + public Op And(params Op[] args) +#pragma warning restore CA1822 // 将成员标记为 static + { + var filter = new OpAnd(); + foreach (var op in args) + filter.Add(op.Filter!); + return new Op(filter); + } + + /// + /// or 操作符 + /// + /// 操作符类型的可变参数 + /// Op对象 +#pragma warning disable CA1822 // 将成员标记为 static + public Op Or(params Op[] args) +#pragma warning restore CA1822 // 将成员标记为 static + { + var filter = new OpOr(); + foreach (var op in args) + filter.Add(op.Filter!); + return new Op(filter); + } + + /// + /// dxf 操作符,此函数只能用于过滤器中,不是组码操作函数 + /// + /// 组码 + /// Op对象 +#pragma warning disable CA1822 // 将成员标记为 static + public Op Dxf(int code) +#pragma warning restore CA1822 // 将成员标记为 static + { + return new Op(new OpEqual(code)); + } + + /// + /// dxf 操作符,此函数只能用于过滤器中,不是组码操作函数 + /// + /// 组码 + /// 关系运算符的值,比如">,>,=" + /// Op对象 +#pragma warning disable CA1822 // 将成员标记为 static + public Op Dxf(int code, string content) +#pragma warning restore CA1822 // 将成员标记为 static + { + return new Op(new OpComp(content, code)); + } + + /// + /// 非操作符 + /// + /// 过滤器操作符对象 + /// Op对象 + public static Op operator !(Op right) + { + right.Filter = !right.Filter!; + return right; + } + + /// + /// 相等操作符 + /// + /// 过滤器操作符对象 + /// 数据 + /// Op对象 + public static Op operator ==(Op left, object right) + { + var eq = (OpEqual)left.Filter!; + eq.SetValue(right); + return left; + } + + /// + /// 不等操作符 + /// + /// 过滤器操作符对象 + /// 数据 + /// Op对象 + public static Op operator !=(Op left, object right) + { + var eq = (OpEqual)left.Filter!; + eq.SetValue(right); + left.Filter = eq.Not; + return left; + } + + private static Op GetCompOp(string content, Op left, object right) + { + var eq = (OpEqual)left.Filter!; + var comp = new OpComp(content, eq.Value.TypeCode, right); + return new Op(comp); + } + + /// + /// 大于操作符 + /// + /// 过滤器操作符对象 + /// 数据 + /// Op对象 + public static Op operator >(Op left, object right) + { + return GetCompOp(">", left, right); + } + + /// + /// 小于操作符 + /// + /// 过滤器操作符对象 + /// 数据 + /// Op对象 + public static Op operator <(Op left, object right) + { + return GetCompOp("<", left, right); + } + + /// + /// 大于等于操作符 + /// + /// 过滤器操作符对象 + /// 数据 + /// Op对象 + public static Op operator >=(Op left, object right) + { + return GetCompOp(">=", left, right); + } + + /// + /// 小于等于操作符 + /// + /// 过滤器操作符对象 + /// 数据 + /// Op对象 + public static Op operator <=(Op left, object right) + { + return GetCompOp("<=", left, right); + } + + /// + /// 大于等于操作符 + /// + /// 过滤器操作符对象 + /// 点 + /// Op对象 + public static Op operator >=(Op left, Point3d right) + { + return GetCompOp(">,>,*", left, right); + } + + /// + /// 小于等于操作符 + /// + /// 过滤器操作符对象 + /// 点 + /// Op对象 + public static Op operator <=(Op left, Point3d right) + { + return GetCompOp("<,<,*", left, right); + } + + /// + /// 并操作符 + /// + /// 过滤器操作符对象 + /// 过滤器操作符对象 + /// Op对象 + public static Op operator &(Op left, Op right) + { + var filter = new OpAnd + { + left.Filter!, + right.Filter! + }; + return new Op(filter); + } + + /// + /// 或操作符 + /// + /// 过滤器操作符对象 + /// 过滤器操作符对象 + /// Op对象 + public static Op operator |(Op left, Op right) + { + var filter = new OpOr + { + left.Filter!, + right.Filter! + }; + return new Op(filter); + } + + /// + /// 异或操作符 + /// + /// 过滤器操作符对象 + /// 过滤器操作符对象 + /// Op对象 + public static Op operator ^(Op left, Op right) + { + var filter = new OpXor(left.Filter!, right.Filter!); + return new Op(filter); + } + + /// + /// 比较函数 + /// + /// 对象 + /// + /// 是否相等 + /// + public override bool Equals(object? obj) => base.Equals(obj); + + /// + /// 获取HashCode + /// + /// HashCode + public override int GetHashCode() => base.GetHashCode(); + } + + #endregion Operator +} diff --git a/IFoxCAD.Cad/SelectionFilter/OpList.cs b/IFoxCAD.Cad/SelectionFilter/OpList.cs new file mode 100644 index 0000000..d6e84d0 --- /dev/null +++ b/IFoxCAD.Cad/SelectionFilter/OpList.cs @@ -0,0 +1,160 @@ +namespace IFoxCAD.Cad; + +/// +/// 逻辑操作符的列表抽象类 +/// +public abstract class OpList : OpLogi +{ + /// + /// 过滤器列表 + /// + protected readonly List Lst = []; + + /// + /// 添加过滤器条件的虚函数,子类可以重写 + /// + /// 举个利用这个类及其子类创建选择集过滤的例子 + /// + /// ,>,*" } + /// }, + /// }; + /// ]]> + /// + /// 过滤器对象 + public virtual void Add(OpFilter value) + { + Lst.Add(value); + } + + /// + /// 添加过滤条件 + /// + /// 逻辑非~ + /// 组码 + /// 组码值 + public void Add(string speccode, int code, object value) + { + if (speccode == "~") + Lst.Add(new OpEqual(code, value).Not); + } + + /// + /// 添加过滤条件 + /// + /// 组码 + /// 组码值 + public void Add(int code, object value) + { + Lst.Add(new OpEqual(code, value)); + } + + /// + /// 添加过滤条件 + /// + /// 组码 + /// 组码值 + public void Add(DxfCode code, object value) + { + Lst.Add(new OpEqual(code, value)); + } + + /// + /// 添加过滤条件 + /// + /// 组码 + /// 组码值 + /// 比较运算符 + public void Add(int code, object value, string comp) + { + Lst.Add(new OpComp(comp, code, value)); + } + + /// + /// 添加过滤条件 + /// + /// 组码 + /// 组码值 + /// 比较运算符 + public void Add(DxfCode code, object value, string comp) + { + Lst.Add(new OpComp(comp, code, value)); + } + + /// + /// 过滤器迭代器 + /// + /// OpFilter迭代器 + [DebuggerStepThrough] + public override IEnumerator GetEnumerator() + { + return Lst.GetEnumerator(); + } +} + +/// +/// 逻辑与类 +/// +public class OpAnd : OpList +{ + /// + /// 符号名 + /// + public override string Name => "And"; + + /// + /// 添加过滤条件 + /// + /// 过滤器对象 + public override void Add(OpFilter value) + { + if (value is OpAnd opand) + { + foreach (var item in opand) + Lst.Add(item); + } + else + { + Lst.Add(value); + } + } +} + +/// +/// 逻辑或类 +/// +public class OpOr : OpList +{ + /// + /// 符号名 + /// + public override string Name => "Or"; + + /// + /// 添加过滤条件 + /// + /// 过滤器对象 + public override void Add(OpFilter value) + { + if (value is OpOr opor) + { + foreach (var item in opor) + Lst.Add(item); + } + else + { + Lst.Add(value); + } + } +} \ No newline at end of file diff --git a/IFoxCAD.Cad/SelectionFilter/OpLogi.cs b/IFoxCAD.Cad/SelectionFilter/OpLogi.cs new file mode 100644 index 0000000..b5570d1 --- /dev/null +++ b/IFoxCAD.Cad/SelectionFilter/OpLogi.cs @@ -0,0 +1,121 @@ +namespace IFoxCAD.Cad; + +/// +/// 过滤器逻辑运算符抽象类 +/// +public abstract class OpLogi : OpFilter, IEnumerable +{ + /// + /// 返回-4组码的开始内容 + /// + public TypedValue First => new(-4, $"<{Name}"); + + /// + /// 返回-4组码的结束内容 + /// + public TypedValue Last => new(-4, $"{Name}>"); + + /// + /// 获取过滤条件 + /// + /// TypedValue迭代器 + //[System.Diagnostics.DebuggerStepThrough] + public override IEnumerable GetValues() + { + yield return First; + foreach (var item in this) + { + foreach (var value in item.GetValues()) + yield return value; + } + yield return Last; + } + + /// + /// 获取迭代器 + /// + /// OpFilter迭代器 + [DebuggerStepThrough] + public abstract IEnumerator GetEnumerator(); + + [DebuggerStepThrough] + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } +} + +/// +/// 逻辑非类 +/// +public class OpNot : OpLogi +{ + private OpFilter Value { get; } + + /// + /// 逻辑非类构造函数 + /// + /// OpFilter数据 + public OpNot(OpFilter value) + { + Value = value; + } + + /// + /// 符号名 + /// + public override string Name => "Not"; + + /// + /// 获取迭代器 + /// + /// OpFilter迭代器 + [DebuggerStepThrough] + public override IEnumerator GetEnumerator() + { + yield return Value; + } +} + +/// +/// 逻辑异或类 +/// +public class OpXor : OpLogi +{ + /// + /// 左操作数 + /// + public OpFilter Left { get; } + + /// + /// 右操作数 + /// + public OpFilter Right { get; } + + /// + /// 逻辑异或类构造函数 + /// + /// 左操作数 + /// 右操作数 + public OpXor(OpFilter left, OpFilter right) + { + Left = left; + Right = right; + } + + /// + /// 符号名 + /// + public override string Name => "Xor"; + + /// + /// 获取迭代器 + /// + /// 选择集过滤器类型迭代器 + [DebuggerStepThrough] + public override IEnumerator GetEnumerator() + { + yield return Left; + yield return Right; + } +} \ No newline at end of file -- Gitee From 2c6e866a66f132e1a676cc61234f526fc7c0277d Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sat, 30 Mar 2024 20:28:51 +0800 Subject: [PATCH 272/453] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=91=BD=E5=90=8D?= =?UTF-8?q?=E7=A9=BA=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IFoxCAD.Cad/Basal/Win/SystemEx.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/IFoxCAD.Cad/Basal/Win/SystemEx.cs b/IFoxCAD.Cad/Basal/Win/SystemEx.cs index 3ca3314..2ec945b 100644 --- a/IFoxCAD.Cad/Basal/Win/SystemEx.cs +++ b/IFoxCAD.Cad/Basal/Win/SystemEx.cs @@ -1,4 +1,4 @@ -namespace IFoxCAD.Cad.Basal.Win; +namespace IFoxCAD.Basal; public class SystemEx { -- Gitee From fea5562e4ddc5d0c09389e70f884b51d06583253 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sun, 31 Mar 2024 20:32:36 +0800 Subject: [PATCH 273/453] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=85=B3=E9=94=AE?= =?UTF-8?q?=E5=AD=97=E5=85=8D=E5=9B=9E=E8=BD=A6=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/SingleKeyWordHook.cs | 216 ++++++++++++++++++ 1 file changed, 216 insertions(+) create mode 100644 IFoxCAD.Cad/ExtensionMethod/SingleKeyWordHook.cs diff --git a/IFoxCAD.Cad/ExtensionMethod/SingleKeyWordHook.cs b/IFoxCAD.Cad/ExtensionMethod/SingleKeyWordHook.cs new file mode 100644 index 0000000..1d2bb31 --- /dev/null +++ b/IFoxCAD.Cad/ExtensionMethod/SingleKeyWordHook.cs @@ -0,0 +1,216 @@ +using Keys = System.Windows.Forms.Keys; + +namespace IFoxCAD.Cad; + +/// +/// 关键字不需要空格钩子 +/// By DYH 20230508 +/// +public sealed class SingleKeyWordHook : IDisposable +{ + #region 私有字段 + + /// + /// 关键字合集 + /// + private readonly HashSet _keyWords; + + private bool _isResponsed; + private bool _working; + private Keys _key; + private readonly bool _escapeMode; + + #endregion + + #region 公共属性 + + /// + /// 上一个触发的关键字 + /// + public Keys Key => _key; + + /// + /// 上一个触发的关键字字符串 + /// + public string StringResult => _key.ToString().ToUpper(); + + /// + /// 是否响应了 + /// + public bool IsResponsed => _isResponsed && _working; + + #endregion + + #region 构造 + + /// + /// 单字母关键字免输回车钩子 + /// + /// 使用esc(填false则使用回车) + public SingleKeyWordHook(bool escapeMode = true) + { + IsDisposed = false; + _isResponsed = false; + _keyWords = new HashSet(); + _key = Keys.None; + _working = true; + _escapeMode = escapeMode; + Acap.PreTranslateMessage -= Acap_PreTranslateMessage; + Acap.PreTranslateMessage += Acap_PreTranslateMessage; + } + + #endregion + + #region 方法 + + /// + /// 添加Keys + /// + /// Keys集合 + public void AddKeys(params Keys[] values) => values.ForEach(value => _keyWords.Add(value)); + + /// + /// 添加Keys + /// + /// 关键字集合 + public void AddKeys(KeywordCollection keywordCollection) + { + foreach (Keyword item in keywordCollection) + { + if (item.LocalName.Length == 1) + { + Keys k = (Keys)item.LocalName[0]; + _keyWords.Add(k); + } + } + } + + /// + /// 移除Keys + /// + /// Keys集合 + public void Remove(params Keys[] values) => values.ForEach(value => _keyWords.Remove(value)); + + /// + /// 清空Keys + /// + public void Clear() => _keyWords.Clear(); + + /// + /// 复位响应状态,每个循环开始时使用 + /// + public void Reset() + { + _isResponsed = false; + } + + /// + /// 暂停工作 + /// + public void Pause() + { + _working = false; + } + + /// + /// 开始工作 + /// + public void Working() + { + _working = true; + } + + #endregion + + #region 事件 + + private void Acap_PreTranslateMessage(object sender, PreTranslateMessageEventArgs e) + { + if (!_working || e.Message.message != 256) return; + var tempKey = IntPtr.Size == 4 ? (Keys)e.Message.wParam.ToInt32() : (Keys)e.Message.wParam.ToInt64(); + bool contains = _keyWords.Contains(tempKey); + if (contains || tempKey == Keys.ProcessKey) + { + // 标记为true,表示此按键已经被处理,Windows不会再进行处理 + if (_escapeMode) + { + e.Handled = true; + } + + if (contains) + _key = tempKey; + if (!_isResponsed) + { + // 此bool是防止按键被长按时出错 + _isResponsed = true; + // 这里选择发送回车或者ESC//ESC稳妥一些,但是要promptResult的判断顺序 + KeyBoardSendKey(_escapeMode ? Keys.Escape : Keys.Enter); + } + } + } + + #endregion + + #region Dispose + + /// + /// 已经销毁 + /// + public bool IsDisposed { get; private set; } + + /// + /// + /// + /// + private void Dispose(bool disposing) + { + if (IsDisposed) + return; + + Acap.PreTranslateMessage -= Acap_PreTranslateMessage; + if (disposing) + { + _keyWords.Clear(); + } + + IsDisposed = true; + } + + /// + /// 析够里把事件拆了 + /// + ~SingleKeyWordHook() + { + Dispose(disposing: false); + } + /// + /// + /// + public void Dispose() + { + Dispose(disposing: true); + GC.SuppressFinalize(this); + } + + #endregion + + #region 静态方法 + + /// + /// 发送按键 + /// + /// + /// + /// + /// + private static void KeyBoardSendKey(Keys key, byte bScan = 0, uint dwFlags = 0, uint dwExtraInfo = 0) + { + keybd_event(key, bScan, dwFlags, dwExtraInfo); + keybd_event(key, bScan, 2, dwExtraInfo); + } + + [DllImport("user32.dll", EntryPoint = "keybd_event", SetLastError = true)] + private static extern void keybd_event(Keys bVk, byte bScan, uint dwFlags, uint dwExtraInfo); + + #endregion +} \ No newline at end of file -- Gitee From cd7d8be308efd5aaded40c2540d5c4bcf71664b9 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sun, 7 Apr 2024 23:36:42 +0800 Subject: [PATCH 274/453] =?UTF-8?q?WPF=E9=A1=B9=E7=9B=AE=E5=88=9D=E5=A7=8B?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ColorIndex2SolidColorBrushConverter.cs | 163 +++++++++++++++ IFoxCAD.WPF/DependencyObjectExtensions.cs | 39 ++++ IFoxCAD.WPF/GlobalUsings.cs | 7 + IFoxCAD.WPF/IFoxCAD.WPF.csproj | 16 ++ IFoxCAD.WPF/MVVM/RelayCommand.cs | 186 +++++++++++++++++ IFoxCAD.WPF/MVVM/ViewModelBase.cs | 65 ++++++ .../MarkupExtension/EventBindingExtension.cs | 187 ++++++++++++++++++ IFoxCAD.sln | 8 +- 8 files changed, 670 insertions(+), 1 deletion(-) create mode 100644 IFoxCAD.WPF/Converter/ColorIndex2SolidColorBrushConverter.cs create mode 100644 IFoxCAD.WPF/DependencyObjectExtensions.cs create mode 100644 IFoxCAD.WPF/GlobalUsings.cs create mode 100644 IFoxCAD.WPF/IFoxCAD.WPF.csproj create mode 100644 IFoxCAD.WPF/MVVM/RelayCommand.cs create mode 100644 IFoxCAD.WPF/MVVM/ViewModelBase.cs create mode 100644 IFoxCAD.WPF/MarkupExtension/EventBindingExtension.cs diff --git a/IFoxCAD.WPF/Converter/ColorIndex2SolidColorBrushConverter.cs b/IFoxCAD.WPF/Converter/ColorIndex2SolidColorBrushConverter.cs new file mode 100644 index 0000000..8047b27 --- /dev/null +++ b/IFoxCAD.WPF/Converter/ColorIndex2SolidColorBrushConverter.cs @@ -0,0 +1,163 @@ +using System.Collections.Generic; +using System.Globalization; +using System.Windows.Data; +using System.Windows.Media; +using MediaColor = System.Windows.Media.Color; + +namespace IFoxCAD.WPF; + +/// +/// 颜色索引到画刷转换器 +/// 由于不想引用AutoCAD的包,于是用这种ugly的方式来实现 +/// +public class ColorIndex2SolidColorBrushConverter : IValueConverter +{ + public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture) + { + if (value is null || !int.TryParse(value.ToString(), out var index)) + return Binding.DoNothing; + index = Math.Abs(index) % 257; + if (index is 0 or 256) + index = 7; + if (colorDict.TryGetValue(index, out var color)) + return color; + return Binding.DoNothing; + } + + public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) + { + return Binding.DoNothing; + } + + private static readonly Dictionary colorDict = new() + { + { 1, new(MediaColor.FromRgb(255, 0, 0)) }, { 2, new(MediaColor.FromRgb(255, 255, 0)) }, + { 3, new(MediaColor.FromRgb(0, 255, 0)) }, { 4, new(MediaColor.FromRgb(0, 255, 255)) }, + { 5, new(MediaColor.FromRgb(0, 0, 255)) }, { 6, new(MediaColor.FromRgb(255, 0, 255)) }, + { 7, new(MediaColor.FromRgb(255, 255, 255)) }, { 8, new(MediaColor.FromRgb(128, 128, 128)) }, + { 9, new(MediaColor.FromRgb(192, 192, 192)) }, { 10, new(MediaColor.FromRgb(255, 0, 0)) }, + { 11, new(MediaColor.FromRgb(255, 127, 127)) }, { 12, new(MediaColor.FromRgb(204, 0, 0)) }, + { 13, new(MediaColor.FromRgb(204, 102, 102)) }, { 14, new(MediaColor.FromRgb(153, 0, 0)) }, + { 15, new(MediaColor.FromRgb(153, 76, 76)) }, { 16, new(MediaColor.FromRgb(127, 0, 0)) }, + { 17, new(MediaColor.FromRgb(127, 63, 63)) }, { 18, new(MediaColor.FromRgb(76, 0, 0)) }, + { 19, new(MediaColor.FromRgb(76, 38, 38)) }, { 20, new(MediaColor.FromRgb(255, 63, 0)) }, + { 21, new(MediaColor.FromRgb(255, 159, 127)) }, { 22, new(MediaColor.FromRgb(204, 51, 0)) }, + { 23, new(MediaColor.FromRgb(204, 127, 102)) }, { 24, new(MediaColor.FromRgb(153, 38, 0)) }, + { 25, new(MediaColor.FromRgb(153, 95, 76)) }, { 26, new(MediaColor.FromRgb(127, 31, 0)) }, + { 27, new(MediaColor.FromRgb(127, 79, 63)) }, { 28, new(MediaColor.FromRgb(76, 19, 0)) }, + { 29, new(MediaColor.FromRgb(76, 47, 38)) }, { 30, new(MediaColor.FromRgb(255, 127, 0)) }, + { 31, new(MediaColor.FromRgb(255, 191, 127)) }, { 32, new(MediaColor.FromRgb(204, 102, 0)) }, + { 33, new(MediaColor.FromRgb(204, 153, 102)) }, { 34, new(MediaColor.FromRgb(153, 76, 0)) }, + { 35, new(MediaColor.FromRgb(153, 114, 76)) }, { 36, new(MediaColor.FromRgb(127, 63, 0)) }, + { 37, new(MediaColor.FromRgb(127, 95, 63)) }, { 38, new(MediaColor.FromRgb(76, 38, 0)) }, + { 39, new(MediaColor.FromRgb(76, 57, 38)) }, { 40, new(MediaColor.FromRgb(255, 191, 0)) }, + { 41, new(MediaColor.FromRgb(255, 223, 127)) }, { 42, new(MediaColor.FromRgb(204, 153, 0)) }, + { 43, new(MediaColor.FromRgb(204, 178, 102)) }, { 44, new(MediaColor.FromRgb(153, 114, 0)) }, + { 45, new(MediaColor.FromRgb(153, 133, 76)) }, { 46, new(MediaColor.FromRgb(127, 95, 0)) }, + { 47, new(MediaColor.FromRgb(127, 111, 63)) }, { 48, new(MediaColor.FromRgb(76, 57, 0)) }, + { 49, new(MediaColor.FromRgb(76, 66, 38)) }, { 50, new(MediaColor.FromRgb(255, 255, 0)) }, + { 51, new(MediaColor.FromRgb(255, 255, 127)) }, { 52, new(MediaColor.FromRgb(204, 204, 0)) }, + { 53, new(MediaColor.FromRgb(204, 204, 102)) }, { 54, new(MediaColor.FromRgb(153, 153, 0)) }, + { 55, new(MediaColor.FromRgb(153, 153, 76)) }, { 56, new(MediaColor.FromRgb(127, 127, 0)) }, + { 57, new(MediaColor.FromRgb(127, 127, 63)) }, { 58, new(MediaColor.FromRgb(76, 76, 0)) }, + { 59, new(MediaColor.FromRgb(76, 76, 38)) }, { 60, new(MediaColor.FromRgb(191, 255, 0)) }, + { 61, new(MediaColor.FromRgb(223, 255, 127)) }, { 62, new(MediaColor.FromRgb(153, 204, 0)) }, + { 63, new(MediaColor.FromRgb(178, 204, 102)) }, { 64, new(MediaColor.FromRgb(114, 153, 0)) }, + { 65, new(MediaColor.FromRgb(133, 153, 76)) }, { 66, new(MediaColor.FromRgb(95, 127, 0)) }, + { 67, new(MediaColor.FromRgb(111, 127, 63)) }, { 68, new(MediaColor.FromRgb(57, 76, 0)) }, + { 69, new(MediaColor.FromRgb(66, 76, 38)) }, { 70, new(MediaColor.FromRgb(127, 255, 0)) }, + { 71, new(MediaColor.FromRgb(191, 255, 127)) }, { 72, new(MediaColor.FromRgb(102, 204, 0)) }, + { 73, new(MediaColor.FromRgb(153, 204, 102)) }, { 74, new(MediaColor.FromRgb(76, 153, 0)) }, + { 75, new(MediaColor.FromRgb(114, 153, 76)) }, { 76, new(MediaColor.FromRgb(63, 127, 0)) }, + { 77, new(MediaColor.FromRgb(95, 127, 63)) }, { 78, new(MediaColor.FromRgb(38, 76, 0)) }, + { 79, new(MediaColor.FromRgb(57, 76, 38)) }, { 80, new(MediaColor.FromRgb(63, 255, 0)) }, + { 81, new(MediaColor.FromRgb(159, 255, 127)) }, { 82, new(MediaColor.FromRgb(51, 204, 0)) }, + { 83, new(MediaColor.FromRgb(127, 204, 102)) }, { 84, new(MediaColor.FromRgb(38, 153, 0)) }, + { 85, new(MediaColor.FromRgb(95, 153, 76)) }, { 86, new(MediaColor.FromRgb(31, 127, 0)) }, + { 87, new(MediaColor.FromRgb(79, 127, 63)) }, { 88, new(MediaColor.FromRgb(19, 76, 0)) }, + { 89, new(MediaColor.FromRgb(47, 76, 38)) }, { 90, new(MediaColor.FromRgb(0, 255, 0)) }, + { 91, new(MediaColor.FromRgb(127, 255, 127)) }, { 92, new(MediaColor.FromRgb(0, 204, 0)) }, + { 93, new(MediaColor.FromRgb(102, 204, 102)) }, { 94, new(MediaColor.FromRgb(0, 153, 0)) }, + { 95, new(MediaColor.FromRgb(76, 153, 76)) }, { 96, new(MediaColor.FromRgb(0, 127, 0)) }, + { 97, new(MediaColor.FromRgb(63, 127, 63)) }, { 98, new(MediaColor.FromRgb(0, 76, 0)) }, + { 99, new(MediaColor.FromRgb(38, 76, 38)) }, { 100, new(MediaColor.FromRgb(0, 255, 63)) }, + { 101, new(MediaColor.FromRgb(127, 255, 159)) }, { 102, new(MediaColor.FromRgb(0, 204, 51)) }, + { 103, new(MediaColor.FromRgb(102, 204, 127)) }, { 104, new(MediaColor.FromRgb(0, 153, 38)) }, + { 105, new(MediaColor.FromRgb(76, 153, 95)) }, { 106, new(MediaColor.FromRgb(0, 127, 31)) }, + { 107, new(MediaColor.FromRgb(63, 127, 79)) }, { 108, new(MediaColor.FromRgb(0, 76, 19)) }, + { 109, new(MediaColor.FromRgb(38, 76, 47)) }, { 110, new(MediaColor.FromRgb(0, 255, 127)) }, + { 111, new(MediaColor.FromRgb(127, 255, 191)) }, { 112, new(MediaColor.FromRgb(0, 204, 102)) }, + { 113, new(MediaColor.FromRgb(102, 204, 153)) }, { 114, new(MediaColor.FromRgb(0, 153, 76)) }, + { 115, new(MediaColor.FromRgb(76, 153, 114)) }, { 116, new(MediaColor.FromRgb(0, 127, 63)) }, + { 117, new(MediaColor.FromRgb(63, 127, 95)) }, { 118, new(MediaColor.FromRgb(0, 76, 38)) }, + { 119, new(MediaColor.FromRgb(38, 76, 57)) }, { 120, new(MediaColor.FromRgb(0, 255, 191)) }, + { 121, new(MediaColor.FromRgb(127, 255, 223)) }, { 122, new(MediaColor.FromRgb(0, 204, 153)) }, + { 123, new(MediaColor.FromRgb(102, 204, 178)) }, { 124, new(MediaColor.FromRgb(0, 153, 114)) }, + { 125, new(MediaColor.FromRgb(76, 153, 133)) }, { 126, new(MediaColor.FromRgb(0, 127, 95)) }, + { 127, new(MediaColor.FromRgb(63, 127, 111)) }, { 128, new(MediaColor.FromRgb(0, 76, 57)) }, + { 129, new(MediaColor.FromRgb(38, 76, 66)) }, { 130, new(MediaColor.FromRgb(0, 255, 255)) }, + { 131, new(MediaColor.FromRgb(127, 255, 255)) }, { 132, new(MediaColor.FromRgb(0, 204, 204)) }, + { 133, new(MediaColor.FromRgb(102, 204, 204)) }, { 134, new(MediaColor.FromRgb(0, 153, 153)) }, + { 135, new(MediaColor.FromRgb(76, 153, 153)) }, { 136, new(MediaColor.FromRgb(0, 127, 127)) }, + { 137, new(MediaColor.FromRgb(63, 127, 127)) }, { 138, new(MediaColor.FromRgb(0, 76, 76)) }, + { 139, new(MediaColor.FromRgb(38, 76, 76)) }, { 140, new(MediaColor.FromRgb(0, 191, 255)) }, + { 141, new(MediaColor.FromRgb(127, 223, 255)) }, { 142, new(MediaColor.FromRgb(0, 153, 204)) }, + { 143, new(MediaColor.FromRgb(102, 178, 204)) }, { 144, new(MediaColor.FromRgb(0, 114, 153)) }, + { 145, new(MediaColor.FromRgb(76, 133, 153)) }, { 146, new(MediaColor.FromRgb(0, 95, 127)) }, + { 147, new(MediaColor.FromRgb(63, 111, 127)) }, { 148, new(MediaColor.FromRgb(0, 57, 76)) }, + { 149, new(MediaColor.FromRgb(38, 66, 76)) }, { 150, new(MediaColor.FromRgb(0, 127, 255)) }, + { 151, new(MediaColor.FromRgb(127, 191, 255)) }, { 152, new(MediaColor.FromRgb(0, 102, 204)) }, + { 153, new(MediaColor.FromRgb(102, 153, 204)) }, { 154, new(MediaColor.FromRgb(0, 76, 153)) }, + { 155, new(MediaColor.FromRgb(76, 114, 153)) }, { 156, new(MediaColor.FromRgb(0, 63, 127)) }, + { 157, new(MediaColor.FromRgb(63, 95, 127)) }, { 158, new(MediaColor.FromRgb(0, 38, 76)) }, + { 159, new(MediaColor.FromRgb(38, 57, 76)) }, { 160, new(MediaColor.FromRgb(0, 63, 255)) }, + { 161, new(MediaColor.FromRgb(127, 159, 255)) }, { 162, new(MediaColor.FromRgb(0, 51, 204)) }, + { 163, new(MediaColor.FromRgb(102, 127, 204)) }, { 164, new(MediaColor.FromRgb(0, 38, 153)) }, + { 165, new(MediaColor.FromRgb(76, 95, 153)) }, { 166, new(MediaColor.FromRgb(0, 31, 127)) }, + { 167, new(MediaColor.FromRgb(63, 79, 127)) }, { 168, new(MediaColor.FromRgb(0, 19, 76)) }, + { 169, new(MediaColor.FromRgb(38, 47, 76)) }, { 170, new(MediaColor.FromRgb(0, 0, 255)) }, + { 171, new(MediaColor.FromRgb(127, 127, 255)) }, { 172, new(MediaColor.FromRgb(0, 0, 204)) }, + { 173, new(MediaColor.FromRgb(102, 102, 204)) }, { 174, new(MediaColor.FromRgb(0, 0, 153)) }, + { 175, new(MediaColor.FromRgb(76, 76, 153)) }, { 176, new(MediaColor.FromRgb(0, 0, 127)) }, + { 177, new(MediaColor.FromRgb(63, 63, 127)) }, { 178, new(MediaColor.FromRgb(0, 0, 76)) }, + { 179, new(MediaColor.FromRgb(38, 38, 76)) }, { 180, new(MediaColor.FromRgb(63, 0, 255)) }, + { 181, new(MediaColor.FromRgb(159, 127, 255)) }, { 182, new(MediaColor.FromRgb(51, 0, 204)) }, + { 183, new(MediaColor.FromRgb(127, 102, 204)) }, { 184, new(MediaColor.FromRgb(38, 0, 153)) }, + { 185, new(MediaColor.FromRgb(95, 76, 153)) }, { 186, new(MediaColor.FromRgb(31, 0, 127)) }, + { 187, new(MediaColor.FromRgb(79, 63, 127)) }, { 188, new(MediaColor.FromRgb(19, 0, 76)) }, + { 189, new(MediaColor.FromRgb(47, 38, 76)) }, { 190, new(MediaColor.FromRgb(127, 0, 255)) }, + { 191, new(MediaColor.FromRgb(191, 127, 255)) }, { 192, new(MediaColor.FromRgb(102, 0, 204)) }, + { 193, new(MediaColor.FromRgb(153, 102, 204)) }, { 194, new(MediaColor.FromRgb(76, 0, 153)) }, + { 195, new(MediaColor.FromRgb(114, 76, 153)) }, { 196, new(MediaColor.FromRgb(63, 0, 127)) }, + { 197, new(MediaColor.FromRgb(95, 63, 127)) }, { 198, new(MediaColor.FromRgb(38, 0, 76)) }, + { 199, new(MediaColor.FromRgb(57, 38, 76)) }, { 200, new(MediaColor.FromRgb(191, 0, 255)) }, + { 201, new(MediaColor.FromRgb(223, 127, 255)) }, { 202, new(MediaColor.FromRgb(153, 0, 204)) }, + { 203, new(MediaColor.FromRgb(178, 102, 204)) }, { 204, new(MediaColor.FromRgb(114, 0, 153)) }, + { 205, new(MediaColor.FromRgb(133, 76, 153)) }, { 206, new(MediaColor.FromRgb(95, 0, 127)) }, + { 207, new(MediaColor.FromRgb(111, 63, 127)) }, { 208, new(MediaColor.FromRgb(57, 0, 76)) }, + { 209, new(MediaColor.FromRgb(66, 38, 76)) }, { 210, new(MediaColor.FromRgb(255, 0, 255)) }, + { 211, new(MediaColor.FromRgb(255, 127, 255)) }, { 212, new(MediaColor.FromRgb(204, 0, 204)) }, + { 213, new(MediaColor.FromRgb(204, 102, 204)) }, { 214, new(MediaColor.FromRgb(153, 0, 153)) }, + { 215, new(MediaColor.FromRgb(153, 76, 153)) }, { 216, new(MediaColor.FromRgb(127, 0, 127)) }, + { 217, new(MediaColor.FromRgb(127, 63, 127)) }, { 218, new(MediaColor.FromRgb(76, 0, 76)) }, + { 219, new(MediaColor.FromRgb(76, 38, 76)) }, { 220, new(MediaColor.FromRgb(255, 0, 191)) }, + { 221, new(MediaColor.FromRgb(255, 127, 223)) }, { 222, new(MediaColor.FromRgb(204, 0, 153)) }, + { 223, new(MediaColor.FromRgb(204, 102, 178)) }, { 224, new(MediaColor.FromRgb(153, 0, 114)) }, + { 225, new(MediaColor.FromRgb(153, 76, 133)) }, { 226, new(MediaColor.FromRgb(127, 0, 95)) }, + { 227, new(MediaColor.FromRgb(127, 63, 111)) }, { 228, new(MediaColor.FromRgb(76, 0, 57)) }, + { 229, new(MediaColor.FromRgb(76, 38, 66)) }, { 230, new(MediaColor.FromRgb(255, 0, 127)) }, + { 231, new(MediaColor.FromRgb(255, 127, 191)) }, { 232, new(MediaColor.FromRgb(204, 0, 102)) }, + { 233, new(MediaColor.FromRgb(204, 102, 153)) }, { 234, new(MediaColor.FromRgb(153, 0, 76)) }, + { 235, new(MediaColor.FromRgb(153, 76, 114)) }, { 236, new(MediaColor.FromRgb(127, 0, 63)) }, + { 237, new(MediaColor.FromRgb(127, 63, 95)) }, { 238, new(MediaColor.FromRgb(76, 0, 38)) }, + { 239, new(MediaColor.FromRgb(76, 38, 57)) }, { 240, new(MediaColor.FromRgb(255, 0, 63)) }, + { 241, new(MediaColor.FromRgb(255, 127, 159)) }, { 242, new(MediaColor.FromRgb(204, 0, 51)) }, + { 243, new(MediaColor.FromRgb(204, 102, 127)) }, { 244, new(MediaColor.FromRgb(153, 0, 38)) }, + { 245, new(MediaColor.FromRgb(153, 76, 95)) }, { 246, new(MediaColor.FromRgb(127, 0, 31)) }, + { 247, new(MediaColor.FromRgb(127, 63, 79)) }, { 248, new(MediaColor.FromRgb(76, 0, 19)) }, + { 249, new(MediaColor.FromRgb(76, 38, 47)) }, { 250, new(MediaColor.FromRgb(51, 51, 51)) }, + { 251, new(MediaColor.FromRgb(91, 91, 91)) }, { 252, new(MediaColor.FromRgb(132, 132, 132)) }, + { 253, new(MediaColor.FromRgb(173, 173, 173)) }, { 254, new(MediaColor.FromRgb(214, 214, 214)) }, + { 255, new(MediaColor.FromRgb(255, 255, 255)) } + }; +} \ No newline at end of file diff --git a/IFoxCAD.WPF/DependencyObjectExtensions.cs b/IFoxCAD.WPF/DependencyObjectExtensions.cs new file mode 100644 index 0000000..317cba2 --- /dev/null +++ b/IFoxCAD.WPF/DependencyObjectExtensions.cs @@ -0,0 +1,39 @@ +using System.Windows.Media; + +namespace IFoxCAD.WPF; + +/// +/// 依赖属性扩展类 +/// +public static class DependencyObjectExtensions +{ + /// + /// 获取父对象依赖属性 + /// + /// 子对象 + /// 依赖属性 + public static DependencyObject? GetParentObject(this DependencyObject? child) + { + if (child is null) + return null; + + if (child is ContentElement ce) + { + var parent = ContentOperations.GetParent(ce); + if (parent is not null) + return parent; + + var fce = ce as FrameworkContentElement; + return fce?.Parent; + } + + if (child is FrameworkElement fe) + { + var parent = fe.Parent; + if (parent is not null) + return parent; + } + + return VisualTreeHelper.GetParent(child); + } +} \ No newline at end of file diff --git a/IFoxCAD.WPF/GlobalUsings.cs b/IFoxCAD.WPF/GlobalUsings.cs new file mode 100644 index 0000000..391e1c9 --- /dev/null +++ b/IFoxCAD.WPF/GlobalUsings.cs @@ -0,0 +1,7 @@ +global using System; +global using System.Reflection; +global using System.Reflection.Emit; +global using System.Windows; +global using System.Windows.Input; +global using System.Windows.Markup; +global using System.Diagnostics; \ No newline at end of file diff --git a/IFoxCAD.WPF/IFoxCAD.WPF.csproj b/IFoxCAD.WPF/IFoxCAD.WPF.csproj new file mode 100644 index 0000000..c083866 --- /dev/null +++ b/IFoxCAD.WPF/IFoxCAD.WPF.csproj @@ -0,0 +1,16 @@ + + + + net48 + Preview + enable + x64 + IFoxCAD.WPF + true + + + + + + + diff --git a/IFoxCAD.WPF/MVVM/RelayCommand.cs b/IFoxCAD.WPF/MVVM/RelayCommand.cs new file mode 100644 index 0000000..cd6dcf9 --- /dev/null +++ b/IFoxCAD.WPF/MVVM/RelayCommand.cs @@ -0,0 +1,186 @@ +using Microsoft.Xaml.Behaviors; + +namespace IFoxCAD.WPF; + +/// +/// 命令基类 +/// +/// +public class RelayCommand : ICommand +{ + private readonly Func? _canExecute; + private readonly Action _execute; + + /// + /// 初始化 类. + /// + /// 执行函数委托 + /// 是否可执行函数委托 + /// execute + public RelayCommand(Action execute, Func? canExecute = null) + { + _execute = execute ?? throw new ArgumentNullException(nameof(execute)); + _canExecute = canExecute; + } + + /// + /// 当出现影响是否应执行该命令的更改时发生。 + /// + public event EventHandler CanExecuteChanged + { + add + { + if (_canExecute is not null) + CommandManager.RequerySuggested += value; + } + remove + { + if (_canExecute is not null) + CommandManager.RequerySuggested -= value; + } + } + + /// + /// 定义确定此命令是否可在其当前状态下执行的方法。 + /// + /// 此命令使用的数据。 如果此命令不需要传递数据,则该对象可以设置为 。 + /// + /// 如果可执行此命令,则为 ;否则为 。 + /// + [DebuggerStepThrough] + public bool CanExecute(object parameter) + { + return _canExecute is null || _canExecute(parameter); + } + + /// + /// 定义在调用此命令时要调用的方法。 + /// + /// 此命令使用的数据。 如果此命令不需要传递数据,则该对象可以设置为 。 + public void Execute(object parameter) + { + _execute(parameter); + } +} + +/// +/// 命令泛型基类 +/// +/// 事件类型 +/// +public class RelayCommand : ICommand +{ + private readonly Func? _canExecute; + private readonly Action? _execute; + + /// + /// 初始化 类。 + /// + /// 执行函数 + public RelayCommand(Action execute) : this(execute, (_) => true) + { + } + + /// + /// 初始化 类。 + /// + /// 执行函数委托 + /// 是否可执行函数委托 + /// execute + public RelayCommand(Action execute, Func canExecute) + { + _execute = execute ?? throw new ArgumentNullException(nameof(execute)); + _canExecute = canExecute; + } + + /// + /// 当出现影响是否应执行该命令的更改时发生。 + /// + public event EventHandler CanExecuteChanged + { + add + { + if (_canExecute is not null) + CommandManager.RequerySuggested += value; + } + remove + { + if (_canExecute is not null) + CommandManager.RequerySuggested -= value; + } + } + + /// + /// 定义确定此命令是否可在其当前状态下执行的方法。 + /// + /// 此命令使用的数据。 如果此命令不需要传递数据,则该对象可以设置为 。 + /// + /// 如果可执行此命令,则为 ;否则为 。 + /// + public bool CanExecute(object parameter) + { + if (_canExecute is null) + return true; + return _canExecute((T)parameter); + } + + /// + /// 定义在调用此命令时要调用的方法。 + /// + /// 此命令使用的数据。 如果此命令不需要传递数据,则该对象可以设置为 。 + public void Execute(object parameter) + { + if (_execute is not null && CanExecute(parameter)) + _execute((T)parameter); + } +} + +/// +/// 事件命令 +/// +public class EventCommand : TriggerAction +{ + /// + /// 执行动作 + /// + /// 要执行的动作参数, 如果动作为提供参数,就设置为null + protected override void Invoke(object parameter) + { + if (CommandParameter is not null) + parameter = CommandParameter; + if (Command is not null) + Command.Execute(parameter); + } + + /// + /// 事件 + /// + public ICommand? Command + { + get => (ICommand)GetValue(CommandProperty); + set => SetValue(CommandProperty, value); + } + + /// + /// 事件属性 + /// + public static readonly DependencyProperty CommandProperty = + DependencyProperty.Register(nameof(Command), typeof(ICommand), typeof(EventCommand), + new PropertyMetadata(null)); + + /// + /// 事件参数,如果为空,将自动传入事件的真实参数 + /// + public object? CommandParameter + { + get => GetValue(CommandParameterProperty); + set => SetValue(CommandParameterProperty, value); + } + + /// + /// 事件参数属性 + /// + public static readonly DependencyProperty CommandParameterProperty = + DependencyProperty.Register(nameof(CommandParameter), typeof(object), typeof(EventCommand), + new PropertyMetadata(null)); +} \ No newline at end of file diff --git a/IFoxCAD.WPF/MVVM/ViewModelBase.cs b/IFoxCAD.WPF/MVVM/ViewModelBase.cs new file mode 100644 index 0000000..d020ef4 --- /dev/null +++ b/IFoxCAD.WPF/MVVM/ViewModelBase.cs @@ -0,0 +1,65 @@ +using System.ComponentModel; +using System.Runtime.CompilerServices; + +namespace IFoxCAD.WPF; + +/// +/// ViewModel基类 +/// +/// +public class ViewModelBase : INotifyPropertyChanged +{ + /// + /// 属性值更改事件。 + /// + public event PropertyChangedEventHandler? PropertyChanged; + + /// + /// 属性改变时调用 + /// + /// 属性名 + public void OnPropertyChanged([CallerMemberName] string propertyName = "") + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + + /// + /// 设置属性函数,自动通知属性改变事件 + /// + /// 属性类型 + /// 属性 + /// 属性值 + /// 属性名 + /// 成功返回 ,反之 + protected virtual bool Set(ref T storage, T value, [CallerMemberName] string propertyName = "") + { + if (Equals(storage, value)) + return false; + + storage = value; + this.OnPropertyChanged(propertyName); + + return true; + } + + /// + /// 创建命令 + /// + /// 要调用的命令函数委托 + /// WPF命令 + protected RelayCommand CreateCommand(Action executeMethod) + { + return CreateCommand(executeMethod, (_) => true); + } + + /// + /// 创建命令 + /// + /// 要调用的命令函数委托 + /// 命令是否可以执行的委托 + /// WPF命令 + protected RelayCommand CreateCommand(Action executeMethod, Func canExecuteMethod) + { + return new(executeMethod, canExecuteMethod); + } +} \ No newline at end of file diff --git a/IFoxCAD.WPF/MarkupExtension/EventBindingExtension.cs b/IFoxCAD.WPF/MarkupExtension/EventBindingExtension.cs new file mode 100644 index 0000000..b18ed85 --- /dev/null +++ b/IFoxCAD.WPF/MarkupExtension/EventBindingExtension.cs @@ -0,0 +1,187 @@ +namespace IFoxCAD.WPF; + +/// +/// 事件绑定标签类 +/// +/// +public class EventBindingExtension : MarkupExtension +{ + /// + /// 命令属性 + /// + public string? Command { get; set; } + /// + /// 命令参数属性 + /// + public string? CommandParameter { get; set; } + /// + /// 当在派生类中实现时,返回用作此标记扩展的目标属性值的对象。 + /// + /// 可为标记扩展提供服务的服务提供程序帮助程序。 + /// + /// 要在应用了扩展的属性上设置的对象值。 + /// + /// + /// + public override object? ProvideValue(IServiceProvider serviceProvider) + { + if (serviceProvider is null) + throw new ArgumentNullException(nameof(serviceProvider)); + if (serviceProvider.GetService(typeof(IProvideValueTarget)) is not IProvideValueTarget targetProvider) + throw new InvalidOperationException(message: $"{nameof(ProvideValue)}:{nameof(IProvideValueTarget)}"); + + if (targetProvider.TargetObject is not FrameworkElement targetObject) + throw new InvalidOperationException(message: $"{nameof(ProvideValue)}:{nameof(FrameworkElement)}"); + + if (targetProvider.TargetProperty is not MemberInfo memberInfo) + throw new InvalidOperationException(message: $"{nameof(ProvideValue)}:{nameof(MemberInfo)}"); + + if (string.IsNullOrWhiteSpace(Command)) + { + Command = memberInfo.Name.Replace("Add", ""); + if (Command.Contains("Handler")) + Command = Command.Replace("Handler", "Command"); + else + Command += "Command"; + } + + return CreateHandler(memberInfo, Command!, targetObject.GetType()); + } + + private Type? GetEventHandlerType(MemberInfo memberInfo) + { + Type? eventHandlerType = null; + if (memberInfo is EventInfo eventInfo) + { + // var info = memberInfo as EventInfo; + // var eventInfo = info; + eventHandlerType = eventInfo.EventHandlerType; + } + else if (memberInfo is MethodInfo methodInfo) + { + // var info = memberInfo as MethodInfo; + // var methodInfo = info; + var pars = methodInfo.GetParameters(); + eventHandlerType = pars[1].ParameterType; + } + + return eventHandlerType; + } + + private object? CreateHandler(MemberInfo memberInfo, string cmdName, Type targetType) + { + var eventHandlerType = GetEventHandlerType(memberInfo); + if (eventHandlerType is null) + return null; + + var handlerInfo = eventHandlerType.GetMethod("Invoke"); + var method = new DynamicMethod("", handlerInfo!.ReturnType, + [ + handlerInfo.GetParameters()[0].ParameterType, + handlerInfo.GetParameters()[1].ParameterType + ]); + + var gen = method.GetILGenerator(); + gen.Emit(OpCodes.Ldarg, 0); + gen.Emit(OpCodes.Ldarg, 1); + gen.Emit(OpCodes.Ldstr, cmdName); + + if (CommandParameter is null) + gen.Emit(OpCodes.Ldnull); + else + gen.Emit(OpCodes.Ldstr, CommandParameter); + + gen.Emit(OpCodes.Call, getMethod); + gen.Emit(OpCodes.Ret); + + return method.CreateDelegate(eventHandlerType); + } + + static readonly MethodInfo getMethod = typeof(EventBindingExtension) + .GetMethod("HandlerIntern", new Type[] { typeof(object), typeof(object), typeof(string), typeof(string) })!; + +#pragma warning disable IDE0051 // 删除未使用的私有成员 + static void Handler(object sender, object args) +#pragma warning restore IDE0051 // 删除未使用的私有成员 + { + HandlerIntern(sender, args, "cmd", null); + } + /// + /// Handlers the intern. + /// + /// The sender. + /// The arguments. + /// Name of the command. + /// The command parameter. + public static void HandlerIntern(object sender, object args, string cmdName, string? commandParameter) + { + if (sender is FrameworkElement fe) + { + var cmd = GetCommand(fe, cmdName); + object? commandParam = null; + if (!string.IsNullOrWhiteSpace(commandParameter)) + commandParam = GetCommandParameter(fe, args, commandParameter!); + if ((cmd is not null) && cmd.CanExecute(commandParam)) + cmd.Execute(commandParam); + } + } + + internal static ICommand? GetCommand(FrameworkElement target, string cmdName) + { + var vm = FindViewModel(target); + if (vm is null) + return null; + + var vmType = vm.GetType(); + var cmdProp = vmType.GetProperty(cmdName); + if (cmdProp is not null) + return cmdProp.GetValue(vm) as ICommand; +#if DEBUG + throw new Exception("EventBinding path error: '" + cmdName + "' property not found on '" + vmType + "' 'DelegateCommand'"); +#else + return null; +#endif + } + + internal static object GetCommandParameter(FrameworkElement target, object args, string commandParameter) + { + var classify = commandParameter.Split('.'); + object ret = classify[0] switch + { + "$e" => args, + "$this" => classify.Length > 1 ? FollowPropertyPath(target, commandParameter.Replace("$this.", ""), target.GetType()) : target, + _ => commandParameter, + }; + return ret; + } + + internal static ViewModelBase? FindViewModel(FrameworkElement? target) + { + if (target is null) + return null; + if (target.DataContext is ViewModelBase vm) + return vm; + return FindViewModel(target.GetParentObject() as FrameworkElement); + } + + internal static object FollowPropertyPath(object target, string path, Type? valueType = null) + { + if (target is null) + throw new ArgumentNullException(nameof(target)); + if (path is null) + throw new ArgumentNullException(nameof(path)); + + valueType ??= target.GetType(); + var spls = path.Split('.'); + foreach (var t in spls) + { + var property = valueType.GetProperty(t); + if (property is null) + throw new NullReferenceException("property"); + + target = property.GetValue(target); + valueType = property.PropertyType; + } + return target; + } +} \ No newline at end of file diff --git a/IFoxCAD.sln b/IFoxCAD.sln index cbb4424..dd317f4 100644 --- a/IFoxCAD.sln +++ b/IFoxCAD.sln @@ -5,7 +5,9 @@ VisualStudioVersion = 17.8.34309.116 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IFoxCAD.Cad", "IFoxCAD.Cad\IFoxCAD.Cad.csproj", "{6B29955A-5796-4035-9297-210FA15D3846}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test", "Test\Test.csproj", "{0C01F295-0985-436B-A15D-228877C60F1D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test", "Test\Test.csproj", "{0C01F295-0985-436B-A15D-228877C60F1D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IFoxCAD.WPF", "IFoxCAD.WPF\IFoxCAD.WPF.csproj", "{9E6049F1-EA67-4F92-93B8-00D20C49E308}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -21,6 +23,10 @@ Global {0C01F295-0985-436B-A15D-228877C60F1D}.Debug|Any CPU.Build.0 = Debug|Any CPU {0C01F295-0985-436B-A15D-228877C60F1D}.Release|Any CPU.ActiveCfg = Release|Any CPU {0C01F295-0985-436B-A15D-228877C60F1D}.Release|Any CPU.Build.0 = Release|Any CPU + {9E6049F1-EA67-4F92-93B8-00D20C49E308}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9E6049F1-EA67-4F92-93B8-00D20C49E308}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9E6049F1-EA67-4F92-93B8-00D20C49E308}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9E6049F1-EA67-4F92-93B8-00D20C49E308}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE -- Gitee From 65628470a22af26c87465a5a27ac38d7e2a6c18d Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Mon, 8 Apr 2024 00:19:41 +0800 Subject: [PATCH 275/453] =?UTF-8?q?=E4=BA=8B=E4=BB=B6=E7=BB=91=E5=AE=9ARel?= =?UTF-8?q?ayCommand?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MarkupExtension/EventBindingExtension.cs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/IFoxCAD.WPF/MarkupExtension/EventBindingExtension.cs b/IFoxCAD.WPF/MarkupExtension/EventBindingExtension.cs index b18ed85..abe6a38 100644 --- a/IFoxCAD.WPF/MarkupExtension/EventBindingExtension.cs +++ b/IFoxCAD.WPF/MarkupExtension/EventBindingExtension.cs @@ -10,10 +10,12 @@ public class EventBindingExtension : MarkupExtension /// 命令属性 /// public string? Command { get; set; } + /// /// 命令参数属性 /// public string? CommandParameter { get; set; } + /// /// 当在派生类中实现时,返回用作此标记扩展的目标属性值的对象。 /// @@ -78,7 +80,7 @@ public class EventBindingExtension : MarkupExtension var method = new DynamicMethod("", handlerInfo!.ReturnType, [ handlerInfo.GetParameters()[0].ParameterType, - handlerInfo.GetParameters()[1].ParameterType + handlerInfo.GetParameters()[1].ParameterType ]); var gen = method.GetILGenerator(); @@ -98,14 +100,14 @@ public class EventBindingExtension : MarkupExtension } static readonly MethodInfo getMethod = typeof(EventBindingExtension) - .GetMethod("HandlerIntern", new Type[] { typeof(object), typeof(object), typeof(string), typeof(string) })!; + .GetMethod(nameof(HandlerIntern), + new Type[] { typeof(object), typeof(object), typeof(string), typeof(string) })!; -#pragma warning disable IDE0051 // 删除未使用的私有成员 static void Handler(object sender, object args) -#pragma warning restore IDE0051 // 删除未使用的私有成员 { HandlerIntern(sender, args, "cmd", null); } + /// /// Handlers the intern. /// @@ -137,7 +139,8 @@ public static void HandlerIntern(object sender, object args, string cmdName, str if (cmdProp is not null) return cmdProp.GetValue(vm) as ICommand; #if DEBUG - throw new Exception("EventBinding path error: '" + cmdName + "' property not found on '" + vmType + "' 'DelegateCommand'"); + throw new Exception("EventBinding path error: '" + cmdName + "' property not found on '" + vmType + + "' 'DelegateCommand'"); #else return null; #endif @@ -149,7 +152,9 @@ internal static object GetCommandParameter(FrameworkElement target, object args, object ret = classify[0] switch { "$e" => args, - "$this" => classify.Length > 1 ? FollowPropertyPath(target, commandParameter.Replace("$this.", ""), target.GetType()) : target, + "$this" => classify.Length > 1 + ? FollowPropertyPath(target, commandParameter.Replace("$this.", ""), target.GetType()) + : target, _ => commandParameter, }; return ret; @@ -182,6 +187,7 @@ internal static object FollowPropertyPath(object target, string path, Type? valu target = property.GetValue(target); valueType = property.PropertyType; } + return target; } } \ No newline at end of file -- Gitee From f7c2c8bb6504357f43b6886daef8356b69a698be Mon Sep 17 00:00:00 2001 From: vicwjb Date: Sat, 20 Apr 2024 11:17:33 +0800 Subject: [PATCH 276/453] =?UTF-8?q?=E9=89=B4=E4=BA=8E=E5=B7=B2=E7=BB=8F?= =?UTF-8?q?=E5=B0=86wpf=E9=A1=B9=E7=9B=AE=E8=BF=9B=E8=A1=8C=E4=BA=86?= =?UTF-8?q?=E6=8B=86=E5=88=86=EF=BC=8C=E7=A7=BB=E9=99=A4wpf?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ColorIndex2SolidColorBrushConverter.cs | 163 --------------- IFoxCAD.WPF/DependencyObjectExtensions.cs | 39 ---- IFoxCAD.WPF/GlobalUsings.cs | 7 - IFoxCAD.WPF/IFoxCAD.WPF.csproj | 16 -- IFoxCAD.WPF/MVVM/RelayCommand.cs | 186 ----------------- IFoxCAD.WPF/MVVM/ViewModelBase.cs | 65 ------ .../MarkupExtension/EventBindingExtension.cs | 193 ------------------ IFoxCAD.sln | 6 - 8 files changed, 675 deletions(-) delete mode 100644 IFoxCAD.WPF/Converter/ColorIndex2SolidColorBrushConverter.cs delete mode 100644 IFoxCAD.WPF/DependencyObjectExtensions.cs delete mode 100644 IFoxCAD.WPF/GlobalUsings.cs delete mode 100644 IFoxCAD.WPF/IFoxCAD.WPF.csproj delete mode 100644 IFoxCAD.WPF/MVVM/RelayCommand.cs delete mode 100644 IFoxCAD.WPF/MVVM/ViewModelBase.cs delete mode 100644 IFoxCAD.WPF/MarkupExtension/EventBindingExtension.cs diff --git a/IFoxCAD.WPF/Converter/ColorIndex2SolidColorBrushConverter.cs b/IFoxCAD.WPF/Converter/ColorIndex2SolidColorBrushConverter.cs deleted file mode 100644 index 8047b27..0000000 --- a/IFoxCAD.WPF/Converter/ColorIndex2SolidColorBrushConverter.cs +++ /dev/null @@ -1,163 +0,0 @@ -using System.Collections.Generic; -using System.Globalization; -using System.Windows.Data; -using System.Windows.Media; -using MediaColor = System.Windows.Media.Color; - -namespace IFoxCAD.WPF; - -/// -/// 颜色索引到画刷转换器 -/// 由于不想引用AutoCAD的包,于是用这种ugly的方式来实现 -/// -public class ColorIndex2SolidColorBrushConverter : IValueConverter -{ - public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture) - { - if (value is null || !int.TryParse(value.ToString(), out var index)) - return Binding.DoNothing; - index = Math.Abs(index) % 257; - if (index is 0 or 256) - index = 7; - if (colorDict.TryGetValue(index, out var color)) - return color; - return Binding.DoNothing; - } - - public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) - { - return Binding.DoNothing; - } - - private static readonly Dictionary colorDict = new() - { - { 1, new(MediaColor.FromRgb(255, 0, 0)) }, { 2, new(MediaColor.FromRgb(255, 255, 0)) }, - { 3, new(MediaColor.FromRgb(0, 255, 0)) }, { 4, new(MediaColor.FromRgb(0, 255, 255)) }, - { 5, new(MediaColor.FromRgb(0, 0, 255)) }, { 6, new(MediaColor.FromRgb(255, 0, 255)) }, - { 7, new(MediaColor.FromRgb(255, 255, 255)) }, { 8, new(MediaColor.FromRgb(128, 128, 128)) }, - { 9, new(MediaColor.FromRgb(192, 192, 192)) }, { 10, new(MediaColor.FromRgb(255, 0, 0)) }, - { 11, new(MediaColor.FromRgb(255, 127, 127)) }, { 12, new(MediaColor.FromRgb(204, 0, 0)) }, - { 13, new(MediaColor.FromRgb(204, 102, 102)) }, { 14, new(MediaColor.FromRgb(153, 0, 0)) }, - { 15, new(MediaColor.FromRgb(153, 76, 76)) }, { 16, new(MediaColor.FromRgb(127, 0, 0)) }, - { 17, new(MediaColor.FromRgb(127, 63, 63)) }, { 18, new(MediaColor.FromRgb(76, 0, 0)) }, - { 19, new(MediaColor.FromRgb(76, 38, 38)) }, { 20, new(MediaColor.FromRgb(255, 63, 0)) }, - { 21, new(MediaColor.FromRgb(255, 159, 127)) }, { 22, new(MediaColor.FromRgb(204, 51, 0)) }, - { 23, new(MediaColor.FromRgb(204, 127, 102)) }, { 24, new(MediaColor.FromRgb(153, 38, 0)) }, - { 25, new(MediaColor.FromRgb(153, 95, 76)) }, { 26, new(MediaColor.FromRgb(127, 31, 0)) }, - { 27, new(MediaColor.FromRgb(127, 79, 63)) }, { 28, new(MediaColor.FromRgb(76, 19, 0)) }, - { 29, new(MediaColor.FromRgb(76, 47, 38)) }, { 30, new(MediaColor.FromRgb(255, 127, 0)) }, - { 31, new(MediaColor.FromRgb(255, 191, 127)) }, { 32, new(MediaColor.FromRgb(204, 102, 0)) }, - { 33, new(MediaColor.FromRgb(204, 153, 102)) }, { 34, new(MediaColor.FromRgb(153, 76, 0)) }, - { 35, new(MediaColor.FromRgb(153, 114, 76)) }, { 36, new(MediaColor.FromRgb(127, 63, 0)) }, - { 37, new(MediaColor.FromRgb(127, 95, 63)) }, { 38, new(MediaColor.FromRgb(76, 38, 0)) }, - { 39, new(MediaColor.FromRgb(76, 57, 38)) }, { 40, new(MediaColor.FromRgb(255, 191, 0)) }, - { 41, new(MediaColor.FromRgb(255, 223, 127)) }, { 42, new(MediaColor.FromRgb(204, 153, 0)) }, - { 43, new(MediaColor.FromRgb(204, 178, 102)) }, { 44, new(MediaColor.FromRgb(153, 114, 0)) }, - { 45, new(MediaColor.FromRgb(153, 133, 76)) }, { 46, new(MediaColor.FromRgb(127, 95, 0)) }, - { 47, new(MediaColor.FromRgb(127, 111, 63)) }, { 48, new(MediaColor.FromRgb(76, 57, 0)) }, - { 49, new(MediaColor.FromRgb(76, 66, 38)) }, { 50, new(MediaColor.FromRgb(255, 255, 0)) }, - { 51, new(MediaColor.FromRgb(255, 255, 127)) }, { 52, new(MediaColor.FromRgb(204, 204, 0)) }, - { 53, new(MediaColor.FromRgb(204, 204, 102)) }, { 54, new(MediaColor.FromRgb(153, 153, 0)) }, - { 55, new(MediaColor.FromRgb(153, 153, 76)) }, { 56, new(MediaColor.FromRgb(127, 127, 0)) }, - { 57, new(MediaColor.FromRgb(127, 127, 63)) }, { 58, new(MediaColor.FromRgb(76, 76, 0)) }, - { 59, new(MediaColor.FromRgb(76, 76, 38)) }, { 60, new(MediaColor.FromRgb(191, 255, 0)) }, - { 61, new(MediaColor.FromRgb(223, 255, 127)) }, { 62, new(MediaColor.FromRgb(153, 204, 0)) }, - { 63, new(MediaColor.FromRgb(178, 204, 102)) }, { 64, new(MediaColor.FromRgb(114, 153, 0)) }, - { 65, new(MediaColor.FromRgb(133, 153, 76)) }, { 66, new(MediaColor.FromRgb(95, 127, 0)) }, - { 67, new(MediaColor.FromRgb(111, 127, 63)) }, { 68, new(MediaColor.FromRgb(57, 76, 0)) }, - { 69, new(MediaColor.FromRgb(66, 76, 38)) }, { 70, new(MediaColor.FromRgb(127, 255, 0)) }, - { 71, new(MediaColor.FromRgb(191, 255, 127)) }, { 72, new(MediaColor.FromRgb(102, 204, 0)) }, - { 73, new(MediaColor.FromRgb(153, 204, 102)) }, { 74, new(MediaColor.FromRgb(76, 153, 0)) }, - { 75, new(MediaColor.FromRgb(114, 153, 76)) }, { 76, new(MediaColor.FromRgb(63, 127, 0)) }, - { 77, new(MediaColor.FromRgb(95, 127, 63)) }, { 78, new(MediaColor.FromRgb(38, 76, 0)) }, - { 79, new(MediaColor.FromRgb(57, 76, 38)) }, { 80, new(MediaColor.FromRgb(63, 255, 0)) }, - { 81, new(MediaColor.FromRgb(159, 255, 127)) }, { 82, new(MediaColor.FromRgb(51, 204, 0)) }, - { 83, new(MediaColor.FromRgb(127, 204, 102)) }, { 84, new(MediaColor.FromRgb(38, 153, 0)) }, - { 85, new(MediaColor.FromRgb(95, 153, 76)) }, { 86, new(MediaColor.FromRgb(31, 127, 0)) }, - { 87, new(MediaColor.FromRgb(79, 127, 63)) }, { 88, new(MediaColor.FromRgb(19, 76, 0)) }, - { 89, new(MediaColor.FromRgb(47, 76, 38)) }, { 90, new(MediaColor.FromRgb(0, 255, 0)) }, - { 91, new(MediaColor.FromRgb(127, 255, 127)) }, { 92, new(MediaColor.FromRgb(0, 204, 0)) }, - { 93, new(MediaColor.FromRgb(102, 204, 102)) }, { 94, new(MediaColor.FromRgb(0, 153, 0)) }, - { 95, new(MediaColor.FromRgb(76, 153, 76)) }, { 96, new(MediaColor.FromRgb(0, 127, 0)) }, - { 97, new(MediaColor.FromRgb(63, 127, 63)) }, { 98, new(MediaColor.FromRgb(0, 76, 0)) }, - { 99, new(MediaColor.FromRgb(38, 76, 38)) }, { 100, new(MediaColor.FromRgb(0, 255, 63)) }, - { 101, new(MediaColor.FromRgb(127, 255, 159)) }, { 102, new(MediaColor.FromRgb(0, 204, 51)) }, - { 103, new(MediaColor.FromRgb(102, 204, 127)) }, { 104, new(MediaColor.FromRgb(0, 153, 38)) }, - { 105, new(MediaColor.FromRgb(76, 153, 95)) }, { 106, new(MediaColor.FromRgb(0, 127, 31)) }, - { 107, new(MediaColor.FromRgb(63, 127, 79)) }, { 108, new(MediaColor.FromRgb(0, 76, 19)) }, - { 109, new(MediaColor.FromRgb(38, 76, 47)) }, { 110, new(MediaColor.FromRgb(0, 255, 127)) }, - { 111, new(MediaColor.FromRgb(127, 255, 191)) }, { 112, new(MediaColor.FromRgb(0, 204, 102)) }, - { 113, new(MediaColor.FromRgb(102, 204, 153)) }, { 114, new(MediaColor.FromRgb(0, 153, 76)) }, - { 115, new(MediaColor.FromRgb(76, 153, 114)) }, { 116, new(MediaColor.FromRgb(0, 127, 63)) }, - { 117, new(MediaColor.FromRgb(63, 127, 95)) }, { 118, new(MediaColor.FromRgb(0, 76, 38)) }, - { 119, new(MediaColor.FromRgb(38, 76, 57)) }, { 120, new(MediaColor.FromRgb(0, 255, 191)) }, - { 121, new(MediaColor.FromRgb(127, 255, 223)) }, { 122, new(MediaColor.FromRgb(0, 204, 153)) }, - { 123, new(MediaColor.FromRgb(102, 204, 178)) }, { 124, new(MediaColor.FromRgb(0, 153, 114)) }, - { 125, new(MediaColor.FromRgb(76, 153, 133)) }, { 126, new(MediaColor.FromRgb(0, 127, 95)) }, - { 127, new(MediaColor.FromRgb(63, 127, 111)) }, { 128, new(MediaColor.FromRgb(0, 76, 57)) }, - { 129, new(MediaColor.FromRgb(38, 76, 66)) }, { 130, new(MediaColor.FromRgb(0, 255, 255)) }, - { 131, new(MediaColor.FromRgb(127, 255, 255)) }, { 132, new(MediaColor.FromRgb(0, 204, 204)) }, - { 133, new(MediaColor.FromRgb(102, 204, 204)) }, { 134, new(MediaColor.FromRgb(0, 153, 153)) }, - { 135, new(MediaColor.FromRgb(76, 153, 153)) }, { 136, new(MediaColor.FromRgb(0, 127, 127)) }, - { 137, new(MediaColor.FromRgb(63, 127, 127)) }, { 138, new(MediaColor.FromRgb(0, 76, 76)) }, - { 139, new(MediaColor.FromRgb(38, 76, 76)) }, { 140, new(MediaColor.FromRgb(0, 191, 255)) }, - { 141, new(MediaColor.FromRgb(127, 223, 255)) }, { 142, new(MediaColor.FromRgb(0, 153, 204)) }, - { 143, new(MediaColor.FromRgb(102, 178, 204)) }, { 144, new(MediaColor.FromRgb(0, 114, 153)) }, - { 145, new(MediaColor.FromRgb(76, 133, 153)) }, { 146, new(MediaColor.FromRgb(0, 95, 127)) }, - { 147, new(MediaColor.FromRgb(63, 111, 127)) }, { 148, new(MediaColor.FromRgb(0, 57, 76)) }, - { 149, new(MediaColor.FromRgb(38, 66, 76)) }, { 150, new(MediaColor.FromRgb(0, 127, 255)) }, - { 151, new(MediaColor.FromRgb(127, 191, 255)) }, { 152, new(MediaColor.FromRgb(0, 102, 204)) }, - { 153, new(MediaColor.FromRgb(102, 153, 204)) }, { 154, new(MediaColor.FromRgb(0, 76, 153)) }, - { 155, new(MediaColor.FromRgb(76, 114, 153)) }, { 156, new(MediaColor.FromRgb(0, 63, 127)) }, - { 157, new(MediaColor.FromRgb(63, 95, 127)) }, { 158, new(MediaColor.FromRgb(0, 38, 76)) }, - { 159, new(MediaColor.FromRgb(38, 57, 76)) }, { 160, new(MediaColor.FromRgb(0, 63, 255)) }, - { 161, new(MediaColor.FromRgb(127, 159, 255)) }, { 162, new(MediaColor.FromRgb(0, 51, 204)) }, - { 163, new(MediaColor.FromRgb(102, 127, 204)) }, { 164, new(MediaColor.FromRgb(0, 38, 153)) }, - { 165, new(MediaColor.FromRgb(76, 95, 153)) }, { 166, new(MediaColor.FromRgb(0, 31, 127)) }, - { 167, new(MediaColor.FromRgb(63, 79, 127)) }, { 168, new(MediaColor.FromRgb(0, 19, 76)) }, - { 169, new(MediaColor.FromRgb(38, 47, 76)) }, { 170, new(MediaColor.FromRgb(0, 0, 255)) }, - { 171, new(MediaColor.FromRgb(127, 127, 255)) }, { 172, new(MediaColor.FromRgb(0, 0, 204)) }, - { 173, new(MediaColor.FromRgb(102, 102, 204)) }, { 174, new(MediaColor.FromRgb(0, 0, 153)) }, - { 175, new(MediaColor.FromRgb(76, 76, 153)) }, { 176, new(MediaColor.FromRgb(0, 0, 127)) }, - { 177, new(MediaColor.FromRgb(63, 63, 127)) }, { 178, new(MediaColor.FromRgb(0, 0, 76)) }, - { 179, new(MediaColor.FromRgb(38, 38, 76)) }, { 180, new(MediaColor.FromRgb(63, 0, 255)) }, - { 181, new(MediaColor.FromRgb(159, 127, 255)) }, { 182, new(MediaColor.FromRgb(51, 0, 204)) }, - { 183, new(MediaColor.FromRgb(127, 102, 204)) }, { 184, new(MediaColor.FromRgb(38, 0, 153)) }, - { 185, new(MediaColor.FromRgb(95, 76, 153)) }, { 186, new(MediaColor.FromRgb(31, 0, 127)) }, - { 187, new(MediaColor.FromRgb(79, 63, 127)) }, { 188, new(MediaColor.FromRgb(19, 0, 76)) }, - { 189, new(MediaColor.FromRgb(47, 38, 76)) }, { 190, new(MediaColor.FromRgb(127, 0, 255)) }, - { 191, new(MediaColor.FromRgb(191, 127, 255)) }, { 192, new(MediaColor.FromRgb(102, 0, 204)) }, - { 193, new(MediaColor.FromRgb(153, 102, 204)) }, { 194, new(MediaColor.FromRgb(76, 0, 153)) }, - { 195, new(MediaColor.FromRgb(114, 76, 153)) }, { 196, new(MediaColor.FromRgb(63, 0, 127)) }, - { 197, new(MediaColor.FromRgb(95, 63, 127)) }, { 198, new(MediaColor.FromRgb(38, 0, 76)) }, - { 199, new(MediaColor.FromRgb(57, 38, 76)) }, { 200, new(MediaColor.FromRgb(191, 0, 255)) }, - { 201, new(MediaColor.FromRgb(223, 127, 255)) }, { 202, new(MediaColor.FromRgb(153, 0, 204)) }, - { 203, new(MediaColor.FromRgb(178, 102, 204)) }, { 204, new(MediaColor.FromRgb(114, 0, 153)) }, - { 205, new(MediaColor.FromRgb(133, 76, 153)) }, { 206, new(MediaColor.FromRgb(95, 0, 127)) }, - { 207, new(MediaColor.FromRgb(111, 63, 127)) }, { 208, new(MediaColor.FromRgb(57, 0, 76)) }, - { 209, new(MediaColor.FromRgb(66, 38, 76)) }, { 210, new(MediaColor.FromRgb(255, 0, 255)) }, - { 211, new(MediaColor.FromRgb(255, 127, 255)) }, { 212, new(MediaColor.FromRgb(204, 0, 204)) }, - { 213, new(MediaColor.FromRgb(204, 102, 204)) }, { 214, new(MediaColor.FromRgb(153, 0, 153)) }, - { 215, new(MediaColor.FromRgb(153, 76, 153)) }, { 216, new(MediaColor.FromRgb(127, 0, 127)) }, - { 217, new(MediaColor.FromRgb(127, 63, 127)) }, { 218, new(MediaColor.FromRgb(76, 0, 76)) }, - { 219, new(MediaColor.FromRgb(76, 38, 76)) }, { 220, new(MediaColor.FromRgb(255, 0, 191)) }, - { 221, new(MediaColor.FromRgb(255, 127, 223)) }, { 222, new(MediaColor.FromRgb(204, 0, 153)) }, - { 223, new(MediaColor.FromRgb(204, 102, 178)) }, { 224, new(MediaColor.FromRgb(153, 0, 114)) }, - { 225, new(MediaColor.FromRgb(153, 76, 133)) }, { 226, new(MediaColor.FromRgb(127, 0, 95)) }, - { 227, new(MediaColor.FromRgb(127, 63, 111)) }, { 228, new(MediaColor.FromRgb(76, 0, 57)) }, - { 229, new(MediaColor.FromRgb(76, 38, 66)) }, { 230, new(MediaColor.FromRgb(255, 0, 127)) }, - { 231, new(MediaColor.FromRgb(255, 127, 191)) }, { 232, new(MediaColor.FromRgb(204, 0, 102)) }, - { 233, new(MediaColor.FromRgb(204, 102, 153)) }, { 234, new(MediaColor.FromRgb(153, 0, 76)) }, - { 235, new(MediaColor.FromRgb(153, 76, 114)) }, { 236, new(MediaColor.FromRgb(127, 0, 63)) }, - { 237, new(MediaColor.FromRgb(127, 63, 95)) }, { 238, new(MediaColor.FromRgb(76, 0, 38)) }, - { 239, new(MediaColor.FromRgb(76, 38, 57)) }, { 240, new(MediaColor.FromRgb(255, 0, 63)) }, - { 241, new(MediaColor.FromRgb(255, 127, 159)) }, { 242, new(MediaColor.FromRgb(204, 0, 51)) }, - { 243, new(MediaColor.FromRgb(204, 102, 127)) }, { 244, new(MediaColor.FromRgb(153, 0, 38)) }, - { 245, new(MediaColor.FromRgb(153, 76, 95)) }, { 246, new(MediaColor.FromRgb(127, 0, 31)) }, - { 247, new(MediaColor.FromRgb(127, 63, 79)) }, { 248, new(MediaColor.FromRgb(76, 0, 19)) }, - { 249, new(MediaColor.FromRgb(76, 38, 47)) }, { 250, new(MediaColor.FromRgb(51, 51, 51)) }, - { 251, new(MediaColor.FromRgb(91, 91, 91)) }, { 252, new(MediaColor.FromRgb(132, 132, 132)) }, - { 253, new(MediaColor.FromRgb(173, 173, 173)) }, { 254, new(MediaColor.FromRgb(214, 214, 214)) }, - { 255, new(MediaColor.FromRgb(255, 255, 255)) } - }; -} \ No newline at end of file diff --git a/IFoxCAD.WPF/DependencyObjectExtensions.cs b/IFoxCAD.WPF/DependencyObjectExtensions.cs deleted file mode 100644 index 317cba2..0000000 --- a/IFoxCAD.WPF/DependencyObjectExtensions.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System.Windows.Media; - -namespace IFoxCAD.WPF; - -/// -/// 依赖属性扩展类 -/// -public static class DependencyObjectExtensions -{ - /// - /// 获取父对象依赖属性 - /// - /// 子对象 - /// 依赖属性 - public static DependencyObject? GetParentObject(this DependencyObject? child) - { - if (child is null) - return null; - - if (child is ContentElement ce) - { - var parent = ContentOperations.GetParent(ce); - if (parent is not null) - return parent; - - var fce = ce as FrameworkContentElement; - return fce?.Parent; - } - - if (child is FrameworkElement fe) - { - var parent = fe.Parent; - if (parent is not null) - return parent; - } - - return VisualTreeHelper.GetParent(child); - } -} \ No newline at end of file diff --git a/IFoxCAD.WPF/GlobalUsings.cs b/IFoxCAD.WPF/GlobalUsings.cs deleted file mode 100644 index 391e1c9..0000000 --- a/IFoxCAD.WPF/GlobalUsings.cs +++ /dev/null @@ -1,7 +0,0 @@ -global using System; -global using System.Reflection; -global using System.Reflection.Emit; -global using System.Windows; -global using System.Windows.Input; -global using System.Windows.Markup; -global using System.Diagnostics; \ No newline at end of file diff --git a/IFoxCAD.WPF/IFoxCAD.WPF.csproj b/IFoxCAD.WPF/IFoxCAD.WPF.csproj deleted file mode 100644 index c083866..0000000 --- a/IFoxCAD.WPF/IFoxCAD.WPF.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - - net48 - Preview - enable - x64 - IFoxCAD.WPF - true - - - - - - - diff --git a/IFoxCAD.WPF/MVVM/RelayCommand.cs b/IFoxCAD.WPF/MVVM/RelayCommand.cs deleted file mode 100644 index cd6dcf9..0000000 --- a/IFoxCAD.WPF/MVVM/RelayCommand.cs +++ /dev/null @@ -1,186 +0,0 @@ -using Microsoft.Xaml.Behaviors; - -namespace IFoxCAD.WPF; - -/// -/// 命令基类 -/// -/// -public class RelayCommand : ICommand -{ - private readonly Func? _canExecute; - private readonly Action _execute; - - /// - /// 初始化 类. - /// - /// 执行函数委托 - /// 是否可执行函数委托 - /// execute - public RelayCommand(Action execute, Func? canExecute = null) - { - _execute = execute ?? throw new ArgumentNullException(nameof(execute)); - _canExecute = canExecute; - } - - /// - /// 当出现影响是否应执行该命令的更改时发生。 - /// - public event EventHandler CanExecuteChanged - { - add - { - if (_canExecute is not null) - CommandManager.RequerySuggested += value; - } - remove - { - if (_canExecute is not null) - CommandManager.RequerySuggested -= value; - } - } - - /// - /// 定义确定此命令是否可在其当前状态下执行的方法。 - /// - /// 此命令使用的数据。 如果此命令不需要传递数据,则该对象可以设置为 。 - /// - /// 如果可执行此命令,则为 ;否则为 。 - /// - [DebuggerStepThrough] - public bool CanExecute(object parameter) - { - return _canExecute is null || _canExecute(parameter); - } - - /// - /// 定义在调用此命令时要调用的方法。 - /// - /// 此命令使用的数据。 如果此命令不需要传递数据,则该对象可以设置为 。 - public void Execute(object parameter) - { - _execute(parameter); - } -} - -/// -/// 命令泛型基类 -/// -/// 事件类型 -/// -public class RelayCommand : ICommand -{ - private readonly Func? _canExecute; - private readonly Action? _execute; - - /// - /// 初始化 类。 - /// - /// 执行函数 - public RelayCommand(Action execute) : this(execute, (_) => true) - { - } - - /// - /// 初始化 类。 - /// - /// 执行函数委托 - /// 是否可执行函数委托 - /// execute - public RelayCommand(Action execute, Func canExecute) - { - _execute = execute ?? throw new ArgumentNullException(nameof(execute)); - _canExecute = canExecute; - } - - /// - /// 当出现影响是否应执行该命令的更改时发生。 - /// - public event EventHandler CanExecuteChanged - { - add - { - if (_canExecute is not null) - CommandManager.RequerySuggested += value; - } - remove - { - if (_canExecute is not null) - CommandManager.RequerySuggested -= value; - } - } - - /// - /// 定义确定此命令是否可在其当前状态下执行的方法。 - /// - /// 此命令使用的数据。 如果此命令不需要传递数据,则该对象可以设置为 。 - /// - /// 如果可执行此命令,则为 ;否则为 。 - /// - public bool CanExecute(object parameter) - { - if (_canExecute is null) - return true; - return _canExecute((T)parameter); - } - - /// - /// 定义在调用此命令时要调用的方法。 - /// - /// 此命令使用的数据。 如果此命令不需要传递数据,则该对象可以设置为 。 - public void Execute(object parameter) - { - if (_execute is not null && CanExecute(parameter)) - _execute((T)parameter); - } -} - -/// -/// 事件命令 -/// -public class EventCommand : TriggerAction -{ - /// - /// 执行动作 - /// - /// 要执行的动作参数, 如果动作为提供参数,就设置为null - protected override void Invoke(object parameter) - { - if (CommandParameter is not null) - parameter = CommandParameter; - if (Command is not null) - Command.Execute(parameter); - } - - /// - /// 事件 - /// - public ICommand? Command - { - get => (ICommand)GetValue(CommandProperty); - set => SetValue(CommandProperty, value); - } - - /// - /// 事件属性 - /// - public static readonly DependencyProperty CommandProperty = - DependencyProperty.Register(nameof(Command), typeof(ICommand), typeof(EventCommand), - new PropertyMetadata(null)); - - /// - /// 事件参数,如果为空,将自动传入事件的真实参数 - /// - public object? CommandParameter - { - get => GetValue(CommandParameterProperty); - set => SetValue(CommandParameterProperty, value); - } - - /// - /// 事件参数属性 - /// - public static readonly DependencyProperty CommandParameterProperty = - DependencyProperty.Register(nameof(CommandParameter), typeof(object), typeof(EventCommand), - new PropertyMetadata(null)); -} \ No newline at end of file diff --git a/IFoxCAD.WPF/MVVM/ViewModelBase.cs b/IFoxCAD.WPF/MVVM/ViewModelBase.cs deleted file mode 100644 index d020ef4..0000000 --- a/IFoxCAD.WPF/MVVM/ViewModelBase.cs +++ /dev/null @@ -1,65 +0,0 @@ -using System.ComponentModel; -using System.Runtime.CompilerServices; - -namespace IFoxCAD.WPF; - -/// -/// ViewModel基类 -/// -/// -public class ViewModelBase : INotifyPropertyChanged -{ - /// - /// 属性值更改事件。 - /// - public event PropertyChangedEventHandler? PropertyChanged; - - /// - /// 属性改变时调用 - /// - /// 属性名 - public void OnPropertyChanged([CallerMemberName] string propertyName = "") - { - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); - } - - /// - /// 设置属性函数,自动通知属性改变事件 - /// - /// 属性类型 - /// 属性 - /// 属性值 - /// 属性名 - /// 成功返回 ,反之 - protected virtual bool Set(ref T storage, T value, [CallerMemberName] string propertyName = "") - { - if (Equals(storage, value)) - return false; - - storage = value; - this.OnPropertyChanged(propertyName); - - return true; - } - - /// - /// 创建命令 - /// - /// 要调用的命令函数委托 - /// WPF命令 - protected RelayCommand CreateCommand(Action executeMethod) - { - return CreateCommand(executeMethod, (_) => true); - } - - /// - /// 创建命令 - /// - /// 要调用的命令函数委托 - /// 命令是否可以执行的委托 - /// WPF命令 - protected RelayCommand CreateCommand(Action executeMethod, Func canExecuteMethod) - { - return new(executeMethod, canExecuteMethod); - } -} \ No newline at end of file diff --git a/IFoxCAD.WPF/MarkupExtension/EventBindingExtension.cs b/IFoxCAD.WPF/MarkupExtension/EventBindingExtension.cs deleted file mode 100644 index abe6a38..0000000 --- a/IFoxCAD.WPF/MarkupExtension/EventBindingExtension.cs +++ /dev/null @@ -1,193 +0,0 @@ -namespace IFoxCAD.WPF; - -/// -/// 事件绑定标签类 -/// -/// -public class EventBindingExtension : MarkupExtension -{ - /// - /// 命令属性 - /// - public string? Command { get; set; } - - /// - /// 命令参数属性 - /// - public string? CommandParameter { get; set; } - - /// - /// 当在派生类中实现时,返回用作此标记扩展的目标属性值的对象。 - /// - /// 可为标记扩展提供服务的服务提供程序帮助程序。 - /// - /// 要在应用了扩展的属性上设置的对象值。 - /// - /// - /// - public override object? ProvideValue(IServiceProvider serviceProvider) - { - if (serviceProvider is null) - throw new ArgumentNullException(nameof(serviceProvider)); - if (serviceProvider.GetService(typeof(IProvideValueTarget)) is not IProvideValueTarget targetProvider) - throw new InvalidOperationException(message: $"{nameof(ProvideValue)}:{nameof(IProvideValueTarget)}"); - - if (targetProvider.TargetObject is not FrameworkElement targetObject) - throw new InvalidOperationException(message: $"{nameof(ProvideValue)}:{nameof(FrameworkElement)}"); - - if (targetProvider.TargetProperty is not MemberInfo memberInfo) - throw new InvalidOperationException(message: $"{nameof(ProvideValue)}:{nameof(MemberInfo)}"); - - if (string.IsNullOrWhiteSpace(Command)) - { - Command = memberInfo.Name.Replace("Add", ""); - if (Command.Contains("Handler")) - Command = Command.Replace("Handler", "Command"); - else - Command += "Command"; - } - - return CreateHandler(memberInfo, Command!, targetObject.GetType()); - } - - private Type? GetEventHandlerType(MemberInfo memberInfo) - { - Type? eventHandlerType = null; - if (memberInfo is EventInfo eventInfo) - { - // var info = memberInfo as EventInfo; - // var eventInfo = info; - eventHandlerType = eventInfo.EventHandlerType; - } - else if (memberInfo is MethodInfo methodInfo) - { - // var info = memberInfo as MethodInfo; - // var methodInfo = info; - var pars = methodInfo.GetParameters(); - eventHandlerType = pars[1].ParameterType; - } - - return eventHandlerType; - } - - private object? CreateHandler(MemberInfo memberInfo, string cmdName, Type targetType) - { - var eventHandlerType = GetEventHandlerType(memberInfo); - if (eventHandlerType is null) - return null; - - var handlerInfo = eventHandlerType.GetMethod("Invoke"); - var method = new DynamicMethod("", handlerInfo!.ReturnType, - [ - handlerInfo.GetParameters()[0].ParameterType, - handlerInfo.GetParameters()[1].ParameterType - ]); - - var gen = method.GetILGenerator(); - gen.Emit(OpCodes.Ldarg, 0); - gen.Emit(OpCodes.Ldarg, 1); - gen.Emit(OpCodes.Ldstr, cmdName); - - if (CommandParameter is null) - gen.Emit(OpCodes.Ldnull); - else - gen.Emit(OpCodes.Ldstr, CommandParameter); - - gen.Emit(OpCodes.Call, getMethod); - gen.Emit(OpCodes.Ret); - - return method.CreateDelegate(eventHandlerType); - } - - static readonly MethodInfo getMethod = typeof(EventBindingExtension) - .GetMethod(nameof(HandlerIntern), - new Type[] { typeof(object), typeof(object), typeof(string), typeof(string) })!; - - static void Handler(object sender, object args) - { - HandlerIntern(sender, args, "cmd", null); - } - - /// - /// Handlers the intern. - /// - /// The sender. - /// The arguments. - /// Name of the command. - /// The command parameter. - public static void HandlerIntern(object sender, object args, string cmdName, string? commandParameter) - { - if (sender is FrameworkElement fe) - { - var cmd = GetCommand(fe, cmdName); - object? commandParam = null; - if (!string.IsNullOrWhiteSpace(commandParameter)) - commandParam = GetCommandParameter(fe, args, commandParameter!); - if ((cmd is not null) && cmd.CanExecute(commandParam)) - cmd.Execute(commandParam); - } - } - - internal static ICommand? GetCommand(FrameworkElement target, string cmdName) - { - var vm = FindViewModel(target); - if (vm is null) - return null; - - var vmType = vm.GetType(); - var cmdProp = vmType.GetProperty(cmdName); - if (cmdProp is not null) - return cmdProp.GetValue(vm) as ICommand; -#if DEBUG - throw new Exception("EventBinding path error: '" + cmdName + "' property not found on '" + vmType + - "' 'DelegateCommand'"); -#else - return null; -#endif - } - - internal static object GetCommandParameter(FrameworkElement target, object args, string commandParameter) - { - var classify = commandParameter.Split('.'); - object ret = classify[0] switch - { - "$e" => args, - "$this" => classify.Length > 1 - ? FollowPropertyPath(target, commandParameter.Replace("$this.", ""), target.GetType()) - : target, - _ => commandParameter, - }; - return ret; - } - - internal static ViewModelBase? FindViewModel(FrameworkElement? target) - { - if (target is null) - return null; - if (target.DataContext is ViewModelBase vm) - return vm; - return FindViewModel(target.GetParentObject() as FrameworkElement); - } - - internal static object FollowPropertyPath(object target, string path, Type? valueType = null) - { - if (target is null) - throw new ArgumentNullException(nameof(target)); - if (path is null) - throw new ArgumentNullException(nameof(path)); - - valueType ??= target.GetType(); - var spls = path.Split('.'); - foreach (var t in spls) - { - var property = valueType.GetProperty(t); - if (property is null) - throw new NullReferenceException("property"); - - target = property.GetValue(target); - valueType = property.PropertyType; - } - - return target; - } -} \ No newline at end of file diff --git a/IFoxCAD.sln b/IFoxCAD.sln index dd317f4..1e17231 100644 --- a/IFoxCAD.sln +++ b/IFoxCAD.sln @@ -7,8 +7,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IFoxCAD.Cad", "IFoxCAD.Cad\ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test", "Test\Test.csproj", "{0C01F295-0985-436B-A15D-228877C60F1D}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IFoxCAD.WPF", "IFoxCAD.WPF\IFoxCAD.WPF.csproj", "{9E6049F1-EA67-4F92-93B8-00D20C49E308}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -23,10 +21,6 @@ Global {0C01F295-0985-436B-A15D-228877C60F1D}.Debug|Any CPU.Build.0 = Debug|Any CPU {0C01F295-0985-436B-A15D-228877C60F1D}.Release|Any CPU.ActiveCfg = Release|Any CPU {0C01F295-0985-436B-A15D-228877C60F1D}.Release|Any CPU.Build.0 = Release|Any CPU - {9E6049F1-EA67-4F92-93B8-00D20C49E308}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9E6049F1-EA67-4F92-93B8-00D20C49E308}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9E6049F1-EA67-4F92-93B8-00D20C49E308}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9E6049F1-EA67-4F92-93B8-00D20C49E308}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE -- Gitee From adc65a030f10ca9dc1ed9777d4e437d258b97a1e Mon Sep 17 00:00:00 2001 From: vicwjb Date: Sat, 20 Apr 2024 20:35:05 +0800 Subject: [PATCH 277/453] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=85=B1=E4=BA=AB?= =?UTF-8?q?=E9=A1=B9=E7=9B=AE=EF=BC=8C=E5=B9=B6=E8=B0=83=E6=95=B4=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E5=90=8D=E7=A7=B0=E4=B8=BAIFoxCad.AutoCad?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Basal/General/ArrayEx.cs | 0 .../Basal/General/DebugHelper.cs | 0 .../Basal/General/EnumEx.cs | 0 .../Basal/General/LinqEx.cs | 0 .../Basal/General/LoopList.cs | 0 .../Basal/General/LoopState.cs | 0 .../Basal/Nullable/ArgumentNullEx.cs | 0 .../CallerArgumentExpressionAttribute.cs | 0 .../Basal/Win/SystemEx.cs | 0 .../Basal/Win/Win32Api.cs | 0 CADShared/CADShared.projitems | 70 +++++++++++++++++++ CADShared/CADShared.shproj | 12 ++++ .../ExtensionMethod/CollectionEx.cs | 0 .../ExtensionMethod/DBDictionaryEx.cs | 0 .../ExtensionMethod/DBObjectEx.cs | 0 .../ExtensionMethod/EditorEx.cs | 0 .../Entity/BlockReferenceEx.cs | 0 .../ExtensionMethod/Entity/BoundingInfo.cs | 0 .../ExtensionMethod/Entity/CircleEx.cs | 0 .../Entity/EntityBoundingInfo.cs | 0 .../ExtensionMethod/Entity/EntityEx.cs | 0 .../ExtensionMethod/Entity/PolylineEx.cs | 0 .../ExtensionMethod/Enums.cs | 0 .../ExtensionMethod/Geomerty/Curve2dEx.cs | 0 .../ExtensionMethod/Geomerty/Curve3dEx.cs | 0 .../ExtensionMethod/Geomerty/GeometryEx.cs | 0 .../ExtensionMethod/Geomerty/PointEx.cs | 0 .../ExtensionMethod/Jig/JigEx.cs | 0 .../ExtensionMethod/Jig/JigExTransient.cs | 0 .../ExtensionMethod/ObjectIdEx.cs | 0 .../ExtensionMethod/RedrawEx.cs | 0 .../ExtensionMethod/SelectionSetEx.cs | 0 .../ExtensionMethod/SingleKeyWordHook.cs | 0 .../ExtensionMethod/SymbolTableEx.cs | 0 .../ExtensionMethod/SymbolTableRecordEx.cs | 0 .../ExtensionMethod/TangentEx.cs | 0 .../ExtensionMethod/TransactionEx.cs | 0 .../ExtensionMethod/WindowEx.cs | 0 .../Initialize/AcadEMR.cs | 0 .../Initialize/AssemInfo.cs | 0 .../Initialize/AutoReg.cs | 0 .../Initialize/AutoRegAssem.cs | 0 .../Initialize/CheckFactory.cs | 0 .../Initialize/IAutoGo.cs | 0 .../Initialize/MethodInfoHelper.cs | 0 .../ResultData/LispList.cs | 0 .../ResultData/TypedValueList.cs | 0 .../ResultData/XDataList.cs | 0 .../ResultData/XRecordDataList.cs | 0 {IFoxCAD.Cad => CADShared}/Runtime/DBTrans.cs | 0 {IFoxCAD.Cad => CADShared}/Runtime/Env.cs | 0 .../Runtime/IdleAction.cs | 0 .../Runtime/IdleNoCommandAction.cs | 0 .../Runtime/SymbolTable.cs | 0 .../SelectionFilter/OpComp.cs | 0 .../SelectionFilter/OpEqual.cs | 0 .../SelectionFilter/OpFilter.cs | 0 .../SelectionFilter/OpList.cs | 0 .../SelectionFilter/OpLogi.cs | 0 .../GlobalUsing.cs | 0 .../IFoxCAD.AutoCad.csproj | 1 + IFoxCAD.sln | 4 +- Test/Test.csproj | 2 +- 63 files changed, 87 insertions(+), 2 deletions(-) rename {IFoxCAD.Cad => CADShared}/Basal/General/ArrayEx.cs (100%) rename {IFoxCAD.Cad => CADShared}/Basal/General/DebugHelper.cs (100%) rename {IFoxCAD.Cad => CADShared}/Basal/General/EnumEx.cs (100%) rename {IFoxCAD.Cad => CADShared}/Basal/General/LinqEx.cs (100%) rename {IFoxCAD.Cad => CADShared}/Basal/General/LoopList.cs (100%) rename {IFoxCAD.Cad => CADShared}/Basal/General/LoopState.cs (100%) rename {IFoxCAD.Cad => CADShared}/Basal/Nullable/ArgumentNullEx.cs (100%) rename {IFoxCAD.Cad => CADShared}/Basal/Nullable/CallerArgumentExpressionAttribute.cs (100%) rename {IFoxCAD.Cad => CADShared}/Basal/Win/SystemEx.cs (100%) rename {IFoxCAD.Cad => CADShared}/Basal/Win/Win32Api.cs (100%) create mode 100644 CADShared/CADShared.projitems create mode 100644 CADShared/CADShared.shproj rename {IFoxCAD.Cad => CADShared}/ExtensionMethod/CollectionEx.cs (100%) rename {IFoxCAD.Cad => CADShared}/ExtensionMethod/DBDictionaryEx.cs (100%) rename {IFoxCAD.Cad => CADShared}/ExtensionMethod/DBObjectEx.cs (100%) rename {IFoxCAD.Cad => CADShared}/ExtensionMethod/EditorEx.cs (100%) rename {IFoxCAD.Cad => CADShared}/ExtensionMethod/Entity/BlockReferenceEx.cs (100%) rename {IFoxCAD.Cad => CADShared}/ExtensionMethod/Entity/BoundingInfo.cs (100%) rename {IFoxCAD.Cad => CADShared}/ExtensionMethod/Entity/CircleEx.cs (100%) rename {IFoxCAD.Cad => CADShared}/ExtensionMethod/Entity/EntityBoundingInfo.cs (100%) rename {IFoxCAD.Cad => CADShared}/ExtensionMethod/Entity/EntityEx.cs (100%) rename {IFoxCAD.Cad => CADShared}/ExtensionMethod/Entity/PolylineEx.cs (100%) rename {IFoxCAD.Cad => CADShared}/ExtensionMethod/Enums.cs (100%) rename {IFoxCAD.Cad => CADShared}/ExtensionMethod/Geomerty/Curve2dEx.cs (100%) rename {IFoxCAD.Cad => CADShared}/ExtensionMethod/Geomerty/Curve3dEx.cs (100%) rename {IFoxCAD.Cad => CADShared}/ExtensionMethod/Geomerty/GeometryEx.cs (100%) rename {IFoxCAD.Cad => CADShared}/ExtensionMethod/Geomerty/PointEx.cs (100%) rename {IFoxCAD.Cad => CADShared}/ExtensionMethod/Jig/JigEx.cs (100%) rename {IFoxCAD.Cad => CADShared}/ExtensionMethod/Jig/JigExTransient.cs (100%) rename {IFoxCAD.Cad => CADShared}/ExtensionMethod/ObjectIdEx.cs (100%) rename {IFoxCAD.Cad => CADShared}/ExtensionMethod/RedrawEx.cs (100%) rename {IFoxCAD.Cad => CADShared}/ExtensionMethod/SelectionSetEx.cs (100%) rename {IFoxCAD.Cad => CADShared}/ExtensionMethod/SingleKeyWordHook.cs (100%) rename {IFoxCAD.Cad => CADShared}/ExtensionMethod/SymbolTableEx.cs (100%) rename {IFoxCAD.Cad => CADShared}/ExtensionMethod/SymbolTableRecordEx.cs (100%) rename {IFoxCAD.Cad => CADShared}/ExtensionMethod/TangentEx.cs (100%) rename {IFoxCAD.Cad => CADShared}/ExtensionMethod/TransactionEx.cs (100%) rename {IFoxCAD.Cad => CADShared}/ExtensionMethod/WindowEx.cs (100%) rename {IFoxCAD.Cad => CADShared}/Initialize/AcadEMR.cs (100%) rename {IFoxCAD.Cad => CADShared}/Initialize/AssemInfo.cs (100%) rename {IFoxCAD.Cad => CADShared}/Initialize/AutoReg.cs (100%) rename {IFoxCAD.Cad => CADShared}/Initialize/AutoRegAssem.cs (100%) rename {IFoxCAD.Cad => CADShared}/Initialize/CheckFactory.cs (100%) rename {IFoxCAD.Cad => CADShared}/Initialize/IAutoGo.cs (100%) rename {IFoxCAD.Cad => CADShared}/Initialize/MethodInfoHelper.cs (100%) rename {IFoxCAD.Cad => CADShared}/ResultData/LispList.cs (100%) rename {IFoxCAD.Cad => CADShared}/ResultData/TypedValueList.cs (100%) rename {IFoxCAD.Cad => CADShared}/ResultData/XDataList.cs (100%) rename {IFoxCAD.Cad => CADShared}/ResultData/XRecordDataList.cs (100%) rename {IFoxCAD.Cad => CADShared}/Runtime/DBTrans.cs (100%) rename {IFoxCAD.Cad => CADShared}/Runtime/Env.cs (100%) rename {IFoxCAD.Cad => CADShared}/Runtime/IdleAction.cs (100%) rename {IFoxCAD.Cad => CADShared}/Runtime/IdleNoCommandAction.cs (100%) rename {IFoxCAD.Cad => CADShared}/Runtime/SymbolTable.cs (100%) rename {IFoxCAD.Cad => CADShared}/SelectionFilter/OpComp.cs (100%) rename {IFoxCAD.Cad => CADShared}/SelectionFilter/OpEqual.cs (100%) rename {IFoxCAD.Cad => CADShared}/SelectionFilter/OpFilter.cs (100%) rename {IFoxCAD.Cad => CADShared}/SelectionFilter/OpList.cs (100%) rename {IFoxCAD.Cad => CADShared}/SelectionFilter/OpLogi.cs (100%) rename {IFoxCAD.Cad => IFoxCAD.AutoCad}/GlobalUsing.cs (100%) rename IFoxCAD.Cad/IFoxCAD.Cad.csproj => IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj (94%) diff --git a/IFoxCAD.Cad/Basal/General/ArrayEx.cs b/CADShared/Basal/General/ArrayEx.cs similarity index 100% rename from IFoxCAD.Cad/Basal/General/ArrayEx.cs rename to CADShared/Basal/General/ArrayEx.cs diff --git a/IFoxCAD.Cad/Basal/General/DebugHelper.cs b/CADShared/Basal/General/DebugHelper.cs similarity index 100% rename from IFoxCAD.Cad/Basal/General/DebugHelper.cs rename to CADShared/Basal/General/DebugHelper.cs diff --git a/IFoxCAD.Cad/Basal/General/EnumEx.cs b/CADShared/Basal/General/EnumEx.cs similarity index 100% rename from IFoxCAD.Cad/Basal/General/EnumEx.cs rename to CADShared/Basal/General/EnumEx.cs diff --git a/IFoxCAD.Cad/Basal/General/LinqEx.cs b/CADShared/Basal/General/LinqEx.cs similarity index 100% rename from IFoxCAD.Cad/Basal/General/LinqEx.cs rename to CADShared/Basal/General/LinqEx.cs diff --git a/IFoxCAD.Cad/Basal/General/LoopList.cs b/CADShared/Basal/General/LoopList.cs similarity index 100% rename from IFoxCAD.Cad/Basal/General/LoopList.cs rename to CADShared/Basal/General/LoopList.cs diff --git a/IFoxCAD.Cad/Basal/General/LoopState.cs b/CADShared/Basal/General/LoopState.cs similarity index 100% rename from IFoxCAD.Cad/Basal/General/LoopState.cs rename to CADShared/Basal/General/LoopState.cs diff --git a/IFoxCAD.Cad/Basal/Nullable/ArgumentNullEx.cs b/CADShared/Basal/Nullable/ArgumentNullEx.cs similarity index 100% rename from IFoxCAD.Cad/Basal/Nullable/ArgumentNullEx.cs rename to CADShared/Basal/Nullable/ArgumentNullEx.cs diff --git a/IFoxCAD.Cad/Basal/Nullable/CallerArgumentExpressionAttribute.cs b/CADShared/Basal/Nullable/CallerArgumentExpressionAttribute.cs similarity index 100% rename from IFoxCAD.Cad/Basal/Nullable/CallerArgumentExpressionAttribute.cs rename to CADShared/Basal/Nullable/CallerArgumentExpressionAttribute.cs diff --git a/IFoxCAD.Cad/Basal/Win/SystemEx.cs b/CADShared/Basal/Win/SystemEx.cs similarity index 100% rename from IFoxCAD.Cad/Basal/Win/SystemEx.cs rename to CADShared/Basal/Win/SystemEx.cs diff --git a/IFoxCAD.Cad/Basal/Win/Win32Api.cs b/CADShared/Basal/Win/Win32Api.cs similarity index 100% rename from IFoxCAD.Cad/Basal/Win/Win32Api.cs rename to CADShared/Basal/Win/Win32Api.cs diff --git a/CADShared/CADShared.projitems b/CADShared/CADShared.projitems new file mode 100644 index 0000000..bab98e0 --- /dev/null +++ b/CADShared/CADShared.projitems @@ -0,0 +1,70 @@ + + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + true + 00D9188F-646C-4E1A-AD53-5F6C0754346F + + + CADShared + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CADShared/CADShared.shproj b/CADShared/CADShared.shproj new file mode 100644 index 0000000..d138ef0 --- /dev/null +++ b/CADShared/CADShared.shproj @@ -0,0 +1,12 @@ + + + + {5178502E-9A78-4588-B849-33ED439976B2} + + + + + + + diff --git a/IFoxCAD.Cad/ExtensionMethod/CollectionEx.cs b/CADShared/ExtensionMethod/CollectionEx.cs similarity index 100% rename from IFoxCAD.Cad/ExtensionMethod/CollectionEx.cs rename to CADShared/ExtensionMethod/CollectionEx.cs diff --git a/IFoxCAD.Cad/ExtensionMethod/DBDictionaryEx.cs b/CADShared/ExtensionMethod/DBDictionaryEx.cs similarity index 100% rename from IFoxCAD.Cad/ExtensionMethod/DBDictionaryEx.cs rename to CADShared/ExtensionMethod/DBDictionaryEx.cs diff --git a/IFoxCAD.Cad/ExtensionMethod/DBObjectEx.cs b/CADShared/ExtensionMethod/DBObjectEx.cs similarity index 100% rename from IFoxCAD.Cad/ExtensionMethod/DBObjectEx.cs rename to CADShared/ExtensionMethod/DBObjectEx.cs diff --git a/IFoxCAD.Cad/ExtensionMethod/EditorEx.cs b/CADShared/ExtensionMethod/EditorEx.cs similarity index 100% rename from IFoxCAD.Cad/ExtensionMethod/EditorEx.cs rename to CADShared/ExtensionMethod/EditorEx.cs diff --git a/IFoxCAD.Cad/ExtensionMethod/Entity/BlockReferenceEx.cs b/CADShared/ExtensionMethod/Entity/BlockReferenceEx.cs similarity index 100% rename from IFoxCAD.Cad/ExtensionMethod/Entity/BlockReferenceEx.cs rename to CADShared/ExtensionMethod/Entity/BlockReferenceEx.cs diff --git a/IFoxCAD.Cad/ExtensionMethod/Entity/BoundingInfo.cs b/CADShared/ExtensionMethod/Entity/BoundingInfo.cs similarity index 100% rename from IFoxCAD.Cad/ExtensionMethod/Entity/BoundingInfo.cs rename to CADShared/ExtensionMethod/Entity/BoundingInfo.cs diff --git a/IFoxCAD.Cad/ExtensionMethod/Entity/CircleEx.cs b/CADShared/ExtensionMethod/Entity/CircleEx.cs similarity index 100% rename from IFoxCAD.Cad/ExtensionMethod/Entity/CircleEx.cs rename to CADShared/ExtensionMethod/Entity/CircleEx.cs diff --git a/IFoxCAD.Cad/ExtensionMethod/Entity/EntityBoundingInfo.cs b/CADShared/ExtensionMethod/Entity/EntityBoundingInfo.cs similarity index 100% rename from IFoxCAD.Cad/ExtensionMethod/Entity/EntityBoundingInfo.cs rename to CADShared/ExtensionMethod/Entity/EntityBoundingInfo.cs diff --git a/IFoxCAD.Cad/ExtensionMethod/Entity/EntityEx.cs b/CADShared/ExtensionMethod/Entity/EntityEx.cs similarity index 100% rename from IFoxCAD.Cad/ExtensionMethod/Entity/EntityEx.cs rename to CADShared/ExtensionMethod/Entity/EntityEx.cs diff --git a/IFoxCAD.Cad/ExtensionMethod/Entity/PolylineEx.cs b/CADShared/ExtensionMethod/Entity/PolylineEx.cs similarity index 100% rename from IFoxCAD.Cad/ExtensionMethod/Entity/PolylineEx.cs rename to CADShared/ExtensionMethod/Entity/PolylineEx.cs diff --git a/IFoxCAD.Cad/ExtensionMethod/Enums.cs b/CADShared/ExtensionMethod/Enums.cs similarity index 100% rename from IFoxCAD.Cad/ExtensionMethod/Enums.cs rename to CADShared/ExtensionMethod/Enums.cs diff --git a/IFoxCAD.Cad/ExtensionMethod/Geomerty/Curve2dEx.cs b/CADShared/ExtensionMethod/Geomerty/Curve2dEx.cs similarity index 100% rename from IFoxCAD.Cad/ExtensionMethod/Geomerty/Curve2dEx.cs rename to CADShared/ExtensionMethod/Geomerty/Curve2dEx.cs diff --git a/IFoxCAD.Cad/ExtensionMethod/Geomerty/Curve3dEx.cs b/CADShared/ExtensionMethod/Geomerty/Curve3dEx.cs similarity index 100% rename from IFoxCAD.Cad/ExtensionMethod/Geomerty/Curve3dEx.cs rename to CADShared/ExtensionMethod/Geomerty/Curve3dEx.cs diff --git a/IFoxCAD.Cad/ExtensionMethod/Geomerty/GeometryEx.cs b/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs similarity index 100% rename from IFoxCAD.Cad/ExtensionMethod/Geomerty/GeometryEx.cs rename to CADShared/ExtensionMethod/Geomerty/GeometryEx.cs diff --git a/IFoxCAD.Cad/ExtensionMethod/Geomerty/PointEx.cs b/CADShared/ExtensionMethod/Geomerty/PointEx.cs similarity index 100% rename from IFoxCAD.Cad/ExtensionMethod/Geomerty/PointEx.cs rename to CADShared/ExtensionMethod/Geomerty/PointEx.cs diff --git a/IFoxCAD.Cad/ExtensionMethod/Jig/JigEx.cs b/CADShared/ExtensionMethod/Jig/JigEx.cs similarity index 100% rename from IFoxCAD.Cad/ExtensionMethod/Jig/JigEx.cs rename to CADShared/ExtensionMethod/Jig/JigEx.cs diff --git a/IFoxCAD.Cad/ExtensionMethod/Jig/JigExTransient.cs b/CADShared/ExtensionMethod/Jig/JigExTransient.cs similarity index 100% rename from IFoxCAD.Cad/ExtensionMethod/Jig/JigExTransient.cs rename to CADShared/ExtensionMethod/Jig/JigExTransient.cs diff --git a/IFoxCAD.Cad/ExtensionMethod/ObjectIdEx.cs b/CADShared/ExtensionMethod/ObjectIdEx.cs similarity index 100% rename from IFoxCAD.Cad/ExtensionMethod/ObjectIdEx.cs rename to CADShared/ExtensionMethod/ObjectIdEx.cs diff --git a/IFoxCAD.Cad/ExtensionMethod/RedrawEx.cs b/CADShared/ExtensionMethod/RedrawEx.cs similarity index 100% rename from IFoxCAD.Cad/ExtensionMethod/RedrawEx.cs rename to CADShared/ExtensionMethod/RedrawEx.cs diff --git a/IFoxCAD.Cad/ExtensionMethod/SelectionSetEx.cs b/CADShared/ExtensionMethod/SelectionSetEx.cs similarity index 100% rename from IFoxCAD.Cad/ExtensionMethod/SelectionSetEx.cs rename to CADShared/ExtensionMethod/SelectionSetEx.cs diff --git a/IFoxCAD.Cad/ExtensionMethod/SingleKeyWordHook.cs b/CADShared/ExtensionMethod/SingleKeyWordHook.cs similarity index 100% rename from IFoxCAD.Cad/ExtensionMethod/SingleKeyWordHook.cs rename to CADShared/ExtensionMethod/SingleKeyWordHook.cs diff --git a/IFoxCAD.Cad/ExtensionMethod/SymbolTableEx.cs b/CADShared/ExtensionMethod/SymbolTableEx.cs similarity index 100% rename from IFoxCAD.Cad/ExtensionMethod/SymbolTableEx.cs rename to CADShared/ExtensionMethod/SymbolTableEx.cs diff --git a/IFoxCAD.Cad/ExtensionMethod/SymbolTableRecordEx.cs b/CADShared/ExtensionMethod/SymbolTableRecordEx.cs similarity index 100% rename from IFoxCAD.Cad/ExtensionMethod/SymbolTableRecordEx.cs rename to CADShared/ExtensionMethod/SymbolTableRecordEx.cs diff --git a/IFoxCAD.Cad/ExtensionMethod/TangentEx.cs b/CADShared/ExtensionMethod/TangentEx.cs similarity index 100% rename from IFoxCAD.Cad/ExtensionMethod/TangentEx.cs rename to CADShared/ExtensionMethod/TangentEx.cs diff --git a/IFoxCAD.Cad/ExtensionMethod/TransactionEx.cs b/CADShared/ExtensionMethod/TransactionEx.cs similarity index 100% rename from IFoxCAD.Cad/ExtensionMethod/TransactionEx.cs rename to CADShared/ExtensionMethod/TransactionEx.cs diff --git a/IFoxCAD.Cad/ExtensionMethod/WindowEx.cs b/CADShared/ExtensionMethod/WindowEx.cs similarity index 100% rename from IFoxCAD.Cad/ExtensionMethod/WindowEx.cs rename to CADShared/ExtensionMethod/WindowEx.cs diff --git a/IFoxCAD.Cad/Initialize/AcadEMR.cs b/CADShared/Initialize/AcadEMR.cs similarity index 100% rename from IFoxCAD.Cad/Initialize/AcadEMR.cs rename to CADShared/Initialize/AcadEMR.cs diff --git a/IFoxCAD.Cad/Initialize/AssemInfo.cs b/CADShared/Initialize/AssemInfo.cs similarity index 100% rename from IFoxCAD.Cad/Initialize/AssemInfo.cs rename to CADShared/Initialize/AssemInfo.cs diff --git a/IFoxCAD.Cad/Initialize/AutoReg.cs b/CADShared/Initialize/AutoReg.cs similarity index 100% rename from IFoxCAD.Cad/Initialize/AutoReg.cs rename to CADShared/Initialize/AutoReg.cs diff --git a/IFoxCAD.Cad/Initialize/AutoRegAssem.cs b/CADShared/Initialize/AutoRegAssem.cs similarity index 100% rename from IFoxCAD.Cad/Initialize/AutoRegAssem.cs rename to CADShared/Initialize/AutoRegAssem.cs diff --git a/IFoxCAD.Cad/Initialize/CheckFactory.cs b/CADShared/Initialize/CheckFactory.cs similarity index 100% rename from IFoxCAD.Cad/Initialize/CheckFactory.cs rename to CADShared/Initialize/CheckFactory.cs diff --git a/IFoxCAD.Cad/Initialize/IAutoGo.cs b/CADShared/Initialize/IAutoGo.cs similarity index 100% rename from IFoxCAD.Cad/Initialize/IAutoGo.cs rename to CADShared/Initialize/IAutoGo.cs diff --git a/IFoxCAD.Cad/Initialize/MethodInfoHelper.cs b/CADShared/Initialize/MethodInfoHelper.cs similarity index 100% rename from IFoxCAD.Cad/Initialize/MethodInfoHelper.cs rename to CADShared/Initialize/MethodInfoHelper.cs diff --git a/IFoxCAD.Cad/ResultData/LispList.cs b/CADShared/ResultData/LispList.cs similarity index 100% rename from IFoxCAD.Cad/ResultData/LispList.cs rename to CADShared/ResultData/LispList.cs diff --git a/IFoxCAD.Cad/ResultData/TypedValueList.cs b/CADShared/ResultData/TypedValueList.cs similarity index 100% rename from IFoxCAD.Cad/ResultData/TypedValueList.cs rename to CADShared/ResultData/TypedValueList.cs diff --git a/IFoxCAD.Cad/ResultData/XDataList.cs b/CADShared/ResultData/XDataList.cs similarity index 100% rename from IFoxCAD.Cad/ResultData/XDataList.cs rename to CADShared/ResultData/XDataList.cs diff --git a/IFoxCAD.Cad/ResultData/XRecordDataList.cs b/CADShared/ResultData/XRecordDataList.cs similarity index 100% rename from IFoxCAD.Cad/ResultData/XRecordDataList.cs rename to CADShared/ResultData/XRecordDataList.cs diff --git a/IFoxCAD.Cad/Runtime/DBTrans.cs b/CADShared/Runtime/DBTrans.cs similarity index 100% rename from IFoxCAD.Cad/Runtime/DBTrans.cs rename to CADShared/Runtime/DBTrans.cs diff --git a/IFoxCAD.Cad/Runtime/Env.cs b/CADShared/Runtime/Env.cs similarity index 100% rename from IFoxCAD.Cad/Runtime/Env.cs rename to CADShared/Runtime/Env.cs diff --git a/IFoxCAD.Cad/Runtime/IdleAction.cs b/CADShared/Runtime/IdleAction.cs similarity index 100% rename from IFoxCAD.Cad/Runtime/IdleAction.cs rename to CADShared/Runtime/IdleAction.cs diff --git a/IFoxCAD.Cad/Runtime/IdleNoCommandAction.cs b/CADShared/Runtime/IdleNoCommandAction.cs similarity index 100% rename from IFoxCAD.Cad/Runtime/IdleNoCommandAction.cs rename to CADShared/Runtime/IdleNoCommandAction.cs diff --git a/IFoxCAD.Cad/Runtime/SymbolTable.cs b/CADShared/Runtime/SymbolTable.cs similarity index 100% rename from IFoxCAD.Cad/Runtime/SymbolTable.cs rename to CADShared/Runtime/SymbolTable.cs diff --git a/IFoxCAD.Cad/SelectionFilter/OpComp.cs b/CADShared/SelectionFilter/OpComp.cs similarity index 100% rename from IFoxCAD.Cad/SelectionFilter/OpComp.cs rename to CADShared/SelectionFilter/OpComp.cs diff --git a/IFoxCAD.Cad/SelectionFilter/OpEqual.cs b/CADShared/SelectionFilter/OpEqual.cs similarity index 100% rename from IFoxCAD.Cad/SelectionFilter/OpEqual.cs rename to CADShared/SelectionFilter/OpEqual.cs diff --git a/IFoxCAD.Cad/SelectionFilter/OpFilter.cs b/CADShared/SelectionFilter/OpFilter.cs similarity index 100% rename from IFoxCAD.Cad/SelectionFilter/OpFilter.cs rename to CADShared/SelectionFilter/OpFilter.cs diff --git a/IFoxCAD.Cad/SelectionFilter/OpList.cs b/CADShared/SelectionFilter/OpList.cs similarity index 100% rename from IFoxCAD.Cad/SelectionFilter/OpList.cs rename to CADShared/SelectionFilter/OpList.cs diff --git a/IFoxCAD.Cad/SelectionFilter/OpLogi.cs b/CADShared/SelectionFilter/OpLogi.cs similarity index 100% rename from IFoxCAD.Cad/SelectionFilter/OpLogi.cs rename to CADShared/SelectionFilter/OpLogi.cs diff --git a/IFoxCAD.Cad/GlobalUsing.cs b/IFoxCAD.AutoCad/GlobalUsing.cs similarity index 100% rename from IFoxCAD.Cad/GlobalUsing.cs rename to IFoxCAD.AutoCad/GlobalUsing.cs diff --git a/IFoxCAD.Cad/IFoxCAD.Cad.csproj b/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj similarity index 94% rename from IFoxCAD.Cad/IFoxCAD.Cad.csproj rename to IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj index 29ebc51..09590ae 100644 --- a/IFoxCAD.Cad/IFoxCAD.Cad.csproj +++ b/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj @@ -34,4 +34,5 @@ + diff --git a/IFoxCAD.sln b/IFoxCAD.sln index 1e17231..02a5e11 100644 --- a/IFoxCAD.sln +++ b/IFoxCAD.sln @@ -3,10 +3,12 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.8.34309.116 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IFoxCAD.Cad", "IFoxCAD.Cad\IFoxCAD.Cad.csproj", "{6B29955A-5796-4035-9297-210FA15D3846}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IFoxCAD.AutoCad", "IFoxCAD.AutoCad\IFoxCAD.AutoCad.csproj", "{6B29955A-5796-4035-9297-210FA15D3846}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test", "Test\Test.csproj", "{0C01F295-0985-436B-A15D-228877C60F1D}" EndProject +Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "CADShared", "CADShared\CADShared.shproj", "{5178502E-9A78-4588-B849-33ED439976B2}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU diff --git a/Test/Test.csproj b/Test/Test.csproj index c0139b4..c110209 100644 --- a/Test/Test.csproj +++ b/Test/Test.csproj @@ -8,7 +8,7 @@ - + -- Gitee From cebd8f9e566c0bde92919b2e5799691340c41c8e Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Wed, 24 Apr 2024 09:57:34 +0800 Subject: [PATCH 278/453] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=9D=A2=E5=9F=9F?= =?UTF-8?q?=E8=BD=AC=E6=9B=B2=E7=BA=BF=E7=9A=84=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/CADShared.projitems | 1 + CADShared/ExtensionMethod/Entity/RegionEx.cs | 71 ++++++++++++++++++++ Test/TestPointEx.cs | 6 ++ 3 files changed, 78 insertions(+) create mode 100644 CADShared/ExtensionMethod/Entity/RegionEx.cs create mode 100644 Test/TestPointEx.cs diff --git a/CADShared/CADShared.projitems b/CADShared/CADShared.projitems index bab98e0..ff89251 100644 --- a/CADShared/CADShared.projitems +++ b/CADShared/CADShared.projitems @@ -29,6 +29,7 @@ + diff --git a/CADShared/ExtensionMethod/Entity/RegionEx.cs b/CADShared/ExtensionMethod/Entity/RegionEx.cs new file mode 100644 index 0000000..2be600d --- /dev/null +++ b/CADShared/ExtensionMethod/Entity/RegionEx.cs @@ -0,0 +1,71 @@ +using Autodesk.AutoCAD.BoundaryRepresentation; + +namespace IFoxCAD.Cad; + +public static class RegionEx +{ + /// + /// 面域转曲线 + /// + /// + /// + public static IEnumerable ToCurves(this Region region) + { + using var brep = new Brep(region); + var loops = brep.Complexes + .SelectMany(complex => complex.Shells) + .SelectMany(shell => shell.Faces) + .SelectMany(face => face.Loops); + foreach (var loop in loops) + { + var curves3d = loop.Edges.Select(edge => ((ExternalCurve3d)edge.Curve).NativeCurve).ToList(); + if (1 < curves3d.Count) + { + if (curves3d.All(curve3d => curve3d is CircularArc3d or LineSegment3d)) + { + var pl = (Polyline)Curve.CreateFromGeCurve(new CompositeCurve3d(curves3d.ToOrderedArray())); + pl.Closed = true; + yield return pl; + } + else + { + foreach (var curve3d in curves3d) yield return Curve.CreateFromGeCurve(curve3d); + } + } + else + { + yield return Curve.CreateFromGeCurve(curves3d.First()); + } + } + } + /// + /// 按首尾相连对曲线集合进行排序 + /// + /// + /// + /// + private static Curve3d[] ToOrderedArray(this IEnumerable source) + { + var tol = new Tolerance(0.001, 0.001); + var list = source.ToList(); + var count = list.Count; + var array = new Curve3d[count]; + var i = 0; + array[0] = list[0]; + list.RemoveAt(0); + while (i < count - 1) + { + var pt = array[i++].EndPoint; + int index; + if ((index = list.FindIndex(c => c.StartPoint.IsEqualTo(pt, tol))) != -1) + array[i] = list[index]; + else if ((index = list.FindIndex(c => c.EndPoint.IsEqualTo(pt, tol))) != -1) + array[i] = list[index].GetReverseParameterCurve(); + else + throw new ArgumentException("非连续曲线."); + list.RemoveAt(index); + } + + return array; + } +} \ No newline at end of file diff --git a/Test/TestPointEx.cs b/Test/TestPointEx.cs new file mode 100644 index 0000000..39ec186 --- /dev/null +++ b/Test/TestPointEx.cs @@ -0,0 +1,6 @@ +namespace Test; + +public class TestPointEx +{ + +} \ No newline at end of file -- Gitee From fd76757f2f3357512c62e7953b4469583eb954f1 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Wed, 24 Apr 2024 17:36:09 +0800 Subject: [PATCH 279/453] =?UTF-8?q?=E8=A1=A5=E5=85=85=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/ExtensionMethod/Entity/RegionEx.cs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/CADShared/ExtensionMethod/Entity/RegionEx.cs b/CADShared/ExtensionMethod/Entity/RegionEx.cs index 2be600d..12a9961 100644 --- a/CADShared/ExtensionMethod/Entity/RegionEx.cs +++ b/CADShared/ExtensionMethod/Entity/RegionEx.cs @@ -2,13 +2,16 @@ namespace IFoxCAD.Cad; +/// +/// 面域扩展 +/// public static class RegionEx { /// /// 面域转曲线 /// - /// - /// + /// 面域 + /// 曲线集合 public static IEnumerable ToCurves(this Region region) { using var brep = new Brep(region); @@ -29,7 +32,10 @@ public static IEnumerable ToCurves(this Region region) } else { - foreach (var curve3d in curves3d) yield return Curve.CreateFromGeCurve(curve3d); + foreach (var curve3d in curves3d) + { + yield return Curve.CreateFromGeCurve(curve3d); + } } } else @@ -38,6 +44,7 @@ public static IEnumerable ToCurves(this Region region) } } } + /// /// 按首尾相连对曲线集合进行排序 /// -- Gitee From f0bc45c15210047ecd528c3619332d4c51cc41c5 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Tue, 23 Apr 2024 16:28:51 +0800 Subject: [PATCH 280/453] =?UTF-8?q?=E6=B8=85=E7=90=86=E6=97=A0=E7=94=A8?= =?UTF-8?q?=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2HJE@WH1`PPUBOH2ZFL$BT.png" | Bin 65425 -> 0 bytes ...43\347\240\201\350\247\204\350\214\203.md" | 132 ------- docs/DBTrans.md | 139 ------- docs/SelectionFilter.md | 208 ----------- docs/SymbolTable.md | 146 -------- docs/WPF.md | 353 ------------------ docs/autoreg.md | 62 --- ...4\344\272\214\347\273\264\347\240\201.png" | Bin 20425 -> 0 bytes docs/png/nuget.png | Bin 159167 -> 0 bytes docs/png/nuget1.png | Bin 27373 -> 0 bytes docs/png/standard.png | Bin 148673 -> 0 bytes ...66\346\236\204\350\257\264\346\230\216.md" | 84 +++-- ...60\347\232\204\350\257\264\346\230\216.md" | 15 - README.md => readme.md | 2 +- 14 files changed, 44 insertions(+), 1097 deletions(-) delete mode 100644 "docs/0x01\344\273\243\347\240\201\350\247\204\350\214\203.assets/2HJE@WH1`PPUBOH2ZFL$BT.png" delete mode 100644 "docs/0x01\344\273\243\347\240\201\350\247\204\350\214\203.md" delete mode 100644 docs/DBTrans.md delete mode 100644 docs/SelectionFilter.md delete mode 100644 docs/SymbolTable.md delete mode 100644 docs/WPF.md delete mode 100644 docs/autoreg.md delete mode 100644 "docs/png/ifoxcad\347\224\250\346\210\267\344\272\244\346\265\201\347\276\244\347\276\244\344\272\214\347\273\264\347\240\201.png" delete mode 100644 docs/png/nuget.png delete mode 100644 docs/png/nuget1.png delete mode 100644 docs/png/standard.png delete mode 100644 "docs/\345\205\263\344\272\216\346\211\251\345\261\225\345\207\275\346\225\260\347\232\204\350\257\264\346\230\216.md" rename README.md => readme.md (96%) diff --git "a/docs/0x01\344\273\243\347\240\201\350\247\204\350\214\203.assets/2HJE@WH1`PPUBOH2ZFL$BT.png" "b/docs/0x01\344\273\243\347\240\201\350\247\204\350\214\203.assets/2HJE@WH1`PPUBOH2ZFL$BT.png" deleted file mode 100644 index 459930b8d54d075d94b4d06e960fbbc7edbdd17b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 65425 zcmce-V{~QD_5~Vt2OW2;j_q`8+h(VeoY=OLj*S!Bwr$(CZNB{a-uu6IjQ8=4@xGir zM(sMa3u{%aHRr5gIT=wn7%UhN5D++VF(CyI5O5|C5YRd(u+I{K4sJLQkRKr8Li|e3 zpr;;R-BJ7QKlofPxN{#QVEredL6PJ@8UCc@dsXr5JqfuS=cvgkLA?2d@CXxU7b1Lz z1ow}Dh)VD$&b2|AcDwNT7&UKdaeE+Tjq>m0e&`8GOJhG69d)AHO|ctK#YIMB#DZHC z_3G1P%Ek@xaz9?hi)SxGk9;w27QUDDYJJCM%4gaM7?K1xH4KQ3?n!PSdX=Q*c|BM5 zZ;n?2icRaaKi4r#$>5r}A!o=Q{?TT45YF@z6dA5ABZ*g=oOoF&@EEOb(yXFH!c%$b z3!J?;=>zxWls5SDm^=A~z~*#)Q_Vf!WUmb7M*e$h(E;Tf6XaX5V&OeKS|P23nwO~{ z^qE|m5*rF;JZ-1*6jnyGO5vv1ae~J}d^db-0xybw+TB{q27rA^+;pMG`ZWg6P;^XL3Uzx3`aasjp@l)tTV)Gq>7fi|YkSiR8 zA73ECb=v{*lXs&TtXACl@0o)D64W)C6{|(hl zgf`dAn8w_cuNjY^=MZ<_x+WnIlSb-%QJ2ixCYOXDP|mSf~3uoVHp&b=X`3da&uK zdy_NNP0(JdEs^)Ti5a+F_rnekSFrgUjLD!k7ub5*PEQcBvxvpyr6&An?~62z`*60QXI=Sl|!xQ=kU)zuxs3 zWXc?96uKC)@E$Y#gU#f~J-$urHGYKv0p$ZhYy?M~#9icO#+Ou2n65QZ+$_fBvEP?D zC0>!ybUw@|C(V#Xh+IL6n5+xw-K8_@PMF45GH7La*ysqdSZ5drgCX)q^*U%ZGq}a4 z!mdIOX9^9d49GQVFVySXql*>TNcvT@qK5N8BO5G{v0)UnraCndq|-G{@A9*pmFgiH zJ(*`6qunDkh9^Fi?f%j-9=|B{iyL>sv(L@qMZG`86y2Eim6S}m+&AnEv(^t#t8r%w zuALK(gy)2st7d3D8_n)YwscE3i(Qz&aob}f$Bbn?CWk(M@hcQ#be8rAEF%Y?r#U?| z4JMOF=H0+>(Um4!`hwbPpJ^~Becii6SsUs-aBmh08rz8fU80qrsI;l-GKh71AoN%P z<7-M%yPC9{fn0aP1M|Vl1b?mOOc-hd5QTBiAR8r`}S0w0rsP!lg+_N zD|+Sj;5^&PT%@d<4UG;ROXHJdiD-f=gD>}MTGK;E5Oqd~i*b)gDbVY&=S=%1K^BWr zg(Iyv2@}V@jh?$sg$u;#-;U$-4NUM0bF#}o=ND|ye=RV`KaWg&#Hd$=bp$4F@y|8? zTlBBT7$OKDA5-QBo?U*TOdC@#D7QN#093&IePwR z1ceRpf0N+D3Hdnyr{P$CkN*y}^DGjCzGmeEvm5@uW8IYD=X;P@5}SDG4Awn)OZ%gx zx>VJB&|aQH$p&jNO{6o|qCp1kD7%|T-h4rEmw&{Z1MEy>_y8mj!h4r$$2Se6@t_xU7ILVP; z!KxGy!DaWrEdY_X+zI-<@+>SuR zu0Ay{Cf}AfdAhxO%b4aIfpTN5aqJT|^sZ)UD*`=IYuePnDBc0frv>^`2euMkZ2S5-f9U*E1fWhfCI04Aem8|)+{rO_Nn_cWS2rxk{!;hSX z=U5AK-9HDF2lV2w+iT~Uuhq@E_5NpiKz{rX;G+Tp%TwazjVu(~p`d{&{n`5>2E#%8 zdB|}IdR~hwr#7Jb^gePSI6s{)G%mj?TEAl|II-~+f>``dM@%7Vi6^9P!_u_gQsoQ2 zcvAD9Dj0Y-*@Rcw37oNu#uu;|`dgzdu^P3v&Hl#tPW!;)O)^9S3%|GeR!P^y*XVZSEsStOCM{fR11#C7?VZcZTY#YCB zDjxEvB)L)|eIt!cdJpO&}j~ z?M~zH3zBZu^8obrI4pr6go3aKJc|l_z>$IX%#;wNHTZwMcR8pt$~$Umx#6U%Mt`HP zf`?_i{q;~Y#j6;XtHd|{f1J0BpYJ6b*zm>ZXN?SyYgnh?U19rzZ)Eld#M*zx;jKcD z2{|>|^~CjtUaB6klLTjCV`U*3$hN=fE>=nTpBem>iR5j(&qoA*1NwiC0P-Uf9`p~O zSn$j9e@zqw5yKe58wkg|O^^RKRQdOZj{n(5;V}>YeX9O7=g&q#04$S#dfflhn}4>< zLP5TP`Sc>a3K@`p+U0{qq`wSFMcJv)b_;3eJ$Na)h~sxWMSvp6ZeePnXO zFV~4sjLl#YyeD7_+=^r}2Zno-$_zi%}xe#TKnCxrJWu>cGb)nvZdYtc#? zB^*EOKd$eiL-2Xxs9LW@UH%Pi?JhVf!gW6**de$jP?Dcei_+RnT>XB+jb)pc^|BFh z#Yk-)&28xAo?L}nBKO%BNG_^ziiXz{!7hv|KcOSjvFVAq-z(yV`{Q`G71)q)##+so z0peFh%3A0#dNOLK>wV{|4Zy@*Y&`i;?(9d-e139xv-!@Yq4C1H(m%*d!_yqY*w3*E z^7kg$Vy`~>@&G*e`9KzVSSf1w4~Hs|>gn=g=0H+L;~%|z#C@QgXXm!Y=5gdbG=ELP z!|(GH^gE++UXmO zS;ym8VB;*OtzX+(TzhP28o$H1A-hIkRB&RBg`2!>$TJ;LK5k7L_AI;q@^y^Ym?WuL z_tk)UPWX+%Bbvq@S=8?-MIjT6jAiLt%}TfN!!=}kp8qTmxh;LN4w6cwWh z|7CcePHN1~WcTW<@BAlvFjANz+EDT{ThXzlP`}j|vossrSu=$Ta*mo!{Pm{-y3nSYje^6Z+82 z-*ve*5pV$eyhxg-)o6i*rZ+RECV(qo5rXpay*OJ+*3864*v&tu=B^K`Xl4XaF>yS( z^>@4{&hYHP%UCO}1)`&FU-OMj{U&B;<1b3d8fQXsHIawaXe1>Cjt862)dA?*cxk~0 zn+JkfB6g-rn5$Y#nvq@hRR2N>IDvmzV>=(;2vGg#CL_iDrB?R#CQB9L_wK=)R&Ji9 z$+@Hl|H$Ik*+us}@#oUtsxsP0&NLPiTL&l{gGm{zI{imZwcR5mecSsNnr4!gAD4S$ zJ$%$j&Ya7RbNT2J;z)Het0w(tBz@QC%#;GY9%(-lmBdhSzkkfB_!cceDJuFC$3{ox z=~(DwF{>D(ZJq%9)vVI8+zJbX_wxMA#i}?FQk^x%&g0s-sVCScdWpXckQX$v)NcuK z4m}4j$ps!v+aFoS2t*|W?bH}KXOn&pV)<*8tdX5%zW~ov>&ZymVd`#1|4LCi5VjDH z8{MzAoGPyMp`b-8l!-~XZvrkqJhuvaOFIK=f$=TuOO9(02aBSV2o@F^Rg*L74J_}H z5d`wx%*0QN1LWpw5Rxz|X3Ob92{K5U%=U-5f@2baxr!7QZ>VN2rkdAdXpc%LyH9iIMl0Q)AY{=@Ta`UT=yVyZBv@n`_ZO8h2Oms-gep$FJcgC!@}KsVhfsRaQ}; zJK}mN_y`+MFx!KeBs%b5eXRZMh>ov0-wDIQaOPWakrtC{Y{d6Bpw#K`9+rGt<_QQ6 za(-8Pr7fjJZ*r4zOj_-X;Ev01kdP@5V?N8Ekhb~dgqO%}853PO(BL$2gbr;NP#4oW z^)dMmA+6WYAL|P_r;sZIrzToh>xdkvRFl7kw#ElTZgW8m$H((@ggkmFsl_P}IvW1z z3HCP*oI_$kyYG__8eFQHWgoDXyAZhoid5+MYAo9ICh2a%8?>ousp5?&ZIdp%4-jQ zcc6#&2U8d#%Mf05fo#sna_0U3Zcay& z0IjkukLr|s2myljL%#dR=|GG$u3{P-0oG((`T(&`!+f{Uk&R@(Ucb70&wArlO7r$j z4(|aOBPm7#i;{DMf(1Oz{3g>}5(1jl^2NNygWrbqAJpul~4T&>Sy)H)ruBk+(o@Rj`bEn;ZJxJjRX1G6m(> z8+N_D#@S&}url1&TRG@_-E&YjQ45rlU;3EqLQWU{sZ1@hW2@5pgi@AjdCWo7R8C&? zD`TNG^c`L~&Dno%Oah6=3 z)!0_Q7N#1)M2la4%M1z0nrWWm@4QKY4JfFK$Q(h)QemGSQ3|iein_s5u)R{9L=Ugk zJhTo>cLvwsOe5@`FI5J*qmy@3jUy}2HV=CT=Wx^WE)S448=k-IwZ5S6qvUfMRdX-y z<#6?>+fcOFX9v~6-5>p`M&%BXE6G>{PhVUT+JtUDgTkP&n02f0)WNBvsg`e zRw_Vkf`%N-zOgq8XyEInfs;Nyk${oRJ(Vu?i);EF18PfU2L|#G0u>vVU?WN$Nt!Yq zlFHo9kFy#F^gD@}h0!~;_Opikiw{I1VaNdh2AuOfjXM%71Le&dl8M>*nC#Y!G(Qa; z$a{4Ug?9p@-rwF?wBy;yFg`GkNSir8`_rKqw8GJqX9kN03om=&YXXz=IZ%=0$*v?B zkoOtZ0nK?KY=+Qb&#TMjhk7FVqw?kErQ*NXEl;A^NbTA56kZ`l1s1(?_=I{$(`Kav zw=DZ4J^{BhLAD0nhU_+6bE=WH!5ezzz4~PV&)QFr1Wptq+S?kTWPbYQs5fZP-IUTy z6Rxi`0vlP^L$q15ErZvb-ts!1pOfg-%u%gtA z;nxtMa+zZ8?}EfpQDs#M1N`$H12v~7Fzo(5@IA;nn!(`eX0xvLh(HH*)6r`Y8PE26 zVlN_#RpWEs`kqNfDYFO@dlh+lJ2TH?)QzRC*#5aK7`>!wDY$MDO3xStT5wK9zv9te zNoi0^rG`4GXr+9_q-cu}+dejEK+&U&Pcou|-p=e)o%-gxf^?SqX?3=9}JgAx^sG7?!c;n?RX zaeRbQj#f~erLjY)BDZE7LuG=!)nsZ?h!PpvQjlwI}0So4%3)%SFp4NQmM-xoh;2 z#rWenLj#Ax(@Nrz7%S87x0iKFI2t$A;Y#zl8>$wH{~Xur#Pde{(lgWhL*0$99oo_6 zD{Cf8tn*{VA{K&b1vZv$Fu%rWM}`P5Q%ploInIy-DCwa$7YI8LD{Ukc5qxfqwY{?% zR#Jl|W?$vTNaw=K* z0;)XGrW(YqT9}^&s={kQ*Ith}`DiZcc4VSsGkikrlt`CTwVCl>(C4pC#7~o-pI1}l zo!#jFPN28X)1WFbf-_>r@*WD!zg=7NiQG5J+xBgZ_w-ir*9;3}_gnDaB7!&+Y!TN; zmuAZe$FkVrp%}&B@*|8nzynb)H(jJ*)R+_J90O+W_?PInd2@zd^!GWJ?wv{FvJB%T z@Uh{NOsi$34Hl_cg%(iWmeuTuAm^BYV&Is^3Z^u%`wM27!IUs&m8`|DBEybxsCuF* znor?z&caFyOVdM0hLmsatFFN_@JCu`yCpV6kEUeC8*;HjZ**hwgQg{R1yw`WY2o2x z`L27%rb$RaC{D>j<6I~+VYgSrp42AW9jRc1!hO?1L5zzQh3;ki>Z$q*{NUw47DIcu^VGXS`Z49K7kkJ-lE5rvf7PJ3WK2iB(?zbVI9C?Y2=FVbXvGCmIPgpWu{9+y!dy{4H$u91;d#;k< zh3_H>e)FCMz0&mb5@w#FaI#~d95`Jk^KAOqso^vVF)5g}w&@`ic7t}; zY;amJHx0F@1OpGuz|9*735MzHu(3(*-h|>E{iGRHh~rRUx&IgafgZp3!}pQ-@RR?b ztQD~|Q%9p|=*NQj`A|zN&5BROT@R~ki}Kz+ZMqeSas%Xf!L%dWK7FYfh>xd>>uxiN z$K_0xw?GO+u)RJCOfF8uml`arf{N5;SyNX;l_}pAb0<~NemqqYEtlM(n(GslPF%(B zJ>IMVBGi}-a=kZfH*@j~Vp8fyrV`Uz1&{!%~)^eTgO@=p8o}z5DDos zd6@i@BlD;wO}Yb^8dK>NoXt745%Hc2N`{PPo|vouVPWE?MweH;KJe;Y25@K>aH-zQ zsr^+_ULxbe7eo7jeQ1!u#@%qC%b)y9r}8jX=uZ0{w?W>-MNLmdlY!YpNUpMFV=uMg z9=$&^hnWlY9r!`jh6S`@cBCxGjR^Xo7#qqe60{%{2oANbvd&5!={?)}!>ZeYuXj7k*#9o6mnRYqIn!oi&7~!Z->HED@84?z~phLj*)YSVi81`5TDq z64Dd@@VC>w%TurXhiw550C5p-vQoT`9D)I2-mMKx;OOVGy#`UD%1gwm5y-?|?DwRB z{9?y+S_%Jx_j~O6&ZI@0G!{GicyTR2)+1z};H}u|e%H5n+MGQj`H#R@4rAGzF>V8f`_w>e*K@i-W;DO zY0>`|=(G_fM9%nTY1!w!y>QeB`$}bHPnvRVl0cxdb0>N^HG?BXQmE}OZu}PE?c+AP zw$>gK4<*#R72>p}e3Zkoxr__)Z!G|w_D}iS>OZ(QgcVeeB)@LQ%92mxrFPe%Zf}Ob zq;uV91UH5N$#nIyNY*Cpxl0^yIBng6MBI5I1_{~u*BPTIKCWuWkLM5o(k0~8|Kn;H zp_1S;ctjPHfJy=pE8!cxhMSwle&47GFGB29+w)}%di>g#1ZD%QmWhQ#Im(~7M?S{2 z%zG}13;VwT@@0F(;}c`9tZFvl^ktelX5+UK-N_aXi?=BfeMB1z;Ly-!c)-!gICJK^ zZ?L8Z>Ze<0!uR*>Ufl&PV4A6ZS#17;y{c#kuz}vr7wIqAK;_tmRhYdxxvkxSCz^PpYJMq5Olw0LvKlDDg;MzTS zHtx8aZD1Ibg?ZVInFpn2uy}f@>}lt#bszW`;fGc(WL3jqdhohsSmrJCH*dH#>=Q@! zxW3z2g`2FtRN#s>&mG%Dwa))eRSZZ@)JgImPeq~Mo!;V|reBEpD7*=;i;u4-P>O#w z(_t(j-&yObsD}y$?#W?QNF?nV&D18^Y2m&G8;beU1DBh}S{Ib|eqt<=%6^4j=(SR{ z?74^sQ*IN=+fpK)^I(TQ+YEo6esc;I_C(nHtA>-Tml`UvNUO>SBcx^hPVt zo9wdrA|vwp!s2WJ`en{}93i9h33P%lSgd2*-VM9roruEX@zqT?P51SFeT20gbvu}$ zaCk^zFq!_&zS4wFinKP&t%WKcHob~GsS+rN^=34}?i``=efN7f3`ukEjeRYF_jBGd z44v{1nZQsbn8HW{!!9N?N$77AB^dI}N{RWBUmvtex8hemv1A&`u4t8qLP%1ypbzA4 zSB%qvKH)|3MuN~EiZTsCx~!vR#+lUq58>M$@yN9E%P)G1NGQ}zVSW{NT3T>D7A%LvE(vzl2=V~Zi)3XTu0d6*JxcE!U zh_qoB1VwmT`j}C@$L?drPx+AyO0TC6nbjYIq@aHR>wxNUbdLvX*_Hd4RIcBt^w_6w z$S-YDK`(c|x9h9Bm0rn!)#aO*u$7b-D2$hg*ru(Q3+J%gw5a!_m;g%`2_vDSoYb&# zi_6-hLL*xM*5OIMs#{T1j*~)mzG({EXdoJi19}{>M7T?yGXJ`aWg#EQTX+;NtpP=) zEL5$hv<}ius#KfJXZ$8|n1EtlUjl>s2mMe01(d0!h>l-yf1PH7Se|j8^WZ7(q3u1e z!|}Ou878#DE34VpTU>p7#pm3k$JX-rYLJR7@$EL{U9iUD;=M3Uz2*)j0_nW@4*iA= zJ+W1%!gb|%c~1DSUn;`-sPXkgHmK=?$IVbp=TXD126$2eFl-158KN#BNJIEQ%69y) zL&(t-9jCo`In;eg5?&W_mH{NPZuBV%VxgveY$MMeOf9D95}Wz>Mbp+XnYa_1&Dr&)L-uoe#f>0uC)EfU8Gwbxw4Pg_`%KZpG$i}_vu=vp6pwqx zJJI*e;5f~KN=vgkC6p`mtoqO1Fhs9T@@KP*pK9#8?+p9qWKo&vKm$VEd* zhhwn$tyc?}?1sDkhbHh&#t6`Sk1hH&$o7e6MnpQT|FokdBHUa7G-Fv(ve>--D`#@_ zRCx^5LB`-kSp$LF$3TaAyN>t#A&lO*#{D#qG|jDM|2!6$hWE&kr2SQt;RWU$BF= zCP%!Q{QhsCCD=EQ99hTtvYrXAII1vW9u9;?I^x;HMAB@O$goAjPQ)E? zRsn6siZ}!Kd)!6>9U7X?WJ?{uNn?S zyqC#`G6jfiL&Y7G+$g^pr`8AnE<5Fdq)hpm7%WP7Y9sFxMsK~9K>+N1kL<$cubk6` z<-M?ndUeKaBlP=S5`mAvxu2^CveyhW9hI^;pC~0Q-N?9W-?E*mjJ&dZWciv~j^OLb zG=5R#Gh=VCr({Ju|D>H7i8K|3^Sw016@w5R^0V= z0~D+%=kU85~Tvj4g$P`sszdRgWQ z8Z>mfv54^Wu4T!d_o~<*XlL-X?Qufx(bzy4m<0GW>;3@|pOk;6bt-R1&3glEwk~KF zEhIxPHONGLmtHebJ_2$#We4zcV zwcpqcmHfkn+g=fb1~K=oKb9ls<_>@^>n)~2d!lCT`5iVwJCvSnAiEZ+c%5>F zQK0zrY*rukML}xtGVlRaL4@F`araG1Yub1|D1rytJxpQ1Fh9{k?`q*eRaI{7@aG*n z_1m%7d+sQBO$h}pLIl0_Ph-iAaWe)@CMef=d`_@nTEbmA(>i@jl(*bi__m~m=%no3 zYiU-Y>;}T@VCppdk161Cx6q9#p{N*_pvT$m@I+el>m@m**c#ybRc@?V>07+wBW%gV zJ3fPaPr^4GU(d=CSvEHa&VF($*p1oIf@9s0l496PCl5ISLmB3x4e<`@w{ipI6XFp5 z*bWweIxen*u|jHFXbjgr1c)EVyC#=JcYb8J=wbgLrd930mpwv@Bi{0YDcS2-&n~a` z3~*U$jP9w__n8i$yL-h;db^R*FalS+-r3D>)9HKV1cvkAr~H8pjh;mUvnYxn{BW9@jiK7R-zzawXNV*s3#{gip)7WdWduHJOkf(A~{K-oJis9g*yXRYWA0 zaaDQ3?H~{}5Fd!eA}pm@?FBojGKg~QqFf}?<)Mv2L0@7V1<@J>mukpf5qA(Q4t`^> zeU_nh{3Jd}nAIp0NLbgJX6!8jH(C}w3-et7y{Qr5Ql1!?i0;-H=lMLtLbR@xzbq^B zu5n1-(Pf8S*y2K|w5)Hg&bhZKZ$xO&-=CX!uFJ_!Cw7P%spy6r3UxjcC?QrBD1|X4 z;Uw?;T`p2Mb(MVsaV|huPgo5W>+IXPz#$}Q)L)*4WclgU5W-K#LL}XL^p@y6{bYA~_DMNHhMrTR8ESMjJPEN$C7R*3|7kCn8;NL&%1vT0Tu@j+k8FbRuc z>@PM}igT2?WqjZtGyf(aZ+A&I69mv~T+Vq8g`5o=;8bEo-=tEICN|b3g0Ymrnm`Dv3pM?6aXT z7KS_uD$V(=g#kYh(LV9Az6eYTHK;xFyKT)Rj|AfFZ;XtD#s#qIJgjjJQ1Eyr(Z2+e;de9p9WrzWqJRs=>bGO$0{hGk(0;^ zLT^}qm{rDl@|$3$Z|>H2yv}dX=u~!6I6uW?yUt?3x}8E=8jg7`tk9FB_Z|35={)z5 zwI4&r?!zX+96-3Ka}p2(0CS=h-=*zsOBGU49_$cJQeP%0D(%0zSv4n9Z9Cz1byS!p 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
  • <@J2maNRvDBImzCe;=5^G|HpMi#5^ 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

    npTOhE zMs)Ncq38P(QKunnvUY)boY!pC8w2{k2y~Y~@^YKKS|1F0fj@tC&VV|U@!>j{8sFcT zyxwB+T7w#a{8K8u6R1C>Jg|YyA^oXiDSXg>(pfI=nBIZ^+kvDqzQdXtt0eKb0&f~n z<}vS;J%TzOHdE(q99b`_=>K*AdOz4?P$_=vAO6V0!I0@`-b$H!44nPj0j5(rUm;pI W(pFr0_ZPrGKXDNm;R-?BAO8;*`RE`3 diff --git "a/docs/0x01\344\273\243\347\240\201\350\247\204\350\214\203.md" "b/docs/0x01\344\273\243\347\240\201\350\247\204\350\214\203.md" deleted file mode 100644 index 26f0909..0000000 --- "a/docs/0x01\344\273\243\347\240\201\350\247\204\350\214\203.md" +++ /dev/null @@ -1,132 +0,0 @@ -# IFox工程规范 - -## 代码规范 - -### 0x01 分离逻辑代码和业务代码 - -Good: - -```c# -foreach (xx in yyy) - if (xx == "a") - { - 业务(); - break; - } -``` - -Bad: - -```c# -bool flag = false; -foreach (xx in yyy) - if (xx == "a") - { - 业务(); - flag = true; - break; - } -if(!flag) - 其他业务(); -``` - -Good: - -```c# -bool flag = false; -foreach (xx in yyy) - if (xx == "a") - { - flag = true; - break; - } -if(!flag) - 其他业务(); -else - 业务(); -``` - -主要原因是统一业务在判断分支上,能够更清晰分离逻辑代码和业务代码. - -### 0x02 分离逻辑代码和业务代码 - -![img](0x01%E4%BB%A3%E7%A0%81%E8%A7%84%E8%8C%83.assets/2HJE@WH1%60PPUBOH2ZFL$BT.png) - -上述代码中出现了这种情形: for {业务1,业务2,业务1,业务2....} - -如果有这样的逻辑,那么我们看代码的时候总是认为业务2某种条件必须要跟着业务1. - -优化代码的人一看:这代码就不能动了!! 相信我,若干年后的你就是这个优化代码的人. - -所以这样的情况下,我们采用的是用个`List`收集拆离(业务)的id,然后在最后进行循环拆离(业务). - -### 0x03 .editorconfig 配置要求 - -c#的代码风格是两个大括号隔行 - -```c# -if() -{ - ... -} -``` - -但是,由于vs没有制作好的原因,导致`委托箭头`代码格式化总是会出现格式化错误. -所以我们推荐用 .editorconfig 文件约束这个`委托箭头` - -在.edirorconfig文件上面增加此句: - -``` -csharp_style_var_elsewhere = false -``` - -没有这个文件的话,请使用如下步骤: - -```mermaid -graph LR -vs --> 选项 --> 文本编辑器 --> c# -->代码样式,展开它 --> 格式设置 --> 新行 --> 右页,大括号的新行选项 --> 将lambda表达式的左括号置于新行,取消掉勾勾 -``` - -保存为 .editorconfig 文件,并放在.sln旁边,加入git管理: - -```mermaid -graph LR -vs --> 选项 --> 文本编辑器 --> c# -->代码样式 --> 右页,基于设置生成.editorconfig文件 --> 保存到工程中 -``` - -以后每次打开工程vs会自动识别这个 .editorconfig 文件,而不会用你电脑默认设置的. - -### 0x04 所有的注释符号//后面加空格 - -利用此正则替换: - -``` -(? - { - ltt.AsciiDescription = "虚线"; - ltt.PatternLength = 0.95; //线型的总长度 - ltt.NumDashes = 4; //组成线型的笔画数目 - ltt.SetDashLengthAt(0, 0.5); //0.5个单位的划线 - ltt.SetDashLengthAt(1, -0.25); //0.25个单位的空格 - ltt.SetDashLengthAt(2, 0); // 一个点 - ltt.SetDashLengthAt(3, -0.25); //0.25个单位的空格 - }); - // 这段代码同时演示了 ifoxcad 类库关于符号表的public ObjectId Add(string name, Action action)这个函数的用法。 - // 或者直接调用: - tr.LinetypeTable.Add("hah", "虚线",0.95,new double[]{0.5,-0.25,0,-0.25}); - // 获取线型表 - tr.LinetypeTable["hah"]; - ``` - - **其他符号表的操作类同。如果类库没有提供的Add函数的重载,那么Action委托可以完成你想完成的所有事情。** - -## 基础属性操作 - -事务管理器类提供了`Document`、 `Editor` 、`Database`三个属性来在事务内部处理相关事项。 - -同时还提供了关于字典的相关属性。 - -## 对象获取操作 - -提供了1个泛型 `GetObject`函数的重载来根据ObjectId来获取到对象。 - -## 字典操作(未完待续) - -- 扩展字典 - - `SetXRecord` 保存扩展数据到字典 - - `GetXRecord ` 获取扩展数据 - -- 对象字典 - - `SetToDictionary` 保存数据到字典 - - `GetFromDictionary` 从字典获取数据 - - `GetSubDictionary` 获取子对象字典 diff --git a/docs/SelectionFilter.md b/docs/SelectionFilter.md deleted file mode 100644 index bc31b55..0000000 --- a/docs/SelectionFilter.md +++ /dev/null @@ -1,208 +0,0 @@ -# 选择集过滤器用法 - -## 选择集过滤器简介 - -桌子提供了选择集过滤器是为了更精确的选择对象。可以通过使用选择过滤器来限制哪些对象被选中并添加到选择集,选择过滤器列表通过属性或类型过滤所选对象。 - -在桌子的 .net api 中:选择过滤器由一对 TypedValue 参数构成。TypedValue 的第一个参数表明过滤器的类型(例如对象),第二个参数为要过滤的值(例如圆)。过滤器类型是一个 DXF 组码,用来指定使用哪种过滤器。 - -默认的使用桌子api来创建选择集(带过滤器)分三步: - -1. 创建一个TypedValue数组来定义过滤器条件 - - ```csharp - TypedValue[] acTypValAr = new TypedValue[1]; // 创建数组 - acTypValAr.SetValue(new TypedValue((int)DxfCode.Start, "CIRCLE"), 0); - // 添加一个过滤条件,例如选择圆 - - // 如果要创建多个过滤条件怎么办? - TypedValue[] acTypValAr = new TypedValue[3]; - acTypValAr.SetValue(new TypedValue((int)DxfCode.Color, 5), 0); - acTypValAr.SetValue(new TypedValue((int)DxfCode.Start, "CIRCLE"), 1); - acTypValAr.SetValue(new TypedValue((int)DxfCode.LayerName, "0"), 2); - // 实际上只要不停的往数组里添加条件就可以了 - ``` - -2. 创建SelectionFilter对象 - - ```csharp - // 将过滤器条件赋值给 SelectionFilter 对象 - SelectionFilter acSelFtr = new SelectionFilter(acTypValAr); - ``` - -3. 创建选择集 - - ```csharp - // 请求用户在图形区域选择对象 - PromptSelectionResult acSSPrompt; - acSSPrompt = acDocEd.GetSelection(acSelFtr); - ``` - -看起来很是简单对不对,单个条件和多个条件的过滤非常简单。当指定多个选择条件时,AutoCAD 假设所选对象必须满足每个条件。我们还可以用另外一种方式定义过滤条件。对于数值项,可以使用关系运算(比如,圆的半径必须大于等于 5.0)。对于所有项,可以使用逻辑运算(比如单行文字或多行文字)。使用 DXF 组码-4 或常量 DxfCode.Operator 表示选择过滤器中的关系预算符类型。运算符本身用字符串表示。 - -比如: - -1. 过滤半径大于等于5.0的圆 - - ```csharp - TypedValue[] acTypValAr = { - new TypedValue((int)DxfCode.Start, "CIRCLE"), - new TypedValue((int)DxfCode.Operator, ">="), - new TypedValue(40, 5) - }; - ``` - -2. 过滤单行文本或者多行文本 - - ```csharp - TypedValue[] acTypValAr = { - new TypedValue((int)DxfCode.Operator, "") - }; - ``` - -3. 更复杂的过滤条件呢?比如选择的对象为不是位于0图层的直线,或者位于2图层的组码10的x坐标>10,y坐标>10的非圆图元。 - - 对应的lisp代码如下: - - ```lisp - '((-4 . "") - (-4 . "not>") - (-4 . "") - (8 . "2") - (-4 . ">,>,*")(10 10 10 0) - (-4 . "and>") - (-4 . "or>")) - ``` - - 对应的c#代码: - - ```csharp - TypedValue[] acTypValAr = { - new TypedValue((int)DxfCode.Operator, ""), - new TypedValue((int)DxfCode.Operator, "not>"), - new TypedValue((int)DxfCode.Operator, ""), - new TypedValue((int)DxfCode.LayerName, "2"), - new TypedValue((int)DxfCode.Operator, ">,>,*"), - new TypedValue(10, new Point3d(10,10,0)), - new TypedValue((int)DxfCode.Operator, "and>"), - new TypedValue((int)DxfCode.Operator, "or>") - }; - ``` - - 这个过滤器是不是看起来很乱,一眼看去根本不知道是要过滤什么,写起来也很麻烦。所以说,虽然桌子提供了api,但是简单的过滤条件很好用,但是复杂的过滤条件就很复杂了。 - - 因此IFox内裤提供了关于选择集过滤器的辅助类来帮助用户用更简单的方式来创建选择集的过滤器。 - -## 内裤过滤器对象与cad过滤器对应关系 - -IFoxCad内裤对于DxfCode.Operator枚举构建了一些辅助函数来表达关系运算和逻辑运算;提供了dxf函数来表达组码。其对应的关系如下表: - -| 内裤过滤器对象、函数 | cad .net api 过滤器对象、函数、枚举 | 备注 | -|:----------:|:------------------------:|:-------------------:| -| OpFilter | SelectionFilter | 隐式转换 | -| OpOr | "" | | -| Op.Or | "" | | -| OpAnd | "" | | -| Op.And | "" | | -| OpNot | "" | | -| OpXor | "" | | -| OpEqual | 相等运算 | | -| OpComp | 比较运算符 | | -| Dxf() | 组码函数 | 仅用于过滤器中,不是组码操作函数 | -| ! | "" | | -| == | "=" | | -| != | "!=" | | -| > | ">" | | -| < | "<" | | -| >= | ">=" 或 ">,>,*" | ">,>,*"用于跟point3d比较 | -| <= | "<=" 或 "<,<,*" | "<,<,*"用于跟point3d比较 | -| & | "" | | -| ^ | "" | | -| \| | "" | | - -## 具体用法 - -IFoxCad内裤提供了三种方式来构建过滤器,其实大同小异,就是写法不一样,用户可以根据自己的喜好来选择。 - -- 第一种 - - ```csharp - var fd = - new OpOr //定义一个 (-4 . "") - { - !new OpAnd //定义(-4 . "")(-4 . "not>") - { - { 0, "line" }, //{组码,组码值} - { 8, "0" }, //{组码,组码值} - }, - new OpAnd //定义(-4 . "") - { - !new OpEqual(0, "circle"), //定义(-4 . "") - { 8, "2" }, //{组码,组码值} - { 10, new Point3d(10,10,0), ">,>,*" } //(-4 . ">,>,*")(10 10 10 0) - }, - }; - editor.SelectAll(fd); //这里直接传入fd就可以了 - ``` - - 以上代码的含义为:选择的对象为不是位于0图层的直线,或者位于2图层的组码10的x坐标>10,y坐标>10的非圆图元。其同含义的lisp代码如下: - - ```lisp - '((-4 . "") - (-4 . "not>") - (-4 . "") - (8 . "2") - (-4 . ">,>,*")(10 10 10 0) - (-4 . "and>") - (-4 . "or>")) - ``` - -- 第二种 - - ```csharp - var p = new Point3d(10, 10, 0); - var f = OpFilter.Bulid(e => - !(e.Dxf(0) == "line" & e.Dxf(8) == "0") - | e.Dxf(0) != "circle" - & e.Dxf(8) == "2" - & e.Dxf(10) >= p); - editor.SelectAll(f); //这里直接传入f就可以了 - ``` - - 代码含义如第一种。 - -- 第三种 - - ```csharp - var f2 = OpFilter.Bulid( - e =>e.Or( - !e.And(e.Dxf(0) == "line", e.Dxf(8) == "0"), - e.And(e.Dxf(0) != "circle", e.Dxf(8) == "2", e.Dxf(10) >= new Point3d(10, 10, 0))) - ); - editor.SelectAll(f2); //这里直接传入f2就可以了 - ``` - - 代码含义如第一种,第三种和第二种的写法非常像,区别就是关于 and 、or 、not 等运算符,一个是采用c#的语法,一个是采用定义的函数。and 与&等价,or与|等价,not 与!等价。 \ No newline at end of file diff --git a/docs/SymbolTable.md b/docs/SymbolTable.md deleted file mode 100644 index a5144ba..0000000 --- a/docs/SymbolTable.md +++ /dev/null @@ -1,146 +0,0 @@ -# 符号表用法 - -每个图形文件都包含有9个固定的符号表。不能往数据库里添加新的符号表。如图层表(LayerTable),其中包含图层表记录,还有块表(BlockTable),其中包含块表记录等。所有的图形实体(线、圆、弧等等)都属于一个块表记录。缺省情况下,任何图形文件都包含为模型空间和图纸空间预定义的块表记录。每个符号表都有对应的符号表记录,可以理解为符号表是一个集合,而符号表记录是这个集合的元素。CAD的符号表和符号表记录的对应关系如下: - -| 名称 | 符号表 | 符号表记录 | -|:-------:|:--------------:|:--------------------:| -| 块表 | BlockTable | BlockTableRecord | -| 标注样式表 | DimStyleTable | DimStyleTableRecord | -| 图层表 | LayerTable | LayerTableRecord | -| 线型表 | LinetypeTable | LinetypeTableRecord | -| 注册应用程序表 | RegAppTable | RegAppTableRecord | -| 字体样式表 | TextStyleTable | TextStyleTableRecord | -| 坐标系表 | UcsTable | UcsTableRecord | -| 视口表 | ViewportTable | ViewportTableRecord | -| 视图表 | ViewTable | ViewTableRecord | - -那么如何来操作这些符号表呢?下面是一个新建图层的例子: - -```csharp -Document acDoc = Application.DocumentManager.MdiActiveDocument; -Database acCurDb = acDoc.Database; -using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction()) -{ - // 返回当前数据库的图层表 - LayerTable acLyrTbl = acTrans.GetObject(acCurDb.LayerTableId,OpenMode.ForRead) as LayerTable; - // 检查图层表里是否有图层 MyLayer - if (acLyrTbl.Has("MyLayer") != true) - { - // 以写模式打开图层表 - acLyrTbl.UpgradeOpen(); - // 新创建一个图层表记录,并命名为”MyLayer” - LayerTableRecord acLyrTblRec = new LayerTableRecord(); - acLyrTblRec.Name = "MyLayer"; - // 添加新的图层表记录到图层表,添加事务 - acLyrTbl.Add(acLyrTblRec); - acTrans.AddNewlyCreatedDBObject(acLyrTblRec, true); - //提交修改 - acTrans.Commit(); - } - // 关闭事务,回收内存; -} -``` - -上面的例子用了20多行的代码来完成一个很简单的功能,这就是AutoCAD提供的api太过于基础,没有进行进一步的封装造成。那么如果我们单独为图层表封装一个函数来处理图层表,其他的8个符号表也要同样的各自封装函数,这样看起来没什么问题,但是对于代码的复用却没有很好的考虑进去。仔细思考一下,其实对于符号来说无非就是增删改三个主要的操作等,对于符号表记录来说无非就是一些属性的操作,增加实体的操作等。那么有没有一种办法可以统一管理9个符号表呢?其实AutoCAD提供了9个符号表和符号表记录的抽象基类,SymbolTable和SymbolTableRecord,但是这两个类提供的功能又很简单,只有寥寥几个函数和属性,完全不能满足我们的需求。因此ifoxcad内裤提供了符号表类来封装9个符号表的大部分功能。那么用内裤来完成上述的操作是什么样子的呢?见下面的例子: - -```csharp -// 以下代码采用最新的c#版本语法 -using var tr = new DBTrans(); // 打开事务 -var layertable = tr.LayerTable.Add("MyLayer"); //添加图层 -``` - -同样的功能我们只需要两行就可以搞定了。那么有同学会问了,我同样单独对每个符号表的封装一样可以达到这个效果?是的,确实可以达到一样的效果,但是我只封装了一次,只是针对符号表的差异部分做了一些增量的处理,其他的代码都是复用的,而你要写9次。 - -言归正传,通过上述的例子,我们会发现几个现象: - -1. 符号表的操作是在事务内。 -2. 符号表成了事务的属性 -3. 添加符号表记录到符号表调用Add函数就可以了(其实提供了好多的重载,来完成不同的细粒度的操作)。 - -符号表的操作都在事务内,这样由事务统一管理符号表的变动,减少出错的可能。 - -符号表作为事务的属性,那么获取符号表记录就变成了属性的索引值。`var layertable = tr.LayerTable["MyLayer"];` - -不管是什么符号表,都是一个Add函数搞定添加操作。 - -而删除就是:`tr.LayerTable.Remove("1");` *注意,这里的关于删除图层的操作需要调用Delete函数* - -看,我教会了你操作图层表,那么其他的8个表你都会了,都是一样的操作。 - -## 块表添加图元 - -一般的情况下,添加图元的操作都是要在事务里完成。目前大部分的添加图元的自定义函数都是DataBase或Editor对象的扩展函数。但是实际上添加图元的本质是读写图形数据库,具体的手段是对块表里的块表记录的读写。而实际的操作其实都是在事务里完成,所以符合cad操作规则的写法其实应该是事务作为一系列操作的主体来进行。因此ifoxcad内裤的封装思路为:扩展块表记录的函数,在事务管理器类里通过属性调用AddEntity函数来添加图元。 - -对于这个添加图元的操作,一共分为如下几步: - -1. 创建图元对象,可以在事务外创建,也可以在事务内创建。 -2. 打开要添加图元的块表记录,在事务内打开。 -3. 添加图元到块表记录 - -下面看示例: - -- 添加图元到当前空间 - - ```csharp - // 以下代码采用最新的c#版本语法 - using var tr = new DBTrans(); //开启事务管理器 - var line1 = new Line(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); //定义一个直线 - tr.CurrentSpace.AddEntity(line1); // 将直线添加到当前绘图空间的块表记录 - ``` - -- 添加图元到模型/图纸空间 - - ```csharp - // 以下代码采用最新的c#版本语法 - using var tr = new DBTrans(); //开启事务管理器 - var line1 = new Line(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); //定义一个直线 - tr.CurrentSpace.AddEntity(line1); // 将直线添加到当前绘图空间的块表记录 - tr.ModelSpace.AddEntity(line1); // 将直线添加到当前模型空间的块表记录 - tr.PaperSpace.AddEntity(line1); // 将直线添加到当前图纸空间的块表记录 - ``` - -- 添加图元到块表 - - ```csharp - // 以下代码采用最新的c#版本语法 - using var tr = new DBTrans(); //开启事务管理器 - var line1 = new Line(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); //定义一个直线 - var btr = tr.BlockTable.Add("test"); //定义一个块表记录 - btr.AddEntity(line1); // 将直线添加到当前控件的块表记录 - ``` - - 那么大家猜一猜,这个添加到块表是实现了一种什么样的功能。 - -- 块表 - - 块表这里需要特殊的说明一下: - - 比如说添加一个块,用如下代码: - - `tr.BlockTable.Add(blockName, btr => btr.AddEntity(ents));` - - 这里的blockName就是块名,ents就是图元列表。这种方式虽然可以更细粒度的控制定义的块。 - - 插入块参照,比如: - - `tr.InsertBlock(point,objectid); // 用于插入块参照,提供了重载函数来满足不同的需求` - -- 其他函数的介绍 - - `tr.BlockTable.GetRecord()` 函数,可以获取到块表的块表记录,同理层表等符号表也有同样的函数。 - - `tr.BlockTable.GetRecordFrom()` 函数,可以从文件拷贝块表记录,同理层表等符号表也有同样的函数。 - - `tr.BlockTable.GetBlockFrom()` 函数,从文件拷贝块定义,同理层表等符号表也有同样用途的函数。 - -- 添加图元函数 - - 内裤提供了一些便利的添加图元函数,可以不用先定义一个entity对象,然后添加到块表记录。 - - ```csharp - using var tr = new DBTrans(); - tr.CurrentSpace.AddLine(new Point3d(0,0,0),new Point3d(1,1,0)); - tr.CurrentSpace.AddCircle(new Point3d(0,0,0),10); - ``` - - diff --git a/docs/WPF.md b/docs/WPF.md deleted file mode 100644 index 73f4f11..0000000 --- a/docs/WPF.md +++ /dev/null @@ -1,353 +0,0 @@ - - -# WPF支持 - -在项目文件里将``替换为``。 - -在``标签里的`NET45`下面添加: -```xml -true -true -``` - -最后的项目文件如下: - -```xml - - - net47 - - true - - true - - - -``` - -# mvvm模式支持 - -## 一、简单mvvm的实现 - -使用WPF的最佳实践就是采用mvvm模式,为了支持在cad插件里使用mvvm,ifoxcad内裤定义了两个简单基类来完成属性通知和命令定义。当然这是一种及其简单的mvvm模式的支持,你还要自己手动来写大部分的代码来实现完整的mvvm模式。 - -要实现mvvm模式,要新建一个XXXView文件,一个XXXViewModel文件。我们应该采用一种通用的命名约定,即所有的gui显示都有XXXView来完成,而所有的业务逻辑都由XXXViewModel来完成。下面以一个具体的示例来说明怎么在cad的插件里使用mvvm模式。 - -1. 将我们上一节建立的MyWindow1文件改名为MyWindowView,然后将涉及到的类名也全部更改为MyWindowView。 - -2. 然后将MyWindowView.xaml文件的内容改为: - -```xaml - - - - - - - - -``` - -就是添加了一个文本框,一个按钮。 - -3. 新建MyWindowViewModel.cs文件,内容如下: - -```c# -using IFoxCad.WPF; // 这里引入IFoxCad.WPF命名空间,以便可以使用ViewModelBase和RelayCommand - -namespace Test -{ - class MyWindowViewModel : ViewModelBase - { - // 定义一个属性用于在文本框里显示 - private string _name; - public string Name - { - get { return _name; } - set - { - Set(ref _name, value); - } - } - - // 定义一个命令用于按钮的点击动作 - private RelayCommand clickCommand; - public RelayCommand ClickCommand - { - get - { - if (clickCommand == null) - { - clickCommand = new RelayCommand( - execute => Name = "hello " + Name, // 定义要执行的行为 - can => {return !string.IsNullOrEmpty(Name);}); // 定义命令是否可用 - } - return clickCommand; - } - } - // 初始化Name属性为 World - public MyWindowViewModel() - { - Name = "World"; - } - } -} - -``` - -这里需要注意的是,定义的属性是为了将属性绑定到文本框的Text属性上,这个叫做数据绑定。然后wpf里对于我们winform里的事件其实采用的更高级一些的命令来完成。本示例,定义的命令也是一个属性,这个属性返回一个RelayCommand对象的实例,这是实例的初始化函数包括两个部分,一个是要执行的动作,第二个是确定什么条件下按钮是不可用的,这个是通过命令是否可用来完成,是要命令是不能执行的,wpf会自动将控件切换为不可用状态,使其不可点击。 - -4. 现在回过头来对在xaml里将刚刚的viewmodel里定义的属性和命令绑定到控件上。 - -```xaml - - -``` - -将这两行代码替换一下。然后在后台代码里(MyWindowView.xaml.cs)添加一行代码将viewmodel绑定到view上。 - -```c# -public MyWindowView() -{ - InitializeComponent(); - DataContext = new MyWindowViewModel(); //这里将一个viewmodel的实例绑定到view的DataContext属性上。 -} -``` - -5. 至此,一个简单的wpf的mvvm模式的代码就完成了,下面的代码演示了怎么在cad里显示这个wpf窗体。 - -```c# -[CommandMethod("test")] -public void Test() -{ - var test = new MyWindowView(); - Application.ShowModalWindow(test); -} -``` - -6. 最后,这个窗体的效果是,当你点击按钮时,文本框的文字前面会加上hello。当你将文本框的文字全部删除后,按钮会变成不可用状态。如果你在试验的时候没有这个效果,这是cad的延迟导致的。多删除几次试几次后就会如期运行。 - -## 二、mvvm中的事件处理 - -在WPF里,并不是所有的控件都提供了commad属性用于绑定命令,所以还是需要进行控件的事件处理的,比如窗口的Loaded事件,鼠标事件,键盘事件等。关于WPF的事件处理,IFoxCad内裤提供了两种方式进行处理,一种就是利用 **Microsoft.Xaml.Behaviors.dll** 这个类库,利用了 **i:Interaction.Triggers** 标签在xaml文件里将命令绑定到事件上,这种方式是网上比较常见的一种方式;第二种是自定义了一个xaml标签 **eb:EventBinding** ,利用这个标签将命令绑定到事件上。两种方式实现的效果是一样的,但是 **eb:EventBinding** 标签绑定的方式的代码量要小一些。 - -下面就两种方式实现同一种事件处理的效果提供了两种方式的代码示例作为说明。由于两种方式的差异主要在xaml文件里,ViewModel的代码是一样的。因此主要讲述两种xaml的差异部分,ViewModel的代码直接贴在下面不做讲解。 - -```c# -public class TestViewModel : ViewModelBase -{ - - private bool _IsReceiveMouseMove = true; - public bool IsReceiveMouseMove - { - get { return _IsReceiveMouseMove; } - set - { - Set(ref _IsReceiveMouseMove, value); - } - } - - private string _tipText; - public string TipText - { - get { return _tipText; } - set - { - Set(ref _tipText, value); - } - } - - - - private RelayCommand loadedCommand; - - public RelayCommand LoadedCommand - { - get - { - if (loadedCommand == null) - { - loadedCommand = new RelayCommand(execute => MessageBox.Show("程序加载完毕!")); - - } - return loadedCommand; - } - - } - - private RelayCommand mouseMoveCommand; - public RelayCommand MouseMoveCommand - { - get - { - if (mouseMoveCommand == null) - { - mouseMoveCommand = - new RelayCommand( - e => - { - var point = e.GetPosition(e.Device.Target); - var left = "左键放开"; - var mid = "中键放开"; - var right = "右键放开"; - - if (e.LeftButton == MouseButtonState.Pressed) - { - left = "左键放下"; - } - if (e.MiddleButton == MouseButtonState.Pressed) - { - mid = "中键放下"; - } - if (e.RightButton == MouseButtonState.Pressed) - { - right = "右键放下"; - } - - TipText = $"当前鼠标位置 X:{point.X} Y:{point.Y} 当前鼠标状态:{left} {mid} {right}."; - }, - o => IsReceiveMouseMove); - } - return mouseMoveCommand; - } - } -} -``` - -### 2.1 自定义标签的方式 - -首先是在xaml里引入命名空间。 - -`xmlns:eb="clr-namespace:IFoxCAD.WPF;assembly=IFoxCAD.WPF"` - -然后 - -`Loaded="{eb:EventBinding Command=LoadedCommand}"` - -`MouseMove="{eb:EventBinding Command=MouseMoveCommand,CommandParameter=$e}"` 这里要注意的是显式的传入了鼠标移动事件的参数。 - -注意命令参数部分,如果这个事件是带参数的,或者说这个命令是带参数的,要传入参数。 - -关于命令及命令参数使用方式如下: - -- Command - 1. `{eb:EventBinding}` 利用简单的名字匹配来自动搜寻命令,也就是说不用指定命令名,不是很推荐。 - 2. `{eb:EventBinding Command=CommandName}` 指定命令名,建议总是使用这种方式 - -- CommandParameter - 1. `$e` (事件参数,这里特指的是事件本身带的参数,也就是你以前写事件的处理函数时候的XXXXEventArgs e这个参数) - 2. `$this` or ​`$this.Property` (view本身或者属性) - 3. `string` (要传入的字符串) - -完整的xaml代码如下: - -```xaml - - - - - -``` - -### 2.2 利用Behaviors的方式 - -首先nuget安装**Microsoft.Xaml.Behaviors.Wpf**包。 - -然后在xaml文件里,引入命名空间。 - -`xmlns:eb="clr-namespace:IFoxCad.WPF;assembly=IFoxCad"` - -`xmlns:i="http://schemas.microsoft.com/xaml/behaviors"` - -然后绑定命令到事件上: - -```xaml - - - - - - - - -``` - -细心的同学可能会发现绑定命令的地方标签是不一样的。 - -**i:InvokeCommandAction** 这个标签是由 **Microsoft.Xaml.Behaviors.Wpf** 包提供的。 - -**eb:EventCommand** 这个标签是由IFoxCad内裤提供的。 - -两者的区别就是InvokeCommandAction 是不能传入事件的参数的,所以为了处理事件参数自定义了EventCommand。就如同上面的鼠标移动事件,是有时间参数要处理的,所以用了自定义的EventCommand,虽然xaml文件里没有显式的传入这个参数。 - -虽然InvokeCommandAction这个标签的后面是可以带命令参数的,比如: - -```xaml - - - - - -``` - -但是这个命令参数是不能处理事件自带的参数的 。 - -最后是完整的xaml代码: - -```xaml - - - - - - - - - - - - - - -``` - -### 2.3 关于两种方式的选择 - -送给选择困难症的:如果可以选择自定义标签的方式,简单一些。遇到问题解决不了,就用behaviors的方式,网上的资源丰富一些,也许能找到你的答案。 - -## 三、 关于mvvm模式的建议 - -我们并不推荐严格的mvvm模式,主要原因是要引入比如message模式等方式处理类似窗口关闭,窗口间通信等问题。鉴于cad插件的界面复杂程度还没到后台事件满天飞,逻辑复杂的地步,因此后台写点事件处理,界面和后逻辑混在一起也未尝不可。 - -仅仅是建议,你爱怎样就怎样。 - diff --git a/docs/autoreg.md b/docs/autoreg.md deleted file mode 100644 index 72f377c..0000000 --- a/docs/autoreg.md +++ /dev/null @@ -1,62 +0,0 @@ -## 自动加载与初始化 - -### 1、简单版 - -为了将程序集的初始化和通过写注册表的方式实现自动加载统一设置,减少每次重复的工作量,类裤提供了`AutoLoad`抽象类来完成此功能,只要在需要初始化的类继承`AutoLoad`类,然后实现`Initialize()` 和 `Terminate()` 两个函数就可以了。 -特别强调的是,一个程序集里只能有一个类继承,不管是不是同一个命名空间。 - -如果要将dll的目录加入支持文件目录,请在 `Initialize` 函数中调用`AppendSupportPath(CurrentDirectory.FullName);` - -其他需要初始化执行的函数及设置都需要在 `Initialize` 函数中执行。 - -### 2、功能版 - -使用特性进行分段初始化是目前最佳选择,下面的说明已和最新版本不符,等待修正吧。 - -```csharp - using Autodesk.AutoCAD.Runtime; - using IFoxCAD.Cad; - using System; - using System.Reflection; - -/* - * 自动执行接口 - * 这里必须要实现一次这个接口,才能使用 IFoxInitialize 特性进行自动执行 - */ -public class CmdINI : AutoRegAssem -{ - // 这里可以写任何普通的函数,也可以写下面 AutoTest 类里的实现了 IFoxInitialize 特性的初始化函数 - // 继承AutoRegAssem的主要作用是写注册表用来自动加载dll,同时执行实现了 IFoxInitialize 特性的函数 - // 注意这里的自动执行是在cad启动后,加载了dll之后执行,而不是运行命令后执行。 - - [IFoxInitialize] - public void InitOne() - { - // TODO 您想在加载dll之后自动执行的函数 - // 可以随便在哪里类里 可以多次实现 IFoxInitialize 特性 - } - -} - -// 其他的类中的函数: -// 实现自动接口之后,在任意一个函数上面使用此特性,减少每次改动 CmdINI 类 -public class AutoTest -{ - [IFoxInitialize] - public void Initialize() - { - // TODO 您想在加载dll之后自动执行的函数 - } - [IFoxInitialize] - public void InitTwo() - { - // TODO 您想在加载dll之后自动执行的函数 - // 可以随便在哪里类里 可以多次实现 IFoxInitialize 特性 - } - [IFoxInitialize(isInitialize: false)] // 特性的参数为false的时候就表示卸载时执行的函数 - public void Terminate() - { - // TODO 您想在关闭cad时自动执行的函数 - } -} -``` diff --git "a/docs/png/ifoxcad\347\224\250\346\210\267\344\272\244\346\265\201\347\276\244\347\276\244\344\272\214\347\273\264\347\240\201.png" "b/docs/png/ifoxcad\347\224\250\346\210\267\344\272\244\346\265\201\347\276\244\347\276\244\344\272\214\347\273\264\347\240\201.png" deleted file mode 100644 index a9d08c483b80f21d4b0ac6a0afe80f9b6b4233e6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20425 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Ð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 diff --git a/docs/png/nuget1.png b/docs/png/nuget1.png deleted file mode 100644 index 91983ffef3b246ea796296b14fe09963663de184..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27373 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 diff --git a/docs/png/standard.png b/docs/png/standard.png deleted file mode 100644 index dfc34fecb32120f54436115208a4abaea2dac516..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 148673 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%0DO&7ix%Xw#WJ4GhT6iE|`sg)>zmh51hyQTaFv=}2 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 diff --git "a/docs/\345\205\263\344\272\216IFoxCAD\347\232\204\346\236\266\346\236\204\350\257\264\346\230\216.md" "b/docs/\345\205\263\344\272\216IFoxCAD\347\232\204\346\236\266\346\236\204\350\257\264\346\230\216.md" index f96d39d..b282930 100644 --- "a/docs/\345\205\263\344\272\216IFoxCAD\347\232\204\346\236\266\346\236\204\350\257\264\346\230\216.md" +++ "b/docs/\345\205\263\344\272\216IFoxCAD\347\232\204\346\236\266\346\236\204\350\257\264\346\230\216.md" @@ -71,42 +71,26 @@ IFoxCAD是基于NFOX类库的重制版,主要是提供一个最小化的内核 ## 一、组织结构图 - IFoxCAD - - - IFoxCAD.Basal - cad以外常用的类库 - - - LinqEx - linq扩展类 - - - LoopList - 环链表 - - - IFoxCAD.Cad - cad相关的类库 - - - Runtime - 包含系统级别的功能 - - - AcadVersion - cad版本号类 - - AssemInfo - 程序集信息 - - AutoRegAssem - 程序集加载类型 - - DBTrans - 事务处理类 - - Env - 系统管理类 - - SymbolTable - 符号表类 - - - ExtensionMethod - 扩展函数,以Ex结尾 - - - SymbolTableEx - 符号表扩展类 - - SymbolTableRecordEx - 符号表记录扩展类 - - EntityEx - 实体扩展类 - - 。。。。。。 - - - ResultData - - - 待补充。。。 - - - SelectionFilter - - - 待补充。。。 - - - IFoxCAD.WPF - wpf的mvvm模式相关的类库 - - ## 二、关于DBTrans类的说明 +``` + ├───CADShared -- 共享项目,所有的代码都在这里 + │ ├───Basal -- 一些基础类的函数 + │ │ ├───General + │ │ ├───Nullable + │ │ └───Win + │ ├───ExtensionMethod -- 扩展函数 + │ │ ├───Entity + │ │ ├───Geomerty + │ │ └───Jig + │ ├───Initialize -- 初始化 + │ ├───ResultData -- 扩展数据 + │ ├───Runtime -- 核心类 + │ └───SelectionFilter -- 选择集过滤器类 + ├───docs -- 架构及api定义说明文档 + ├───IFoxCAD.AutoCad -- AutoCAD的类库,内部除了globalusing外无其他代码 + └───Test -- 测试类 + ``` + +## 二、关于DBTrans类的说明 ### 2.1 为什么要构建DBTrans类? @@ -128,17 +112,18 @@ DBTrans的每个实例都具有这些属性,而这些属性就对应于cad的 属性: -- Top ---返回当前事务 +- Top ---返回当前DBTrans对象 - Database ---数据库 - Document ---文档 - Editor ---命令行 -- Trans ---事务管理器 +- Transaction ---事务 构造函数: -- DBTrans(Document doc = null, bool commit = true) +- DBTrans(Document? doc = null, bool commit = true, bool docLock = false) - DBTrans(Database database, bool commit = true) -- DBTrans(string fileName, bool commit = true) +- DBTrans(string fileName, bool commit = true, FileOpenMode fileOpenMode = FileOpenMode.OpenForReadAndWriteNoShare, + string? password = null, bool activeOpen = false) 符号表: @@ -152,10 +137,27 @@ DBTrans的每个实例都具有这些属性,而这些属性就对应于cad的 - ViewTable 视图表 - ViewportTable 视口表 +字典: + +- NamedObjectsDict 命名对象字典 +- GroupDict 组字典 +- MLeaderStyleDict 多重引线样式字典 +- MLStyleDict 多线样式字典 +- MaterialDict 材质字典 +- TableStyleDict 表格样式字典 +- VisualStyleDict 视觉样式字典 +- ColorDict 颜色字典 +- PlotSettingsDict 打印设置字典 +- PlotStyleNameDict 打印样式表名字典 +- LayoutDict 布局字典 +- DataLinkDict 数据链接字典 +- DetailViewStyleDict 详细视图样式字典 +- SectionViewStyleDict 剖面视图样式字典 + 方法: - GetObject ---根据对象id获取图元对象 -- 。。。 +- Task 前台后台任务分别处理 接口: diff --git "a/docs/\345\205\263\344\272\216\346\211\251\345\261\225\345\207\275\346\225\260\347\232\204\350\257\264\346\230\216.md" "b/docs/\345\205\263\344\272\216\346\211\251\345\261\225\345\207\275\346\225\260\347\232\204\350\257\264\346\230\216.md" deleted file mode 100644 index 41d9336..0000000 --- "a/docs/\345\205\263\344\272\216\346\211\251\345\261\225\345\207\275\346\225\260\347\232\204\350\257\264\346\230\216.md" +++ /dev/null @@ -1,15 +0,0 @@ -# 关于扩展函数的说明 - -## 一、命名规则 - -扩展函数全部都放在 **ExtensionMethod** 文件夹里。 - -然后每个类别都需要分别建立一个以EX为结尾的文件。比如: - -DBObjectEx 实体对象扩展类 - -SymbolTableRecordEx 实体对象扩展类 - -EditorEx.cs 表示关于命令的扩展 - -![输入图片说明](https://images.gitee.com/uploads/images/2021/0701/225314_5b34dd8d_9063830.png "屏幕截图.png") diff --git a/README.md b/readme.md similarity index 96% rename from README.md rename to readme.md index f154371..1e9570c 100644 --- a/README.md +++ b/readme.md @@ -12,7 +12,7 @@ 可以加群交流: -![IFoxCad用户交流群群二维码](./docs/png/ifoxcad用户交流群群二维码.png) +[点击链接加入群聊【IFoxCad交流群】](https://qm.qq.com/q/tJZELgdzHi) **QQ群为丐群,所以也可以加入qq频道交流:** -- Gitee From a95e707f8c4f443384ca1d130ec5a11724bfeb15 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 25 Apr 2024 18:09:10 +0800 Subject: [PATCH 281/453] 1 --- CADShared/Runtime/IdleNoCommandAction.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/CADShared/Runtime/IdleNoCommandAction.cs b/CADShared/Runtime/IdleNoCommandAction.cs index 093eae6..fde2f52 100644 --- a/CADShared/Runtime/IdleNoCommandAction.cs +++ b/CADShared/Runtime/IdleNoCommandAction.cs @@ -52,18 +52,23 @@ private static void Acap_Idle(object sender, EventArgs e) Acap.Idle -= Acap_Idle; return; } + // 判断是否有活动的命令 if (Convert.ToBoolean(Acap.GetSystemVariable(CmdActiveName))) return; +#if RELEASE try { - // 执行委托 - _actions.Dequeue()?.Invoke(); +#endif + // 执行委托 + _actions.Dequeue()?.Invoke(); +#if RELEASE } catch { // 不进行操作 } +#endif System.Windows.Forms.Cursor.Position = System.Windows.Forms.Cursor.Position; } } \ No newline at end of file -- Gitee From b909f82529ece40bbf9ea7448b738b4fe22ebfa4 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sun, 28 Apr 2024 14:04:30 +0800 Subject: [PATCH 282/453] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=A4=9A=E4=BD=99?= =?UTF-8?q?=E7=9A=84=E9=94=99=E8=AF=AF=E6=B3=9B=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/ExtensionMethod/Entity/BlockReferenceEx.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CADShared/ExtensionMethod/Entity/BlockReferenceEx.cs b/CADShared/ExtensionMethod/Entity/BlockReferenceEx.cs index 7a4e91b..a7f0974 100644 --- a/CADShared/ExtensionMethod/Entity/BlockReferenceEx.cs +++ b/CADShared/ExtensionMethod/Entity/BlockReferenceEx.cs @@ -65,7 +65,7 @@ public static void XClip(this BlockReference brf, Point3d pt1, Point3d pt2) ///

    /// 更新动态块参数值 /// - public static bool ChangeBlockProperty(this BlockReference blockReference, + public static bool ChangeBlockProperty(this BlockReference blockReference, Dictionary propertyNameValues) { if (!blockReference.IsDynamicBlock) @@ -96,7 +96,7 @@ public static bool ChangeBlockProperty(this BlockReference blockReference, /// /// 更新动态块参数值 /// - public static bool ChangeBlockProperty(this BlockReference blockReference, + public static bool ChangeBlockProperty(this BlockReference blockReference, string propName, object value) { if (!blockReference.IsDynamicBlock) -- Gitee From c616a13298d47f33c058920f39eeabc27e0439f5 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 9 May 2024 14:10:02 +0800 Subject: [PATCH 283/453] =?UTF-8?q?=E5=85=B3=E9=94=AE=E5=AD=97=E5=85=8D?= =?UTF-8?q?=E5=9B=9E=E8=BD=A6=E6=96=B0=E5=A2=9E=E4=B8=80=E7=A7=8D=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/SingleKeyWordHook.cs | 42 +++++++++++++++---- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/CADShared/ExtensionMethod/SingleKeyWordHook.cs b/CADShared/ExtensionMethod/SingleKeyWordHook.cs index 1d2bb31..a40d6ab 100644 --- a/CADShared/ExtensionMethod/SingleKeyWordHook.cs +++ b/CADShared/ExtensionMethod/SingleKeyWordHook.cs @@ -8,6 +8,13 @@ namespace IFoxCAD.Cad; /// public sealed class SingleKeyWordHook : IDisposable { + #region 静态字段 + + private static readonly string _enterStr = Convert.ToChar(Keys.Enter).ToString(); + private static readonly string _backStr = Convert.ToChar(Keys.Back).ToString(); + + #endregion + #region 私有字段 /// @@ -18,7 +25,7 @@ public sealed class SingleKeyWordHook : IDisposable private bool _isResponsed; private bool _working; private Keys _key; - private readonly bool _escapeMode; + private readonly SingleKeyWordWorkType _workType; #endregion @@ -46,15 +53,15 @@ public sealed class SingleKeyWordHook : IDisposable /// /// 单字母关键字免输回车钩子 /// - /// 使用esc(填false则使用回车) - public SingleKeyWordHook(bool escapeMode = true) + /// 使用esc(填false则使用回车) + public SingleKeyWordHook(SingleKeyWordWorkType workType = SingleKeyWordWorkType.ESCAPE) { IsDisposed = false; _isResponsed = false; _keyWords = new HashSet(); _key = Keys.None; _working = true; - _escapeMode = escapeMode; + _workType = workType; Acap.PreTranslateMessage -= Acap_PreTranslateMessage; Acap.PreTranslateMessage += Acap_PreTranslateMessage; } @@ -79,7 +86,7 @@ public void AddKeys(KeywordCollection keywordCollection) { if (item.LocalName.Length == 1) { - Keys k = (Keys)item.LocalName[0]; + var k = (Keys)item.LocalName[0]; _keyWords.Add(k); } } @@ -132,7 +139,7 @@ private void Acap_PreTranslateMessage(object sender, PreTranslateMessageEventArg if (contains || tempKey == Keys.ProcessKey) { // 标记为true,表示此按键已经被处理,Windows不会再进行处理 - if (_escapeMode) + if (_workType != SingleKeyWordWorkType.ENTER) { e.Handled = true; } @@ -143,8 +150,19 @@ private void Acap_PreTranslateMessage(object sender, PreTranslateMessageEventArg { // 此bool是防止按键被长按时出错 _isResponsed = true; - // 这里选择发送回车或者ESC//ESC稳妥一些,但是要promptResult的判断顺序 - KeyBoardSendKey(_escapeMode ? Keys.Escape : Keys.Enter); + switch (_workType) + { + case SingleKeyWordWorkType.ESCAPE: + // ESC稳妥一些,但是要判断promptResult的顺序 + KeyBoardSendKey(Keys.Escape); + break; + case SingleKeyWordWorkType.ENTER: + KeyBoardSendKey(Keys.Enter); + break; + case SingleKeyWordWorkType.WRITE_LINE: + Utils.WriteToCommandLine(Convert.ToChar(_key) + _enterStr); + break; + } } } } @@ -183,6 +201,7 @@ private void Dispose(bool disposing) { Dispose(disposing: false); } + /// /// /// @@ -213,4 +232,11 @@ private static void KeyBoardSendKey(Keys key, byte bScan = 0, uint dwFlags = 0, private static extern void keybd_event(Keys bVk, byte bScan, uint dwFlags, uint dwExtraInfo); #endregion +} + +public enum SingleKeyWordWorkType : byte +{ + ESCAPE, + ENTER, + WRITE_LINE, } \ No newline at end of file -- Gitee From 3478ac1107f2b3f9eae76b6587d1ac07ca155d70 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 9 May 2024 15:15:04 +0800 Subject: [PATCH 284/453] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=B8=80=E7=A7=8D?= =?UTF-8?q?=E5=85=B3=E9=94=AE=E5=AD=97=E5=85=8D=E5=9B=9E=E8=BD=A6=E7=9A=84?= =?UTF-8?q?=E5=BF=AB=E6=8D=B7=E7=94=A8=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/ExtensionMethod/SingleKeyWordHook.cs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/CADShared/ExtensionMethod/SingleKeyWordHook.cs b/CADShared/ExtensionMethod/SingleKeyWordHook.cs index a40d6ab..c18a916 100644 --- a/CADShared/ExtensionMethod/SingleKeyWordHook.cs +++ b/CADShared/ExtensionMethod/SingleKeyWordHook.cs @@ -234,6 +234,22 @@ private static void KeyBoardSendKey(Keys key, byte bScan = 0, uint dwFlags = 0, #endregion } +public static class SingleKeywordHookEx +{ + /// + /// 钩取单文本关键字 + /// + /// 关键字集合 + /// 工作模式 + /// 单文本关键字类(需要using) + public static SingleKeyWordHook HookSingleKeyword(this KeywordCollection keywords, SingleKeyWordWorkType workType = SingleKeyWordWorkType.WRITE_LINE) + { + var singleKeyWordHook = new SingleKeyWordHook(workType); + singleKeyWordHook.AddKeys(keywords); + return singleKeyWordHook; + } +} + public enum SingleKeyWordWorkType : byte { ESCAPE, -- Gitee From 2c63244a9f12aa58effdb671d0abaf901ff0bf57 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 9 May 2024 16:40:53 +0800 Subject: [PATCH 285/453] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/ExtensionMethod/Entity/PolylineEx.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CADShared/ExtensionMethod/Entity/PolylineEx.cs b/CADShared/ExtensionMethod/Entity/PolylineEx.cs index 55b57ee..a2b97d6 100644 --- a/CADShared/ExtensionMethod/Entity/PolylineEx.cs +++ b/CADShared/ExtensionMethod/Entity/PolylineEx.cs @@ -146,7 +146,7 @@ public static Polyline CreatePolyline(this IEnumerable pointList, doubl /// 线宽 /// 是否闭合 /// Polyline - public static Polyline CreatePolyline(this IEnumerable pointList, double plineWidth = 0, bool closed = false) + public static Polyline ToPolyline(this IEnumerable pointList, double plineWidth = 0, bool closed = false) { var pl = new Polyline(); var enumerable = pointList.ToList(); -- Gitee From 1c88d74270d9d963c23f2be581acb4dd874f03ac Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 9 May 2024 16:41:58 +0800 Subject: [PATCH 286/453] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/ExtensionMethod/Entity/PolylineEx.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CADShared/ExtensionMethod/Entity/PolylineEx.cs b/CADShared/ExtensionMethod/Entity/PolylineEx.cs index a2b97d6..25a034a 100644 --- a/CADShared/ExtensionMethod/Entity/PolylineEx.cs +++ b/CADShared/ExtensionMethod/Entity/PolylineEx.cs @@ -126,7 +126,7 @@ public static Polyline CreatePolyline(this Extents3d points, Action? a /// 线宽 /// 是否闭合 /// Polyline - public static Polyline CreatePolyline(this IEnumerable pointList, double plineWidth = 0, bool closed = false) + public static Polyline ToPolyline(this IEnumerable pointList, double plineWidth = 0, bool closed = false) { var pl = new Polyline(); var enumerable = pointList.ToList(); -- Gitee From 33b56f5942c84def7d3513db3defcfe9433a0ce0 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Mon, 13 May 2024 16:28:26 +0800 Subject: [PATCH 287/453] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=94=99=E8=AF=AF?= =?UTF-8?q?=E7=9A=84=E6=96=B9=E6=B3=95=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/Runtime/Env.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CADShared/Runtime/Env.cs b/CADShared/Runtime/Env.cs index 009f3e4..05655ed 100644 --- a/CADShared/Runtime/Env.cs +++ b/CADShared/Runtime/Env.cs @@ -757,7 +757,7 @@ public static bool IsDxfVersion(this DwgVersion dwgVersion) /// 获取cad年份 /// /// 超出年份就报错 - public static int GetAcadVersion() + public static int GetAcadYear() { var ver = Acaop.Version.Major + "." + Acaop.Version.Minor; var acadVersion = ver switch @@ -781,6 +781,7 @@ public static int GetAcadVersion() "24.1" => 2022, "24.2" => 2023, "24.3" => 2024, + "25.0" => 2025, _ => throw new NotImplementedException() }; return acadVersion; -- Gitee From 850ec916ff7ba623f944d7c93c918b066e80e781 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Mon, 13 May 2024 16:33:12 +0800 Subject: [PATCH 288/453] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=81=87=E5=88=B0?= =?UTF-8?q?=E9=9D=9Eacad=E8=87=AA=E5=AE=9A=E4=B9=89=E7=9A=84dimblk?= =?UTF-8?q?=E6=97=B6=E9=80=A0=E6=88=90=E7=9A=84=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/Runtime/Env.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CADShared/Runtime/Env.cs b/CADShared/Runtime/Env.cs index 05655ed..967c0b0 100644 --- a/CADShared/Runtime/Env.cs +++ b/CADShared/Runtime/Env.cs @@ -309,10 +309,10 @@ public static string GetDimblkName(DimblkType dimblk) /// 箭头ID public static ObjectId GetDimblkId(DimblkType dimblk) { - var oldDimblk = Dimblk; + var oldDimblk = Acaop.GetSystemVariable("dimblk"); Dimblk = dimblk; var id = HostApplicationServices.WorkingDatabase.Dimblk; - Dimblk = oldDimblk; + Acaop.SetSystemVariable("dimblk",oldDimblk); return id; } -- Gitee From f1c0584e997b307d7b83d2d98f6e1ec38d3a951e Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Tue, 14 May 2024 12:10:24 +0800 Subject: [PATCH 289/453] =?UTF-8?q?PrepareForJig=E7=9A=84=E9=A2=9C?= =?UTF-8?q?=E8=89=B2=E4=BD=BF=E7=94=A8=E6=9C=AC=E8=89=B2=EF=BC=8C=E9=98=B2?= =?UTF-8?q?=E6=AD=A2=E5=A4=B1=E7=9C=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/ExtensionMethod/EditorEx.cs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/CADShared/ExtensionMethod/EditorEx.cs b/CADShared/ExtensionMethod/EditorEx.cs index ad36df9..9219c6b 100644 --- a/CADShared/ExtensionMethod/EditorEx.cs +++ b/CADShared/ExtensionMethod/EditorEx.cs @@ -1135,19 +1135,26 @@ public static void PrepareForJig(this Editor ed, params Entity[] ents) /// 实体(已存在数据库中) public static void PrepareForJig(this Editor ed, IEnumerable ents) { - var dic = new Dictionary(); + var dic = new Dictionary(); foreach (var ent in ents) { if (ent.IsNewObject) continue; - dic.Add(ent, ent.ColorIndex); - ent.ColorIndex = 250; - ent.Draw(); + dic.Add(ent, ent.Color); + using (ent.ForWrite()) + { + ent.ColorIndex = 250; + ent.Draw(); + } } ed.Redraw(); foreach (var kvp in dic) { - kvp.Key.ColorIndex = kvp.Value; + var ent = kvp.Key; + using (ent.ForWrite()) + { + kvp.Key.Color = kvp.Value; + } } } #endregion -- Gitee From 0018b382920ea1ae40a2064973656815cd5569c1 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Tue, 14 May 2024 14:37:14 +0800 Subject: [PATCH 290/453] =?UTF-8?q?=E7=BB=9F=E4=B8=80=E7=AC=A6=E5=8F=B7?= =?UTF-8?q?=E8=A1=A8=E7=9A=84=E5=88=A0=E9=99=A4=E6=93=8D=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/Runtime/SymbolTable.cs | 96 ++++++++++++++++++++++---------- 1 file changed, 68 insertions(+), 28 deletions(-) diff --git a/CADShared/Runtime/SymbolTable.cs b/CADShared/Runtime/SymbolTable.cs index 632a05c..6ee557d 100644 --- a/CADShared/Runtime/SymbolTable.cs +++ b/CADShared/Runtime/SymbolTable.cs @@ -1,5 +1,7 @@ // ReSharper disable RedundantNameQualifier + namespace IFoxCAD.Cad; + /// /// 符号表管理类 /// @@ -10,10 +12,12 @@ public class SymbolTable : IEnumerable where TRecord : SymbolTableRecord, new() { #region 程序集内部属性 + /// /// 事务管理器 /// private DBTrans DTrans { get; set; } + /// /// 数据库 /// @@ -22,13 +26,16 @@ public class SymbolTable : IEnumerable #endregion #region 公开属性 + /// /// 当前符号表 /// public TTable CurrentSymbolTable { get; private set; } + #endregion #region 构造函数 + /// /// 构造函数,初始化Trans和CurrentSymbolTable属性 /// @@ -56,6 +63,7 @@ internal SymbolTable(DBTrans tr, ObjectId tableId, bool defaultBehavior = true) #endregion #region 索引器 + /// /// 索引器 /// @@ -66,6 +74,7 @@ internal SymbolTable(DBTrans tr, ObjectId tableId, bool defaultBehavior = true) #endregion #region Has + /// /// 判断是否存在符号表记录 /// @@ -75,6 +84,7 @@ public bool Has(string key) { return CurrentSymbolTable.Has(key); } + /// /// 判断是否存在符号表记录 /// @@ -84,9 +94,11 @@ public bool Has(ObjectId objectId) { return CurrentSymbolTable.Has(objectId); } + #endregion #region 添加符号表记录 + /// /// 添加符号表记录 /// @@ -100,8 +112,10 @@ public ObjectId Add(TRecord record) id = CurrentSymbolTable.Add(record); DTrans.Transaction.AddNewlyCreatedDBObject(record, true); } + return id; } + /// /// 添加符号表记录 /// @@ -121,9 +135,11 @@ public ObjectId Add(string name, Action? action = null) action?.Invoke(record); return id; } + #endregion #region 删除符号表记录 + /// /// 删除符号表记录 /// @@ -140,6 +156,22 @@ private static void Remove(TRecord record) /// 符号表记录名 public void Remove(string name) { + if (CurrentSymbolTable is LayerTable lt) + { + if (SymbolUtilityServices.IsLayerZeroName(name) + || SymbolUtilityServices.IsLayerDefpointsName(name)) + return; + lt.GenerateUsageData(); + if (GetRecord(name) is not LayerTableRecord { IsUsed: false } ltr) + return; + using (ltr.ForWrite()) + { + ltr.Erase(); + } + + return; + } + var record = GetRecord(name); if (record is not null) Remove(record); @@ -155,9 +187,11 @@ public void Remove(ObjectId id) if (record is not null) Remove(record); } + #endregion #region 修改符号表记录 + /// /// 修改符号表 /// @@ -189,9 +223,11 @@ public void Change(ObjectId id, Action action) action.Invoke(record); } } + #endregion #region 获取符号表记录 + /// /// 获取符号表记录 /// @@ -202,9 +238,9 @@ public void Change(ObjectId id, Action action) /// 符号表记录 [System.Diagnostics.DebuggerStepThrough] public TRecord? GetRecord(ObjectId id, - OpenMode openMode = OpenMode.ForRead, - bool openErased = false, - bool openLockedLayer = false) + OpenMode openMode = OpenMode.ForRead, + bool openErased = false, + bool openLockedLayer = false) { return DTrans.GetObject(id, openMode, openErased, openLockedLayer); } @@ -219,9 +255,9 @@ public void Change(ObjectId id, Action action) /// 符号表记录 [System.Diagnostics.DebuggerStepThrough] public TRecord? GetRecord(string name, - OpenMode openMode = OpenMode.ForRead, - bool openErased = false, - bool openLockedLayer = false) + OpenMode openMode = OpenMode.ForRead, + bool openErased = false, + bool openLockedLayer = false) { return GetRecord(this[name], openMode, openErased, openLockedLayer); } @@ -298,16 +334,18 @@ private ObjectId GetRecordFrom(SymbolTable table, string name, /// 是否覆盖, 为覆盖, 为不覆盖 /// 对象id internal ObjectId GetRecordFrom(Func> tableSelector, - string fileName, - string name, - bool over) + string fileName, + string name, + bool over) { using DBTrans tr = new(fileName); return GetRecordFrom(tableSelector(tr), name, over); } + #endregion #region 遍历 + #line hidden // 调试的时候跳过它 /// RecordGraphicsModified = 1, + /// /// 标注更新 /// RecomputeDimensionBlock = 2, + /// /// 重画 /// Draw = 4, + /// /// 亮显 /// Highlight = 8, + /// /// 亮显取消 /// Unhighlight = 16, + /// /// 显示图元 /// VisibleTrue = 32, + /// /// 隐藏图元 /// VisibleFalse = 64, + /// /// 平移更新,可以令ctrl+z撤回时候保证刷新 /// MoveZero = 128, } + /// /// 刷新模式 /// @@ -48,23 +57,28 @@ public enum BrightEditor /// 刷新屏幕,图元不生成(例如块还是旧的显示) /// UpdateScreen = 1, + /// /// 刷新全图 /// Regen = 2, + /// /// 清空选择集 /// SelectionClean = 4, + /// /// 视口外 /// ViewportsFrom = 8, + /// /// 视口内 /// ViewportsIn = 16, } + /// /// 重绘扩展 /// @@ -87,7 +101,7 @@ public static void Redraw(this Editor ed, Entity? ent = null) // 刷新 ed.Redraw(BrightEditor.UpdateScreen); } - + /* * 我发现命令加 CommandFlags.Redraw 就不需要以下处理了: @@ -127,7 +141,8 @@ public static void Redraw(this Editor ed, BrightEditor bright) ed.Regen(); if ((bright & BrightEditor.SelectionClean) == BrightEditor.SelectionClean) - ed.SetImpliedSelection([]); + // ReSharper disable once UseCollectionExpression + ed.SetImpliedSelection(new ObjectId[0]); if ((bright & BrightEditor.ViewportsFrom) == BrightEditor.ViewportsFrom) ed.UpdateTiledViewportsFromDatabase(); // 更新视口外 @@ -177,6 +192,7 @@ public static void Redraw(this Entity ent, BrightEntity bright) #region 实体刷新 + /// /// 刷新实体显示 /// @@ -196,5 +212,6 @@ public static void Flush(this Entity entity) /// 实体id [Obsolete("此处已经被RedrawEx代替")] public static void Flush(this ObjectId id) => Flush(id.GetObject()!); + #endregion } \ No newline at end of file -- Gitee From eaf824b3977bb771ffd79dcda08762ccd11a89a9 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sun, 20 Oct 2024 22:00:58 +0800 Subject: [PATCH 332/453] =?UTF-8?q?0.9.1=E5=8F=91nuget=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj b/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj index 55a1de2..5665e87 100644 --- a/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj +++ b/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj @@ -17,7 +17,7 @@ IFox.CAD.ACAD IFox.CAD.ACAD IFox.CAD.ACAD - 0.9.0 + 0.9.1 xsfhlzh, vicwjb, liuqihong, DYH 基于.NET的二次开发基本类库. https://www.nuget.org/packages/IFox.CAD.ACAD/ @@ -26,7 +26,7 @@ IFox,Cad,AutoCad,C#,NET, InspireFunction readme.md - 普通包更新至0.9,修改部分api优化代码 + 补充四叉树、填充、文字、等扩展 LICENSE -- Gitee From ff46cc6a163d0dff00c2461dbdda450188975d92 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Tue, 22 Oct 2024 23:27:11 +0800 Subject: [PATCH 333/453] =?UTF-8?q?=E8=A1=A5=E5=85=85AddOrChange=E6=96=B9?= =?UTF-8?q?=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/Runtime/SymbolTable.cs | 72 ++++++++++++++++---------------- 1 file changed, 35 insertions(+), 37 deletions(-) diff --git a/CADShared/Runtime/SymbolTable.cs b/CADShared/Runtime/SymbolTable.cs index 4e4e15e..aef1d3c 100644 --- a/CADShared/Runtime/SymbolTable.cs +++ b/CADShared/Runtime/SymbolTable.cs @@ -7,8 +7,7 @@ namespace IFoxCAD.Cad; /// /// 符号表 /// 符号表记录 -public class SymbolTable : IEnumerable - where TTable : SymbolTable +public class SymbolTable : IEnumerable where TTable : SymbolTable where TRecord : SymbolTableRecord, new() { #region 程序集内部属性 @@ -126,16 +125,34 @@ public ObjectId Add(string name, Action? action = null) { var id = this[name]; if (!id.IsNull) return id; - var record = new TRecord() - { - Name = name - }; + var record = new TRecord() { Name = name }; id = Add(record); using (record.ForWrite()) action?.Invoke(record); return id; } + /// + /// 有则修改无则添加符号表记录 + /// + /// 符号表记录名 + /// 符号表记录处理函数的无返回值委托 + /// 对象id + public ObjectId AddOrChange(string name, Action action) + { + var id = this[name]; + if (id.IsNull) + { + id = Add(name, action); + } + else + { + Change(name, action); + } + + return id; + } + #endregion #region 删除符号表记录 @@ -158,8 +175,8 @@ public void Remove(string name) { if (CurrentSymbolTable is LayerTable lt) { - if (SymbolUtilityServices.IsLayerZeroName(name) - || SymbolUtilityServices.IsLayerDefpointsName(name)) + if (SymbolUtilityServices.IsLayerZeroName(name) || + SymbolUtilityServices.IsLayerDefpointsName(name)) return; lt.GenerateUsageData(); if (GetRecord(name) is not LayerTableRecord { IsUsed: false } ltr) @@ -237,9 +254,7 @@ public void Change(ObjectId id, Action action) /// 是否打开锁定图层对象,默认为不打开 /// 符号表记录 [System.Diagnostics.DebuggerStepThrough] - public TRecord? GetRecord(ObjectId id, - OpenMode openMode = OpenMode.ForRead, - bool openErased = false, + public TRecord? GetRecord(ObjectId id, OpenMode openMode = OpenMode.ForRead, bool openErased = false, bool openLockedLayer = false) { return DTrans.GetObject(id, openMode, openErased, openLockedLayer); @@ -254,9 +269,7 @@ public void Change(ObjectId id, Action action) /// 是否打开锁定图层对象,默认为不打开 /// 符号表记录 [System.Diagnostics.DebuggerStepThrough] - public TRecord? GetRecord(string name, - OpenMode openMode = OpenMode.ForRead, - bool openErased = false, + public TRecord? GetRecord(string name, OpenMode openMode = OpenMode.ForRead, bool openErased = false, bool openLockedLayer = false) { return GetRecord(this[name], openMode, openErased, openLockedLayer); @@ -315,11 +328,7 @@ private ObjectId GetRecordFrom(SymbolTable table, string name, using IdMapping map = new(); using ObjectIdCollection ids = new(); ids.Add(id); - table.Database.WblockCloneObjects( - ids, - CurrentSymbolTable.Id, - map, - DuplicateRecordCloning.Replace, + table.Database.WblockCloneObjects(ids, CurrentSymbolTable.Id, map, DuplicateRecordCloning.Replace, false); rid = map[id].Value; return rid; @@ -334,9 +343,7 @@ private ObjectId GetRecordFrom(SymbolTable table, string name, /// 是否覆盖, 为覆盖, 为不覆盖 /// 对象id internal ObjectId GetRecordFrom(Func> tableSelector, - string fileName, - string name, - bool over) + string fileName, string name, bool over) { using DBTrans tr = new(fileName); return GetRecordFrom(tableSelector(tr), name, over); @@ -355,11 +362,8 @@ internal ObjectId GetRecordFrom(Func> tabl /// 检查id是否删除,默认true /// 是否打开已删除对象,默认为不打开 /// 是否打开锁定图层对象,默认为不打开 - public void ForEach(Action task, - OpenMode openMode = OpenMode.ForRead, - bool checkIdOk = true, - bool openErased = false, - bool openLockedLayer = false) + public void ForEach(Action task, OpenMode openMode = OpenMode.ForRead, bool checkIdOk = true, + bool openErased = false, bool openLockedLayer = false) { ForEach((a, _, _) => { @@ -375,11 +379,8 @@ public void ForEach(Action task, /// 检查id是否删除,默认true /// 是否打开已删除对象,默认为不打开 /// 是否打开锁定图层对象,默认为不打开 - public void ForEach(Action task, - OpenMode openMode = OpenMode.ForRead, - bool checkIdOk = true, - bool openErased = false, - bool openLockedLayer = false) + public void ForEach(Action task, OpenMode openMode = OpenMode.ForRead, + bool checkIdOk = true, bool openErased = false, bool openLockedLayer = false) { ForEach((a, b, _) => { task.Invoke(a, b); }, openMode, checkIdOk, openErased, openLockedLayer); } @@ -393,11 +394,8 @@ public void ForEach(Action task, /// 是否打开已删除对象,默认为不打开 /// 是否打开锁定图层对象,默认为不打开 [System.Diagnostics.DebuggerStepThrough] - public void ForEach(Action task, - OpenMode openMode = OpenMode.ForRead, - bool checkIdOk = true, - bool openErased = false, - bool openLockedLayer = false) + public void ForEach(Action task, OpenMode openMode = OpenMode.ForRead, + bool checkIdOk = true, bool openErased = false, bool openLockedLayer = false) { //if (task == null) // throw new ArgumentNullException(nameof(task)); -- Gitee From 71ad4469509c3bd7961dddc5bb07617246922cc6 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Tue, 22 Oct 2024 23:41:49 +0800 Subject: [PATCH 334/453] =?UTF-8?q?=E5=8F=91=E5=8C=850.9.1.1=20=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E7=AC=A6=E5=8F=B7=E8=A1=A8AddOrChange=E5=87=BD?= =?UTF-8?q?=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj | 44 +++++++++++++------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj b/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj index 5665e87..180b2d5 100644 --- a/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj +++ b/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj @@ -10,23 +10,23 @@ true true - + true IFox.CAD.ACAD - IFox.CAD.ACAD - IFox.CAD.ACAD - 0.9.1 - xsfhlzh, vicwjb, liuqihong, DYH - 基于.NET的二次开发基本类库. - https://www.nuget.org/packages/IFox.CAD.ACAD/ - https://gitee.com/inspirefunction/ifoxcad - git - IFox,Cad,AutoCad,C#,NET, + IFox.CAD.ACAD + IFox.CAD.ACAD + 0.9.1.1 + xsfhlzh, vicwjb, liuqihong, DYH + 基于.NET的二次开发基本类库. + https://www.nuget.org/packages/IFox.CAD.ACAD/ + https://gitee.com/inspirefunction/ifoxcad + git + IFox,Cad,AutoCad,C#,NET, InspireFunction readme.md - 补充四叉树、填充、文字、等扩展 + 增加符号表AddOrChange函数 LICENSE @@ -43,27 +43,27 @@ - - True - \ - - - True - \ - + + True + \ + + + True + \ + - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + - + -- Gitee From 8921a4d001032ce808f0fbbd86dd568f7f72d525 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Tue, 22 Oct 2024 23:50:11 +0800 Subject: [PATCH 335/453] =?UTF-8?q?=E8=A1=A5=E5=85=85=E9=9A=8F=E6=9C=BA?= =?UTF-8?q?=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/CADShared.projitems | 1 + CADShared/ExtensionMethod/RandomEx.cs | 208 ++++++++++++++++++++++++++ IFoxCAD.sln.DotSettings | 3 +- Test/Tools.cs | 25 ++-- 4 files changed, 224 insertions(+), 13 deletions(-) create mode 100644 CADShared/ExtensionMethod/RandomEx.cs diff --git a/CADShared/CADShared.projitems b/CADShared/CADShared.projitems index 7ff0f7e..46532fd 100644 --- a/CADShared/CADShared.projitems +++ b/CADShared/CADShared.projitems @@ -59,6 +59,7 @@ + diff --git a/CADShared/ExtensionMethod/RandomEx.cs b/CADShared/ExtensionMethod/RandomEx.cs new file mode 100644 index 0000000..cf24538 --- /dev/null +++ b/CADShared/ExtensionMethod/RandomEx.cs @@ -0,0 +1,208 @@ +/* + *┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━模块信息━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ + *┃ 作 者:YxrWendao + *┃ 创建时间:2022/8/30 22:49:30 + *┃ 模块描述:随机数生成器 + *┃ 使用范围:通用 + *┃ 说 明:本模块中除GetRandom与NextColor方法是IFoxCAD原有的以外,其他方法均通过网络收集整理而来。 + *┃ 代码版本:1.0 + *┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ + */ + +namespace IFoxCAD.Basal; + +/// +/// 随机值扩展类 +/// +public static class RandomEx +{ + /// + /// 生成一个指定范围的浮点数值
    + /// 相关链接 + ///
    + /// 一个随机值产生器 + /// 范围最小浮点数值 + /// 范围最大浮点数值 + /// + public static double NextDouble(Random ran, double minValue, double maxValue) + { + return ran.NextDouble() * (maxValue - minValue) + minValue; + } + + /// + /// 生成一个指定范围的浮点数值 + /// + /// 范围最小浮点数值 + /// 范围最大浮点数值 + /// + public static double NextDouble(double minValue, double maxValue) + { + return NextDouble(GetRandom(), minValue, maxValue); + } + + /// + /// 生成一个布尔随机数 + /// + /// + public static bool NextBool() + { + return NextBool(GetRandom()); + } + + /// + /// 生成一个布尔随机数
    + ///
    + /// + public static bool NextBool(Random ran) + { + bool[] arr = [true, false]; + return arr[ran.Next(2)]; + } + + /// + /// 生成一个不连续或指定值的随机值 + /// + /// 一个字符串数组 + /// + public static string NextString(string[] arr) + { + return NextString(GetRandom(), arr); + } + + /// + /// 生成一个不连续或指定值的随机值 + /// + /// 一个随机值产生器 + /// 一个字符串数组 + /// + public static string NextString(Random ran, string[] arr) + { + var n = ran.Next(arr.Length - 1); + return arr[n]; + } + + /// + /// 生成一个不连续或指定值的随机值 + /// + /// 一个双精度值数组 + /// + public static double NextDouble(double[] arr) + { + return NextDouble(GetRandom(), arr); + } + + /// + /// 生成不连续或指定值的随机值 + /// + /// 一个随机值产生器 + /// 一个双精度值数组 + /// + public static double NextDouble(Random ran, double[] arr) + { + var n = ran.Next(arr.Length - 1); + return arr[n]; + } + + /// + /// 生成指定范围内的整数 + /// + /// 范围最大整数值 + /// + public static int NextInt(int max) + { + return NextInt(GetRandom(), max); + } + + /// + /// 生成指定范围内的整数 + /// + /// 一个随机值产生器 + /// 范围最大整数值 + /// + public static int NextInt(Random ran, int max) + { + return ran.Next(max); + } + + /// + /// 生成指定范围内的整数 + /// + /// 范围的最小整数 + /// 范围的最大整数 + /// 返回一个介于之间的整数 + public static int NextInt(int min, int max) + { + return NextInt(GetRandom(), min, max); + } + + /// + /// 生成指定范围内的整数 + /// + /// 一个随机值产生器 + /// 范围的最小整数 + /// 范围的最大整数 + /// 返回一个介于之间的整数 + public static int NextInt(Random ran, int min, int max) + { + return ran.Next(min, max); + } + + /// + /// 生成一个随机颜色 + /// + /// 返回 + public static System.Drawing.Color NextColor() + { + return NextColor(GetRandom()); + } + + /// + /// 生成一个随机颜色 + /// + /// + public static System.Drawing.Color NextColor(Random ran) + { + var r = ran.Next(255); + var g = ran.Next(255); + var b = ran.Next(255); + b = (r + g > 400) ? r + g - 400 : b; // 0 : 380 - R - G; + b = (b > 255) ? 255 : b; + return System.Drawing.Color.FromArgb(r, g, b); + } + + + /* + * 知识准备: + * | 高位64位 | 低位32位 | + * Convert.ToString(int.MaxValue, 2)输出二进制 "1111111111111111111111111111111" 31个;最高位是符号位,所以少1位 + * Convert.ToString(long.MaxValue,2)输出二进制,刚好长一倍 "11111111111111111111111111111111 1111111111111111111111111111111" 63个;最高位是符号位,所以少1位 + * Convert.ToString(0xffffffffL, 2)int.MaxValue再按位多1 "1 1111111111111111111111111111111" 32个;前面的0不会打印出来 + * + * Convert.ToString(long.MaxValue>>32, 2)相当于平移高位的到低位范围,也就是上面少打印的二进制 + * 验证右移是不是高位保留,答案是 + * var a = Convert.ToInt64("101111111111111111111111111111111111111111111111111111111111111", 2); + * Convert.ToString(a >> 32,2); + * + * 解释代码: + * 0x01: + * (int)(long.MaxValue & 0xffffffffL) | (int)(long.MaxValue >> 32); + * Convert.ToString(long.MaxValue & 0xffffffffL, 2)// 去掉高位:"11111111111111111111111111111111" 32个,再强转int + * 按位与&是保证符号位肯定是1,其他尽可能为0,高位被去掉只是MaxValue&0的原因,强转才是去掉高位..."尽可能"一词带来第一次随机性 + * 0x02: + * Convert.ToString((long.MaxValue >> 32), 2) // 去掉低位: "1111111111111111111111111111111" 31个,再强转int + * 按位或|是尽可能为1..."尽可能"一词带来第二次随机性 + * + */ + + /// + /// 带有随机种子的随机数
    + /// 为什么这样写随机种子呢 + ///
    + /// + public static Random GetRandom() + { + var tick = DateTime.Now.Ticks; + var tickSeeds = (int)(tick & 0xffffffffL) | (int)(tick >> 32); + return new Random(tickSeeds); + } +} \ No newline at end of file diff --git a/IFoxCAD.sln.DotSettings b/IFoxCAD.sln.DotSettings index 916f197..5dc555a 100644 --- a/IFoxCAD.sln.DotSettings +++ b/IFoxCAD.sln.DotSettings @@ -17,4 +17,5 @@ True True True - True \ No newline at end of file + True + True \ No newline at end of file diff --git a/Test/Tools.cs b/Test/Tools.cs index cff5937..4a9eefa 100644 --- a/Test/Tools.cs +++ b/Test/Tools.cs @@ -2,7 +2,6 @@ public static class Tools { - /// /// 计时器 /// @@ -10,10 +9,10 @@ public static class Tools public static void TestTimes2(int count, string message, Action action) { System.Diagnostics.Stopwatch watch = new(); - watch.Start(); // 开始监视代码运行时间 + watch.Start(); // 开始监视代码运行时间 for (var i = 0; i < count; i++) - action.Invoke();// 需要测试的代码 - watch.Stop(); // 停止监视 + action.Invoke(); // 需要测试的代码 + watch.Stop(); // 停止监视 var timespan = watch.Elapsed; // 获取当前实例测量得出的总时间 var time = timespan.TotalMilliseconds; var name = "毫秒"; @@ -22,7 +21,8 @@ public static void TestTimes2(int count, string message, Action action) time = timespan.TotalSeconds; name = "秒"; } - Env.Print($"{message} 代码执行 {count} 次的时间:{time} ({name})"); // 总毫秒数 + + $"{message} 代码执行 {count} 次的时间:{time} ({name})".Print(); // 总毫秒数 } /// @@ -32,10 +32,10 @@ public static void TestTimes2(int count, string message, Action action) public static void TestTimes3(int count, string message, Action action) { System.Diagnostics.Stopwatch watch = new(); - watch.Start(); // 开始监视代码运行时间 + watch.Start(); // 开始监视代码运行时间 for (var i = 0; i < count; i++) - action.Invoke(i);// 需要测试的代码 - watch.Stop(); // 停止监视 + action.Invoke(i); // 需要测试的代码 + watch.Stop(); // 停止监视 var timespan = watch.Elapsed; // 获取当前实例测量得出的总时间 var time = timespan.TotalMilliseconds; var name = "毫秒"; @@ -44,9 +44,9 @@ public static void TestTimes3(int count, string message, Action action) time = timespan.TotalSeconds; name = "秒"; } - Env.Print($"{message} 代码执行 {count} 次的时间:{time} ({name})"); // 总毫秒数 - } + $"{message} 代码执行 {count} 次的时间:{time} ({name})".Print(); // 总毫秒数 + } /// @@ -56,7 +56,8 @@ public static void TestTimes3(int count, string message, Action action) public static void TestTimes(int count, string message, Action action, Timer.TimeEnum timeEnum = Timer.TimeEnum.Millisecond) { - var time = Timer.RunTime(() => { + var time = Timer.RunTime(() => + { for (var i = 0; i < count; i++) action.Invoke(); }, timeEnum); @@ -69,6 +70,6 @@ public static void TestTimes(int count, string message, Action action, _ => " 秒" }; - Env.Print($"{message} 代码执行 {count} 次的时间:{time} ({timeNameZn})"); + $"{message} 代码执行 {count} 次的时间:{time} ({timeNameZn})".Print(); } } \ No newline at end of file -- Gitee From eb8efa54305ac987b090028747fdd60ae75785de Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Wed, 23 Oct 2024 00:23:01 +0800 Subject: [PATCH 336/453] =?UTF-8?q?=E8=A1=A5=E5=85=85=E9=9A=8F=E6=9C=BA?= =?UTF-8?q?=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj b/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj index 180b2d5..20950c1 100644 --- a/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj +++ b/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj @@ -17,7 +17,7 @@ IFox.CAD.ACAD IFox.CAD.ACAD IFox.CAD.ACAD - 0.9.1.1 + 0.9.1.2 xsfhlzh, vicwjb, liuqihong, DYH 基于.NET的二次开发基本类库. https://www.nuget.org/packages/IFox.CAD.ACAD/ @@ -26,7 +26,7 @@ IFox,Cad,AutoCad,C#,NET, InspireFunction readme.md - 增加符号表AddOrChange函数 + 补充随机数扩展 LICENSE -- Gitee From 1c148e28f60f904e07fbaec76eb6a7cdd14a4fe9 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Wed, 23 Oct 2024 00:24:59 +0800 Subject: [PATCH 337/453] =?UTF-8?q?=E6=97=A5=E5=B8=B8=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Test/Test.csproj | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Test/Test.csproj b/Test/Test.csproj index c110209..9ffaa05 100644 --- a/Test/Test.csproj +++ b/Test/Test.csproj @@ -7,6 +7,14 @@ enable + + x64 + + + + x64 + + -- Gitee From 1a419d2f580eaf9692a73e5eb53daca60e121297 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Wed, 23 Oct 2024 11:05:43 +0800 Subject: [PATCH 338/453] =?UTF-8?q?=E8=A1=A5=E5=85=85AcPreferences?= =?UTF-8?q?=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/CADShared.projitems | 1 + CADShared/Runtime/AcPreferences.cs | 302 +++++++++++++++++++++++++++++ 2 files changed, 303 insertions(+) create mode 100644 CADShared/Runtime/AcPreferences.cs diff --git a/CADShared/CADShared.projitems b/CADShared/CADShared.projitems index 7ff0f7e..ba1c390 100644 --- a/CADShared/CADShared.projitems +++ b/CADShared/CADShared.projitems @@ -87,6 +87,7 @@ + diff --git a/CADShared/Runtime/AcPreferences.cs b/CADShared/Runtime/AcPreferences.cs new file mode 100644 index 0000000..4fe234a --- /dev/null +++ b/CADShared/Runtime/AcPreferences.cs @@ -0,0 +1,302 @@ +namespace IFoxCAD.Cad; + +public static class AcPreferences +{ + public static class Display + { + static Display() + { + dynamic preferences = Acap.Preferences; + _acadDisplay = preferences.Display; + } + + private static readonly dynamic _acadDisplay; + + /// + /// 布局显示边距 + /// + public static bool LayoutDisplayMargins + { + get => _acadDisplay.LayoutDisplayMargins; + set => _acadDisplay.LayoutDisplayMargins = value; + } + + /// + /// 布局显示纸 + /// + public static bool LayoutDisplayPaper + { + get => _acadDisplay.LayoutDisplayPaper; + set => _acadDisplay.LayoutDisplayPaper = value; + } + + /// + /// 布局显示纸张阴影 + /// + public static bool LayoutDisplayPaperShadow + { + get => _acadDisplay.LayoutDisplayPaperShadow; + set => _acadDisplay.LayoutDisplayPaperShadow = value; + } + + /// + /// 布局显示绘图设置 + /// + public static bool LayoutShowPlotSetup + { + get => _acadDisplay.LayoutShowPlotSetup; + set => _acadDisplay.LayoutShowPlotSetup = value; + } + + /// + /// 布局创建视口 + /// + public static bool LayoutCreateViewport + { + get => _acadDisplay.LayoutCreateViewport; + set => _acadDisplay.LayoutCreateViewport = value; + } + + /// + /// 显示滚动条 + /// + public static bool DisplayScrollBars + { + get => _acadDisplay.DisplayScrollBars; + set => _acadDisplay.DisplayScrollBars = value; + } + + /// + /// 显示屏幕菜单 + /// + public static bool DisplayScreenMenu + { + get => _acadDisplay.DisplayScreenMenu; + set => _acadDisplay.DisplayScreenMenu = value; + } + + /// + /// 使用光标十字的大小 + /// + public static int CursorSize + { + get => _acadDisplay.CursorSize; + set => _acadDisplay.CursorSize = value; + } + + /// + /// 停靠的可见线 + /// + public static int DockedVisibleLines + { + get => _acadDisplay.DockedVisibleLines; + set => _acadDisplay.DockedVisibleLines = value; + } + + /// + /// 显示光栅图像 + /// + public static bool ShowRasterImage + { + get => _acadDisplay.ShowRasterImage; + set => _acadDisplay.ShowRasterImage = value; + } + + /// + /// 模型空间背景颜色 + /// + public static Color GraphicsWinModelBackgrndColor + { + get + { + uint color = _acadDisplay.GraphicsWinModelBackgrndColor; + return UIntToColor(color); + } + set + { + var color = ColorToUInt(value); + _acadDisplay.GraphicsWinModelBackgrndColor = color; + } + } + + /// + /// 命令栏win文本背景颜色 + /// + public static Color TextWinBackgrndColor + { + get + { + uint color = _acadDisplay.TextWinBackgrndColor; + return UIntToColor(color); + } + set + { + var color = ColorToUInt(value); + _acadDisplay.TextWinBackgrndColor = color; + } + } + + /// + /// 命令栏win文本字体颜色 + /// + public static Color TextWinTextColor + { + get + { + uint color = _acadDisplay.TextWinTextColor; + return UIntToColor(color); + } + set + { + var color = ColorToUInt(value); + _acadDisplay.TextWinTextColor = color; + } + } + + /// + /// 模型鼠标十字颜色 + /// + public static Color ModelCrosshairColor + { + get + { + uint color = _acadDisplay.ModelCrosshairColor; + return UIntToColor(color); + } + set + { + var color = ColorToUInt(value); + _acadDisplay.ModelCrosshairColor = color; + } + } + + /// + /// 布局鼠标十字颜色 + /// + public static Color LayoutCrosshairColor + { + get + { + uint color = _acadDisplay.LayoutCrosshairColor; + return UIntToColor(color); + } + set + { + var color = ColorToUInt(value); + _acadDisplay.LayoutCrosshairColor = color; + } + } + + /// + /// 自动跟踪VEC颜色 + /// + public static Color AutoTrackingVecColor + { + get + { + uint color = _acadDisplay.AutoTrackingVecColor; + return UIntToColor(color); + } + set + { + var color = ColorToUInt(value); + _acadDisplay.AutoTrackingVecColor = color; + } + } + + /// + /// 文本字体 + /// + public static string TextFont + { + get => _acadDisplay.TextFont; + set => _acadDisplay.TextFont = value; + } + + /// + /// 文本字体样式 + /// + public static dynamic TextFontStyle + { + get => _acadDisplay.TextFontStyle; + set => _acadDisplay.TextFontStyle = value; + } + + /// + /// 文本字体大小 + /// + public static int TextFontSize + { + get => _acadDisplay.TextFontSize; + set => _acadDisplay.TextFontSize = value; + } + + /// + /// 历史文本的容量,最多2048行 + /// + public static int HistoryLines + { + get => _acadDisplay.HistoryLines; + set => _acadDisplay.HistoryLines = value; + } + + /// + /// 最大化自动设置窗体 + /// + public static bool MaxAutoCADWindow + { + get => _acadDisplay.MaxAutoCADWindow; + set => _acadDisplay.MaxAutoCADWindow = value; + } + + /// + /// 显示布局选项卡 + /// + public static bool DisplayLayoutTabs + { + get => _acadDisplay.DisplayLayoutTabs; + set => _acadDisplay.DisplayLayoutTabs = value; + } + + /// + /// 图像框架亮点 + /// + public static bool ImageFrameHighlight + { + get => _acadDisplay.ImageFrameHighlight; + set => _acadDisplay.ImageFrameHighlight = value; + } + + /// + /// 真彩色图像 + /// + public static bool TrueColorImages + { + get => _acadDisplay.TrueColorImages; + set => _acadDisplay.TrueColorImages = value; + } + + /// + /// 参照淡化 + /// + public static int XRefFadeIntensity + { + get => _acadDisplay.XRefFadeIntensity; + set => _acadDisplay.XRefFadeIntensity = value; + } + } + + private static uint ColorToUInt(Color color) + { + var c = color.ColorValue; + return (uint)(c.R | c.G << 8 | c.B << 16); + } + + private static Color UIntToColor(uint color) + { + var r = (byte)(color >> 0); + var g = (byte)(color >> 8); + var b = (byte)(color >> 16); + return Color.FromRgb(r, g, b); + } +} \ No newline at end of file -- Gitee From 83b92b510aa6eb94a7925afdfea4e252df97adad Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Wed, 23 Oct 2024 14:42:15 +0800 Subject: [PATCH 339/453] =?UTF-8?q?=E8=A1=A5=E5=85=85AcPreferences?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj b/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj index 20950c1..a1f181c 100644 --- a/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj +++ b/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj @@ -17,7 +17,7 @@ IFox.CAD.ACAD IFox.CAD.ACAD IFox.CAD.ACAD - 0.9.1.2 + 0.9.1.3 xsfhlzh, vicwjb, liuqihong, DYH 基于.NET的二次开发基本类库. https://www.nuget.org/packages/IFox.CAD.ACAD/ @@ -26,7 +26,7 @@ IFox,Cad,AutoCad,C#,NET, InspireFunction readme.md - 补充随机数扩展 + 补充AcPreferences LICENSE -- Gitee From fea1202d095e536f99fdf991bef01b1a1d307ea6 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 24 Oct 2024 08:55:43 +0800 Subject: [PATCH 340/453] =?UTF-8?q?=E5=88=A0=E9=99=A4=E8=BF=87=E6=9C=9F?= =?UTF-8?q?=E7=9A=84flush=E5=88=B7=E6=96=B0=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/ExtensionMethod/RedrawEx.cs | 32 ++------------------------- 1 file changed, 2 insertions(+), 30 deletions(-) diff --git a/CADShared/ExtensionMethod/RedrawEx.cs b/CADShared/ExtensionMethod/RedrawEx.cs index e1deab2..1a6165e 100644 --- a/CADShared/ExtensionMethod/RedrawEx.cs +++ b/CADShared/ExtensionMethod/RedrawEx.cs @@ -94,15 +94,12 @@ public static void Redraw(this Editor ed, Entity? ent = null) using (ent?.ForWrite()) { // 刷新图元 - ent?.Redraw(BrightEntity.Draw | - BrightEntity.RecordGraphicsModified | - BrightEntity.RecomputeDimensionBlock | - BrightEntity.MoveZero); + ent?.Redraw(BrightEntity.Draw | BrightEntity.RecordGraphicsModified | + BrightEntity.RecomputeDimensionBlock | BrightEntity.MoveZero); // 刷新 ed.Redraw(BrightEditor.UpdateScreen); } - /* * 我发现命令加 CommandFlags.Redraw 就不需要以下处理了: * 数据库事务和文档事务不一样,文档事务有刷新函数. @@ -189,29 +186,4 @@ public static void Redraw(this Entity ent, BrightEntity bright) if ((bright & BrightEntity.MoveZero) == BrightEntity.MoveZero) ent.Move(Point3d.Origin, Point3d.Origin); } - - - #region 实体刷新 - - /// - /// 刷新实体显示 - /// - /// 实体对象 - [Obsolete("此处已经被RedrawEx代替")] - public static void Flush(this Entity entity) - { - var tr = DBTrans.GetTop(entity.Database); - entity.RecordGraphicsModified(true); - tr.Transaction.TransactionManager.QueueForGraphicsFlush(); - tr.Document?.TransactionManager.FlushGraphics(); - } - - /// - /// 刷新实体显示 - /// - /// 实体id - [Obsolete("此处已经被RedrawEx代替")] - public static void Flush(this ObjectId id) => Flush(id.GetObject()!); - - #endregion } \ No newline at end of file -- Gitee From 22b3a859885bcd40bf813716a75f9a0a7572e9c0 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sun, 27 Oct 2024 23:18:31 +0800 Subject: [PATCH 341/453] =?UTF-8?q?=E5=8C=85=E5=9B=B4=E7=9B=92=E8=A1=A5?= =?UTF-8?q?=E5=85=85Hatch=E7=9A=84=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Entity/EntityBoundingInfo.cs | 40 ++++++++++++++----- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/CADShared/ExtensionMethod/Entity/EntityBoundingInfo.cs b/CADShared/ExtensionMethod/Entity/EntityBoundingInfo.cs index c239ce4..854f9cc 100644 --- a/CADShared/ExtensionMethod/Entity/EntityBoundingInfo.cs +++ b/CADShared/ExtensionMethod/Entity/EntityBoundingInfo.cs @@ -5,7 +5,6 @@ /// internal static class EntityBoundingInfo { - /// /// 获取包围盒信息 /// @@ -15,6 +14,7 @@ internal static class EntityBoundingInfo { return new(ext); } + /// /// 获取多行文本的正交包围盒 /// @@ -27,8 +27,10 @@ static Extents3d GetMTextBox(MText mText) { ext.AddPoint(p); } + return ext; } + /// /// 获取块的包围盒 /// @@ -52,9 +54,11 @@ static void GetBlockBox(this Entity en, ref Extents3d ext, ref Matrix3d mat) if (!att.Constant || att.Invisible) continue; } + GetBlockBox(ent1, ref ext, ref matins); } } + if (block.AttributeCollection.Count > 0) { foreach (var att in block.GetAttributes()) @@ -99,11 +103,14 @@ static void GetBlockBox(this Entity en, ref Extents3d ext, ref Matrix3d mat) else ext.AddExtents(entext); } + return; } } + return; } + /// /// 获取多行文字最小包围盒4点坐标 /// @@ -155,19 +162,19 @@ public static Point3d[] GetMTextBoxCorners(MText mtext) break; } - var xform = - Matrix3d.Displacement(mtext.Location.GetAsVector()) * - Matrix3d.Rotation(mtext.Rotation, mtext.Normal, Point3d.Origin) * - Matrix3d.PlaneToWorld(new Plane(Point3d.Origin, mtext.Normal)); + var xform = Matrix3d.Displacement(mtext.Location.GetAsVector()) * + Matrix3d.Rotation(mtext.Rotation, mtext.Normal, Point3d.Origin) * + Matrix3d.PlaneToWorld(new Plane(Point3d.Origin, mtext.Normal)); return [ point1.TransformBy(xform), - new Point3d(point2.X, point1.Y, 0.0).TransformBy(xform), - point2.TransformBy(xform), - new Point3d(point1.X, point2.Y, 0.0).TransformBy(xform) + new Point3d(point2.X, point1.Y, 0.0).TransformBy(xform), + point2.TransformBy(xform), + new Point3d(point1.X, point2.Y, 0.0).TransformBy(xform) ]; } + /// /// 获取实体包围盒 /// @@ -201,13 +208,27 @@ public static Point3d[] GetMTextBoxCorners(MText mtext) var mat = Matrix3d.Identity; block!.GetBlockBox(ref blockExt, ref mat); if (!blockExt.IsEmptyExt()) - ext = blockExt; + ext = blockExt; + break; + // 和尚_2024-10-26 + case Hatch hatch: + var hc = new HatchConverter(hatch); + hc.GetBoundarysData(); + var extTmp = new Extents3d(); + foreach (var curve in hc.CreateBoundary()) + { + extTmp.AddExtents(GetEntityBoxEx(curve)!.Value); + curve.Dispose(); + } + + ext = extTmp; break; default: if (ent.Bounds.HasValue) ext = ent.GeometricExtents; break; } + if (ext != null) //实体不是点时,pass if (ent is not DBPoint && ext.Value.MinPoint.IsEqualTo(ext.Value.MaxPoint)) @@ -227,5 +248,4 @@ static bool IsEmptyExt(this Extents3d ext) else return false; } - } \ No newline at end of file -- Gitee From 3a9a1f757ab2e1271d19d95bc81bb0eb2e24d404 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Mon, 28 Oct 2024 11:05:33 +0800 Subject: [PATCH 342/453] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E5=9D=97=E8=A1=A8=E8=AE=B0=E5=BD=95=E6=89=A9=E5=B1=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Entity/BlockReferenceEx.cs | 37 +++++++++++++------ 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/CADShared/ExtensionMethod/Entity/BlockReferenceEx.cs b/CADShared/ExtensionMethod/Entity/BlockReferenceEx.cs index 7024393..2bd61cc 100644 --- a/CADShared/ExtensionMethod/Entity/BlockReferenceEx.cs +++ b/CADShared/ExtensionMethod/Entity/BlockReferenceEx.cs @@ -7,8 +7,8 @@ public static class BlockReferenceEx { #region 裁剪块参照 - private const string filterDictName = "ACAD_FILTER"; - private const string spatialName = "SPATIAL"; + private const string kFilterDictName = "ACAD_FILTER"; + private const string kSpatialName = "SPATIAL"; /// /// 裁剪块参照 @@ -24,8 +24,8 @@ public static void XClip(this BlockReference brf, IEnumerable pt3ds) double.NegativeInfinity, true); using SpatialFilter sf = new(); sf.Definition = sfd; - var dict = brf.GetXDictionary().GetSubDictionary(true, [filterDictName])!; - dict.SetData(spatialName, sf); + var dict = brf.GetXDictionary().GetSubDictionary(true, [kFilterDictName])!; + dict.SetData(kSpatialName, sf); } /// @@ -47,9 +47,10 @@ public static void XClip(this BlockReference brf, Point3d pt1, Point3d pt2) ]; using SpatialFilter sf = new(); - sf.Definition = new(pts, Vector3d.ZAxis, 0.0, double.PositiveInfinity, double.NegativeInfinity, true); - var dict = brf.GetXDictionary().GetSubDictionary(true, [filterDictName])!; - dict.SetData(spatialName, sf); + sf.Definition = new(pts, Vector3d.ZAxis, 0.0, double.PositiveInfinity, + double.NegativeInfinity, true); + var dict = brf.GetXDictionary().GetSubDictionary(true, [kFilterDictName])!; + dict.SetData(kSpatialName, sf); #if !acad pts.Dispose(); #endif @@ -69,7 +70,8 @@ public static bool ChangeBlockProperty(this BlockReference blockReference, return false; using (blockReference.ForWrite()) { - foreach (DynamicBlockReferenceProperty item in blockReference.DynamicBlockReferencePropertyCollection) + foreach (DynamicBlockReferenceProperty item in blockReference + .DynamicBlockReferencePropertyCollection) { if (propertyNameValues.TryGetValue(item.PropertyName, out var value)) { @@ -93,13 +95,15 @@ public static bool ChangeBlockProperty(this BlockReference blockReference, /// /// 更新动态块参数值 /// - public static bool ChangeBlockProperty(this BlockReference blockReference, string propName, object value) + public static bool ChangeBlockProperty(this BlockReference blockReference, string propName, + object value) { if (!blockReference.IsDynamicBlock) return false; using (blockReference.ForWrite()) { - foreach (DynamicBlockReferenceProperty item in blockReference.DynamicBlockReferencePropertyCollection) + foreach (DynamicBlockReferenceProperty item in blockReference + .DynamicBlockReferencePropertyCollection) { if (item.PropertyName != propName) continue; @@ -174,6 +178,16 @@ public static IEnumerable GetAttributes(this BlockReference #endregion + /// + /// 获取块表记录 + /// + /// 块参照 + /// 块表记录 + public static BlockTableRecord GetBlockTableRecord(this BlockReference brf) + { + return (BlockTableRecord)brf.BlockTableRecord.GetObject(OpenMode.ForRead); + } + /// /// 获取块的有效名字 /// @@ -201,7 +215,8 @@ public static string GetBlockName(this BlockReference blk) /// 子块名 /// 子块的位置 /// - public static Point3d? GetNestedBlockPosition(this BlockReference parentBlockRef, string nestedBlockName) + public static Point3d? GetNestedBlockPosition(this BlockReference parentBlockRef, + string nestedBlockName) { var tr = DBTrans.GetTopTransaction(parentBlockRef.Database); -- Gitee From abb7c70669d5fa5265d796b1e4609e8377f852b2 Mon Sep 17 00:00:00 2001 From: yupeng_dyp Date: Mon, 28 Oct 2024 04:39:26 +0000 Subject: [PATCH 343/453] update CADShared/Runtime/DBTrans.cs. Signed-off-by: yupeng_dyp --- CADShared/Runtime/DBTrans.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CADShared/Runtime/DBTrans.cs b/CADShared/Runtime/DBTrans.cs index bb951bc..8b658c7 100644 --- a/CADShared/Runtime/DBTrans.cs +++ b/CADShared/Runtime/DBTrans.cs @@ -639,6 +639,10 @@ private void Dispose(bool disposing) // 将文档锁销毁 _documentLock?.Dispose(); + + //直接以文件 new 事务,最好及时释放 Database + if (!string.IsNullOrWhiteSpace(_fileName)) + Database.Dispose(); } // 将当前事务栈弹栈 -- Gitee From 33638b43396622de499a1a4535f14c5736047ffb Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 31 Oct 2024 17:20:21 +0800 Subject: [PATCH 344/453] =?UTF-8?q?=E5=A2=9E=E5=8A=A0CurveEx=E6=89=A9?= =?UTF-8?q?=E5=B1=95=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/CADShared.projitems | 1 + CADShared/ExtensionMethod/Entity/CurveEx.cs | 918 ++++++++++++++++++ .../ExtensionMethod/Geomerty/Curve3dEx.cs | 120 +-- 3 files changed, 958 insertions(+), 81 deletions(-) create mode 100644 CADShared/ExtensionMethod/Entity/CurveEx.cs diff --git a/CADShared/CADShared.projitems b/CADShared/CADShared.projitems index 1e17760..6974a92 100644 --- a/CADShared/CADShared.projitems +++ b/CADShared/CADShared.projitems @@ -43,6 +43,7 @@ + diff --git a/CADShared/ExtensionMethod/Entity/CurveEx.cs b/CADShared/ExtensionMethod/Entity/CurveEx.cs new file mode 100644 index 0000000..494666a --- /dev/null +++ b/CADShared/ExtensionMethod/Entity/CurveEx.cs @@ -0,0 +1,918 @@ +// ReSharper disable ForCanBeConvertedToForeach + +namespace IFoxCAD.Cad; + +/// +/// 实体类曲线扩展类 +/// +public static class CurveEx +{ + /// + /// 曲线长度 + /// + /// 曲线 + /// 长度 + public static double GetLength(this Curve curve) + { + return curve.GetDistanceAtParameter(curve.EndParam); + } + + /*/// + /// 获取分割曲线集合 + /// + /// 曲线 + /// 打断参数表 + /// 打断后曲线的集合 + public static IEnumerable GetSplitCurves(this Curve curve, IEnumerable pars) + { + //if (pars is null) + // throw new ArgumentNullException(nameof(pars)); + ArgumentNullEx.ThrowIfNull(pars); + return curve.GetSplitCurves(new DoubleCollection(pars.ToArray())).Cast(); + }*/ + + /// + /// 获取分割曲线集合 + /// + /// 曲线 + /// 打断参数表 + /// 对参数表是否进行排序 + /// + /// 按参数值升序排序
    + /// 不排序,默认值 + ///
    + /// + /// 打断后曲线的集合 + public static IEnumerable GetSplitCurves(this Curve curve, IEnumerable pars, + bool isOrder = false) + { + //if (pars is null) + // throw new ArgumentNullException(nameof(pars)); + ArgumentNullEx.ThrowIfNull(pars); + if (isOrder) + pars = pars.OrderBy(x => x); + + return curve.GetSplitCurves(new DoubleCollection(pars.ToArray())).Cast(); + } + + /* + /// + /// 获取分割曲线集合 + /// + /// 曲线 + /// 打断点表 + /// 打断后曲线的集合 + public static IEnumerable GetSplitCurves(this Curve curve, IEnumerable points) + { + //if (points is null) + // throw new ArgumentNullException(nameof(points)); + ArgumentNullEx.ThrowIfNull(points); + using var pts = new Point3dCollection(points.ToArray()); + return curve.GetSplitCurves(pts).Cast(); + }*/ + + /// + /// 获取分割曲线集合 + /// + /// 曲线 + /// 打断点表 + /// 对点表是否进行排序 + /// + /// 按参数值升序排序
    + /// 不排序,默认值 + ///
    + /// + /// 打断后曲线的集合 + public static IEnumerable GetSplitCurves(this Curve curve, IEnumerable points, + bool isOrder = false) + { + //if (points is null) + // throw new ArgumentNullException(nameof(points)); + ArgumentNullEx.ThrowIfNull(points); + if (isOrder) + points = points.OrderBy(point => + { + var pt = curve.GetClosestPointTo(point, false); + return curve.GetParameterAtPoint(pt); + }); + + using Point3dCollection pts = new(points.ToArray()); + return curve.GetSplitCurves(pts).Cast(); + } + + /// + /// 曲线打断 + /// + /// 曲线列表 + /// 打断后的曲线列表 + public static List BreakCurve(this List curves) + { + ArgumentNullEx.ThrowIfNull(curves); + + var tol = new Tolerance(0.01, 0.01); + + List geCurves = []; // 存储曲线转换后的复合曲线 + List> paramsList = []; // 存储每个曲线的交点参数值 + + for (var i = 0; i < curves.Count; i++) + { + var cc3d = curves[i].ToCompositeCurve3d(); + if (cc3d is not null) + { + geCurves.Add(cc3d); + paramsList.Add([]); + } + } + + // List oldCurves = []; + List newCurves = []; + var cci3d = new CurveCurveIntersector3d(); + + for (var i = 0; i < curves.Count; i++) + { + var gc1 = geCurves[i]; + var pars1 = paramsList[i]; // 引用 + for (var j = i; j < curves.Count; j++) + { + var gc2 = geCurves[j]; + var pars2 = paramsList[j]; // 引用 + + cci3d.Set(gc1, gc2, Vector3d.ZAxis, tol); + + for (var k = 0; k < cci3d.NumberOfIntersectionPoints; k++) + { + var pars = cci3d.GetIntersectionParameters(k); + pars1.Add(pars[0]); // 引用修改会同步到源对象 + pars2.Add(pars[1]); // 引用修改会同步到源对象 + } + } + + if (pars1.Count > 0) + { + var c3ds = gc1.GetSplitCurves(pars1); + if (c3ds is not null && c3ds.Count > 1) + { + foreach (var c3d in c3ds) + { + var c3dCur = c3d.ToCurve(); + if (c3dCur is not null) + { + c3dCur.SetPropertiesFrom(curves[i]); + newCurves.Add(c3dCur); + } + } + // oldCurves.Add(curves[i]); + } + } + } + + return newCurves; + } + + /// + /// 在z法向量平面打断曲线 + /// + /// 曲线列表 + /// 打断后的曲线列表 + /// 传入的曲线列表错误 + public static List BreakCurveOnZPlane(this List curves) + { + if (curves is null) + throw new ArgumentNullException(nameof(curves)); + var zPlane = new Plane(Point3d.Origin, Vector3d.ZAxis); + var curvesTemp = curves.Select(c => c.GetProjectedCurve(zPlane, Vector3d.ZAxis)).ToList(); + List geCurves = []; // 存储曲线转换后的复合曲线 + List> paramsList = []; // 存储每个曲线的交点参数值 + + for (var i = 0; i < curvesTemp.Count; i++) + { + paramsList.Add([]); + var cc3d = curvesTemp[i].ToCompositeCurve3d(); + if (cc3d is not null) + { + geCurves.Add(cc3d); + } + } + + List newCurves = []; + var cci3d = new CurveCurveIntersector3d(); + + for (var i = 0; i < curvesTemp.Count; i++) + { + var gc1 = geCurves[i]; + var pars1 = paramsList[i]; // 引用 + for (var j = i; j < curvesTemp.Count; j++) + { + var gc2 = geCurves[j]; + var pars2 = paramsList[j]; // 引用 + + cci3d.Set(gc1, gc2, Vector3d.ZAxis); + + for (var k = 0; k < cci3d.NumberOfIntersectionPoints; k++) + { + var pars = cci3d.GetIntersectionParameters(k); + pars1.Add(pars[0]); // 引用修改会同步到源对象 + pars2.Add(pars[1]); // 引用修改会同步到源对象 + } + } + + var curNow = curvesTemp[i]; + var length = curNow.GetLength(); + var np = pars1.Where(p => p >= 0 && p <= length) + .Select(curNow.GetParameterAtDistance) + .Where(p => + !(Math.Abs(p - curNow.StartParam) < 1e-6 || + Math.Abs(p - curNow.EndParam) < 1e-6)) + .ToList(); + if (np.Count > 0) + { + var splitCurs = curNow.GetSplitCurves(np, true).ToList(); + if (splitCurs.Count > 1) + { + newCurves.AddRange(splitCurs); + } + else + { + newCurves.Add(curNow.CloneEx()); + } + } + else + { + newCurves.Add(curNow.CloneEx()); + } + } + + return newCurves; + } +#if !gcad + /// + /// 打段曲线2维By四叉树 + /// + /// 目前对xLine,ray的支持存在错误 + /// 需要更多的测试 + /// + /// + /// 曲线列表 + /// 容差 + /// 打断后的曲线列表 + public static List BreakCurve2dByQuadTree(this List sourceCurveList, + double tol = 1e-6) + { + //var tolerance = new Tolerance(tol, tol); + var zPlane = new Plane(Point3d.Origin, Vector3d.ZAxis); + var curves = sourceCurveList.Select(c => c.GetOrthoProjectedCurve(zPlane)).ToList(); + List geCurves = []; + List xLines = []; + var minX = double.MaxValue; + var minY = double.MaxValue; + var maxX = double.MinValue; + var maxY = double.MinValue; + // 遍历每条曲线,计算出四叉树对象,加到四叉树曲线对象列表和四叉树容器中 + for (var i = 0; i < curves.Count; i++) + { + var curTemp = curves[i]; + if (curTemp is Ray || curTemp is Xline) + { + xLines.Add(curTemp); + } + else + { + var cc3d = curTemp.ToCompositeCurve3d(); + if (cc3d is not null) + { + var e3d = curTemp.GeometricExtents; + var rect = new Rect(e3d.MinPoint.Point2d(), e3d.MaxPoint.Point2d()); + var cit = new BreakCurveInfo(rect, curTemp, cc3d); + if (rect.Left < minX) minX = rect.Left; + if (rect.Right > maxX) maxX = rect.Right; + if (rect.Bottom < minY) minY = rect.Bottom; + if (rect.Top > maxY) maxY = rect.Top; + geCurves.Add(cit); + } + } + } + + // 建四叉树容器 + var maxBox = new Rect(minX - 10, minY - 10, maxX + 10, maxY + 10); + xLines.ForEach(xl => + { + var cc3d = new CompositeCurve3d([xl.GetGeCurve()]); + var bci = new BreakCurveInfo(maxBox, xl, cc3d); + geCurves.Add(bci); + }); + List newCurves = []; + var quadTree = new QuadTree(maxBox); + foreach (var bci in geCurves) + { + quadTree.Insert(bci); + } + + var cci3d = new CurveCurveIntersector3d(); + + foreach (var gc1 in geCurves) + { + var parsList = new HashSet(); + var cts = quadTree.Query(new Rect(gc1.Left - tol, gc1.Bottom - tol, gc1.Right + tol, + gc1.Top + tol)); + cts.Remove(gc1); + foreach (var gc2 in cts) + { + cci3d.Set(gc1.Cc3d, gc2.Cc3d, Vector3d.ZAxis, Tolerance.Global); + for (var k = 0; k < cci3d.NumberOfIntersectionPoints; k++) + { + var pars = cci3d.GetIntersectionParameters(k); + parsList.Add(pars[0]); + } + + if (!gc2.Curve.Closed) + { + var cpt1 = gc1.Cc3d.GetClosestPointTo(gc2.Cc3d.StartPoint); + var cpt2 = gc1.Cc3d.GetClosestPointTo(gc2.Cc3d.EndPoint); + if (cpt1.Point.Distance2dTo(gc2.Cc3d.StartPoint) < tol && + cpt1.Point.Distance2dTo(gc1.Cc3d.StartPoint) >= tol) + { + parsList.Add(cpt1.Parameter); + } + + if (cpt2.Point.Distance2dTo(gc2.Cc3d.EndPoint) < tol && + cpt2.Point.Distance2dTo(gc1.Cc3d.EndPoint) >= tol) + { + parsList.Add(cpt2.Parameter); + } + } + } + + if (gc1.Curve is Polyline || gc1.Curve is Spline) + { + cci3d.Set(gc1.Cc3d, gc1.Cc3d, Vector3d.ZAxis); + for (var k = 0; k < cci3d.NumberOfIntersectionPoints; k++) + { + var pars = cci3d.GetIntersectionParameters(k); + if (Math.Abs(pars[0] - pars[1]) < 1e-6) + continue; + parsList.Add(pars[0]); + parsList.Add(pars[1]); + } + } + + var parsNew = parsList.OrderBy(d => d).ToList(); + + var cur = gc1.Curve; + if (parsNew.Count > 0) + { + var c3ds = gc1.Cc3d.GetSplitCurves(parsNew); + if (c3ds is not null && c3ds.Count > 1) + { + if (cur is Arc || (cur is Ellipse { Closed: false })) + { + foreach (var c3d in c3ds) + { + var c3dCur = Curve.CreateFromGeCurve(c3d); + + if (c3dCur is null || c3dCur.Closed || c3dCur is Circle || + c3dCur.GetLength() < tol) + continue; + c3dCur.SetPropertiesFrom(cur); + newCurves.Add(c3dCur); + } + + continue; + } + + foreach (var c3d in c3ds) + { + var c3dCur = Curve.CreateFromGeCurve(c3d); + if (c3dCur is not null) + { + c3dCur.SetPropertiesFrom(cur); + newCurves.Add(c3dCur); + } + } + } + else + { + newCurves.Add(cur.CloneEx()); + } + } + else + { + newCurves.Add(cur.CloneEx()); + } + } + + return newCurves; + } + + private class BreakCurveInfo : QuadEntity + { + // ReSharper disable once UnusedAutoPropertyAccessor.Local + public Rect Rect { get; } + public Curve Curve { get; } + public CompositeCurve3d Cc3d { get; } + + public BreakCurveInfo(Rect rect, Curve curve, CompositeCurve3d cc3d) : base(rect) + { + Curve = curve; + Cc3d = cc3d; + Rect = rect; + } + } +#endif + /// + /// 获取非等比转换的曲线(旋转投影法) + /// + /// 转换前的曲线 + /// 基点 + /// x方向比例 + /// y方向比例 + /// 转换后的曲线 + public static Curve GetScaleCurve(this Curve cur, Point3d pt, double x, double y) + { + // 先做个z平面 + using var zPlane = new Plane(pt, Vector3d.ZAxis); + // 克隆一个,防止修改到原来的 + using var cur2 = cur.CloneEx(); + + // 因为旋转投影后只能比原来小,所以遇到先放大 + while (Math.Abs(x) > 1 || Math.Abs(y) > 1) + { + cur2.TransformBy(Matrix3d.Scaling(2, pt)); + x /= 2; + y /= 2; + } + + // 旋转投影 + var xA = Math.Acos(x); + cur2.TransformBy(Matrix3d.Rotation(xA, Vector3d.YAxis, pt)); + + using var cur3 = cur2.GetOrthoProjectedCurve(zPlane); + + // 再次旋转投影 + var yA = Math.Acos(y); + cur3.TransformBy(Matrix3d.Rotation(yA, Vector3d.XAxis, pt)); + var cur4 = cur3.GetOrthoProjectedCurve(zPlane); + + //设置属性 + cur4.SetPropertiesFrom(cur); + return cur4; + } + + // 转换DBCurve为GeCurved + + #region Curve + + /// + /// 将曲线转换为ge曲线,此函数将在未来淘汰,二惊加油 + /// + /// 曲线 + /// ge曲线 + public static Curve3d? ToCurve3d(this Curve curve) + { + return curve switch + { + Line li => ToCurve3d(li), + Circle ci => ToCurve3d(ci), + Arc arc => ToCurve3d(arc), + Ellipse el => ToCurve3d(el), + Polyline pl => ToCurve3d(pl), + Polyline2d pl2 => ToCurve3d(pl2), + Polyline3d pl3 => ToCurve3d(pl3), + Spline sp => ToCurve3d(sp), + _ => null + }; + } + + /// + /// 将曲线转换为复合曲线 + /// + /// 曲线 + /// 复合曲线 + public static CompositeCurve3d? ToCompositeCurve3d(this Curve curve) + { + return curve switch + { + Line li => new CompositeCurve3d([ToCurve3d(li)]), + Circle ci => new CompositeCurve3d([ToCurve3d(ci)]), + Arc arc => new CompositeCurve3d([ToCurve3d(arc)]), + Ellipse el => new CompositeCurve3d([ToCurve3d(el)]), + Polyline pl => new CompositeCurve3d([ToCurve3d(pl)]), + + Polyline2d pl2 => new CompositeCurve3d([ToCurve3d(pl2)!]), + Polyline3d pl3 => new CompositeCurve3d([ToCurve3d(pl3)]), + Spline sp => new CompositeCurve3d([ToCurve3d(sp)]), + _ => null + }; + } + + /// + /// 将曲线转换为Nurb曲线 + /// + /// 曲线 + /// Nurb曲线 + public static NurbCurve3d? ToNurbCurve3d(this Curve curve) + { + return curve switch + { + Line li => ToNurbCurve3d(li), + Circle ci => ToNurbCurve3d(ci), + Arc arc => ToNurbCurve3d(arc), + Ellipse el => ToNurbCurve3d(el), + Polyline pl => ToNurbCurve3d(pl), + Polyline2d pl2 => ToNurbCurve3d(pl2), + Polyline3d pl3 => ToNurbCurve3d(pl3), + Spline sp => ToNurbCurve3d(sp), + _ => null + }; + } + + #region Line + + /// + /// 将直线转换为ge直线 + /// + /// 直线 + /// ge直线 + public static LineSegment3d ToCurve3d(this Line line) + { + return new LineSegment3d(line.StartPoint, line.EndPoint); + } + + /// + /// 将直线转换为Nurb曲线 + /// + /// 直线 + /// Nurb曲线 + public static NurbCurve3d ToNurbCurve3d(this Line line) + { + return new NurbCurve3d(ToCurve3d(line)); + } + + #endregion Line + + #region Circle + + /// + /// 将圆转换为ge圆弧曲线 + /// + /// 圆 + /// ge圆弧曲线 + public static CircularArc3d ToCurve3d(this Circle cir) + { + return new CircularArc3d(cir.Center, cir.Normal, cir.Radius); + } + + /// + /// 将圆转换为ge椭圆曲线 + /// + /// 圆 + /// ge椭圆曲线 + public static EllipticalArc3d ToEllipticalArc3d(this Circle cir) + { + return ToCurve3d(cir).ToEllipticalArc3d(); + } + + /// + /// 将圆转换为Nurb曲线 + /// + /// 圆 + /// Nurb曲线 + public static NurbCurve3d ToNurbCurve3d(this Circle cir) + { + return new NurbCurve3d(ToEllipticalArc3d(cir)); + } + + #endregion Circle + + #region Arc + + /// + /// 将圆弧转换为ge圆弧曲线 + /// + /// 圆弧 + /// ge圆弧曲线 + public static CircularArc3d ToCurve3d(this Arc arc) + { + Plane plane = new(arc.Center, arc.Normal); + + return new CircularArc3d(arc.Center, arc.Normal, plane.GetCoordinateSystem().Xaxis, + arc.Radius, arc.StartAngle, arc.EndAngle); + } + + /// + /// 将圆弧转换为ge椭圆曲线 + /// + /// 圆弧 + /// ge椭圆曲线 + public static EllipticalArc3d ToEllipticalArc3d(this Arc arc) + { + return ToCurve3d(arc).ToEllipticalArc3d(); + } + + /// + /// 将圆弧转换为三维Nurb曲线 + /// + /// 圆弧 + /// 三维Nurb曲线 + public static NurbCurve3d ToNurbCurve3d(this Arc arc) + { + return new NurbCurve3d(ToEllipticalArc3d(arc)); + } + + #endregion Arc + + #region Ellipse + + /// + /// 将椭圆转换为三维ge椭圆曲线 + /// + /// 椭圆 + /// 三维ge椭圆曲线 + public static EllipticalArc3d ToCurve3d(this Ellipse ell) + { + return new EllipticalArc3d(ell.Center, ell.MajorAxis.GetNormal(), ell.MinorAxis.GetNormal(), + ell.MajorRadius, ell.MinorRadius, ell.StartParam, ell.EndParam); + } + + /// + /// 将椭圆转换为三维Nurb曲线 + /// + /// 椭圆 + /// 三维Nurb曲线 + public static NurbCurve3d ToNurbCurve3d(this Ellipse ell) + { + return new NurbCurve3d(ToCurve3d(ell)); + } + + #endregion Ellipse + + #region Spline + + /// + /// 将样条曲线转换为三维Nurb曲线 + /// + /// 样条曲线 + /// 三维Nurb曲线 + public static NurbCurve3d ToCurve3d(this Spline spl) + { + NurbCurve3d nc3d; + var nData = spl.NurbsData; + KnotCollection knots = [.. nData.GetKnots()]; + + if (nData.Rational) + { + nc3d = new NurbCurve3d(nData.Degree, knots, nData.GetControlPoints(), + nData.GetWeights(), nData.Periodic); + } + else + { + nc3d = new NurbCurve3d(nData.Degree, knots, nData.GetControlPoints(), nData.Periodic); + } + + if (spl.HasFitData) + { + var fData = spl.FitData; + var vec = new Vector3d(); + if (fData.TangentsExist && (fData.StartTangent != vec || fData.EndTangent != vec)) + nc3d.SetFitData(fData.GetFitPoints(), fData.StartTangent, fData.EndTangent); + } + + return nc3d; + } + + #endregion Spline + + #region Polyline2d + + /// + /// 将二维多段线转换为三维ge曲线 + /// + /// 二维多段线 + /// 三维ge曲线 + public static Curve3d? ToCurve3d(this Polyline2d pl2d) + { + switch (pl2d.PolyType) + { + case Poly2dType.SimplePoly: + case Poly2dType.FitCurvePoly: + Polyline pl = new(); + pl.SetDatabaseDefaults(); + pl.ConvertFrom(pl2d, false); + return ToCurve3d(pl); + default: + return ToNurbCurve3d(pl2d); + } + + // Polyline pl = new Polyline(); + // pl.ConvertFrom(pl2d, false); + // return ToCurve3d(pl); + } + + /// + /// 将二维多段线转换为三维Nurb曲线 + /// + /// 二维多段线 + /// 三维Nurb曲线 + public static NurbCurve3d? ToNurbCurve3d(this Polyline2d pl2d) + { + switch (pl2d.PolyType) + { + case Poly2dType.SimplePoly: + case Poly2dType.FitCurvePoly: + Polyline pl = new(); + pl.SetDatabaseDefaults(); + pl.ConvertFrom(pl2d, false); + return ToNurbCurve3d(pl); + + default: + return ToCurve3d(pl2d.Spline); + } + } + + /// + /// 将二维多段线转换为三维ge多段线 + /// + /// 二维多段线 + /// 三维ge多段线 + public static PolylineCurve3d ToPolylineCurve3d(this Polyline2d pl) + { + using Point3dCollection p3dc = new(); + foreach (Vertex2d ver in pl) + p3dc.Add(ver.Position); + return new PolylineCurve3d(p3dc); + } + + #endregion Polyline2d + + #region Polyline3d + + /// + /// 将三维多段线转换为三维曲线 + /// + /// 三维多段线 + /// 三维曲线 + public static Curve3d ToCurve3d(this Polyline3d pl3d) + { + return pl3d.PolyType switch + { + Poly3dType.SimplePoly => ToPolylineCurve3d(pl3d), + _ => ToNurbCurve3d(pl3d), + }; + } + + /// + /// 将三维多段线转换为三维Nurb曲线 + /// + /// 三维多段线 + /// 三维Nurb曲线 + public static NurbCurve3d ToNurbCurve3d(this Polyline3d pl3d) + { + return ToCurve3d(pl3d.Spline); + } + + /// + /// 将三维多段线转换为三维ge多段线 + /// + /// 三维多段线 + /// 三维ge多段线 + public static PolylineCurve3d ToPolylineCurve3d(this Polyline3d pl) + { + using Point3dCollection p3dc = new(); + foreach (ObjectId id in pl) + { + if (id.GetObject(OpenMode.ForRead) is PolylineVertex3d ver) + p3dc.Add(ver.Position); + } + + return new PolylineCurve3d(p3dc); + } + + #endregion Polyline3d + + #region Polyline + + /// + /// 多段线转换为复合曲线 + /// + /// 多段线对象 + /// 复合曲线对象 + public static CompositeCurve3d ToCurve3d(this Polyline pl) + { + List c3ds = []; + + for (var i = 0; i < pl.NumberOfVertices; i++) + { + switch (pl.GetSegmentType(i)) + { + case SegmentType.Line: + c3ds.Add(pl.GetLineSegmentAt(i)); + break; + + case SegmentType.Arc: + c3ds.Add(pl.GetArcSegmentAt(i)); + break; + } + } + + return new CompositeCurve3d([.. c3ds]); + } + + /// + /// 多段线转换为Nurb曲线 + /// + /// 多段线 + /// Nurb曲线 + public static NurbCurve3d? ToNurbCurve3d(this Polyline pl) + { + NurbCurve3d? nc3d = null; + for (var i = 0; i < pl.NumberOfVertices; i++) + { + NurbCurve3d? nc3dTemp = null; + switch (pl.GetSegmentType(i)) + { + case SegmentType.Line: + nc3dTemp = new NurbCurve3d(pl.GetLineSegmentAt(i)); + break; + + case SegmentType.Arc: + nc3dTemp = pl.GetArcSegmentAt(i).ToNurbCurve3d(); + break; + } + + if (nc3d is null) + nc3d = nc3dTemp; + else if (nc3dTemp is not null) + nc3d.JoinWith(nc3dTemp); + } + + return nc3d; + } + + /// + /// 为优化多段线倒角 + /// + /// 优化多段线 + /// 顶点索引号 + /// 倒角半径 + /// 倒角类型 + public static void ChamferAt(this Polyline polyline, int index, double radius, bool isFillet) + { + if (index < 1 || index > polyline.NumberOfVertices - 2) + throw new Exception("错误的索引号"); + + if (SegmentType.Line != polyline.GetSegmentType(index - 1) || + SegmentType.Line != polyline.GetSegmentType(index)) + throw new Exception("非直线段不能倒角"); + + // 获取当前索引号的前后两段直线,并组合为Ge复合曲线 + Curve3d[] c3ds = + [ + polyline.GetLineSegmentAt(index - 1), + polyline.GetLineSegmentAt(index) + ]; + CompositeCurve3d cc3d = new(c3ds); + + // 试倒直角 + // 子曲线的个数有三种情况: + // 1、=3时倒角方向正确 + // 2、=2时倒角方向相反 + // 3、=0或为直线时失败 + c3ds = cc3d.GetTrimmedOffset(radius, Vector3d.ZAxis, OffsetCurveExtensionType.Chamfer); + + if (c3ds.Length > 0 && c3ds[0] is CompositeCurve3d) + { + var newCc3d = c3ds[0] as CompositeCurve3d; + c3ds = newCc3d!.GetCurves(); + if (c3ds.Length == 3) + { + c3ds = cc3d.GetTrimmedOffset(-radius, Vector3d.ZAxis, + OffsetCurveExtensionType.Chamfer); + if (c3ds.Length == 0 || c3ds[0] is LineSegment3d) + throw new Exception("倒角半径过大"); + } + else if (c3ds.Length == 2) + { + radius = -radius; + } + } + else + { + throw new Exception("倒角半径过大"); + } + + // GetTrimmedOffset会生成倒角+偏移,故先反方向倒角,再倒回 + c3ds = cc3d.GetTrimmedOffset(-radius, Vector3d.ZAxis, OffsetCurveExtensionType.Extend); + var type = isFillet ? OffsetCurveExtensionType.Fillet : OffsetCurveExtensionType.Chamfer; + c3ds = c3ds[0].GetTrimmedOffset(radius, Vector3d.ZAxis, type); + + // 将结果Ge曲线转为Db曲线,并将相关的数值反映到原曲线 + if (c3ds[0].ToCurve() is not Polyline plTemp) + return; + polyline.RemoveVertexAt(index); + polyline.AddVertexAt(index, plTemp.GetPoint2dAt(1), plTemp.GetBulgeAt(1), 0, 0); + polyline.AddVertexAt(index + 1, plTemp.GetPoint2dAt(2), 0, 0, 0); + } + + #endregion Polyline + + #endregion +} \ No newline at end of file diff --git a/CADShared/ExtensionMethod/Geomerty/Curve3dEx.cs b/CADShared/ExtensionMethod/Geomerty/Curve3dEx.cs index 6cbcbfb..d3d6139 100644 --- a/CADShared/ExtensionMethod/Geomerty/Curve3dEx.cs +++ b/CADShared/ExtensionMethod/Geomerty/Curve3dEx.cs @@ -63,24 +63,20 @@ public static Curve3d GetSubCurve(this Curve3d curve, double from, double to) clone.HardTrimByParams(from, to); return clone; } - else - { - clone.HardTrimByParams(inter.LowerBound, to); - clone.HardTrimByParams(from, to); - return clone; - } - } - else - { - NurbCurve3d clone1 = (NurbCurve3d)curve.Clone(); - clone1.HardTrimByParams(from, inter.UpperBound); - NurbCurve3d clone2 = (NurbCurve3d)curve.Clone(); - clone2.HardTrimByParams(inter.LowerBound, to); - clone1.JoinWith(clone2); - return clone1; + + clone.HardTrimByParams(inter.LowerBound, to); + clone.HardTrimByParams(from, to); + return clone; } + + NurbCurve3d clone1 = (NurbCurve3d)curve.Clone(); + clone1.HardTrimByParams(from, inter.UpperBound); + NurbCurve3d clone2 = (NurbCurve3d)curve.Clone(); + clone2.HardTrimByParams(inter.LowerBound, to); + clone1.JoinWith(clone2); + return clone1; } - else + { Curve3d clone = (Curve3d)curve.Clone(); clone.SetInterval(new Interval(from, to, Tolerance.Global.EqualPoint)); @@ -150,7 +146,8 @@ public static bool IsCircular(this Curve3d curve) /// 三维复合曲线 /// 曲线参数列表 /// 三维复合曲线列表 - public static List? GetSplitCurves(this CompositeCurve3d c3d, List pars) + public static List? GetSplitCurves(this CompositeCurve3d c3d, + List pars) { // 曲线参数剔除重复的 if (pars.Count > 0) @@ -218,26 +215,18 @@ public static bool IsCircular(this Curve3d curve) if (cp1.SegmentIndex == cp2.SegmentIndex) { cc3ds.Add( - c3ds[cp1.SegmentIndex].GetSubCurve( - cp1.LocalParameter, - cp2.LocalParameter)); + c3ds[cp1.SegmentIndex].GetSubCurve(cp1.LocalParameter, cp2.LocalParameter)); } else { inter = c3ds[cp1.SegmentIndex].GetInterval(); - cc3ds.Add( - c3ds[cp1.SegmentIndex].GetSubCurve( - cp1.LocalParameter, - inter.UpperBound)); + cc3ds.Add(c3ds[cp1.SegmentIndex].GetSubCurve(cp1.LocalParameter, inter.UpperBound)); for (var j = cp1.SegmentIndex + 1; j < cp2.SegmentIndex; j++) cc3ds.Add((Curve3d)c3ds[j].Clone()); inter = c3ds[cp2.SegmentIndex].GetInterval(); - cc3ds.Add( - c3ds[cp2.SegmentIndex].GetSubCurve( - inter.LowerBound, - cp2.LocalParameter)); + cc3ds.Add(c3ds[cp2.SegmentIndex].GetSubCurve(inter.LowerBound, cp2.LocalParameter)); } curves.Add(new(cc3ds.ToArray())); @@ -335,12 +324,11 @@ public static Polyline ToPolyline(this CompositeCurve3d cc3d) /// 实体类构造线 public static Xline ToCurve(this Line3d line3d) { - return - new Xline - { - BasePoint = line3d.PointOnLine, - SecondPoint = line3d.PointOnLine + line3d.Direction - }; + return new Xline + { + BasePoint = line3d.PointOnLine, + SecondPoint = line3d.PointOnLine + line3d.Direction + }; } /// @@ -350,14 +338,11 @@ public static Xline ToCurve(this Line3d line3d) /// 起点参数 /// 终点参数 /// 三维解析类线段 - public static LineSegment3d ToLineSegment3d(this Line3d line3d, double fromParameter, double toParameter) + public static LineSegment3d ToLineSegment3d(this Line3d line3d, double fromParameter, + double toParameter) { - return - new LineSegment3d - ( - line3d.EvaluatePoint(fromParameter), - line3d.EvaluatePoint(toParameter) - ); + return new LineSegment3d(line3d.EvaluatePoint(fromParameter), + line3d.EvaluatePoint(toParameter)); } #endregion Line3d @@ -389,10 +374,8 @@ public static Curve ToCurve(this CircularArc3d ca3d) { return ToCircle(ca3d); } - else - { - return ToArc(ca3d); - } + + return ToArc(ca3d); } /// @@ -412,7 +395,8 @@ public static Arc ToArc(this CircularArc3d ca3d) { // 必须新建,而不能直接使用GetPlane()获取 var angle = ca3d.ReferenceVector.AngleOnPlane(new Plane(ca3d.Center, ca3d.Normal)); - return new Arc(ca3d.Center, ca3d.Normal, ca3d.Radius, ca3d.StartAngle + angle, ca3d.EndAngle + angle); + return new Arc(ca3d.Center, ca3d.Normal, ca3d.Radius, ca3d.StartAngle + angle, + ca3d.EndAngle + angle); } /// @@ -426,15 +410,8 @@ public static EllipticalArc3d ToEllipticalArc3d(this CircularArc3d ca3d) Vector3d xAxis = ca3d.ReferenceVector; Vector3d yAxis = zAxis.CrossProduct(xAxis); - return - new EllipticalArc3d( - ca3d.Center, - xAxis, - yAxis, - ca3d.Radius, - ca3d.Radius, - ca3d.StartAngle, - ca3d.EndAngle); + return new EllipticalArc3d(ca3d.Center, xAxis, yAxis, ca3d.Radius, ca3d.Radius, + ca3d.StartAngle, ca3d.EndAngle); } /// @@ -460,14 +437,8 @@ public static NurbCurve3d ToNurbCurve3d(this CircularArc3d ca3d) /// 实体类椭圆弧 public static Ellipse ToCurve(this EllipticalArc3d ea3d) { - Ellipse ell = - new( - ea3d.Center, - ea3d.Normal, - ea3d.MajorAxis * ea3d.MajorRadius, - ea3d.MinorRadius / ea3d.MajorRadius, - 0, - Math.PI * 2); + Ellipse ell = new(ea3d.Center, ea3d.Normal, ea3d.MajorAxis * ea3d.MajorRadius, + ea3d.MinorRadius / ea3d.MajorRadius, 0, Math.PI * 2); // Ge椭圆角度就是Db椭圆的参数 if (!ea3d.IsClosed()) { @@ -495,19 +466,12 @@ public static Spline ToCurve(this NurbCurve3d nc3d) NurbCurve3dFitData fData = nc3d.FitData; if (fData.TangentsExist) { - spl = new Spline( - fData.FitPoints, - fData.StartTangent, - fData.EndTangent, - nc3d.Order, + spl = new Spline(fData.FitPoints, fData.StartTangent, fData.EndTangent, nc3d.Order, fData.FitTolerance.EqualPoint); } else { - spl = new Spline( - fData.FitPoints, - nc3d.Order, - fData.FitTolerance.EqualPoint); + spl = new Spline(fData.FitPoints, nc3d.Order, fData.FitTolerance.EqualPoint); } } else @@ -518,15 +482,9 @@ public static Spline ToCurve(this NurbCurve3d nc3d) NurbCurve3dData nurbCurve3dData = nc3d.DefinitionData; - spl = new Spline( - nurbCurve3dData.Degree, - nurbCurve3dData.Rational, - nc3d.IsClosed(), - nurbCurve3dData.Periodic, - nurbCurve3dData.ControlPoints, - knots, - nurbCurve3dData.Weights, - Tolerance.Global.EqualPoint, + spl = new Spline(nurbCurve3dData.Degree, nurbCurve3dData.Rational, nc3d.IsClosed(), + nurbCurve3dData.Periodic, nurbCurve3dData.ControlPoints, knots, + nurbCurve3dData.Weights, Tolerance.Global.EqualPoint, nurbCurve3dData.Knots.Tolerance); } -- Gitee From 4cc3dfca9d44794f259687443e4ea861ed048bd5 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 31 Oct 2024 17:27:14 +0800 Subject: [PATCH 345/453] =?UTF-8?q?=E6=9B=B4=E6=96=B00.9.1.4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj b/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj index a1f181c..167c76b 100644 --- a/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj +++ b/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj @@ -17,7 +17,7 @@ IFox.CAD.ACAD IFox.CAD.ACAD IFox.CAD.ACAD - 0.9.1.3 + 0.9.1.4 xsfhlzh, vicwjb, liuqihong, DYH 基于.NET的二次开发基本类库. https://www.nuget.org/packages/IFox.CAD.ACAD/ @@ -26,7 +26,7 @@ IFox,Cad,AutoCad,C#,NET, InspireFunction readme.md - 补充AcPreferences + 补充CurveEx扩展类 LICENSE -- Gitee From c77e28e501bccf173bb24eb74c27fd662eb50ac6 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Fri, 1 Nov 2024 01:25:45 +0800 Subject: [PATCH 346/453] =?UTF-8?q?=E4=BF=AE=E6=94=B9redraw=E5=87=BD?= =?UTF-8?q?=E6=95=B0=E7=9A=84=E7=9B=AE=E6=A0=87=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/ExtensionMethod/RedrawEx.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/CADShared/ExtensionMethod/RedrawEx.cs b/CADShared/ExtensionMethod/RedrawEx.cs index 1a6165e..adbb9ee 100644 --- a/CADShared/ExtensionMethod/RedrawEx.cs +++ b/CADShared/ExtensionMethod/RedrawEx.cs @@ -110,9 +110,7 @@ public static void Redraw(this Editor ed, Entity? ent = null) * tm.FlushGraphics(); // 将当前 刷新队列 的图形提交到显示器 * ed.UpdateScreen(); // 仅刷新屏幕,图元不生成(例如块还是旧的显示) */ - var dm = Acaop.DocumentManager; - var doc = dm.MdiActiveDocument; - var tm = doc.TransactionManager; + var tm = ed.Document.TransactionManager; tm.QueueForGraphicsFlush(); tm.FlushGraphics(); -- Gitee From 9244ad7535b6124c04c1cd4cccda5dc4b6639047 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Fri, 1 Nov 2024 01:29:03 +0800 Subject: [PATCH 347/453] =?UTF-8?q?=E5=BF=BD=E7=95=A5=E6=9E=9A=E4=B8=BE?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/ExtensionMethod/RedrawEx.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CADShared/ExtensionMethod/RedrawEx.cs b/CADShared/ExtensionMethod/RedrawEx.cs index adbb9ee..d268252 100644 --- a/CADShared/ExtensionMethod/RedrawEx.cs +++ b/CADShared/ExtensionMethod/RedrawEx.cs @@ -1,4 +1,6 @@ -namespace IFoxCAD.Cad; +// ReSharper disable InconsistentNaming + +namespace IFoxCAD.Cad; /// /// 亮显模式 -- Gitee From b869680d9a7f64227472605e522f9e5aedf4ca74 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Tue, 5 Nov 2024 11:21:46 +0800 Subject: [PATCH 348/453] =?UTF-8?q?=E8=A1=A5=E5=85=85=E6=B3=A8=E9=87=8A?= =?UTF-8?q?=EF=BC=8C=E4=BC=98=E5=8C=96=E9=83=A8=E5=88=86=E7=B1=BB=E7=9A=84?= =?UTF-8?q?=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/Assoc/AssocUtils.cs | 11 +- CADShared/Basal/Win/PInvokeUser32.cs | 316 ++++++++++++++++++ CADShared/Basal/Win/SystemEx.cs | 7 +- CADShared/Basal/Win/Win32Api.cs | 32 -- CADShared/Basal/Win/WindowsAPI.cs | 268 ++++----------- CADShared/CADShared.projitems | 2 +- CADShared/ExtensionMethod/PaneEx.cs | 15 + .../ExtensionMethod/SingleKeyWordHook.cs | 20 +- CADShared/ExtensionMethod/WindowEx.cs | 18 +- CADShared/Initialize/AssemInfo.cs | 4 + CADShared/Runtime/AcPreferences.cs | 6 + CADShared/Runtime/SystemVariableManager.cs | 3 + IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj | 3 +- IFoxCAD.sln.DotSettings | 3 + 14 files changed, 466 insertions(+), 242 deletions(-) create mode 100644 CADShared/Basal/Win/PInvokeUser32.cs delete mode 100644 CADShared/Basal/Win/Win32Api.cs diff --git a/CADShared/Assoc/AssocUtils.cs b/CADShared/Assoc/AssocUtils.cs index 8c17ed3..8781c07 100644 --- a/CADShared/Assoc/AssocUtils.cs +++ b/CADShared/Assoc/AssocUtils.cs @@ -2,6 +2,9 @@ namespace IFoxCAD.Cad.Assoc; +/// +/// 关联动作辅助类 +/// public static class AssocUtils { /// @@ -12,14 +15,16 @@ public static class AssocUtils /// 拥有者Id /// 动作id /// 动作bodyId - /// - public static ErrorStatus CreateActionAndActionBodyAndPostToDatabase(RXClass actionBodyClass, ObjectId ownerId, out ObjectId actionId, out ObjectId actionBodyId) + /// 错误信息 + public static ErrorStatus CreateActionAndActionBodyAndPostToDatabase(RXClass actionBodyClass, + ObjectId ownerId, out ObjectId actionId, out ObjectId actionBodyId) { actionId = actionBodyId = ObjectId.Null; try { if (!actionBodyClass.IsDerivedFrom(RXObject.GetClass(typeof(AssocActionBody))) || - Activator.CreateInstance(actionBodyClass.GetRuntimeType()) is not AssocActionBody actionBody) + Activator.CreateInstance(actionBodyClass.GetRuntimeType()) is not AssocActionBody + actionBody) return ErrorStatus.NotThatKindOfClass; var db = ownerId.Database; using var tr = new DBTrans(db); diff --git a/CADShared/Basal/Win/PInvokeUser32.cs b/CADShared/Basal/Win/PInvokeUser32.cs new file mode 100644 index 0000000..c3df3f9 --- /dev/null +++ b/CADShared/Basal/Win/PInvokeUser32.cs @@ -0,0 +1,316 @@ +namespace IFoxCAD.Basal; + +/// +/// PInvokeUser32 +/// +public static class PInvokeUser32 +{ + #region Win32 + + /// + /// 查找窗口 + /// + /// 类名 + /// 窗口名 + /// 窗口句柄 + [DllImport("user32.dll", SetLastError = true)] + public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); + + /// + /// 发送指定消息给一个或多个接收对象,常用于窗口或控件的消息处理 + /// + /// 目标窗口的句柄如果为0,表示发送给所有顶级窗口 + /// 要发送的消息标识符 + /// 附加的消息特定信息,通常用于传递额外的参数 + /// 附加的消息特定信息,通常用于传递额外的参数 + /// 返回值取决于发送的消息类型,通常表示操作的结果或状态 + [DllImport("user32.dll", CharSet = CharSet.Auto)] + public static extern IntPtr SendMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam); + + #region user32 + + /// + /// 获取窗口客户区的大小,客户区为窗口中除标题栏,菜单栏之外的地方 + /// + /// + /// + /// + [DllImport("user32.dll", CharSet = CharSet.Auto, EntryPoint = "GetClientRect")] + public static extern bool GetClientRect(IntPtr hwnd, out WindowsAPI.IntRect lpRect); + + /// + /// 查找主线程
    + /// 代替
    + /// 托管线程和他们不一样: + /// System.Threading.Thread.CurrentThread.ManagedThreadId + /// + ///
    + /// 主窗口 + /// 进程ID + /// 线程ID + [DllImport("user32.dll", SetLastError = true)] + public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId); + + /// + /// 设置焦点 + /// + /// + /// + [DllImport("user32.dll")] + public static extern IntPtr SetFocus(IntPtr hWnd); + + /// + /// 获取当前窗口 + /// + /// 当前窗口标识符 + [DllImport("user32.dll")] + public static extern IntPtr GetForegroundWindow(); + + /// + /// 将一个消息的组成部分合成一个消息并放入对应线程消息队列的方法 + /// + /// 控件句柄 + /// 消息是什么键盘按键、鼠标点击还是其他 + /// + /// + /// + [DllImport("user32.dll")] + public static extern bool PostMessage(IntPtr hhwnd, int msg, IntPtr wparam, IntPtr lparam); + + /// + /// 发送击键 + /// + /// + /// + /// + /// + [DllImport("user32.dll", EntryPoint = "keybd_event")] + public static extern void KeybdEvent(byte bVk, byte bScan, int dwFlags, int dwExtraInfo); + + /// + /// 获取窗口文字的长度 + /// + /// 窗口标识符 + /// 文字长度 + [DllImport("user32.dll")] + public static extern int GetWindowTextLength(IntPtr hWnd); + + /// + /// 获取窗口的标题 + /// + /// 窗口标识符 + /// 窗口文字 + /// 文字长度 + /// + [DllImport("User32.dll", CharSet = CharSet.Auto)] + public static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int nMaxCount); + + // [DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)] + // internal static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount); + + /// + /// 获取某个线程的输入法布局 + /// + /// 线程ID + /// 布局码 + [DllImport("user32.dll")] + public static extern int GetKeyboardLayout(int threadId); + + /// + /// 获取按键的当前状态 + /// + /// 按键虚拟代码 + /// 表示没按下>0;按下<0 + [DllImport("user32.dll")] + public static extern short GetKeyState(int nVirtualKey); + + /// + /// 检索指定窗口所属的类的名称 + /// + /// 窗口标识符 + /// 存储窗口类名称的字符串缓冲区 + /// 缓冲区的最大字符数 + /// 如果函数成功,返回值是窗口类名的长度,不包括终止的空字符如果窗口没有类名,返回值为零如果函数失败,返回值为零,并且 GetLastError 返回值提供扩展错误信息 + [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] + public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount); + + /// + /// 检索由指定窗口拥有的下一个窗口的句柄 + /// + /// 要获取其拥有的下一个窗口的句柄的窗口 + /// 指定要获取的窗口的类型 + /// 如果函数成功,返回值是指定窗口拥有的下一个窗口的句柄如果没有更多窗口,返回值为null + [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] + public static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd); + + /// + /// 检索指定窗口的子窗口链表中的第一个窗口 + /// + /// 要获取其第一个子窗口的父窗口句柄 + /// 如果函数成功,返回值是子窗口的句柄如果没有子窗口,返回值为null + [DllImport("user32.DLL", CharSet = CharSet.Unicode, + CallingConvention = CallingConvention.StdCall, SetLastError = true)] + public static extern IntPtr GetTopWindow(IntPtr hWnd); + + /// + /// 获取线程对应的窗体信息 + /// + /// 线程 + /// + /// + [DllImport("user32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool GetGUIThreadInfo(uint idThread, ref GuiThreadInfo lpgui); + + /// + /// 获取线程对应的窗体信息 + /// + [StructLayout(LayoutKind.Sequential)] + public struct GuiThreadInfo + { + /// + /// 结构体的大小 + /// + public int cbSize; + + /// + /// 状态标志 + /// + public int flags; + + /// + /// 当前激活的窗口句柄 + /// + public IntPtr hwndActive; + + /// + /// 当前焦点的窗口句柄 + /// + public IntPtr hwndFocus; + + /// + /// 当前捕获的窗口句柄 + /// + public IntPtr hwndCapture; + + /// + /// 当前菜单所有者的窗口句柄 + /// + public IntPtr hwndMenuOwner; + + /// + /// 当前正在移动或改变大小的窗口句柄 + /// + public IntPtr hwndMoveSize; + + /// + /// 当前插入符号的窗口句柄 + /// + public IntPtr hwndCaret; + + /// + /// 插入符号的位置和大小 + /// + public System.Drawing.Rectangle rcCaret; + + /// + /// 创建GuiThreadInfo实例 + /// + /// 窗口线程的进程ID + /// GuiThreadInfo实例 + public static GuiThreadInfo Create(uint windowThreadProcessId) + { + if (windowThreadProcessId == 0) + throw new ArgumentNullException(nameof(windowThreadProcessId)); + + GuiThreadInfo gti = new(); + gti.cbSize = Marshal.SizeOf(gti); + GetGUIThreadInfo(windowThreadProcessId, ref gti); + return gti; + } + } + + /// + /// 获取当前焦点的窗口句柄 + /// + /// 窗口句柄 + [DllImport("user32.dll", SetLastError = true)] + public static extern IntPtr GetFocus(); + + /// + /// 发送消息到指定窗口 + /// + /// 窗口句柄 + /// 消息 + /// 附加参数 + /// 附加参数 + /// 消息处理结果 + [DllImport("user32.dll")] + public static extern IntPtr SendMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam); + + /// + /// 获取指定窗口的父窗口句柄 + /// + /// 窗口句柄 + /// 父窗口句柄 + [DllImport("user32.dll", SetLastError = true)] + public static extern IntPtr GetParent(IntPtr hWnd); + + /// + /// 将虚拟键代码和扫描码转换为ASCII字符 + /// + /// 虚拟键代码 + /// 扫描码 + /// 键盘状态 + /// 转换后的字符 + /// 状态标志 + /// 转换的字符数 + [DllImport("user32.dll")] + public static extern int ToAscii(int uVirtKey, int uScancode, byte[] lpdKeyState, + byte[] lpwTransKey, int fuState); + + /// + /// 获取当前激活的窗口句柄 + /// + /// 窗口句柄 + [DllImport("user32.dll", SetLastError = true)] + public static extern IntPtr GetActiveWindow(); + + /// + /// 获取窗口对应的线程和进程ID + /// + /// 窗口句柄 + /// 进程ID + /// 线程ID + [DllImport("user32.dll", SetLastError = true)] + public static extern long GetWindowThreadProcessId(IntPtr hwnd, ref int lpdwProcessId); + + /// + /// 检查窗口是否最小化 + /// + /// 窗口句柄 + /// 是否最小化 + [DllImport("user32.dll")] + public static extern bool IsIconic(int hWnd); + + /// + /// 检查窗口是否启用 + /// + /// 窗口句柄 + /// 是否启用 + [DllImport("user32.dll")] + public static extern bool IsWindowEnabled(IntPtr hWnd); + + #endregion + + #endregion +} + +internal class WmMessage +{ + #region Message + + public const uint Close = 0x0010; + + #endregion +} \ No newline at end of file diff --git a/CADShared/Basal/Win/SystemEx.cs b/CADShared/Basal/Win/SystemEx.cs index 2ec945b..50d93db 100644 --- a/CADShared/Basal/Win/SystemEx.cs +++ b/CADShared/Basal/Win/SystemEx.cs @@ -1,14 +1,15 @@ namespace IFoxCAD.Basal; +/// +/// 系统扩展 +/// public class SystemEx { - - /// /// 关闭进程 /// /// 进程名 - /// + /// 成功返回true public static bool CloseProc(string procName) { var result = false; diff --git a/CADShared/Basal/Win/Win32Api.cs b/CADShared/Basal/Win/Win32Api.cs deleted file mode 100644 index e3973dc..0000000 --- a/CADShared/Basal/Win/Win32Api.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace IFoxCAD.Basal; - -public static class Win32Api -{ - #region Win32 - - /// - /// 查找窗口 - /// - /// - /// - /// - [DllImport("user32.dll", SetLastError = true)] - public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); - - [DllImport("user32.dll", CharSet = CharSet.Auto)] - public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam); - - /// - /// 关闭窗口 - /// - /// - public static void CloseWindow(IntPtr hWnd) - { - SendMessage(hWnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero); - } - - // 定义 WM_CLOSE 消息 - const UInt32 WM_CLOSE = 0x0010; - - #endregion -} \ No newline at end of file diff --git a/CADShared/Basal/Win/WindowsAPI.cs b/CADShared/Basal/Win/WindowsAPI.cs index 210ace1..1fd45b6 100644 --- a/CADShared/Basal/Win/WindowsAPI.cs +++ b/CADShared/Basal/Win/WindowsAPI.cs @@ -2,9 +2,11 @@ #define Marshal namespace IFoxCAD.Basal; + public partial class WindowsAPI { #region kernel32 + // https://blog.csdn.net/haelang/article/details/45147121 [DllImport("kernel32.dll")] public extern static uint GetLastError(); @@ -33,14 +35,15 @@ public partial class WindowsAPI /// /// [DllImport("kernel32.dll", SetLastError = true)] - static extern IntPtr GlobalLock(IntPtr hMem); + private static extern IntPtr GlobalLock(IntPtr hMem); + /// /// 解锁内存 /// /// /// [DllImport("kernel32.dll", SetLastError = true)] - static extern bool GlobalUnlock(IntPtr hMem); + private static extern bool GlobalUnlock(IntPtr hMem); #if !Marshal /* const int GMEM_MOVEABLE = 0x0002; @@ -97,7 +100,11 @@ public static bool GlobalLockTask(IntPtr data, Action task) return false; task.Invoke(ptr); } - finally { GlobalUnlock(data); } + finally + { + GlobalUnlock(data); + } + return true; } @@ -149,6 +156,7 @@ public static bool GlobalLockTask(IntPtr data, Action task) result = (T?)Marshal.PtrToStructure(new IntPtr(pB), typeof(T)); } } + return result; } @@ -158,7 +166,7 @@ public static bool GlobalLockTask(IntPtr data, Action task) ///
    /// 要转换的结构体 [MethodImpl] - public static byte[] StructToBytes(T structObj) where T : unmanaged/*非托管的T从来不为空*/ + public static byte[] StructToBytes(T structObj) where T : unmanaged /*非托管的T从来不为空*/ { // 得到结构体的大小 var typeSize = Marshal.SizeOf(structObj); @@ -225,12 +233,17 @@ public static void StructToPtr(T structObj, } } #endif + #endregion } -public partial class WindowsAPI +/// +/// 系统Api +/// +public static partial class WindowsAPI { #region imm32 + /// /// 获取输入法的虚拟键码 /// @@ -238,6 +251,7 @@ public partial class WindowsAPI /// [DllImport("imm32.dll")] public static extern IntPtr ImmGetVirtualKey(IntPtr hWnd); + /// /// 获取输入法状态 /// @@ -255,6 +269,7 @@ public partial class WindowsAPI /// [DllImport("imm32.dll")] public static extern IntPtr ImmGetContext(IntPtr hwnd); + /// /// 设置输入法的当前状态 /// @@ -263,6 +278,7 @@ public partial class WindowsAPI /// [DllImport("imm32.dll")] public static extern bool ImmSetOpenStatus(IntPtr hwnd, bool fOpen); + /// /// 输入法打开状态 /// @@ -270,191 +286,26 @@ public partial class WindowsAPI /// 非0打开,0关闭;(true中文,false英文) [DllImport("imm32.dll")] public static extern bool ImmGetOpenStatus(IntPtr hwnd); + #endregion } public partial class WindowsAPI { - #region user32 - - /// - /// 获取窗口客户区的大小,客户区为窗口中除标题栏,菜单栏之外的地方 - /// - /// - /// - /// - [DllImport("user32.dll", CharSet = CharSet.Auto, EntryPoint = "GetClientRect")] - public static extern bool GetClientRect(IntPtr hwnd, out IntRect lpRect); - - /// - /// 查找主线程
    - /// 代替
    - /// 托管线程和他们不一样: - ///
    - /// 主窗口 - /// 进程ID - /// 线程ID - [DllImport("user32.dll", SetLastError = true)] - public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId); - - /// - /// 设置焦点 - /// - /// - /// - [DllImport("user32.dll")] - public static extern IntPtr SetFocus(IntPtr hWnd); - - /// - /// 获取当前窗口 - /// - /// 当前窗口标识符 - [DllImport("user32.dll")] - public static extern IntPtr GetForegroundWindow(); - /// - /// 将一个消息的组成部分合成一个消息并放入对应线程消息队列的方法 - /// - /// 控件句柄 - /// 消息是什么。键盘按键、鼠标点击还是其他 - /// - /// - /// - [DllImport("user32.dll")] - public static extern bool PostMessage(IntPtr hhwnd, int msg, IntPtr wparam, IntPtr lparam); - /// - /// 发送击键 - /// - /// - /// - /// - /// - [DllImport("user32.dll", EntryPoint = "keybd_event")] - public static extern void KeybdEvent(byte bVk, byte bScan, int dwFlags, int dwExtraInfo); - /// - /// 获取窗口文字的长度 - /// - /// 窗口标识符 - /// 文字长度 - [DllImport("user32.dll")] - public static extern int GetWindowTextLength(IntPtr hWnd); - /// - /// 获取窗口的标题 - /// - /// 窗口标识符 - /// 窗口文字 - /// 文字长度 - /// - [DllImport("User32.dll", CharSet = CharSet.Auto)] - public static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int nMaxCount); - - // [DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)] - // internal static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount); - - - /// - /// 获取某个线程的输入法布局 - /// - /// 线程ID - /// 布局码 - [DllImport("user32.dll")] - public static extern int GetKeyboardLayout(int threadid); - - - /// - /// 获取按键的当前状态 - /// - /// 按键虚拟代码 - /// 表示没按下>0;按下<0 - [DllImport("user32.dll")] - public static extern short GetKeyState(int nVirtKey); - /// - /// 检索指定窗口所属的类的名称。 - /// - /// 窗口标识符 - /// - /// - /// - [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] - public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount); - - [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] - public static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd); - - [DllImport("user32.DLL", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall, SetLastError = true)] - public static extern IntPtr GetTopWindow(IntPtr hWnd); - - - /// - /// 获取线程对应的窗体信息 - /// - /// 线程 - /// - /// - [DllImport("user32.dll")] - [return: MarshalAs(UnmanagedType.Bool)] - static extern bool GetGUIThreadInfo(uint idThread, ref GuiThreadInfo lpgui); - - /// - /// 获取线程对应的窗体信息 - /// - [StructLayout(LayoutKind.Sequential)] - public struct GuiThreadInfo - { - public int cbSize; - public int flags; - public IntPtr hwndActive; - public IntPtr hwndFocus; - public IntPtr hwndCapture; - public IntPtr hwndMenuOwner; - public IntPtr hwndMoveSize; - public IntPtr hwndCaret; - public System.Drawing.Rectangle rcCaret; - - public static GuiThreadInfo Create(uint windowThreadProcessId) - { - if (windowThreadProcessId == 0) - throw new ArgumentNullException(nameof(windowThreadProcessId)); - - GuiThreadInfo gti = new(); - gti.cbSize = Marshal.SizeOf(gti); - GetGUIThreadInfo(windowThreadProcessId, ref gti); - return gti; - } - } - - [DllImport("user32.dll", SetLastError = true)] - public static extern IntPtr GetFocus(); - - [DllImport("user32.dll")] - public static extern IntPtr SendMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam); - - [DllImport("user32.dll", SetLastError = true)] - public static extern IntPtr GetParent(IntPtr hWnd); - - [DllImport("user32.dll")] - public static extern int ToAscii(int uVirtKey, int uScancode, byte[] lpdKeyState, byte[] lpwTransKey, int fuState); - - [DllImport("user32.dll", SetLastError = true)] - public static extern IntPtr GetActiveWindow(); - - [DllImport("user32.dll", SetLastError = true)] - public static extern long GetWindowThreadProcessId(IntPtr hwnd, ref int lpdwProcessId); + #region 键盘钩子 - [DllImport("user32.dll", SetLastError = true)] - public static extern bool IsIconic(int hWnd); + public delegate IntPtr CallBack(int nCode, int wParam, IntPtr lParam); [DllImport("user32.dll")] - public static extern bool IsWindowEnabled(IntPtr hWnd); - #endregion + public static extern IntPtr SetWindowsHookEx(HookType idHook, CallBack lpfn, IntPtr hmod, + int dwThreadId); - #region 键盘钩子 - public delegate IntPtr CallBack(int nCode, int wParam, IntPtr lParam); - [DllImport("user32.dll")] - public static extern IntPtr SetWindowsHookEx(HookType idHook, CallBack lpfn, IntPtr hmod, int dwThreadId); [DllImport("user32.dll")] public static extern IntPtr UnhookWindowsHookEx(IntPtr hHook); + [DllImport("user32.dll")] public static extern IntPtr CallNextHookEx(IntPtr hHook, int ncode, int wParam, IntPtr lParam); + /// /// Hook键盘数据结构 /// @@ -465,21 +316,23 @@ public static GuiThreadInfo Create(uint windowThreadProcessId) [StructLayout(LayoutKind.Sequential)] public struct KeyboardHookStruct { - public int VkCode; // 键码,该代码必须有一个价值的范围1至254 - public int ScanCode; // 指定的硬件扫描码的关键 - public int Flags; // 键标志 - public int Time; // 指定的时间戳记的这个讯息 - public int DwExtraInfo; // 指定额外信息相关的信息 + public int VkCode; // 键码,该代码必须有一个价值的范围1至254 + public int ScanCode; // 指定的硬件扫描码的关键 + public int Flags; // 键标志 + public int Time; // 指定的时间戳记的这个讯息 + public int DwExtraInfo; // 指定额外信息相关的信息 public static KeyboardHookStruct Create(IntPtr lParam) { return (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct)); } + public void ToPtr(IntPtr lParam) { Marshal.StructureToPtr(this, lParam, true); } } + /// /// 注册表增加低级钩子超时处理,防止系统不允许, /// 否则:偶发性出现 键盘钩子不能用了,而且退出时产生 1404 错误 @@ -492,11 +345,21 @@ public static void CheckLowLevelHooksTimeout(int setLowLevel = 25000) if ((int)registryKey.GetValue(llh, 0) < setLowLevel) registryKey.SetValue(llh, setLowLevel, RegistryValueKind.DWord); } + #endregion } public partial class WindowsAPI { + /// + /// 关闭窗口 + /// + /// + public static void CloseWindow(IntPtr hWnd) + { + PInvokeUser32.SendMessage(hWnd, WmMessage.Close, IntPtr.Zero, IntPtr.Zero); + } + [DllImport("user32.dll")] public static extern bool GetWindowRect(IntPtr hwnd, ref IntRect lpRect); @@ -508,12 +371,13 @@ public partial class WindowsAPI public struct IntRect { [DebuggerBrowsable(DebuggerBrowsableState.Never)] - private string DebuggerDisplay => $"(Left:{_Left},Top:{_Top},Right:{_Right},Bottom:{_Bottom})"; + private string DebuggerDisplay => + $"(Left:{_Left},Top:{_Top},Right:{_Right},Bottom:{_Bottom})"; - int _Left; - int _Top; - int _Right; - int _Bottom; + private int _Left; + private int _Top; + private int _Right; + private int _Bottom; public int Left => _Left; public int Top => _Top; public int Right => _Right; @@ -529,32 +393,34 @@ public IntRect(int left, int top, int right, int bottom) _Bottom = bottom; } - static readonly IntRect _Zero = new(0, 0, 0, 0); + private static readonly IntRect _Zero = new(0, 0, 0, 0); public static IntRect Zero => _Zero; public override string ToString() => $"({_Left},{_Top},{_Right},{_Bottom})"; #region 重载运算符_比较 + public bool Equals(IntRect other) { - return - _Left == other._Left && - _Top == other._Top && - _Right == other._Right && - _Bottom == other._Bottom; + return _Left == other._Left && _Top == other._Top && _Right == other._Right && + _Bottom == other._Bottom; } + public static bool operator !=(IntRect a, IntRect b) { return !(a == b); } + public static bool operator ==(IntRect a, IntRect b) { return a.Equals(b); } + public override bool Equals(object obj) { return obj is IntRect d && Equals(d); } + public override int GetHashCode() { return ((_Left, _Top).GetHashCode(), _Right).GetHashCode() ^ _Bottom.GetHashCode(); @@ -564,6 +430,7 @@ public IntRect Clone() { return (IntRect)MemberwiseClone(); } + #endregion } @@ -576,6 +443,7 @@ public struct IntSize { [DebuggerBrowsable(DebuggerBrowsableState.Never)] private string DebuggerDisplay => $"(Hight:{Hight},Width:{Width})"; + public int Hight; public int Width; @@ -584,6 +452,7 @@ public IntSize(int cx, int cy) Hight = cx; Width = cy; } + public override string ToString() => $"({Hight},{Width})"; } @@ -608,6 +477,7 @@ public Point3D(double x, double y, double z) Y = y; Z = z; } + //public static implicit operator Point3D(Point3d pt) //{ // return new Point3D(pt.X, pt.Y, pt.Z); @@ -628,31 +498,33 @@ public void ToPtr(IntPtr lParam) Marshal.StructureToPtr(this, lParam, true); } - #region 重载运算符_比较 + public bool Equals(Point3D other) { - return - X == other.X && - Y == other.Y && - Z == other.Z; + return X == other.X && Y == other.Y && Z == other.Z; } + public static bool operator !=(Point3D a, Point3D b) { return !(a == b); } + public static bool operator ==(Point3D a, Point3D b) { return a.Equals(b); } + public override bool Equals(object obj) { return obj is Point3D d && Equals(d); } + public override int GetHashCode() { return (X, Y).GetHashCode() ^ Z.GetHashCode(); } + #endregion } } diff --git a/CADShared/CADShared.projitems b/CADShared/CADShared.projitems index 6974a92..916bc51 100644 --- a/CADShared/CADShared.projitems +++ b/CADShared/CADShared.projitems @@ -27,7 +27,7 @@ - + diff --git a/CADShared/ExtensionMethod/PaneEx.cs b/CADShared/ExtensionMethod/PaneEx.cs index f06828c..6295ac5 100644 --- a/CADShared/ExtensionMethod/PaneEx.cs +++ b/CADShared/ExtensionMethod/PaneEx.cs @@ -1,5 +1,8 @@ namespace IFoxCAD.Cad; +/// +/// 托盘类扩展 +/// public static class PaneEx { /// @@ -152,9 +155,21 @@ public static void SetRightMargin(this Pane pane, PaneMarginType marginType) } } +/// +/// 托盘边距类型 +/// public enum PaneMarginType : byte { + /// + /// 无 + /// NONE, + /// + /// 小边距 + /// SMALL, + /// + /// 大边距 + /// LARGE } \ No newline at end of file diff --git a/CADShared/ExtensionMethod/SingleKeyWordHook.cs b/CADShared/ExtensionMethod/SingleKeyWordHook.cs index a0071db..e774feb 100644 --- a/CADShared/ExtensionMethod/SingleKeyWordHook.cs +++ b/CADShared/ExtensionMethod/SingleKeyWordHook.cs @@ -233,7 +233,9 @@ private static void KeyBoardSendKey(Keys key, byte bScan = 0, uint dwFlags = 0, #endregion } - +/// +/// 单文本关键字钩子扩展 +/// public static class SingleKeywordHookEx { /// @@ -250,9 +252,23 @@ public static SingleKeyWordHook HookSingleKeyword(this KeywordCollection keyword } } +/// +/// 单关键字工作模式 +/// public enum SingleKeyWordWorkType : byte { + /// + /// Esc模式 + /// ESCAPE, + + /// + /// Enter模式 + /// ENTER, + + /// + /// Write Line 模式 + /// WRITE_LINE, -} \ No newline at end of file +} diff --git a/CADShared/ExtensionMethod/WindowEx.cs b/CADShared/ExtensionMethod/WindowEx.cs index ef0b46c..f0ac91f 100644 --- a/CADShared/ExtensionMethod/WindowEx.cs +++ b/CADShared/ExtensionMethod/WindowEx.cs @@ -4,8 +4,15 @@ namespace IFoxCAD.Cad; +/// +/// 窗体扩展 +/// public static class WindowEx { + /// + /// 添加Esc退出 + /// + /// wpf窗体 public static void AddEscQuit(this Window window) { window.KeyDown -= Window_KeyDown_Esc; @@ -17,8 +24,6 @@ public static void AddEscQuit(this Window window) /// /// 关闭时减掉事件 /// - /// - /// private static void WindowOnClosed(object sender, EventArgs e) { if (sender is not Window window) @@ -42,6 +47,11 @@ private static void Window_KeyDown_Esc(object sender, System.Windows.Input.KeyEv window.Close(); } + /// + /// 判断wpf是否为模态 + /// + /// 窗体 + /// 是则返回true public static bool IsModel(this Window window) { return (bool)(typeof(Window) @@ -78,6 +88,10 @@ public static void SetSizeByScreenResolution(this PaletteSet paletteSet, int wid paletteSet.SetSize(new Size(newWidth, newHeight)); } + /// + /// 获取屏幕比例 + /// + /// 比例 public static double GetScreenScale() { var scale = Graphics.FromHwnd(IntPtr.Zero).DpiX / 96.0f; diff --git a/CADShared/Initialize/AssemInfo.cs b/CADShared/Initialize/AssemInfo.cs index e1ee17d..1829622 100644 --- a/CADShared/Initialize/AssemInfo.cs +++ b/CADShared/Initialize/AssemInfo.cs @@ -6,6 +6,10 @@ [Serializable] public struct AssemInfo { + /// + /// 程序集信息 + /// + /// 程序集 public AssemInfo(Assembly assembly) { Loader = assembly.Location; diff --git a/CADShared/Runtime/AcPreferences.cs b/CADShared/Runtime/AcPreferences.cs index 4fe234a..53c4c9f 100644 --- a/CADShared/Runtime/AcPreferences.cs +++ b/CADShared/Runtime/AcPreferences.cs @@ -1,7 +1,13 @@ namespace IFoxCAD.Cad; +/// +/// AcapPreference扩展 +/// public static class AcPreferences { + /// + /// 显示属性 + /// public static class Display { static Display() diff --git a/CADShared/Runtime/SystemVariableManager.cs b/CADShared/Runtime/SystemVariableManager.cs index d0b6506..1c0118d 100644 --- a/CADShared/Runtime/SystemVariableManager.cs +++ b/CADShared/Runtime/SystemVariableManager.cs @@ -343,6 +343,9 @@ public static bool PickFirst #region T + /// + /// 视图点 + /// public static Point3d Target => (Point3d)Acaop.GetSystemVariable(nameof(Target)); #endregion diff --git a/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj b/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj index 167c76b..7e86d5c 100644 --- a/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj +++ b/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj @@ -38,8 +38,9 @@ none - True + false $(DefineConstants);acad + bin\Release\IFoxCAD.AutoCad.xml diff --git a/IFoxCAD.sln.DotSettings b/IFoxCAD.sln.DotSettings index 5dc555a..4cfd0e2 100644 --- a/IFoxCAD.sln.DotSettings +++ b/IFoxCAD.sln.DotSettings @@ -1,4 +1,5 @@  + API DB OS True @@ -9,8 +10,10 @@ True True True + True True True + True True True True -- Gitee From 314d910fd9e1e55af31b43b86fc47f87206eeb90 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Tue, 5 Nov 2024 11:49:25 +0800 Subject: [PATCH 349/453] =?UTF-8?q?=E5=8F=91=E5=B8=830.9.1.5=E7=89=88?= =?UTF-8?q?=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/Basal/Win/WindowsAPI.cs | 12 +++++++----- IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj | 5 +++-- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/CADShared/Basal/Win/WindowsAPI.cs b/CADShared/Basal/Win/WindowsAPI.cs index 1fd45b6..bd20e90 100644 --- a/CADShared/Basal/Win/WindowsAPI.cs +++ b/CADShared/Basal/Win/WindowsAPI.cs @@ -15,7 +15,7 @@ public partial class WindowsAPI public static extern long GetHandleInformation(long hObject, ref long lpdwFlags); [DllImport("kernel32.dll")] - public static extern IntPtr GetModuleHandle(string ModuleName); + public static extern IntPtr GetModuleHandle(string moduleName); [DllImport("kernel32.dll")] public static extern int GetCurrentThreadId(); @@ -145,7 +145,7 @@ public static bool GlobalLockTask(IntPtr data, Action task) [MethodImpl] public static T? BytesToStruct(byte[] bytes) { - T? result = default; + T? result; unsafe { // 安全指针方法 @@ -342,8 +342,10 @@ public static void CheckLowLevelHooksTimeout(int setLowLevel = 25000) { const string llh = "LowLevelHooksTimeout"; using var registryKey = Registry.CurrentUser.OpenSubKey("Control Panel\\Desktop", true); - if ((int)registryKey.GetValue(llh, 0) < setLowLevel) + if (registryKey is not null && (int)registryKey.GetValue(llh, 0) < setLowLevel) + { registryKey.SetValue(llh, setLowLevel, RegistryValueKind.DWord); + } } #endregion @@ -416,7 +418,7 @@ public bool Equals(IntRect other) return a.Equals(b); } - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is IntRect d && Equals(d); } @@ -515,7 +517,7 @@ public bool Equals(Point3D other) return a.Equals(b); } - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is Point3D d && Equals(d); } diff --git a/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj b/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj index 7e86d5c..381fe20 100644 --- a/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj +++ b/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj @@ -13,11 +13,12 @@ + true true IFox.CAD.ACAD IFox.CAD.ACAD IFox.CAD.ACAD - 0.9.1.4 + 0.9.1.5 xsfhlzh, vicwjb, liuqihong, DYH 基于.NET的二次开发基本类库. https://www.nuget.org/packages/IFox.CAD.ACAD/ @@ -26,7 +27,7 @@ IFox,Cad,AutoCad,C#,NET, InspireFunction readme.md - 补充CurveEx扩展类 + 补充xml文档 LICENSE -- Gitee From d8a89c876349c1aedccca2b8b1d6946e0abf4aec Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Mon, 11 Nov 2024 15:35:17 +0800 Subject: [PATCH 350/453] =?UTF-8?q?=E6=B7=BB=E5=8A=A0PromptOptionsEx?= =?UTF-8?q?=E4=BA=A4=E4=BA=92=E9=80=89=E9=A1=B9=E6=89=A9=E5=B1=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/CADShared.projitems | 1 + CADShared/ExtensionMethod/PromptOptionsEx.cs | 88 ++++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 CADShared/ExtensionMethod/PromptOptionsEx.cs diff --git a/CADShared/CADShared.projitems b/CADShared/CADShared.projitems index 916bc51..a1e20cb 100644 --- a/CADShared/CADShared.projitems +++ b/CADShared/CADShared.projitems @@ -60,6 +60,7 @@ + diff --git a/CADShared/ExtensionMethod/PromptOptionsEx.cs b/CADShared/ExtensionMethod/PromptOptionsEx.cs new file mode 100644 index 0000000..5b4195c --- /dev/null +++ b/CADShared/ExtensionMethod/PromptOptionsEx.cs @@ -0,0 +1,88 @@ +namespace IFoxCAD.CAD.ExtensionMethod; + +/// +/// 交互设置扩展 +/// +[SuppressMessage("ReSharper", "StringLiteralTypo")] +public static class PromptOptionsEx +{ + /// + /// 保留关键字列表 + /// + internal static readonly HashSet SsgetSaveKeywords = + [ + "WINDOW", "LAST", "CROSSWINDOW", "BOX", "ALL", "FENCE", "WPOLYGON", "CPOLYGON", "GROUP", + "ADD", "REMOVE", "MULTIPLE", "PREVIOUS", "UNDO", "AUTO", "SINGLE", "SUBOBJECT", "OBJECT" + ]; + + /// + /// 添加关键字(顺序为:关键字, 描述, 关键字, 描述)
    + /// 例如 pso.AddKeywords("SZ", "设置", "OP", "选项") + ///
    + /// 选择集选项 + /// 关键字 + public static void AddKeywords(this PromptSelectionOptions pso, params string[] keywords) + { + for (var i = 0; i < keywords.Length / 2; i++) + { + var key = keywords[i].ToUpper(); + if (SsgetSaveKeywords.FirstOrDefault(e => e.StartsWith(key)) is { } saveKey) + { + throw new ArgumentException($"关键字{key}与选择集保留关键字{saveKey}冲突"); + } + + var message = keywords[i + 1]; + var end = $"({key})"; + if (!message.EndsWith(end)) + { + message += end; + } + + pso.Keywords.Add(key, key, message); + } + + var displayString = pso.Keywords.GetDisplayString(true); + pso.MessageForAdding += displayString; + pso.MessageForRemoval += displayString; + } + + /// + /// 将关键视视为错误抛出 + /// + /// 选择集选项 + public static void ThrowKeywordAsException(this PromptSelectionOptions pso) + { + pso.KeywordInput -= PsoOnKeywordInput; + pso.KeywordInput += PsoOnKeywordInput; + } + + /// + /// 选择集关键字输入时用于抛错的事件 + /// + private static void PsoOnKeywordInput(object sender, SelectionTextInputEventArgs e) + { + if (string.IsNullOrEmpty(e.Input)) + return; + throw new KeywordException(e.Input.ToUpper()); + } +} + +/// +/// 关键字错误 +/// +public class KeywordException : Exception +{ + /// + /// 关键字错误 + /// + /// 关键字 + public KeywordException(string input) + { + Input = input; + } + + /// + /// 关键字 + /// + public string Input { get; } +} \ No newline at end of file -- Gitee From a9fb6afd463d277ddb9e2f7efff99f326a834161 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Mon, 11 Nov 2024 15:37:37 +0800 Subject: [PATCH 351/453] =?UTF-8?q?=E8=A7=A3=E5=86=B3=E8=AD=A6=E5=91=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/ExtensionMethod/PromptOptionsEx.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CADShared/ExtensionMethod/PromptOptionsEx.cs b/CADShared/ExtensionMethod/PromptOptionsEx.cs index 5b4195c..0f109b9 100644 --- a/CADShared/ExtensionMethod/PromptOptionsEx.cs +++ b/CADShared/ExtensionMethod/PromptOptionsEx.cs @@ -1,4 +1,5 @@ -namespace IFoxCAD.CAD.ExtensionMethod; +// ReSharper disable UnusedAutoPropertyAccessor.Global +namespace IFoxCAD.CAD.ExtensionMethod; /// /// 交互设置扩展 @@ -9,7 +10,7 @@ public static class PromptOptionsEx /// /// 保留关键字列表 /// - internal static readonly HashSet SsgetSaveKeywords = + internal static readonly HashSet SsGetSaveKeywords = [ "WINDOW", "LAST", "CROSSWINDOW", "BOX", "ALL", "FENCE", "WPOLYGON", "CPOLYGON", "GROUP", "ADD", "REMOVE", "MULTIPLE", "PREVIOUS", "UNDO", "AUTO", "SINGLE", "SUBOBJECT", "OBJECT" @@ -26,7 +27,7 @@ public static void AddKeywords(this PromptSelectionOptions pso, params string[] for (var i = 0; i < keywords.Length / 2; i++) { var key = keywords[i].ToUpper(); - if (SsgetSaveKeywords.FirstOrDefault(e => e.StartsWith(key)) is { } saveKey) + if (SsGetSaveKeywords.FirstOrDefault(e => e.StartsWith(key)) is { } saveKey) { throw new ArgumentException($"关键字{key}与选择集保留关键字{saveKey}冲突"); } -- Gitee From a75cba449fe1dd2652fb66e7f661ec14e247eaab Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Mon, 11 Nov 2024 20:02:03 +0800 Subject: [PATCH 352/453] =?UTF-8?q?=E4=BF=AE=E6=AD=A3zoom=E5=9C=A8plan?= =?UTF-8?q?=E9=9D=9E=E9=BB=98=E8=AE=A4=E7=9A=84=E6=83=85=E5=86=B5=E4=B8=8B?= =?UTF-8?q?=E4=B8=8D=E6=AD=A3=E7=A1=AE=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/ExtensionMethod/EditorEx.cs | 197 +++++++++++++------------ IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj | 4 +- 2 files changed, 102 insertions(+), 99 deletions(-) diff --git a/CADShared/ExtensionMethod/EditorEx.cs b/CADShared/ExtensionMethod/EditorEx.cs index 3290bfb..eaaba65 100644 --- a/CADShared/ExtensionMethod/EditorEx.cs +++ b/CADShared/ExtensionMethod/EditorEx.cs @@ -30,25 +30,17 @@ public static SelectionSet SelectByLineWeight(this Editor editor, LineWeight lin { OpFilter filter = new OpEqual(370, lineWeight); - var lays = - DBTrans.Top.LayerTable - .GetRecords() - .Where(ltr => ltr.LineWeight == lineWeight) - .Select(ltr => ltr.Name) - .ToArray(); + var lays = DBTrans.Top.LayerTable.GetRecords() + .Where(ltr => ltr.LineWeight == lineWeight) + .Select(ltr => ltr.Name) + .ToArray(); if (lays.Length > 0) { - filter = - new OpOr - { - filter, - new OpAnd - { - { 8, string.Join(",", lays) }, - { 370, LineWeight.ByLayer } - } - }; + filter = new OpOr + { + filter, new OpAnd { { 8, string.Join(",", lays) }, { 370, LineWeight.ByLayer } } + }; } var res = editor.SelectAll(filter); @@ -67,10 +59,8 @@ public static SelectionSet SelectByLineWeight(this Editor editor, LineWeight lin /// 不用使用下列关键字 "Window/Last/Crossing/BOX/ALL/Fence/WPolygon/CPolygon/Group/Add/Remove/Multiple/Previous/Undo/AUto/Single" /// /// - public static PromptSelectionResult SSGet(this Editor editor, - string? mode = null, - SelectionFilter? filter = null, - (string add, string remove)? messages = null, + public static PromptSelectionResult SSGet(this Editor editor, string? mode = null, + SelectionFilter? filter = null, (string add, string remove)? messages = null, Dictionary? keywords = null) { PromptSelectionOptions pso = new(); @@ -108,7 +98,6 @@ public static PromptSelectionResult SSGet(this Editor editor, return $"{value.Item1}({key})"; }); - pso.MessageForAdding += $" [{string.Join("/", str)}]"; pso.KeywordInput += (_, e) => { @@ -121,7 +110,6 @@ public static PromptSelectionResult SSGet(this Editor editor, return ss; } - /* * // 定义选择集选项 * var pso = new PromptSelectionOptions @@ -236,7 +224,6 @@ public static void SsgetAddKeys(this PromptSelectionOptions pso, pso.KeywordInput += (_, e) => { dicActions[e.Input].Invoke(); }; } - // #region 即时选择样板 // /// // /// 即时选择,框选更新关键字 @@ -267,7 +254,6 @@ public static void SsgetAddKeys(this PromptSelectionOptions pso, // var psr = Env.Editor.GetSelection(pso, sf); // // 处理代码 - // } // catch (Exception ex)// 捕获关键字 // { @@ -373,9 +359,7 @@ public static void Message(Exception ex) { try { - System.Windows.Forms.MessageBox.Show( - ex.ToString(), - "Error", + System.Windows.Forms.MessageBox.Show(ex.ToString(), "Error", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error); } @@ -394,9 +378,7 @@ public static void InfoMessageBox(string caption, string message) { try { - System.Windows.Forms.MessageBox.Show( - message, - caption, + System.Windows.Forms.MessageBox.Show(message, caption, System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Information); } @@ -469,9 +451,9 @@ public static void WriteMessage(string format, params object[] args) /// 有,没有 public static bool HasEditor() { - return Acaop.DocumentManager.MdiActiveDocument is not null - && Acaop.DocumentManager.Count != 0 - && Acaop.DocumentManager.MdiActiveDocument.Editor is not null; + return Acaop.DocumentManager.MdiActiveDocument is not null && + Acaop.DocumentManager.Count != 0 && + Acaop.DocumentManager.MdiActiveDocument.Editor is not null; } /// @@ -480,8 +462,7 @@ public static bool HasEditor() /// 可以打印,不可以打印 public static bool Acceptable() { - return HasEditor() - && !Acaop.DocumentManager.MdiActiveDocument.Editor.IsDragging; + return HasEditor() && !Acaop.DocumentManager.MdiActiveDocument.Editor.IsDragging; } #endregion Info @@ -530,10 +511,10 @@ public static List GetLines(IEnumerable pnts, bool isClosed /// 点表 /// 颜色码 /// 是否闭合, 为闭合, 为不闭合 - public static void DrawVectors(this Editor editor, IEnumerable pnts, short colorIndex, bool isClosed) + public static void DrawVectors(this Editor editor, IEnumerable pnts, short colorIndex, + bool isClosed) { - var rlst = - new LispList { { LispDataType.Int16, colorIndex } }; + var rlst = new LispList { { LispDataType.Int16, colorIndex } }; rlst.AddRange(GetLines(pnts, isClosed)); editor.DrawVectors(new(rlst.ToArray()), Matrix3d.Identity); } @@ -557,10 +538,10 @@ public static void DrawVectors(this Editor editor, IEnumerable pnts, sh /// 颜色码 /// 半径 /// 多边形边的个数 - public static void DrawCircles(this Editor editor, IEnumerable pnts, short colorIndex, double radius, int numEdges) + public static void DrawCircles(this Editor editor, IEnumerable pnts, short colorIndex, + double radius, int numEdges) { - var rlst = - new LispList { { LispDataType.Int16, colorIndex } }; + var rlst = new LispList { { LispDataType.Int16, colorIndex } }; foreach (var pnt in pnts) { @@ -587,7 +568,8 @@ public static void DrawCircles(this Editor editor, IEnumerable pnts, sh /// 颜色码 /// 半径 /// 多边形边的个数 - public static void DrawCircle(this Editor editor, Point2d pnt, short colorIndex, double radius, int numEdges) + public static void DrawCircle(this Editor editor, Point2d pnt, short colorIndex, double radius, + int numEdges) { var vec = Vector2d.XAxis * radius; var angle = Math.PI * 2 / numEdges; @@ -606,15 +588,16 @@ public static void DrawCircle(this Editor editor, Point2d pnt, short colorIndex, /// 点表 /// CAD颜色索引;默认:1为红色 /// 是否高亮显示;为高亮显示,默认:为不高亮显示 - public static void DrawLineVectors(this Editor editor, IEnumerable points, int colorIndex = 1, - bool drawHighlighted = false) + public static void DrawLineVectors(this Editor editor, IEnumerable points, + int colorIndex = 1, bool drawHighlighted = false) { Point3d endPoint1, endPoint2; using var itor = points.GetEnumerator(); while (itor.MoveNext()) { endPoint1 = itor.Current; - if (!itor.MoveNext()) return; + if (!itor.MoveNext()) + return; endPoint2 = itor.Current; editor.DrawVector(endPoint1, endPoint2, colorIndex, drawHighlighted); } @@ -628,11 +611,12 @@ public static void DrawLineVectors(this Editor editor, IEnumerable poin /// CAD颜色索引;默认:1为红色 /// 是否闭合; 为闭合,默认: 为不闭合 /// 是否高亮显示;为高亮显示,默认:为不高亮显示 - public static void DrawEndToEndVectors(this Editor editor, IEnumerable points, int colorIndex = 1, - bool isclose = false, bool drawHighlighted = false) + public static void DrawEndToEndVectors(this Editor editor, IEnumerable points, + int colorIndex = 1, bool isclose = false, bool drawHighlighted = false) { using var itor = points.GetEnumerator(); - if (!points.Any() || !itor.MoveNext()) return; + if (!points.Any() || !itor.MoveNext()) + return; Point3d endPoint1 = itor.Current, endPoint2 = new(), firstEndPoint = endPoint1; while (itor.MoveNext()) { @@ -750,20 +734,28 @@ public static Matrix3d GetMatrixFromPDcsToMDcs(this Editor editor) /// 源坐标系 /// 目标坐标系 /// 变换矩阵 - public static Matrix3d GetMatrix(this Editor editor, CoordinateSystemCode from, CoordinateSystemCode to) + public static Matrix3d GetMatrix(this Editor editor, CoordinateSystemCode from, + CoordinateSystemCode to) { return (from, to) switch { (CoordinateSystemCode.Wcs, CoordinateSystemCode.Ucs) => editor.GetMatrixFromWcsToUcs(), - (CoordinateSystemCode.Wcs, CoordinateSystemCode.MDcs) => editor.GetMatrixFromWcsToMDcs(), + (CoordinateSystemCode.Wcs, CoordinateSystemCode.MDcs) => + editor.GetMatrixFromWcsToMDcs(), (CoordinateSystemCode.Ucs, CoordinateSystemCode.Wcs) => editor.GetMatrixFromUcsToWcs(), - (CoordinateSystemCode.Ucs, CoordinateSystemCode.MDcs) => editor.GetMatrixFromUcsToWcs() * editor.GetMatrixFromWcsToMDcs(), - (CoordinateSystemCode.MDcs, CoordinateSystemCode.Wcs) => editor.GetMatrixFromMDcsToWcs(), - (CoordinateSystemCode.MDcs, CoordinateSystemCode.Ucs) => editor.GetMatrixFromMDcsToWcs() * editor.GetMatrixFromWcsToUcs(), - (CoordinateSystemCode.MDcs, CoordinateSystemCode.PDcs) => editor.GetMatrixFromMDcsToPDcs(), - (CoordinateSystemCode.PDcs, CoordinateSystemCode.MDcs) => editor.GetMatrixFromPDcsToMDcs(), + (CoordinateSystemCode.Ucs, CoordinateSystemCode.MDcs) => + editor.GetMatrixFromUcsToWcs() * editor.GetMatrixFromWcsToMDcs(), + (CoordinateSystemCode.MDcs, CoordinateSystemCode.Wcs) => + editor.GetMatrixFromMDcsToWcs(), + (CoordinateSystemCode.MDcs, CoordinateSystemCode.Ucs) => + editor.GetMatrixFromMDcsToWcs() * editor.GetMatrixFromWcsToUcs(), + (CoordinateSystemCode.MDcs, CoordinateSystemCode.PDcs) => + editor.GetMatrixFromMDcsToPDcs(), + (CoordinateSystemCode.PDcs, CoordinateSystemCode.MDcs) => + editor.GetMatrixFromPDcsToMDcs(), (CoordinateSystemCode.PDcs, CoordinateSystemCode.Wcs or CoordinateSystemCode.Ucs) - or (CoordinateSystemCode.Wcs or CoordinateSystemCode.Ucs, CoordinateSystemCode.PDcs) => throw new Exception("To be used only with DCS...ErrorStatus.InvalidInput"), + or (CoordinateSystemCode.Wcs or CoordinateSystemCode.Ucs, CoordinateSystemCode.PDcs) + => throw new Exception("To be used only with DCS...ErrorStatus.InvalidInput"), (_, _) => Matrix3d.Identity }; } @@ -825,9 +817,30 @@ public static void ZoomWindow(this Editor ed, Point3d minPoint, Point3d maxPoint /// /// 命令行对象 /// 窗口范围点 - public static void ZoomWindow(this Editor ed, Extents3d ext) + /// 偏移距离 + public static void ZoomWindow(this Editor ed, Extents3d ext, double offsetDist = 0) { - ZoomWindow(ed, ext.MinPoint, ext.MaxPoint); + using var view = ed.GetCurrentView().CloneEx(); + var mt = Matrix3d.WorldToPlane(view.ViewDirection) * + Matrix3d.Displacement(Point3d.Origin - view.Target) * + Matrix3d.Rotation(view.ViewTwist, view.ViewDirection, view.Target); + ext.TransformBy(mt); + var width = ext.MaxPoint.X - ext.MinPoint.X + offsetDist * 2; + var height = ext.MaxPoint.Y - ext.MinPoint.Y + offsetDist * 2; + var ratio = view.Width / view.Height; + if (width / height < ratio) + { + view.Height = height; + view.Width = height * ratio; + } + else + { + view.Height = width / ratio; + view.Width = width; + } + + view.CenterPoint = ext.MinPoint.GetMidPointTo(ext.MaxPoint).Point2d(); + ed.SetCurrentView(view); } /// @@ -842,7 +855,7 @@ public static void Zoom(this Editor ed, Point3d cenPt, double width, double heig using var vtr = ed.GetCurrentView(); vtr.Width = width; vtr.Height = height; - vtr.CenterPoint = (cenPt.Point2d() - vtr.Target.GetAsVector().Convert2d()).RotateBy(vtr.ViewTwist, Point2d.Origin); + vtr.CenterPoint = cenPt.TransformBy(ed.GetMatrixFromWcsToMDcs()).Point2d(); ed.SetCurrentView(vtr); // 更新当前视图 } @@ -853,18 +866,15 @@ public static void Zoom(this Editor ed, Point3d cenPt, double width, double heig /// 第一点 /// 对角点 /// 偏移距离 - public static void ZoomWindow(this Editor ed, Point3d lpt, Point3d rpt, double offsetDist = 0.00) + public static void ZoomWindow(this Editor ed, Point3d lpt, Point3d rpt, + double offsetDist = 0.00) { - Extents3d extents = new(); - extents.AddPoint(lpt); - extents.AddPoint(rpt); - rpt = extents.MaxPoint + new Vector3d(offsetDist, offsetDist, 0); - lpt = extents.MinPoint - new Vector3d(offsetDist, offsetDist, 0); - var ver = rpt - lpt; - ed.Zoom(lpt + ver / 2, ver.X, ver.Y); + Extents3d ext = new(); + ext.AddPoint(lpt); + ext.AddPoint(rpt); + ed.ZoomWindow(ext, offsetDist); } - /// /// 获取有效的数据库范围 /// @@ -928,11 +938,7 @@ public static void ZoomObject(this Editor ed, Entity ent, double offsetDist = 0. /// public static PromptPointResult GetPoint(this Editor ed, string Message, Point3d BasePoint) { - PromptPointOptions ptOp = new(Message) - { - BasePoint = BasePoint, - UseBasePoint = true - }; + PromptPointOptions ptOp = new(Message) { BasePoint = BasePoint, UseBasePoint = true }; return ed.GetPoint(ptOp); } @@ -943,12 +949,10 @@ public static PromptPointResult GetPoint(this Editor ed, string Message, Point3d /// 提示信息 /// double默认值 /// - public static PromptDoubleResult GetDouble(this Editor ed, string Message, double DefaultValue = 1.0) + public static PromptDoubleResult GetDouble(this Editor ed, string Message, + double DefaultValue = 1.0) { - PromptDoubleOptions douOp = new(Message) - { - DefaultValue = DefaultValue - }; + PromptDoubleOptions douOp = new(Message) { DefaultValue = DefaultValue }; return ed.GetDouble(douOp); } @@ -959,12 +963,10 @@ public static PromptDoubleResult GetDouble(this Editor ed, string Message, doubl /// 提示信息 /// double默认值 /// - public static PromptIntegerResult GetInteger(this Editor ed, string Message, int DefaultValue = 1) + public static PromptIntegerResult GetInteger(this Editor ed, string Message, + int DefaultValue = 1) { - PromptIntegerOptions douOp = new(Message) - { - DefaultValue = DefaultValue - }; + PromptIntegerOptions douOp = new(Message) { DefaultValue = DefaultValue }; return ed.GetInteger(douOp); } @@ -977,10 +979,7 @@ public static PromptIntegerResult GetInteger(this Editor ed, string Message, int /// public static PromptResult GetString(this Editor ed, string Message, string DefaultValue = "") { - PromptStringOptions strOp = new(Message) - { - DefaultValue = DefaultValue - }; + PromptStringOptions strOp = new(Message) { DefaultValue = DefaultValue }; return ed.GetString(strOp); } @@ -988,18 +987,18 @@ public static PromptResult GetString(this Editor ed, string Message, string Defa #region 执行lisp - [DllImport("accore.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "acedInvoke")] + [DllImport("accore.dll", CallingConvention = CallingConvention.Cdecl, + EntryPoint = "acedInvoke")] static extern int AcedInvoke(IntPtr args, out IntPtr result); - // 高版本此接口不能使用lisp(command "xx"),但是可以直接在自动运行接口上 [DllImport("accore.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, EntryPoint = "?acedEvaluateLisp@@YAHPEB_WAEAPEAUresbuf@@@Z")] [System.Security.SuppressUnmanagedCodeSecurity] // 初始化默认值 static extern int AcedEvaluateLisp(string lispLine, out IntPtr result); - - [DllImport("accore.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ads_queueexpr")] + [DllImport("accore.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, + EntryPoint = "ads_queueexpr")] static extern int Ads_queueexpr(string strExpr); /// @@ -1049,7 +1048,8 @@ public enum RunLispFlag : byte /// lisp语句 /// 运行方式 /// 缓冲结果,返回值 - public static ResultBuffer? RunLisp(this Editor ed, string lispCode, RunLispFlag flag = RunLispFlag.AdsQueueexpr) + public static ResultBuffer? RunLisp(this Editor ed, string lispCode, + RunLispFlag flag = RunLispFlag.AdsQueueexpr) { if ((flag & RunLispFlag.AdsQueueexpr) == RunLispFlag.AdsQueueexpr) { @@ -1089,8 +1089,8 @@ public enum RunLispFlag : byte /// 选择集的对象,为null时候手选 /// 是否清空选择集 /// - public static void ComExportWMF(this Editor editor, string saveFile, - ObjectId[]? ids = null, bool wmfSetDel = false) + public static void ComExportWMF(this Editor editor, string saveFile, ObjectId[]? ids = null, + bool wmfSetDel = false) { if (string.IsNullOrWhiteSpace(saveFile)) throw new ArgumentNullException(nameof(saveFile)); @@ -1102,7 +1102,8 @@ public static void ComExportWMF(this Editor editor, string saveFile, return; // 剔除后缀 - saveFile = Path.Combine(Path.GetDirectoryName(saveFile), Path.GetFileNameWithoutExtension(saveFile)); + saveFile = Path.Combine(Path.GetDirectoryName(saveFile), + Path.GetFileNameWithoutExtension(saveFile)); // ActiveSelectionSet: // 第一次执行会触发选择,再次重复命令执行的时候,它会无法再选择(即使清空选择集). // 因此此处netAPI进行选择,它就能读取当前选择集缓冲区的对象 @@ -1189,8 +1190,10 @@ public static void PrepareForJig(this Editor ed, IEnumerable ents) /// 坐标(可能为null) public static Point3d? GetCurrentMouthPoint(this Editor ed) { - return ed.RunLisp("(grread T)", RunLispFlag.AcedEvaluateLisp)?.AsArray() - .FirstOrDefault(tv => tv.TypeCode == 5009).Value as Point3d?; + return ed.RunLisp("(grread T)", RunLispFlag.AcedEvaluateLisp) + ?.AsArray() + .FirstOrDefault(tv => tv.TypeCode == 5009) + .Value as Point3d?; } #endregion diff --git a/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj b/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj index 381fe20..258cf1e 100644 --- a/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj +++ b/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj @@ -18,7 +18,7 @@ IFox.CAD.ACAD IFox.CAD.ACAD IFox.CAD.ACAD - 0.9.1.5 + 0.9.1.6 xsfhlzh, vicwjb, liuqihong, DYH 基于.NET的二次开发基本类库. https://www.nuget.org/packages/IFox.CAD.ACAD/ @@ -27,7 +27,7 @@ IFox,Cad,AutoCad,C#,NET, InspireFunction readme.md - 补充xml文档 + 新增PromptOptionsEx交互选项扩展 LICENSE -- Gitee From b7c5a576ced41687c71df7c61c0d01d686febc2a Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Mon, 11 Nov 2024 20:06:34 +0800 Subject: [PATCH 353/453] =?UTF-8?q?=E5=8F=91=E5=B8=830.9.1.7=E7=89=88?= =?UTF-8?q?=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj b/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj index 258cf1e..b4c3a92 100644 --- a/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj +++ b/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj @@ -18,7 +18,7 @@ IFox.CAD.ACAD IFox.CAD.ACAD IFox.CAD.ACAD - 0.9.1.6 + 0.9.1.7 xsfhlzh, vicwjb, liuqihong, DYH 基于.NET的二次开发基本类库. https://www.nuget.org/packages/IFox.CAD.ACAD/ @@ -27,7 +27,7 @@ IFox,Cad,AutoCad,C#,NET, InspireFunction readme.md - 新增PromptOptionsEx交互选项扩展 + 修正zoom在plan非默认的情况下不正确的问题 LICENSE -- Gitee From eebf19487bd1db30e83f5eeabd95d9c25cfcd0ec Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Wed, 13 Nov 2024 17:39:56 +0800 Subject: [PATCH 354/453] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E5=91=BD=E5=90=8D?= =?UTF-8?q?=E7=A9=BA=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/ExtensionMethod/PromptOptionsEx.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CADShared/ExtensionMethod/PromptOptionsEx.cs b/CADShared/ExtensionMethod/PromptOptionsEx.cs index 0f109b9..8b61d5a 100644 --- a/CADShared/ExtensionMethod/PromptOptionsEx.cs +++ b/CADShared/ExtensionMethod/PromptOptionsEx.cs @@ -1,5 +1,5 @@ // ReSharper disable UnusedAutoPropertyAccessor.Global -namespace IFoxCAD.CAD.ExtensionMethod; +namespace IFoxCAD.CAD; /// /// 交互设置扩展 -- Gitee From 2b6b292bfb8c6001cd02393638b57c50df9d085f Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Wed, 13 Nov 2024 17:41:53 +0800 Subject: [PATCH 355/453] =?UTF-8?q?=E5=8F=91=E5=B8=830.9.1.8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj b/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj index b4c3a92..581872f 100644 --- a/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj +++ b/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj @@ -18,7 +18,7 @@ IFox.CAD.ACAD IFox.CAD.ACAD IFox.CAD.ACAD - 0.9.1.7 + 0.9.1.8 xsfhlzh, vicwjb, liuqihong, DYH 基于.NET的二次开发基本类库. https://www.nuget.org/packages/IFox.CAD.ACAD/ -- Gitee From 849ece0d4c1f480ab644b2b7cfb6270583aa8a68 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sun, 17 Nov 2024 19:49:28 +0800 Subject: [PATCH 356/453] =?UTF-8?q?=E4=BD=BFCmdEcho=E7=B3=BB=E7=BB=9F?= =?UTF-8?q?=E5=8F=98=E9=87=8F=E5=8F=AF=E4=BB=A5=E8=A2=ABset?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/Runtime/SystemVariableManager.cs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/CADShared/Runtime/SystemVariableManager.cs b/CADShared/Runtime/SystemVariableManager.cs index 1c0118d..c065bb8 100644 --- a/CADShared/Runtime/SystemVariableManager.cs +++ b/CADShared/Runtime/SystemVariableManager.cs @@ -66,7 +66,8 @@ public int Auprec /// /// 用于显示当前的注释性比例 /// - public static double CanNoScaleValue => Convert.ToDouble(Acaop.GetSystemVariable(nameof(CanNoScale))); + public static double CanNoScaleValue => + Convert.ToDouble(Acaop.GetSystemVariable(nameof(CanNoScale))); /// /// 储存以公元纪年为基准的日历数据和时间 @@ -130,7 +131,8 @@ public static string CLayer /// /// 用于确定全屏显示是打开或关闭状态 /// - public static bool CleanScreenState => Convert.ToBoolean(Acaop.GetSystemVariable(nameof(CleanScreenState))); + public static bool CleanScreenState => + Convert.ToBoolean(Acaop.GetSystemVariable(nameof(CleanScreenState))); /// /// 指示命令窗口是隐藏还是显示状态 @@ -154,7 +156,11 @@ public static bool CmdDia /// /// 在使用 LISP 的函数时,切换回应为打开或关闭 /// - public static bool CmdEcho => Convert.ToBoolean(Acaop.GetSystemVariable(nameof(CmdEcho))); + public static bool CmdEcho + { + get => Convert.ToBoolean(Acaop.GetSystemVariable(nameof(CmdEcho))); + set => Acaop.SetSystemVariable(nameof(CmdEcho), value ? 1 : 0); + } /// /// 当前的命令 -- Gitee From b91bb6c6cf22139feabbbb6177d9b5baafd91113 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sun, 17 Nov 2024 19:54:29 +0800 Subject: [PATCH 357/453] =?UTF-8?q?=E5=8F=91=E5=B8=830.9.1.9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj b/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj index 581872f..39e3dc4 100644 --- a/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj +++ b/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj @@ -18,7 +18,7 @@ IFox.CAD.ACAD IFox.CAD.ACAD IFox.CAD.ACAD - 0.9.1.8 + 0.9.1.9 xsfhlzh, vicwjb, liuqihong, DYH 基于.NET的二次开发基本类库. https://www.nuget.org/packages/IFox.CAD.ACAD/ @@ -27,7 +27,7 @@ IFox,Cad,AutoCad,C#,NET, InspireFunction readme.md - 修正zoom在plan非默认的情况下不正确的问题 + 修复部分系统变量不能Set的问题 LICENSE -- Gitee From 42cd134307baafcda48c08392844ecd2a57f2f50 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Mon, 18 Nov 2024 00:06:18 +0800 Subject: [PATCH 358/453] =?UTF-8?q?=E5=A2=9E=E5=8A=A0net8=E6=94=AF?= =?UTF-8?q?=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/Algorithms/QuadTree/Rect.cs | 13 +++++---- CADShared/Basal/General/EnumEx.cs | 2 +- CADShared/Basal/General/LinqEx.cs | 28 +++++++++++++------ CADShared/Basal/Nullable/ArgumentNullEx.cs | 9 ++++-- CADShared/Basal/Win/PInvokeUser32.cs | 2 +- CADShared/Basal/Win/WindowsAPI.cs | 10 +++---- CADShared/ExtensionMethod/EditorEx.cs | 9 +++--- .../Entity/BlockReferenceEx.cs | 20 +++++++------ CADShared/ExtensionMethod/Entity/CurveEx.cs | 14 ++++++---- CADShared/ExtensionMethod/Entity/DBTextEx.cs | 6 ++-- CADShared/ExtensionMethod/Entity/MTextEx.cs | 6 ++-- .../ExtensionMethod/Geomerty/GeometryEx.cs | 2 ++ CADShared/ExtensionMethod/Geomerty/PointEx.cs | 8 ++++-- .../ExtensionMethod/Hatch/HatchConverter.cs | 10 +++++-- CADShared/ExtensionMethod/Hatch/HatchInfo.cs | 6 +++- CADShared/ExtensionMethod/Jig/JigEx.cs | 8 ++++-- CADShared/ExtensionMethod/SelectionSetEx.cs | 10 +++++-- CADShared/ExtensionMethod/SymbolTableEx.cs | 4 ++- .../ExtensionMethod/SymbolTableRecordEx.cs | 13 ++++++--- CADShared/ExtensionMethod/WindowEx.cs | 2 +- CADShared/ExtensionMethod/XrefEx.cs | 11 ++++++-- CADShared/Initialize/AssemInfo.cs | 4 +-- CADShared/Initialize/AutoRegAssem.cs | 12 +++++--- CADShared/Initialize/MethodInfoHelper.cs | 8 ++++-- CADShared/PE/AcadPeInfo.cs | 14 ++++++---- CADShared/Runtime/DBTrans.cs | 18 +++++++----- CADShared/Runtime/Env.cs | 13 +++++---- CADShared/Runtime/IdleAction.cs | 2 +- CADShared/Runtime/IdleNoCommandAction.cs | 2 +- CADShared/Runtime/SymbolTable.cs | 16 ++++++----- CADShared/Runtime/SystemVariableManager.cs | 12 ++++---- IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj | 28 +++++++++++++++---- 32 files changed, 210 insertions(+), 112 deletions(-) diff --git a/CADShared/Algorithms/QuadTree/Rect.cs b/CADShared/Algorithms/QuadTree/Rect.cs index 60f92f9..28b309a 100644 --- a/CADShared/Algorithms/QuadTree/Rect.cs +++ b/CADShared/Algorithms/QuadTree/Rect.cs @@ -1,6 +1,8 @@ using System.Diagnostics; using System.Runtime.CompilerServices; - +#if a2024 +using ArgumentNullException = IFoxCAD.Basal.ArgumentNullException; +#endif namespace IFoxCAD.Cad; /// @@ -413,8 +415,7 @@ public static bool IsRectAngle(List? ptList, double tolerance = 1e-8) { //if (ptList == null) // throw new ArgumentNullException(nameof(ptList)); - - ArgumentNullEx.ThrowIfNull(ptList); + ArgumentNullException.ThrowIfNull(ptList); var pts = ptList.ToList(); /* * 消重,不这里设置,否则这不是一个正确的单元测试 @@ -469,7 +470,7 @@ public static bool IsRect(List? ptList, double tolerance = 1e-10) { //if (ptList == null) // throw new ArgumentNullException(nameof(ptList)); - ArgumentNullEx.ThrowIfNull(ptList); + ArgumentNullException.ThrowIfNull(ptList); var pts = ptList.ToList(); if (ptList.Count == 5) { @@ -519,7 +520,7 @@ public static bool RectAnglePointOrder(List? pts) { //if (pts == null) // throw new ArgumentNullException(nameof(pts)); - ArgumentNullEx.ThrowIfNull(pts); + ArgumentNullException.ThrowIfNull(pts); if (!IsRectAngle(pts)) return false; @@ -722,7 +723,7 @@ public string ToString(string? format = null, IFormatProvider? formatProvider = /// /// /// - public int CompareTo(Rect rect) + public int CompareTo(Rect? rect) { if (rect == null) return -1; diff --git a/CADShared/Basal/General/EnumEx.cs b/CADShared/Basal/General/EnumEx.cs index 4d1cb6c..0f761ce 100644 --- a/CADShared/Basal/General/EnumEx.cs +++ b/CADShared/Basal/General/EnumEx.cs @@ -31,7 +31,7 @@ public static void CleanCache() if (Cache.TryGetValue(eFullName, out var attribute1)) return attribute1; - var fieldInfo = eType.GetField(Enum.GetName(eType, e)); + var fieldInfo = eType.GetField(Enum.GetName(eType, e) ?? string.Empty); if (fieldInfo == null) return null!; diff --git a/CADShared/Basal/General/LinqEx.cs b/CADShared/Basal/General/LinqEx.cs index 746bacf..20f0505 100644 --- a/CADShared/Basal/General/LinqEx.cs +++ b/CADShared/Basal/General/LinqEx.cs @@ -20,7 +20,7 @@ public static TValue FindByMax(this IEnumerable source, Fu { using var itr = source.GetEnumerator(); if (!itr.MoveNext()) - throw new ArgumentNullException(nameof(source), "对象为 null"); + throw new System.ArgumentNullException(nameof(source), "对象为 null"); var value = itr.Current; var key = func(value); @@ -49,7 +49,7 @@ public static TValue FindByMax(this IEnumerable source, ou { using var itr = source.GetEnumerator(); if (!itr.MoveNext()) - throw new ArgumentNullException(nameof(source), "对象为 null"); + throw new System.ArgumentNullException(nameof(source), "对象为 null"); var value = itr.Current; var key = func(value); @@ -76,7 +76,7 @@ public static TValue FindByMax(this IEnumerable source, Comparis { using var itr = source.GetEnumerator(); if (!itr.MoveNext()) - throw new ArgumentNullException(nameof(source), "对象为 null"); + throw new System.ArgumentNullException(nameof(source), "对象为 null"); var value = itr.Current; @@ -106,7 +106,7 @@ public static TValue FindByMin(this IEnumerable source, ou { using var itr = source.GetEnumerator(); if (!itr.MoveNext()) - throw new ArgumentNullException(nameof(source), "对象为 null"); + throw new System.ArgumentNullException(nameof(source), "对象为 null"); var value = itr.Current; var key = func(value); @@ -135,7 +135,7 @@ public static TValue FindByMin(this IEnumerable source, Fu { using var itr = source.GetEnumerator(); if (!itr.MoveNext()) - throw new ArgumentNullException(nameof(source), "对象为 null"); + throw new System.ArgumentNullException(nameof(source), "对象为 null"); var value = itr.Current; var key = func(value); @@ -161,7 +161,7 @@ public static TValue FindByMin(this IEnumerable source, Comparis { using var itr = source.GetEnumerator(); if (!itr.MoveNext()) - throw new ArgumentNullException(nameof(source), "对象为 null"); + throw new System.ArgumentNullException(nameof(source), "对象为 null"); var value = itr.Current; @@ -190,7 +190,7 @@ public static TValue[] FindByExt(this IEnumerable source, { using var itr = source.GetEnumerator(); if (!itr.MoveNext()) - throw new ArgumentNullException(nameof(source), "对象为 null"); + throw new System.ArgumentNullException(nameof(source), "对象为 null"); var values = new TValue[2]; values[0] = values[1] = itr.Current; @@ -226,7 +226,7 @@ public static TValue[] FindByExt(this IEnumerable source, Compar { using var itr = source.GetEnumerator(); if (!itr.MoveNext()) - throw new ArgumentNullException(nameof(source), "对象为 null"); + throw new System.ArgumentNullException(nameof(source), "对象为 null"); var values = new TValue[2]; values[0] = values[1] = itr.Current; @@ -254,7 +254,7 @@ public static TKey[] FindExt(this IEnumerable source, Func { using var itr = source.GetEnumerator(); if (!itr.MoveNext()) - throw new ArgumentNullException(nameof(source), "对象为 null"); + throw new System.ArgumentNullException(nameof(source), "对象为 null"); var keys = new TKey[2]; keys[0] = keys[1] = func(itr.Current); @@ -288,10 +288,20 @@ internal SpecComparer(Comparison comp) } #region IComparer 成员 + +#if a2024 public int Compare(T x, T y) { return _comp(x, y); } +#else + public int Compare(T? x, T? y) + { + if (x is not null && y is not null) + return _comp(x, y); + return 0; + } +#endif #endregion IComparer 成员 } diff --git a/CADShared/Basal/Nullable/ArgumentNullEx.cs b/CADShared/Basal/Nullable/ArgumentNullEx.cs index 8552c44..ec3f4c9 100644 --- a/CADShared/Basal/Nullable/ArgumentNullEx.cs +++ b/CADShared/Basal/Nullable/ArgumentNullEx.cs @@ -1,10 +1,12 @@  namespace IFoxCAD.Basal; +#if a2024 + /// /// 参数null检查类 /// -public static class ArgumentNullEx +public static class ArgumentNullException { /// /// 检查参数是否为 null @@ -22,5 +24,6 @@ public static void ThrowIfNull([NotNull] object? argument, } [DoesNotReturn] - private static void Throw(string? paramName) => throw new ArgumentNullException(paramName); -} \ No newline at end of file + private static void Throw(string? paramName) => throw new System.ArgumentNullException(paramName); +} +#endif \ No newline at end of file diff --git a/CADShared/Basal/Win/PInvokeUser32.cs b/CADShared/Basal/Win/PInvokeUser32.cs index c3df3f9..ef4dd5d 100644 --- a/CADShared/Basal/Win/PInvokeUser32.cs +++ b/CADShared/Basal/Win/PInvokeUser32.cs @@ -221,7 +221,7 @@ public struct GuiThreadInfo public static GuiThreadInfo Create(uint windowThreadProcessId) { if (windowThreadProcessId == 0) - throw new ArgumentNullException(nameof(windowThreadProcessId)); + throw new System.ArgumentNullException(nameof(windowThreadProcessId)); GuiThreadInfo gti = new(); gti.cbSize = Marshal.SizeOf(gti); diff --git a/CADShared/Basal/Win/WindowsAPI.cs b/CADShared/Basal/Win/WindowsAPI.cs index bd20e90..0bf126f 100644 --- a/CADShared/Basal/Win/WindowsAPI.cs +++ b/CADShared/Basal/Win/WindowsAPI.cs @@ -81,12 +81,12 @@ public partial class WindowsAPI /// 锁定数据对象指针 /// 返回锁定的内存片段指针,锁定期间执行任务 /// 是否锁定成功 - /// + /// public static bool GlobalLockTask(IntPtr data, Action task) { //if (task == null) // throw new ArgumentNullException(nameof(task)); - ArgumentNullEx.ThrowIfNull(task); + ArgumentNullException.ThrowIfNull(task); if (data == IntPtr.Zero) return false; @@ -130,7 +130,7 @@ public static bool GlobalLockTask(IntPtr data, Action task) Marshal.Copy(bytes, 0, structPtr, typeSize); // 将内存空间转换为目标结构体; // 转类型的时候会拷贝一次,看它们地址验证 &result != &structPtr - var result = (T)Marshal.PtrToStructure(structPtr, structType); + var result = (T)Marshal.PtrToStructure(structPtr, structType)!; // 释放内存空间 Marshal.FreeHGlobal(structPtr); @@ -324,7 +324,7 @@ public struct KeyboardHookStruct public static KeyboardHookStruct Create(IntPtr lParam) { - return (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct)); + return (KeyboardHookStruct)(Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct)) ?? throw new InvalidOperationException()); } public void ToPtr(IntPtr lParam) @@ -492,7 +492,7 @@ public Point3D(double x, double y, double z) public static Point3D Create(IntPtr lParam) { - return (Point3D)Marshal.PtrToStructure(lParam, typeof(Point3D)); + return (Point3D)(Marshal.PtrToStructure(lParam, typeof(Point3D)) ?? throw new InvalidOperationException()); } public void ToPtr(IntPtr lParam) diff --git a/CADShared/ExtensionMethod/EditorEx.cs b/CADShared/ExtensionMethod/EditorEx.cs index eaaba65..9d2f6c8 100644 --- a/CADShared/ExtensionMethod/EditorEx.cs +++ b/CADShared/ExtensionMethod/EditorEx.cs @@ -1,3 +1,5 @@ +using ArgumentNullException = System.ArgumentNullException; + namespace IFoxCAD.Cad; /// @@ -171,8 +173,7 @@ public static void SsgetAddKeys(this PromptSelectionOptions pso, if (dicActions[item] != dicActions[key]) dicActions[item] += dicActions[key]; } - else - tmp.Add(item, value); + else if (value != null) tmp.Add(item, value); } dicActions.Remove(key); @@ -1088,7 +1089,7 @@ public enum RunLispFlag : byte /// 保存文件 /// 选择集的对象,为null时候手选 /// 是否清空选择集 - /// + /// public static void ComExportWMF(this Editor editor, string saveFile, ObjectId[]? ids = null, bool wmfSetDel = false) { @@ -1102,7 +1103,7 @@ public static void ComExportWMF(this Editor editor, string saveFile, ObjectId[]? return; // 剔除后缀 - saveFile = Path.Combine(Path.GetDirectoryName(saveFile), + saveFile = Path.Combine(Path.GetDirectoryName(saveFile) ?? string.Empty, Path.GetFileNameWithoutExtension(saveFile)); // ActiveSelectionSet: // 第一次执行会触发选择,再次重复命令执行的时候,它会无法再选择(即使清空选择集). diff --git a/CADShared/ExtensionMethod/Entity/BlockReferenceEx.cs b/CADShared/ExtensionMethod/Entity/BlockReferenceEx.cs index 2bd61cc..fdaf7bd 100644 --- a/CADShared/ExtensionMethod/Entity/BlockReferenceEx.cs +++ b/CADShared/ExtensionMethod/Entity/BlockReferenceEx.cs @@ -1,4 +1,8 @@ -namespace IFoxCAD.Cad; +#if a2024 +using ArgumentNullException = IFoxCAD.Basal.ArgumentNullException; +#endif + +namespace IFoxCAD.Cad; /// /// 块参照扩展类 @@ -195,12 +199,12 @@ public static BlockTableRecord GetBlockTableRecord(this BlockReference brf) /// 名字 public static string GetBlockName(this BlockReference blk) { - ArgumentNullEx.ThrowIfNull(blk); + ArgumentNullException.ThrowIfNull(blk); if (blk.IsDynamicBlock) { var btrId = blk.DynamicBlockTableRecord; var tr = btrId.Database.TransactionManager.TopTransaction; - ArgumentNullEx.ThrowIfNull(tr); + ArgumentNullException.ThrowIfNull(tr); var btr = (BlockTableRecord)tr.GetObject(btrId); return btr.Name; } @@ -245,7 +249,7 @@ public static string GetBlockName(this BlockReference blk) [DebuggerStepThrough] public static void ForEach(this BlockReference brf, Action action) { - ArgumentNullEx.ThrowIfNull(action); + ArgumentNullException.ThrowIfNull(action); var tr = DBTrans.GetTopTransaction(brf.Database); if (tr.GetObject(brf.BlockTableRecord) is BlockTableRecord btr) { @@ -258,11 +262,11 @@ public static void ForEach(this BlockReference brf, Action action) /// /// /// - /// + /// [DebuggerStepThrough] public static void ForEach(this BlockReference brf, Action action) { - ArgumentNullEx.ThrowIfNull(action); + ArgumentNullException.ThrowIfNull(action); var tr = DBTrans.GetTopTransaction(brf.Database); if (tr.GetObject(brf.BlockTableRecord) is BlockTableRecord btr) { @@ -275,11 +279,11 @@ public static void ForEach(this BlockReference brf, Action /// /// /// - /// + /// [DebuggerStepThrough] public static void ForEach(this BlockReference brf, Action action) { - ArgumentNullEx.ThrowIfNull(action); + ArgumentNullException.ThrowIfNull(action); var tr = DBTrans.GetTopTransaction(brf.Database); if (tr.GetObject(brf.BlockTableRecord) is BlockTableRecord btr) { diff --git a/CADShared/ExtensionMethod/Entity/CurveEx.cs b/CADShared/ExtensionMethod/Entity/CurveEx.cs index 494666a..e9cb832 100644 --- a/CADShared/ExtensionMethod/Entity/CurveEx.cs +++ b/CADShared/ExtensionMethod/Entity/CurveEx.cs @@ -1,5 +1,9 @@ // ReSharper disable ForCanBeConvertedToForeach +#if a2024 +using ArgumentNullException = IFoxCAD.Basal.ArgumentNullException; +#endif + namespace IFoxCAD.Cad; /// @@ -48,7 +52,7 @@ public static IEnumerable GetSplitCurves(this Curve curve, IEnumerable x); @@ -88,7 +92,7 @@ public static IEnumerable GetSplitCurves(this Curve curve, IEnumerable { @@ -107,7 +111,7 @@ public static IEnumerable GetSplitCurves(this Curve curve, IEnumerable打断后的曲线列表 public static List BreakCurve(this List curves) { - ArgumentNullEx.ThrowIfNull(curves); + ArgumentNullException.ThrowIfNull(curves); var tol = new Tolerance(0.01, 0.01); @@ -174,11 +178,11 @@ public static List BreakCurve(this List curves) /// /// 曲线列表 /// 打断后的曲线列表 - /// 传入的曲线列表错误 + /// 传入的曲线列表错误 public static List BreakCurveOnZPlane(this List curves) { if (curves is null) - throw new ArgumentNullException(nameof(curves)); + throw new System.ArgumentNullException(nameof(curves)); var zPlane = new Plane(Point3d.Origin, Vector3d.ZAxis); var curvesTemp = curves.Select(c => c.GetProjectedCurve(zPlane, Vector3d.ZAxis)).ToList(); List geCurves = []; // 存储曲线转换后的复合曲线 diff --git a/CADShared/ExtensionMethod/Entity/DBTextEx.cs b/CADShared/ExtensionMethod/Entity/DBTextEx.cs index 00042bf..97a6511 100644 --- a/CADShared/ExtensionMethod/Entity/DBTextEx.cs +++ b/CADShared/ExtensionMethod/Entity/DBTextEx.cs @@ -1,4 +1,6 @@ -namespace IFoxCAD.Cad; +using ArgumentNullException = System.ArgumentNullException; + +namespace IFoxCAD.Cad; /// /// 单行文字扩展类 @@ -15,7 +17,7 @@ public static class DBTextEx /// 文字所在的数据库 /// 文字属性设置委托 /// 文字对象 - /// + /// public static DBText CreateDBText(Point3d position, string text, double height, AttachmentPoint justify = AttachmentPoint.BaseLeft, Database? database = null, Action? action = null) diff --git a/CADShared/ExtensionMethod/Entity/MTextEx.cs b/CADShared/ExtensionMethod/Entity/MTextEx.cs index 027793c..52c85a9 100644 --- a/CADShared/ExtensionMethod/Entity/MTextEx.cs +++ b/CADShared/ExtensionMethod/Entity/MTextEx.cs @@ -1,4 +1,6 @@ -namespace IFoxCAD.Cad; +using ArgumentNullException = System.ArgumentNullException; + +namespace IFoxCAD.Cad; /// /// 多行文字扩展类 @@ -14,7 +16,7 @@ public static class MTextEx /// 文字所在的数据库 /// 文字属性设置委托 /// 文字对象id - /// + /// public static MText CreateMText(Point3d position, string text, double height, Database? database = null, Action? action = null) { diff --git a/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs b/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs index 46e9c6d..3247c4f 100644 --- a/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs +++ b/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs @@ -1,3 +1,5 @@ +using ArgumentNullException = System.ArgumentNullException; + namespace IFoxCAD.Cad; using System.Drawing; diff --git a/CADShared/ExtensionMethod/Geomerty/PointEx.cs b/CADShared/ExtensionMethod/Geomerty/PointEx.cs index c6455b1..86ff1c8 100644 --- a/CADShared/ExtensionMethod/Geomerty/PointEx.cs +++ b/CADShared/ExtensionMethod/Geomerty/PointEx.cs @@ -1,3 +1,7 @@ +#if a2024 +using ArgumentNullException = IFoxCAD.Basal.ArgumentNullException; +#endif + namespace IFoxCAD.Cad; /// @@ -230,7 +234,7 @@ public static double Distance2dTo(this Point3d pt1, Point3d pt2) [DebuggerStepThrough] public static void End2End(this Point2dCollection ptCollection) { - ArgumentNullEx.ThrowIfNull(ptCollection); + ArgumentNullException.ThrowIfNull(ptCollection); if (ptCollection.Count == 0 || ptCollection[0].Equals(ptCollection[^1])) // 首尾相同直接返回 return; @@ -251,7 +255,7 @@ public static void End2End(this Point2dCollection ptCollection) [DebuggerStepThrough] public static void End2End(this Point3dCollection ptCollection) { - ArgumentNullEx.ThrowIfNull(ptCollection); + ArgumentNullException.ThrowIfNull(ptCollection); if (ptCollection.Count == 0 || ptCollection[0].Equals(ptCollection[^1])) // 首尾相同直接返回 return; diff --git a/CADShared/ExtensionMethod/Hatch/HatchConverter.cs b/CADShared/ExtensionMethod/Hatch/HatchConverter.cs index 915cda8..e658723 100644 --- a/CADShared/ExtensionMethod/Hatch/HatchConverter.cs +++ b/CADShared/ExtensionMethod/Hatch/HatchConverter.cs @@ -1,6 +1,10 @@ // ReSharper disable CompareOfFloatsByEqualityOperator // ReSharper disable ForCanBeConvertedToForeach +#if a2024 +using ArgumentNullException = IFoxCAD.Basal.ArgumentNullException; +#endif + namespace IFoxCAD.Cad; using PointV = Point2d; @@ -174,8 +178,8 @@ static void HatchLoopIsPolyline(HatchLoop loop, HatchConverterData hcData) //if (hcData is null) // throw new ArgumentNullException(nameof(hcData)); - ArgumentNullEx.ThrowIfNull(loop); - ArgumentNullEx.ThrowIfNull(hcData); + ArgumentNullException.ThrowIfNull(loop); + ArgumentNullException.ThrowIfNull(hcData); // 判断为圆形: @@ -205,7 +209,7 @@ static void HatchLoopIsPolyline(HatchLoop loop, HatchConverterData hcData) //if (loop is null) // throw new ArgumentNullException(nameof(loop)); - ArgumentNullEx.ThrowIfNull(loop); + ArgumentNullException.ThrowIfNull(loop); if (loop.Curves.Count != 2) throw new ArgumentException("边界非多段线,而且点数!=2,点数为:" + nameof(loop.Curves.Count) + diff --git a/CADShared/ExtensionMethod/Hatch/HatchInfo.cs b/CADShared/ExtensionMethod/Hatch/HatchInfo.cs index 88c0886..89f17fb 100644 --- a/CADShared/ExtensionMethod/Hatch/HatchInfo.cs +++ b/CADShared/ExtensionMethod/Hatch/HatchInfo.cs @@ -1,5 +1,9 @@  +#if a2024 +using ArgumentNullException = IFoxCAD.Basal.ArgumentNullException; +#endif + namespace IFoxCAD.Cad; /* @@ -296,7 +300,7 @@ public HatchInfo AppendLoop(Point2dCollection pts, { //if (pts == null) // throw new ArgumentNullException(nameof(pts)); - ArgumentNullEx.ThrowIfNull(pts); + ArgumentNullException.ThrowIfNull(pts); pts.End2End(); // 2011新增API,可以不生成图元的情况下加入边界, // 通过这里进入的话,边界 _boundaryIds 是空的,那么 Build() 时候就需要过滤空的 diff --git a/CADShared/ExtensionMethod/Jig/JigEx.cs b/CADShared/ExtensionMethod/Jig/JigEx.cs index f484156..23e5d39 100644 --- a/CADShared/ExtensionMethod/Jig/JigEx.cs +++ b/CADShared/ExtensionMethod/Jig/JigEx.cs @@ -1,4 +1,8 @@ -namespace IFoxCAD.Cad; +#if a2024 +using ArgumentNullException = IFoxCAD.Basal.ArgumentNullException; +#endif + +namespace IFoxCAD.Cad; /* 封装jig * 20220726 隐藏事件,利用函数进行数据库图元重绘 @@ -293,7 +297,7 @@ static JigPromptPointOptions JigPointOptions() public void SetSpaceIsKeyword() { var opt = _options; - ArgumentNullEx.ThrowIfNull(opt); + ArgumentNullException.ThrowIfNull(opt); if ((opt.UserInputControls & UserInputControls.NullResponseAccepted) == UserInputControls.NullResponseAccepted) opt.UserInputControls ^= UserInputControls.NullResponseAccepted; // 输入了鼠标右键,结束jig if ((opt.UserInputControls & UserInputControls.AnyBlankTerminatesInput) == UserInputControls.AnyBlankTerminatesInput) diff --git a/CADShared/ExtensionMethod/SelectionSetEx.cs b/CADShared/ExtensionMethod/SelectionSetEx.cs index b4d22e4..cc4f63a 100644 --- a/CADShared/ExtensionMethod/SelectionSetEx.cs +++ b/CADShared/ExtensionMethod/SelectionSetEx.cs @@ -1,4 +1,8 @@ -namespace IFoxCAD.Cad; +#if a2024 +using ArgumentNullException = IFoxCAD.Basal.ArgumentNullException; +#endif + +namespace IFoxCAD.Cad; /// /// 选择集扩展类 @@ -90,7 +94,7 @@ public static void ForEach(this SelectionSet ss, /// 打开模式 /// 是否打开已删除对象,默认为不打开 /// 是否打开锁定图层对象,默认为不打开 - /// + /// [DebuggerStepThrough] public static void ForEach(this SelectionSet ss, Action action, @@ -98,7 +102,7 @@ public static void ForEach(this SelectionSet ss, bool openErased = false, bool openLockedLayer = false) where T : Entity { - ArgumentNullEx.ThrowIfNull(action); + ArgumentNullException.ThrowIfNull(action); LoopState state = new(); var ents = ss.GetEntities(openMode, openErased, openLockedLayer); diff --git a/CADShared/ExtensionMethod/SymbolTableEx.cs b/CADShared/ExtensionMethod/SymbolTableEx.cs index 867c9be..f780fd6 100644 --- a/CADShared/ExtensionMethod/SymbolTableEx.cs +++ b/CADShared/ExtensionMethod/SymbolTableEx.cs @@ -1,4 +1,6 @@ -namespace IFoxCAD.Cad; +using ArgumentNullException = System.ArgumentNullException; + +namespace IFoxCAD.Cad; /// /// 符号表类扩展函数 diff --git a/CADShared/ExtensionMethod/SymbolTableRecordEx.cs b/CADShared/ExtensionMethod/SymbolTableRecordEx.cs index 42cadaa..75010a0 100644 --- a/CADShared/ExtensionMethod/SymbolTableRecordEx.cs +++ b/CADShared/ExtensionMethod/SymbolTableRecordEx.cs @@ -1,4 +1,9 @@ -namespace IFoxCAD.Cad; + +#if a2024 +using ArgumentNullException = IFoxCAD.Basal.ArgumentNullException; +#endif + +namespace IFoxCAD.Cad; /// /// 符号表记录扩展类 @@ -27,7 +32,7 @@ public static class SymbolTableRecordEx public static void DeepCloneEx(this BlockTableRecord btr, ObjectIdCollection objIds, IdMapping maoOut) { if (objIds is null || objIds.Count == 0) - throw new ArgumentNullException(nameof(objIds)); + throw new System.ArgumentNullException(nameof(objIds)); var db = objIds[0].Database; using (btr.ForWrite()) @@ -57,7 +62,7 @@ public static void DeepCloneEx(this BlockTableRecord btr, ObjectIdCollection obj public static IdMapping DeepCloneEx(this BlockTableRecord btr, ObjectIdCollection objIds) { if (objIds is null || objIds.Count == 0) - throw new ArgumentNullException(nameof(objIds)); + throw new System.ArgumentNullException(nameof(objIds)); var db = objIds[0].Database; IdMapping mapOut = new(); @@ -347,7 +352,7 @@ public static void ForEach(this TRecord record, Action /// 关闭时减掉事件 /// - private static void WindowOnClosed(object sender, EventArgs e) + private static void WindowOnClosed(object? sender, EventArgs e) { if (sender is not Window window) return; diff --git a/CADShared/ExtensionMethod/XrefEx.cs b/CADShared/ExtensionMethod/XrefEx.cs index 39a3008..2e1f149 100644 --- a/CADShared/ExtensionMethod/XrefEx.cs +++ b/CADShared/ExtensionMethod/XrefEx.cs @@ -1,4 +1,9 @@ // ReSharper disable ForCanBeConvertedToForeach + +#if a2024 +using ArgumentNullException = IFoxCAD.Basal.ArgumentNullException; +#endif + namespace IFoxCAD.Cad; #region 参照工厂 @@ -471,7 +476,7 @@ public XrefPath(BlockReference brf, DBTrans tr) { //if (brf == null) // throw new ArgumentNullException(nameof(brf)); - ArgumentNullEx.ThrowIfNull(brf); + ArgumentNullException.ThrowIfNull(brf); CurrentDatabasePath = Path.GetDirectoryName(tr.Database.Filename); var btRec = tr.GetObject(brf.BlockTableRecord); // 块表记录 @@ -519,8 +524,8 @@ public XrefPath(BlockReference brf, DBTrans tr) //if (fileRelations == null) // throw new ArgumentNullException(nameof(fileRelations)); - ArgumentNullEx.ThrowIfNull(directory); - ArgumentNullEx.ThrowIfNull(fileRelations); + ArgumentNullException.ThrowIfNull(directory); + ArgumentNullException.ThrowIfNull(fileRelations); string? result = null; switch (converterModes) diff --git a/CADShared/Initialize/AssemInfo.cs b/CADShared/Initialize/AssemInfo.cs index 1829622..de3f40d 100644 --- a/CADShared/Initialize/AssemInfo.cs +++ b/CADShared/Initialize/AssemInfo.cs @@ -13,8 +13,8 @@ public struct AssemInfo public AssemInfo(Assembly assembly) { Loader = assembly.Location; - Fullname = assembly.FullName; - Name = assembly.GetName().Name; + Fullname = assembly.FullName!; + Name = assembly.GetName().Name!; LoadType = AssemLoadType.Starting; } diff --git a/CADShared/Initialize/AutoRegAssem.cs b/CADShared/Initialize/AutoRegAssem.cs index 5431ecb..0d00227 100644 --- a/CADShared/Initialize/AutoRegAssem.cs +++ b/CADShared/Initialize/AutoRegAssem.cs @@ -1,4 +1,8 @@ -namespace IFoxCAD.Cad; +#if a2024 +using ArgumentNullException = IFoxCAD.Basal.ArgumentNullException; +#endif + +namespace IFoxCAD.Cad; /// /// 注册中心 @@ -37,7 +41,7 @@ public abstract class AutoRegAssem : IExtensionApplication /// 路径对象 public static DirectoryInfo? GetDirectory(Assembly? assem) { - ArgumentNullEx.ThrowIfNull(assem); + ArgumentNullException.ThrowIfNull(assem); return new FileInfo(assem.Location).Directory; } @@ -55,8 +59,8 @@ protected AutoRegAssem(AutoRegConfig autoRegConfig) var info = new AssemInfo { Loader = assem.Location, - Fullname = assem.FullName, - Name = assem.GetName().Name, + Fullname = assem.FullName!, + Name = assem.GetName().Name!, LoadType = AssemLoadType.Starting }; diff --git a/CADShared/Initialize/MethodInfoHelper.cs b/CADShared/Initialize/MethodInfoHelper.cs index 2da1d70..af91592 100644 --- a/CADShared/Initialize/MethodInfoHelper.cs +++ b/CADShared/Initialize/MethodInfoHelper.cs @@ -1,4 +1,8 @@ -namespace IFoxCAD.Cad; +#if a2024 +using ArgumentNullException = IFoxCAD.Basal.ArgumentNullException; +#endif + +namespace IFoxCAD.Cad; internal static class MethodInfoHelper { @@ -13,7 +17,7 @@ internal static class MethodInfoHelper /// 已经外部创建的对象,为空则此处创建 public static object? Invoke(this MethodInfo methodInfo, ref object? instance) { - ArgumentNullEx.ThrowIfNull(methodInfo); + ArgumentNullException.ThrowIfNull(methodInfo); object? result = null; if (methodInfo.IsStatic) { diff --git a/CADShared/PE/AcadPeInfo.cs b/CADShared/PE/AcadPeInfo.cs index ffda2d5..fbec0a6 100644 --- a/CADShared/PE/AcadPeInfo.cs +++ b/CADShared/PE/AcadPeInfo.cs @@ -63,7 +63,9 @@ public static PeInfo? PeForAcadExe if (_PeForAcadExe is null) { // 获取此acad.exe获取所有的函数名 - var file = Process.GetCurrentProcess().MainModule.FileName; + var processModule = Process.GetCurrentProcess().MainModule; + if (processModule == null) return _PeForAcadExe; + var file = processModule.FileName; _PeForAcadExe = new PeInfo(file); } return _PeForAcadExe; @@ -81,7 +83,7 @@ public static PeInfo? PeForAccoreDll if (_PeForAccoreDll is null) { // 获取此dll所有的函数名 - var file = Process.GetCurrentProcess().MainModule.FileName; + var file = Process.GetCurrentProcess().MainModule!.FileName; var dll = Path.GetDirectoryName(file) + "\\accore.dll"; if (File.Exists(dll))// 08没有,高版本分离的 _PeForAccoreDll = new PeInfo(dll); @@ -101,7 +103,7 @@ public static PeInfo? PeForAcdbDll if (_PeForAcdbDll is null) { // 获取此dll所有的函数名 - var file = Process.GetCurrentProcess().MainModule.FileName; + var file = Process.GetCurrentProcess().MainModule!.FileName; var dll = Path.GetDirectoryName(file) + $"\\acdb{Acaop.Version.Major}.dll"; if (File.Exists(dll)) _PeForAcdbDll = new PeInfo(dll); @@ -235,9 +237,9 @@ GetMethodErrorNum GetPeMethod(PeInfo? peInfo) // 排序,最少长度原则本身就是让完全相同字符串在最前面 // 这里替换为有序哈希,因为我总是需要不带修饰的返回函数,所以是排序长度的第一个 - _Methods = _Methods.OrderBy(str => str.CName?.Length) - .ThenBy(str => str.MethodName.Length) - .ToList(); + _Methods = _Methods?.OrderBy(str => str.CName?.Length) + .ThenBy(str => str.MethodName.Length) + .ToList(); func = Marshal.GetDelegateForFunctionPointer(Methods.First().GetProcAddress(), typeof(TDelegate)) as TDelegate; return func; diff --git a/CADShared/Runtime/DBTrans.cs b/CADShared/Runtime/DBTrans.cs index 8b658c7..5a34955 100644 --- a/CADShared/Runtime/DBTrans.cs +++ b/CADShared/Runtime/DBTrans.cs @@ -1,3 +1,7 @@ +#if a2024 +using ArgumentNullException = IFoxCAD.Basal.ArgumentNullException; +#endif + namespace IFoxCAD.Cad; using System.Diagnostics; @@ -23,7 +27,7 @@ public sealed class DBTrans : IDisposable /// 事务对象 public static Transaction GetTopTransaction(Database database) { - ArgumentNullEx.ThrowIfNull(database); + ArgumentNullException.ThrowIfNull(database); return database.TransactionManager.TopTransaction ?? throw new Exception("没有顶层事务!"); } @@ -32,12 +36,12 @@ public static Transaction GetTopTransaction(Database database) /// /// 数据库 /// DBTrans 事务 - /// + /// public static DBTrans GetTop(Database database) { - ArgumentNullEx.ThrowIfNull(database); + ArgumentNullException.ThrowIfNull(database); var trans = database.TransactionManager.TopTransaction; - ArgumentNullEx.ThrowIfNull(trans); + ArgumentNullException.ThrowIfNull(trans); foreach (var item in _dBTrans) { @@ -107,7 +111,7 @@ public static DBTrans Top // 由于大量的函数依赖本属性,强迫用户先开启事务 if (_dBTrans.Count == 0) - throw new ArgumentNullException("事务栈没有任何事务,请在调用前创建:" + nameof(DBTrans)); + throw new System.ArgumentNullException("事务栈没有任何事务,请在调用前创建:" + nameof(DBTrans)); var trans = _dBTrans.Peek(); return trans; } @@ -189,7 +193,7 @@ public DBTrans(string fileName, bool activeOpen = false) { if (string.IsNullOrWhiteSpace(fileName)) - throw new ArgumentNullException(nameof(fileName)); + throw new System.ArgumentNullException(nameof(fileName)); _fileName = fileName.Replace("/", "\\"); // doc.Name总是"D:\\JX.dwg" @@ -522,7 +526,7 @@ public DBObject GetObject(ObjectId id, // ReSharper disable once InconsistentNaming public void Task(Action action, bool handlingDBTextDeviation = true) { - ArgumentNullEx.ThrowIfNull(action); + ArgumentNullException.ThrowIfNull(action); // 前台开图 || 后台直接处理 if (Document != null || !handlingDBTextDeviation) { diff --git a/CADShared/Runtime/Env.cs b/CADShared/Runtime/Env.cs index caa38dd..7a25454 100644 --- a/CADShared/Runtime/Env.cs +++ b/CADShared/Runtime/Env.cs @@ -1,4 +1,7 @@ using System.Security; +#if a2024 +using ArgumentNullException = IFoxCAD.Basal.ArgumentNullException; +#endif // ReSharper disable StringLiteralTypo @@ -630,7 +633,7 @@ public static void AppendTrustedPath(params string[] folders) if (!folders.Any()) return; var trustedPath = GetVar("TRUSTEDPATHS").ToString(); var trustedPathLowerArr = - trustedPath + trustedPath! .ToLower() .Split(';') .Where(item => item != "") @@ -656,7 +659,7 @@ public static void AppendTrustedPath(params string[] folders) public static void RemoveTrustedPath(params string[] folders) { if (!folders.Any()) return; - var trustedPathArr = GetVar("TRUSTEDPATHS").ToString().Split(';').ToList(); + var trustedPathArr = GetVar("TRUSTEDPATHS").ToString()!.Split(';').ToList(); foreach (var folder in folders) { var folderLower = @@ -812,7 +815,7 @@ public static string GetAcapVersionDll(string str = "acdb") /// /// /// 成功返回当前值,失败null - /// + /// public static object? SetVarEx(string key, string value) { var currentVar = GetVar(key); @@ -844,7 +847,7 @@ public static string GetAcapVersionDll(string str = "acdb") /// 返回现有变量词典,然后下次就可以利用它进行设置回来了 public static Dictionary SaveCadVar(Dictionary args) { - ArgumentNullEx.ThrowIfNull(args); + ArgumentNullException.ThrowIfNull(args); var dict = new Dictionary(); foreach (var item in args) { @@ -852,7 +855,7 @@ public static Dictionary SaveCadVar(Dictionary a var ok = SetVarEx(item.Key, item.Value); if (ok is not null) { - dict.Add(item.Key, ok.ToString()); + dict.Add(item.Key, $"{ok}"); continue; } diff --git a/CADShared/Runtime/IdleAction.cs b/CADShared/Runtime/IdleAction.cs index 7779641..b3e0bd4 100644 --- a/CADShared/Runtime/IdleAction.cs +++ b/CADShared/Runtime/IdleAction.cs @@ -43,7 +43,7 @@ public static void Add(Action action) /// /// Acap /// 事件参数 - private static void Acap_Idle(object sender, EventArgs e) + private static void Acap_Idle(object? sender, EventArgs e) { if (Count == 0) { diff --git a/CADShared/Runtime/IdleNoCommandAction.cs b/CADShared/Runtime/IdleNoCommandAction.cs index 0767ea4..72a60b9 100644 --- a/CADShared/Runtime/IdleNoCommandAction.cs +++ b/CADShared/Runtime/IdleNoCommandAction.cs @@ -44,7 +44,7 @@ public static void Add(Action action) /// /// Acap /// 事件参数 - private static void Acap_Idle(object sender, EventArgs e) + private static void Acap_Idle(object? sender, EventArgs e) { if (Count == 0) { diff --git a/CADShared/Runtime/SymbolTable.cs b/CADShared/Runtime/SymbolTable.cs index aef1d3c..6da9f27 100644 --- a/CADShared/Runtime/SymbolTable.cs +++ b/CADShared/Runtime/SymbolTable.cs @@ -1,5 +1,9 @@ // ReSharper disable RedundantNameQualifier +#if a2024 +using ArgumentNullException = IFoxCAD.Basal.ArgumentNullException; +#endif + namespace IFoxCAD.Cad; /// @@ -218,11 +222,9 @@ public void Remove(ObjectId id) public void Change(string name, Action action) { var record = GetRecord(name); - if (record is not null) - { - using (record.ForWrite()) - action.Invoke(record); - } + if (record is null) return; + using (record.ForWrite()) + action.Invoke(record); } /// @@ -319,7 +321,7 @@ public IEnumerable GetRecordNames(Func filter) /// 对象id private ObjectId GetRecordFrom(SymbolTable table, string name, bool over) { - ArgumentNullEx.ThrowIfNull(table); + ArgumentNullException.ThrowIfNull(table); var rid = this[name]; var has = rid != ObjectId.Null; @@ -399,7 +401,7 @@ public void ForEach(Action task, OpenMode openMode = Op { //if (task == null) // throw new ArgumentNullException(nameof(task)); - ArgumentNullEx.ThrowIfNull(task); + ArgumentNullException.ThrowIfNull(task); LoopState state = new(); /*这种方式比Action改Func更友好*/ var i = 0; foreach (var id in this) diff --git a/CADShared/Runtime/SystemVariableManager.cs b/CADShared/Runtime/SystemVariableManager.cs index c065bb8..a418ea7 100644 --- a/CADShared/Runtime/SystemVariableManager.cs +++ b/CADShared/Runtime/SystemVariableManager.cs @@ -61,7 +61,7 @@ public int Auprec /// /// 用于设置当前空间的当前注释比例的值 /// - public static string CanNoScale => Acaop.GetSystemVariable(nameof(CanNoScale)).ToString(); + public static string CanNoScale => Acaop.GetSystemVariable(nameof(CanNoScale)).ToString()!; /// /// 用于显示当前的注释性比例 @@ -79,7 +79,7 @@ public int Auprec /// public static string CEColor { - get => Acaop.GetSystemVariable(nameof(CEColor)).ToString(); + get => Acaop.GetSystemVariable(nameof(CEColor)).ToString()!; set => Acaop.SetSystemVariable(nameof(CEColor), value); } @@ -97,7 +97,7 @@ public static double CELtScale /// public static string CELType { - get => Acaop.GetSystemVariable(nameof(CELType)).ToString(); + get => Acaop.GetSystemVariable(nameof(CELType)).ToString()!; set => Acaop.SetSystemVariable(nameof(CELType), value); } @@ -124,7 +124,7 @@ public static double CircleRad /// public static string CLayer { - get => Acaop.GetSystemVariable(nameof(CLayer)).ToString(); + get => Acaop.GetSystemVariable(nameof(CLayer)).ToString()!; set => Acaop.SetSystemVariable(nameof(CLayer), value); } @@ -165,14 +165,14 @@ public static bool CmdEcho /// /// 当前的命令 /// - public static string CmdNames => Acaop.GetSystemVariable(nameof(CmdNames)).ToString(); + public static string CmdNames => Acaop.GetSystemVariable(nameof(CmdNames)).ToString()!; /// /// 返回图形中的当前选项卡(模型或布局)的名称 /// public static string CTab { - get => Acaop.GetSystemVariable(nameof(CTab)).ToString(); + get => Acaop.GetSystemVariable(nameof(CTab)).ToString()!; set => Acaop.SetSystemVariable(nameof(CTab), value); } diff --git a/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj b/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj index 39e3dc4..ec65b11 100644 --- a/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj +++ b/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj @@ -1,7 +1,7 @@  - net48 + net48;net8.0-windows Preview enable x64 @@ -34,16 +34,30 @@ none True - $(DefineConstants);acad + none false - $(DefineConstants);acad + bin\Release\IFoxCAD.AutoCad.xml + + $(Configuration);;acad;a2024 + + + + $(Configuration);acad;a2025 + true + + + + + + + True @@ -55,7 +69,7 @@ - + @@ -63,9 +77,13 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive + + + + - + -- Gitee From 8d2786d23841b55562db5f279d340d953101c31a Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Mon, 18 Nov 2024 11:59:59 +0800 Subject: [PATCH 359/453] =?UTF-8?q?=E4=BC=98=E5=8C=96=E9=9D=A2=E5=9F=9F?= =?UTF-8?q?=E8=BD=AC=E6=9B=B2=E7=BA=BF=E6=97=B6=E5=90=8C=E7=8E=AF=E4=B8=8D?= =?UTF-8?q?=E8=83=BD=E9=97=AD=E5=90=88=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/ExtensionMethod/Entity/RegionEx.cs | 37 ++++++++------------ 1 file changed, 14 insertions(+), 23 deletions(-) diff --git a/CADShared/ExtensionMethod/Entity/RegionEx.cs b/CADShared/ExtensionMethod/Entity/RegionEx.cs index 12a9961..c78753b 100644 --- a/CADShared/ExtensionMethod/Entity/RegionEx.cs +++ b/CADShared/ExtensionMethod/Entity/RegionEx.cs @@ -15,33 +15,24 @@ public static class RegionEx public static IEnumerable ToCurves(this Region region) { using var brep = new Brep(region); - var loops = brep.Complexes - .SelectMany(complex => complex.Shells) + var loops = brep.Complexes.SelectMany(complex => complex.Shells) .SelectMany(shell => shell.Faces) .SelectMany(face => face.Loops); foreach (var loop in loops) { - var curves3d = loop.Edges.Select(edge => ((ExternalCurve3d)edge.Curve).NativeCurve).ToList(); - if (1 < curves3d.Count) - { - if (curves3d.All(curve3d => curve3d is CircularArc3d or LineSegment3d)) - { - var pl = (Polyline)Curve.CreateFromGeCurve(new CompositeCurve3d(curves3d.ToOrderedArray())); - pl.Closed = true; - yield return pl; - } - else - { - foreach (var curve3d in curves3d) - { - yield return Curve.CreateFromGeCurve(curve3d); - } - } - } - else + var curves3d = loop.Edges.Select(edge => ((ExternalCurve3d)edge.Curve).NativeCurve) + .ToList(); + var cur = Curve.CreateFromGeCurve(1 < curves3d.Count + ? new CompositeCurve3d(curves3d.ToOrderedArray()) + : curves3d.First()); + + foreach (var curve3d in curves3d) { - yield return Curve.CreateFromGeCurve(curves3d.First()); + curve3d.Dispose(); } + + cur.SetPropertiesFrom(region); + yield return cur; } } @@ -49,8 +40,8 @@ public static IEnumerable ToCurves(this Region region) /// 按首尾相连对曲线集合进行排序 /// /// - /// - /// + /// 曲线列表 + /// 当不能首尾相连时会抛出此异常 private static Curve3d[] ToOrderedArray(this IEnumerable source) { var tol = new Tolerance(0.001, 0.001); -- Gitee From f3a5b093b9968e8c078da9d4e63f4504b5c5ef87 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Mon, 18 Nov 2024 12:08:03 +0800 Subject: [PATCH 360/453] =?UTF-8?q?=E5=8F=91=E5=B8=830.9.1.10?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj b/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj index 39e3dc4..7a48fc4 100644 --- a/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj +++ b/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj @@ -18,7 +18,7 @@ IFox.CAD.ACAD IFox.CAD.ACAD IFox.CAD.ACAD - 0.9.1.9 + 0.9.1.10 xsfhlzh, vicwjb, liuqihong, DYH 基于.NET的二次开发基本类库. https://www.nuget.org/packages/IFox.CAD.ACAD/ @@ -27,7 +27,7 @@ IFox,Cad,AutoCad,C#,NET, InspireFunction readme.md - 修复部分系统变量不能Set的问题 + 修复region同环曲线不闭合的问题 LICENSE -- Gitee From 0986bb611188b62ab755203b34345d466fe54bd7 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Tue, 14 May 2024 23:49:38 +0800 Subject: [PATCH 361/453] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E5=9B=BE=E5=85=83=E7=9A=84=E6=B5=8B=E8=AF=95=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Test/GlobalUsings.cs | 3 +- Test/TestAddEntity.cs | 208 +++++++++++++++++++++++++++--------------- 2 files changed, 136 insertions(+), 75 deletions(-) diff --git a/Test/GlobalUsings.cs b/Test/GlobalUsings.cs index a7b8c49..5431209 100644 --- a/Test/GlobalUsings.cs +++ b/Test/GlobalUsings.cs @@ -4,4 +4,5 @@ global using Autodesk.AutoCAD.Geometry; global using Autodesk.AutoCAD.Runtime; global using System.ComponentModel; -global using System.Runtime.InteropServices; \ No newline at end of file +global using System.Runtime.InteropServices; +global using Autodesk.AutoCAD.Colors; \ No newline at end of file diff --git a/Test/TestAddEntity.cs b/Test/TestAddEntity.cs index 70cb05f..df868d1 100644 --- a/Test/TestAddEntity.cs +++ b/Test/TestAddEntity.cs @@ -1,98 +1,158 @@ namespace Test; -public partial class Test + +public class TestAddEntity { - [CommandMethod(nameof(Test_Rec))] - public void Test_Rec() +#region 直线 + [CommandMethod(nameof(Test_AddLinetoCurrentSpace))] + public void Test_AddLinetoCurrentSpace() { - Point2d p1 = new(10000.2, 100000.5); - Point2d p2 = new(15000.9, 100000.5); - Point2d p3 = new(15000.9, 105000.7); - Point2d p4 = new(10000.2, 105000.7); + using DBTrans tr = new(); // 开启事务 - var p12 = p2 - p1; - var p23 = p3 - p2; - var p34 = p4 - p3; - var p41 = p1 - p4; - var p13 = p3 - p1; - var p24 = p4 - p2; + Line line = new(new(0, 0, 0), new(1, 1, 0)); // 定义一个直线 + tr.CurrentSpace.AddEntity(line); // 将直线添加到当前空间 + } + [CommandMethod(nameof(Test_AddLinetoModelSpace))] + public void Test_AddLinetoModelSpace() + { + using DBTrans tr = new(); // 开启事务 - const double pi90 = Math.PI / 2; - Env.Print(pi90); + Line line = new(new(0, 0, 0), new(1, 1, 0)); // 定义一个直线 + tr.ModelSpace.AddEntity(line); // 将直线添加到模型空间 + } - Tools.TestTimes(1000000, "对角线", () => - { - var result = false; - if (Math.Abs(p13.Length - p24.Length) <= 1e8) - { - result = p41.IsParallelTo(p12); - } - }); + [CommandMethod(nameof(Test_AddLinetoPaperSpace))] + public void Test_AddLinetoPaperSpace() + { + using DBTrans tr = new(); // 开启事务 -#pragma warning disable CS0219 // 变量已被赋值,但从未使用过它的值 - Tools.TestTimes(1000000, "三次点乘", () => - { - bool result = Math.Abs(p12.DotProduct(p23)) < 1e8 && - Math.Abs(p23.DotProduct(p34)) < 1e8 && - Math.Abs(p34.DotProduct(p41)) < 1e8; - }); + Line line = new(new(0, 0, 0), new(1, 1, 0)); // 定义一个直线 + tr.PaperSpace.AddEntity(line); // 将直线添加到图纸空间 + } - Tools.TestTimes(1000000, "三次垂直", () => - { - bool result = p12.IsParallelTo(p23) && - p23.IsParallelTo(p34) && - p34.IsParallelTo(p41); - }); -#pragma warning restore CS0219 // 变量已被赋值,但从未使用过它的值 + [CommandMethod(nameof(Test_AddEntities))] + public void Test_AddEntities() + { + // 开启事务 + using DBTrans tr = new(); + // 定义三条直线 + Line line1 = new(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); + Line line2 = new(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); + Line line3 = new(new Point3d(1, 1, 0), new Point3d(3, 3, 0)); + var circle = CircleEx.CreateCircle(new(0,0,0),10); + // 一次性添加到当前空间 + tr.CurrentSpace.AddEntity(line2, line2, line3, circle); + // 或者可以传入个列表 + List lines = [line1, line2, line3]; + tr.CurrentSpace.AddEntity(lines); + // 或者可以传入个数组 + Entity[] lines1 = [line1, line2, line3]; + tr.CurrentSpace.AddEntity(lines1); + // 图元数组 + Entity[] lines2 = [line1, line2, line3, circle]; + tr.CurrentSpace.AddEntity(lines2); + // c#12 新语法,集合表达式 + tr.CurrentSpace.AddEntity([line1, line2, circle]); } +#endregion +#region 圆 + [CommandMethod(nameof(Test_AddCircle))] + public void Test_AddCircle() + { + var cir = CircleEx.CreateCircle(Point3d.Origin, new(1,0,0)); // 两点创建圆 + var cir1 = CircleEx.CreateCircle(Point3d.Origin, new(1,1,0), new(2,0,0)); //三点创建圆 + var cir2 = CircleEx.CreateCircle(Point3d.Origin, 5); // 圆心半径创建圆 - [CommandMethod(nameof(Test_EntRoration))] - public void Test_EntRoration() + using DBTrans tr = new(); + tr.CurrentSpace.AddEntity(cir, cir2); + + // 由于三点不一定能成功创建一个圆,因此返回值是可空的,需要判空 + if (cir1 is not null) + { + tr.CurrentSpace.AddEntity(cir1); + } + } +#endregion + +#region 圆弧 + [CommandMethod(nameof(Test_AddArc))] + public void Test_AddArc() { - var line = new Line(new(0, 0, 0), new(100, 0, 0)); + using DBTrans tr = new(); + var arc1 = ArcEx.CreateArcSCE(new Point3d(2, 0, 0), new Point3d(0, 0, 0), new Point3d(0, 2, 0));// 起点,圆心,终点 + var arc2 = ArcEx.CreateArc(new Point3d(4, 0, 0), new Point3d(0, 0, 0), Math.PI / 2); // 起点,圆心,弧度 + var arc3 = ArcEx.CreateArc(new Point3d(1, 0, 0), new Point3d(0, 0, 0), new Point3d(0, 1, 0)); // 起点,圆上一点,终点 + tr.CurrentSpace.AddEntity(arc1, arc2, arc3); + } +#endregion + + + + + +#region 多段线 + [CommandMethod(nameof(Test_AddPolyline1))] + public void Test_AddPolyline1() + { using DBTrans tr = new(); - tr.CurrentSpace.AddEntity(line); - var line2 = (Line)line.Clone(); - tr.CurrentSpace.AddEntity(line2); - line2.Rotation(new(100, 0, 0), Math.PI / 2); + Polyline pl = new(); + pl.SetDatabaseDefaults(); + pl.AddVertexAt(0, new Point2d(0, 0), 0, 0, 0); + pl.AddVertexAt(1, new Point2d(10, 10), 0, 0, 0); + pl.AddVertexAt(2, new Point2d(20, 20), 0, 0, 0); + pl.AddVertexAt(3, new Point2d(30, 30), 0, 0, 0); + pl.AddVertexAt(4, new Point2d(40, 40), 0, 0, 0); + pl.Closed = true; + pl.Color = Color.FromColorIndex(ColorMethod.ByColor, 6); + tr.CurrentSpace.AddEntity(pl); } - [CommandMethod(nameof(Test_TypeSpeed))] - public void Test_TypeSpeed() + [CommandMethod(nameof(Test_AddPolyline2))] + public void Test_AddPolyline2() { - var line = new Line(); - var line1 = line as Entity; - Tools.TestTimes(100000, "is 匹配:", () => - { - var t = line1 is Line; - }); - Tools.TestTimes(100000, "name 匹配:", () => - { - // var t = line.GetType().Name; - var tt = line1.GetType().Name == nameof(Line); - }); - Tools.TestTimes(100000, "dxfname 匹配:", () => - { - // var t = line.GetType().Name; - var tt = line1.GetRXClass().DxfName == nameof(Line); - }); + // 集合表达式 + List<(Point3d, double, double, double)> pts = + [ + (new Point3d(0,0,0),0,0,0), + (new Point3d(10,0,0),0,0,0), + (new Point3d(10,10,0),0,0,0), + (new Point3d(0,10,0),0,0,0), + (new Point3d(5,5,0),0,0,0) + ]; + + using DBTrans tr = new(); + var pl = pts.CreatePolyline(); + tr.CurrentSpace.AddEntity(pl); } - // 测试延迟刷新 - [CommandMethod(nameof(Test_sleeptrans))] - public static void Test_sleeptrans() + + [CommandMethod(nameof(Test_AddPolyline3))] + public void Test_AddPolyline3() { using var tr = new DBTrans(); - for (int i = 0; i < 100; i++) - { - var cir = CircleEx.CreateCircle(new Point3d(i, i, 0), 0.5); - cir.ColorIndex = i; - tr.CurrentSpace.AddEntity(cir); - tr.Editor?.Redraw(cir); - Thread.Sleep(10); - } + List pts = + [ + new(0, 0, 0), + new(0, 1, 0), + new(1, 1, 0), + new(1, 0, 0) + ]; + var pline = pts.CreatePolyline(); + tr.CurrentSpace.AddEntity(pline); + + // 可以通过委托,一次性的创建多段线并设置属性 + var pline1 = pts.CreatePolyline(p => + { + p.Closed = true; + p.ConstantWidth = 0.2; + p.ColorIndex = 1; + }); + tr.CurrentSpace.AddEntity(pline1); } -} \ No newline at end of file + +#endregion + +} -- Gitee From 5a39dc38bef5657a05d1c9489562198dcf099c82 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Tue, 14 May 2024 23:53:47 +0800 Subject: [PATCH 362/453] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E5=9B=BE=E5=B1=82=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Test/TestLayer.cs | 67 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 Test/TestLayer.cs diff --git a/Test/TestLayer.cs b/Test/TestLayer.cs new file mode 100644 index 0000000..c976fd8 --- /dev/null +++ b/Test/TestLayer.cs @@ -0,0 +1,67 @@ +namespace Test; + + +public class TestLayer +{ + [CommandMethod(nameof(Test_LayerAdd0))] + public void Test_LayerAdd0() + { + using DBTrans tr = new(); + tr.LayerTable.Add("1"); + tr.LayerTable.Add("2", lt => { + lt.Color = Color.FromColorIndex(ColorMethod.ByColor, 1); + lt.LineWeight = LineWeight.LineWeight030; + }); + tr.LayerTable.Remove("3"); + tr.LayerTable.Remove("0"); + tr.LayerTable.Change("4", lt => { + lt.Color = Color.FromColorIndex(ColorMethod.ByColor, 2); + }); + } + + + // 添加图层 + [CommandMethod(nameof(Test_LayerAdd1))] + public void Test_LayerAdd1() + { + using DBTrans tr = new(); + tr.LayerTable.Add("test1", Color.FromColorIndex(ColorMethod.ByColor, 1)); + } + + // 添加图层 + [CommandMethod(nameof(Test_LayerAdd2))] + public void Test_LayerAdd2() + { + using DBTrans tr = new(); + tr.LayerTable.Add("test2", 2); + // tr.LayerTable["3"] = new LayerTableRecord(); + } + // 删除图层 + [CommandMethod(nameof(Test_LayerDel))] + public void Test_LayerDel() + { + using DBTrans tr = new(); + tr.LayerTable.Remove("0"); // 删除图层 0 + tr.LayerTable.Remove("Defpoints");// 删除图层 Defpoints + tr.LayerTable.Remove("1"); // 删除不存在的图层 1 + tr.LayerTable.Remove("2"); // 删除有图元的图层 2 + tr.LayerTable.Remove("3"); // 删除图层 3 + + tr.LayerTable.Remove("2"); // 测试是否能强制删除 + } + + [CommandMethod(nameof(Test_PrintLayerName))] + public void Test_PrintLayerName() + { + using DBTrans tr = new(); + foreach (var layerRecord in tr.LayerTable.GetRecords()) + { + Env.Printl(layerRecord.Name); + } + foreach (var layerRecord in tr.LayerTable.GetRecords()) + { + Env.Printl(layerRecord.Name); + break; + } + } +} \ No newline at end of file -- Gitee From de5e36cb06947e6f48d37b33a55d9057bd00ecb5 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Mon, 18 Nov 2024 16:14:40 +0800 Subject: [PATCH 363/453] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=94=99=E8=AF=AF?= =?UTF-8?q?=E7=9A=84=20namespace?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/ExtensionMethod/PromptOptionsEx.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CADShared/ExtensionMethod/PromptOptionsEx.cs b/CADShared/ExtensionMethod/PromptOptionsEx.cs index 8b61d5a..45c5341 100644 --- a/CADShared/ExtensionMethod/PromptOptionsEx.cs +++ b/CADShared/ExtensionMethod/PromptOptionsEx.cs @@ -1,5 +1,5 @@ // ReSharper disable UnusedAutoPropertyAccessor.Global -namespace IFoxCAD.CAD; +namespace IFoxCAD.Cad; /// /// 交互设置扩展 -- Gitee From 2ad65bf1b96fde37c372f0da2881454ab28752f7 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Tue, 19 Nov 2024 11:06:04 +0800 Subject: [PATCH 364/453] =?UTF-8?q?=E6=81=A2=E5=A4=8DIFoxCAD.Basal.Argumen?= =?UTF-8?q?tNullEx=E5=91=BD=E5=90=8D=E7=A9=BA=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/Algorithms/QuadTree/Rect.cs | 2 +- CADShared/Basal/General/LinqEx.cs | 9 +-------- CADShared/Basal/Nullable/ArgumentNullEx.cs | 7 +++---- .../Basal/Nullable/CallerArgumentExpressionAttribute.cs | 8 +++++--- CADShared/Basal/Win/WindowsAPI.cs | 4 +++- CADShared/ExtensionMethod/Entity/BlockReferenceEx.cs | 2 +- CADShared/ExtensionMethod/Entity/CurveEx.cs | 2 +- CADShared/ExtensionMethod/Geomerty/GeometryEx.cs | 6 ++++-- CADShared/ExtensionMethod/Geomerty/PointEx.cs | 2 +- CADShared/ExtensionMethod/Hatch/HatchConverter.cs | 2 +- CADShared/ExtensionMethod/Hatch/HatchInfo.cs | 2 +- CADShared/ExtensionMethod/Jig/JigEx.cs | 2 +- CADShared/ExtensionMethod/SelectionSetEx.cs | 2 +- CADShared/ExtensionMethod/SymbolTableRecordEx.cs | 2 +- CADShared/ExtensionMethod/XrefEx.cs | 2 +- CADShared/Initialize/AutoRegAssem.cs | 2 +- CADShared/Initialize/MethodInfoHelper.cs | 2 +- CADShared/Runtime/DBTrans.cs | 2 +- CADShared/Runtime/Env.cs | 2 +- CADShared/Runtime/SymbolTable.cs | 2 +- IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj | 2 +- 21 files changed, 32 insertions(+), 34 deletions(-) diff --git a/CADShared/Algorithms/QuadTree/Rect.cs b/CADShared/Algorithms/QuadTree/Rect.cs index 28b309a..939e8b4 100644 --- a/CADShared/Algorithms/QuadTree/Rect.cs +++ b/CADShared/Algorithms/QuadTree/Rect.cs @@ -1,7 +1,7 @@ using System.Diagnostics; using System.Runtime.CompilerServices; #if a2024 -using ArgumentNullException = IFoxCAD.Basal.ArgumentNullException; +using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif namespace IFoxCAD.Cad; diff --git a/CADShared/Basal/General/LinqEx.cs b/CADShared/Basal/General/LinqEx.cs index 20f0505..72883be 100644 --- a/CADShared/Basal/General/LinqEx.cs +++ b/CADShared/Basal/General/LinqEx.cs @@ -288,20 +288,13 @@ internal SpecComparer(Comparison comp) } #region IComparer 成员 - -#if a2024 - public int Compare(T x, T y) - { - return _comp(x, y); - } -#else + public int Compare(T? x, T? y) { if (x is not null && y is not null) return _comp(x, y); return 0; } -#endif #endregion IComparer 成员 } diff --git a/CADShared/Basal/Nullable/ArgumentNullEx.cs b/CADShared/Basal/Nullable/ArgumentNullEx.cs index ec3f4c9..7d9ba56 100644 --- a/CADShared/Basal/Nullable/ArgumentNullEx.cs +++ b/CADShared/Basal/Nullable/ArgumentNullEx.cs @@ -1,12 +1,11 @@  -namespace IFoxCAD.Basal; #if a2024 - +namespace IFoxCAD.Basal; /// /// 参数null检查类 /// -public static class ArgumentNullException +public static class ArgumentNullEx { /// /// 检查参数是否为 null @@ -24,6 +23,6 @@ public static void ThrowIfNull([NotNull] object? argument, } [DoesNotReturn] - private static void Throw(string? paramName) => throw new System.ArgumentNullException(paramName); + private static void Throw(string? paramName) => throw new ArgumentNullException(paramName); } #endif \ No newline at end of file diff --git a/CADShared/Basal/Nullable/CallerArgumentExpressionAttribute.cs b/CADShared/Basal/Nullable/CallerArgumentExpressionAttribute.cs index 6fb3c49..583d458 100644 --- a/CADShared/Basal/Nullable/CallerArgumentExpressionAttribute.cs +++ b/CADShared/Basal/Nullable/CallerArgumentExpressionAttribute.cs @@ -1,5 +1,6 @@ -namespace System.Runtime.CompilerServices; - + +#if a2024 +namespace System.Runtime.CompilerServices; /// /// 指示参数将为另一个参数传递的表达式捕获为字符串。 /// @@ -20,4 +21,5 @@ public CallerArgumentExpressionAttribute(string parameterName) /// // ReSharper disable once UnusedAutoPropertyAccessor.Global public string ParameterName { get; } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/CADShared/Basal/Win/WindowsAPI.cs b/CADShared/Basal/Win/WindowsAPI.cs index 0bf126f..657b5d1 100644 --- a/CADShared/Basal/Win/WindowsAPI.cs +++ b/CADShared/Basal/Win/WindowsAPI.cs @@ -1,6 +1,8 @@ #pragma warning disable CS1591 // 缺少对公共可见类型或成员的 XML 注释 #define Marshal - +#if a2024 +using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; +#endif namespace IFoxCAD.Basal; public partial class WindowsAPI diff --git a/CADShared/ExtensionMethod/Entity/BlockReferenceEx.cs b/CADShared/ExtensionMethod/Entity/BlockReferenceEx.cs index fdaf7bd..4fb23ac 100644 --- a/CADShared/ExtensionMethod/Entity/BlockReferenceEx.cs +++ b/CADShared/ExtensionMethod/Entity/BlockReferenceEx.cs @@ -1,5 +1,5 @@ #if a2024 -using ArgumentNullException = IFoxCAD.Basal.ArgumentNullException; +using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif namespace IFoxCAD.Cad; diff --git a/CADShared/ExtensionMethod/Entity/CurveEx.cs b/CADShared/ExtensionMethod/Entity/CurveEx.cs index e9cb832..2694186 100644 --- a/CADShared/ExtensionMethod/Entity/CurveEx.cs +++ b/CADShared/ExtensionMethod/Entity/CurveEx.cs @@ -1,7 +1,7 @@ // ReSharper disable ForCanBeConvertedToForeach #if a2024 -using ArgumentNullException = IFoxCAD.Basal.ArgumentNullException; +using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif namespace IFoxCAD.Cad; diff --git a/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs b/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs index 3247c4f..3558994 100644 --- a/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs +++ b/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs @@ -1,4 +1,6 @@ -using ArgumentNullException = System.ArgumentNullException; +#if a2024 +using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; +#endif namespace IFoxCAD.Cad; @@ -294,7 +296,7 @@ private static double CalArea(IEnumerable pnts) { using var itor = pnts.GetEnumerator(); if (!itor.MoveNext()) - throw new ArgumentNullException(nameof(pnts)); + throw new System.ArgumentNullException(nameof(pnts)); var start = itor.Current; var p2 = start; double area = 0; diff --git a/CADShared/ExtensionMethod/Geomerty/PointEx.cs b/CADShared/ExtensionMethod/Geomerty/PointEx.cs index 86ff1c8..19acd78 100644 --- a/CADShared/ExtensionMethod/Geomerty/PointEx.cs +++ b/CADShared/ExtensionMethod/Geomerty/PointEx.cs @@ -1,5 +1,5 @@ #if a2024 -using ArgumentNullException = IFoxCAD.Basal.ArgumentNullException; +using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif namespace IFoxCAD.Cad; diff --git a/CADShared/ExtensionMethod/Hatch/HatchConverter.cs b/CADShared/ExtensionMethod/Hatch/HatchConverter.cs index e658723..e49793c 100644 --- a/CADShared/ExtensionMethod/Hatch/HatchConverter.cs +++ b/CADShared/ExtensionMethod/Hatch/HatchConverter.cs @@ -2,7 +2,7 @@ // ReSharper disable ForCanBeConvertedToForeach #if a2024 -using ArgumentNullException = IFoxCAD.Basal.ArgumentNullException; +using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif namespace IFoxCAD.Cad; diff --git a/CADShared/ExtensionMethod/Hatch/HatchInfo.cs b/CADShared/ExtensionMethod/Hatch/HatchInfo.cs index 89f17fb..b66c3e2 100644 --- a/CADShared/ExtensionMethod/Hatch/HatchInfo.cs +++ b/CADShared/ExtensionMethod/Hatch/HatchInfo.cs @@ -1,7 +1,7 @@  #if a2024 -using ArgumentNullException = IFoxCAD.Basal.ArgumentNullException; +using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif namespace IFoxCAD.Cad; diff --git a/CADShared/ExtensionMethod/Jig/JigEx.cs b/CADShared/ExtensionMethod/Jig/JigEx.cs index 23e5d39..1a22827 100644 --- a/CADShared/ExtensionMethod/Jig/JigEx.cs +++ b/CADShared/ExtensionMethod/Jig/JigEx.cs @@ -1,5 +1,5 @@ #if a2024 -using ArgumentNullException = IFoxCAD.Basal.ArgumentNullException; +using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif namespace IFoxCAD.Cad; diff --git a/CADShared/ExtensionMethod/SelectionSetEx.cs b/CADShared/ExtensionMethod/SelectionSetEx.cs index cc4f63a..6c4b99c 100644 --- a/CADShared/ExtensionMethod/SelectionSetEx.cs +++ b/CADShared/ExtensionMethod/SelectionSetEx.cs @@ -1,5 +1,5 @@ #if a2024 -using ArgumentNullException = IFoxCAD.Basal.ArgumentNullException; +using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif namespace IFoxCAD.Cad; diff --git a/CADShared/ExtensionMethod/SymbolTableRecordEx.cs b/CADShared/ExtensionMethod/SymbolTableRecordEx.cs index 75010a0..56b7e8b 100644 --- a/CADShared/ExtensionMethod/SymbolTableRecordEx.cs +++ b/CADShared/ExtensionMethod/SymbolTableRecordEx.cs @@ -1,6 +1,6 @@  #if a2024 -using ArgumentNullException = IFoxCAD.Basal.ArgumentNullException; +using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif namespace IFoxCAD.Cad; diff --git a/CADShared/ExtensionMethod/XrefEx.cs b/CADShared/ExtensionMethod/XrefEx.cs index 2e1f149..df6f3ed 100644 --- a/CADShared/ExtensionMethod/XrefEx.cs +++ b/CADShared/ExtensionMethod/XrefEx.cs @@ -1,7 +1,7 @@ // ReSharper disable ForCanBeConvertedToForeach #if a2024 -using ArgumentNullException = IFoxCAD.Basal.ArgumentNullException; +using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif namespace IFoxCAD.Cad; diff --git a/CADShared/Initialize/AutoRegAssem.cs b/CADShared/Initialize/AutoRegAssem.cs index 0d00227..d379434 100644 --- a/CADShared/Initialize/AutoRegAssem.cs +++ b/CADShared/Initialize/AutoRegAssem.cs @@ -1,5 +1,5 @@ #if a2024 -using ArgumentNullException = IFoxCAD.Basal.ArgumentNullException; +using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif namespace IFoxCAD.Cad; diff --git a/CADShared/Initialize/MethodInfoHelper.cs b/CADShared/Initialize/MethodInfoHelper.cs index af91592..26affa2 100644 --- a/CADShared/Initialize/MethodInfoHelper.cs +++ b/CADShared/Initialize/MethodInfoHelper.cs @@ -1,5 +1,5 @@ #if a2024 -using ArgumentNullException = IFoxCAD.Basal.ArgumentNullException; +using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif namespace IFoxCAD.Cad; diff --git a/CADShared/Runtime/DBTrans.cs b/CADShared/Runtime/DBTrans.cs index 5a34955..e1687f7 100644 --- a/CADShared/Runtime/DBTrans.cs +++ b/CADShared/Runtime/DBTrans.cs @@ -1,5 +1,5 @@ #if a2024 -using ArgumentNullException = IFoxCAD.Basal.ArgumentNullException; +using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif namespace IFoxCAD.Cad; diff --git a/CADShared/Runtime/Env.cs b/CADShared/Runtime/Env.cs index 7a25454..9645e5c 100644 --- a/CADShared/Runtime/Env.cs +++ b/CADShared/Runtime/Env.cs @@ -1,6 +1,6 @@ using System.Security; #if a2024 -using ArgumentNullException = IFoxCAD.Basal.ArgumentNullException; +using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif // ReSharper disable StringLiteralTypo diff --git a/CADShared/Runtime/SymbolTable.cs b/CADShared/Runtime/SymbolTable.cs index 6da9f27..9b6f702 100644 --- a/CADShared/Runtime/SymbolTable.cs +++ b/CADShared/Runtime/SymbolTable.cs @@ -1,7 +1,7 @@ // ReSharper disable RedundantNameQualifier #if a2024 -using ArgumentNullException = IFoxCAD.Basal.ArgumentNullException; +using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif namespace IFoxCAD.Cad; diff --git a/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj b/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj index ec65b11..da3615d 100644 --- a/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj +++ b/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj @@ -45,7 +45,7 @@ - $(Configuration);;acad;a2024 + $(Configuration);acad;a2024 -- Gitee From 26f463a2003d95bfdfc4f74a72206df40ed106dc Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Mon, 18 Nov 2024 11:59:59 +0800 Subject: [PATCH 365/453] =?UTF-8?q?=E4=BC=98=E5=8C=96=E9=9D=A2=E5=9F=9F?= =?UTF-8?q?=E8=BD=AC=E6=9B=B2=E7=BA=BF=E6=97=B6=E5=90=8C=E7=8E=AF=E4=B8=8D?= =?UTF-8?q?=E8=83=BD=E9=97=AD=E5=90=88=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/ExtensionMethod/Entity/RegionEx.cs | 37 ++++++++------------ 1 file changed, 14 insertions(+), 23 deletions(-) diff --git a/CADShared/ExtensionMethod/Entity/RegionEx.cs b/CADShared/ExtensionMethod/Entity/RegionEx.cs index 12a9961..c78753b 100644 --- a/CADShared/ExtensionMethod/Entity/RegionEx.cs +++ b/CADShared/ExtensionMethod/Entity/RegionEx.cs @@ -15,33 +15,24 @@ public static class RegionEx public static IEnumerable ToCurves(this Region region) { using var brep = new Brep(region); - var loops = brep.Complexes - .SelectMany(complex => complex.Shells) + var loops = brep.Complexes.SelectMany(complex => complex.Shells) .SelectMany(shell => shell.Faces) .SelectMany(face => face.Loops); foreach (var loop in loops) { - var curves3d = loop.Edges.Select(edge => ((ExternalCurve3d)edge.Curve).NativeCurve).ToList(); - if (1 < curves3d.Count) - { - if (curves3d.All(curve3d => curve3d is CircularArc3d or LineSegment3d)) - { - var pl = (Polyline)Curve.CreateFromGeCurve(new CompositeCurve3d(curves3d.ToOrderedArray())); - pl.Closed = true; - yield return pl; - } - else - { - foreach (var curve3d in curves3d) - { - yield return Curve.CreateFromGeCurve(curve3d); - } - } - } - else + var curves3d = loop.Edges.Select(edge => ((ExternalCurve3d)edge.Curve).NativeCurve) + .ToList(); + var cur = Curve.CreateFromGeCurve(1 < curves3d.Count + ? new CompositeCurve3d(curves3d.ToOrderedArray()) + : curves3d.First()); + + foreach (var curve3d in curves3d) { - yield return Curve.CreateFromGeCurve(curves3d.First()); + curve3d.Dispose(); } + + cur.SetPropertiesFrom(region); + yield return cur; } } @@ -49,8 +40,8 @@ public static IEnumerable ToCurves(this Region region) /// 按首尾相连对曲线集合进行排序 /// /// - /// - /// + /// 曲线列表 + /// 当不能首尾相连时会抛出此异常 private static Curve3d[] ToOrderedArray(this IEnumerable source) { var tol = new Tolerance(0.001, 0.001); -- Gitee From cca500cf3fb346fc935b236fbc5820cef5656eae Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Mon, 18 Nov 2024 12:08:03 +0800 Subject: [PATCH 366/453] =?UTF-8?q?=E5=8F=91=E5=B8=830.9.1.10?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj b/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj index da3615d..244a008 100644 --- a/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj +++ b/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj @@ -18,7 +18,7 @@ IFox.CAD.ACAD IFox.CAD.ACAD IFox.CAD.ACAD - 0.9.1.9 + 0.9.1.10 xsfhlzh, vicwjb, liuqihong, DYH 基于.NET的二次开发基本类库. https://www.nuget.org/packages/IFox.CAD.ACAD/ @@ -27,7 +27,7 @@ IFox,Cad,AutoCad,C#,NET, InspireFunction readme.md - 修复部分系统变量不能Set的问题 + 修复region同环曲线不闭合的问题 LICENSE -- Gitee From df800347cd3a3fad3d3e6b314fc4ef3294ef308f Mon Sep 17 00:00:00 2001 From: vicwjb Date: Wed, 20 Nov 2024 14:14:53 +0800 Subject: [PATCH 367/453] =?UTF-8?q?=E5=88=A0=E9=99=A4=E5=A4=9A=E4=BD=99?= =?UTF-8?q?=E7=9A=84=E9=99=90=E5=AE=9A=E7=AC=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/Basal/General/LinqEx.cs | 18 +++++++++--------- CADShared/Runtime/Env.cs | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/CADShared/Basal/General/LinqEx.cs b/CADShared/Basal/General/LinqEx.cs index 72883be..30036a1 100644 --- a/CADShared/Basal/General/LinqEx.cs +++ b/CADShared/Basal/General/LinqEx.cs @@ -20,7 +20,7 @@ public static TValue FindByMax(this IEnumerable source, Fu { using var itr = source.GetEnumerator(); if (!itr.MoveNext()) - throw new System.ArgumentNullException(nameof(source), "对象为 null"); + throw new ArgumentNullException(nameof(source), "对象为 null"); var value = itr.Current; var key = func(value); @@ -49,7 +49,7 @@ public static TValue FindByMax(this IEnumerable source, ou { using var itr = source.GetEnumerator(); if (!itr.MoveNext()) - throw new System.ArgumentNullException(nameof(source), "对象为 null"); + throw new ArgumentNullException(nameof(source), "对象为 null"); var value = itr.Current; var key = func(value); @@ -76,7 +76,7 @@ public static TValue FindByMax(this IEnumerable source, Comparis { using var itr = source.GetEnumerator(); if (!itr.MoveNext()) - throw new System.ArgumentNullException(nameof(source), "对象为 null"); + throw new ArgumentNullException(nameof(source), "对象为 null"); var value = itr.Current; @@ -106,7 +106,7 @@ public static TValue FindByMin(this IEnumerable source, ou { using var itr = source.GetEnumerator(); if (!itr.MoveNext()) - throw new System.ArgumentNullException(nameof(source), "对象为 null"); + throw new ArgumentNullException(nameof(source), "对象为 null"); var value = itr.Current; var key = func(value); @@ -135,7 +135,7 @@ public static TValue FindByMin(this IEnumerable source, Fu { using var itr = source.GetEnumerator(); if (!itr.MoveNext()) - throw new System.ArgumentNullException(nameof(source), "对象为 null"); + throw new ArgumentNullException(nameof(source), "对象为 null"); var value = itr.Current; var key = func(value); @@ -161,7 +161,7 @@ public static TValue FindByMin(this IEnumerable source, Comparis { using var itr = source.GetEnumerator(); if (!itr.MoveNext()) - throw new System.ArgumentNullException(nameof(source), "对象为 null"); + throw new ArgumentNullException(nameof(source), "对象为 null"); var value = itr.Current; @@ -190,7 +190,7 @@ public static TValue[] FindByExt(this IEnumerable source, { using var itr = source.GetEnumerator(); if (!itr.MoveNext()) - throw new System.ArgumentNullException(nameof(source), "对象为 null"); + throw new ArgumentNullException(nameof(source), "对象为 null"); var values = new TValue[2]; values[0] = values[1] = itr.Current; @@ -226,7 +226,7 @@ public static TValue[] FindByExt(this IEnumerable source, Compar { using var itr = source.GetEnumerator(); if (!itr.MoveNext()) - throw new System.ArgumentNullException(nameof(source), "对象为 null"); + throw new ArgumentNullException(nameof(source), "对象为 null"); var values = new TValue[2]; values[0] = values[1] = itr.Current; @@ -254,7 +254,7 @@ public static TKey[] FindExt(this IEnumerable source, Func { using var itr = source.GetEnumerator(); if (!itr.MoveNext()) - throw new System.ArgumentNullException(nameof(source), "对象为 null"); + throw new ArgumentNullException(nameof(source), "对象为 null"); var keys = new TKey[2]; keys[0] = keys[1] = func(itr.Current); diff --git a/CADShared/Runtime/Env.cs b/CADShared/Runtime/Env.cs index 9645e5c..5841a42 100644 --- a/CADShared/Runtime/Env.cs +++ b/CADShared/Runtime/Env.cs @@ -630,7 +630,7 @@ public static void RemoveSupportPath(params string[] folders) /// 目录 public static void AppendTrustedPath(params string[] folders) { - if (!folders.Any()) return; + if (folders.Length == 0) return; var trustedPath = GetVar("TRUSTEDPATHS").ToString(); var trustedPathLowerArr = trustedPath! -- Gitee From ec91edbbaf9f92d5d32a7be3c3499699f8b0b435 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Wed, 20 Nov 2024 14:22:04 +0800 Subject: [PATCH 368/453] =?UTF-8?q?=E8=B0=83=E6=95=B4=E9=A1=B9=E7=9B=AE?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E7=9A=84=E9=A1=BA=E5=BA=8F=EF=BC=8C=E4=BE=BF?= =?UTF-8?q?=E4=BA=8E=E5=8F=91=E5=B8=83=E6=97=B6=E6=9B=B4=E6=94=B9=E4=BF=A1?= =?UTF-8?q?=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj b/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj index 244a008..7e1b83f 100644 --- a/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj +++ b/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj @@ -13,12 +13,15 @@ + + 0.9.1.10 + 修复region同环曲线不闭合的问题 + true true IFox.CAD.ACAD IFox.CAD.ACAD IFox.CAD.ACAD - 0.9.1.10 xsfhlzh, vicwjb, liuqihong, DYH 基于.NET的二次开发基本类库. https://www.nuget.org/packages/IFox.CAD.ACAD/ @@ -27,7 +30,6 @@ IFox,Cad,AutoCad,C#,NET, InspireFunction readme.md - 修复region同环曲线不闭合的问题 LICENSE -- Gitee From 1a77540c377a5c49b97d2758d492bf80c65af503 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Wed, 20 Nov 2024 17:36:09 +0800 Subject: [PATCH 369/453] =?UTF-8?q?=E4=BC=98=E5=8C=96DBTrans=E7=9A=84?= =?UTF-8?q?=E4=BD=BF=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/Runtime/DBTrans.cs | 110 +++++++++++++++++++---------------- 1 file changed, 61 insertions(+), 49 deletions(-) diff --git a/CADShared/Runtime/DBTrans.cs b/CADShared/Runtime/DBTrans.cs index 8b658c7..9f3cbaa 100644 --- a/CADShared/Runtime/DBTrans.cs +++ b/CADShared/Runtime/DBTrans.cs @@ -33,20 +33,21 @@ public static Transaction GetTopTransaction(Database database) /// 数据库 /// DBTrans 事务 /// - public static DBTrans GetTop(Database database) + public static DBTrans GetTop(Database? database = null) { + database ??= HostApplicationServices.WorkingDatabase; ArgumentNullEx.ThrowIfNull(database); var trans = database.TransactionManager.TopTransaction; ArgumentNullEx.ThrowIfNull(trans); foreach (var item in _dBTrans) { + // 匹配事务栈内DBTrans的transaction的指针与数据库的顶层事务的指针 if (item.Transaction.UnmanagedObject == trans.UnmanagedObject) { return item; } - } // 匹配事务栈内DBTrans的transaction的指针与数据库的顶层事务的指针 - + } return Top; } @@ -77,12 +78,12 @@ public static DBTrans GetTop(Database database) #endregion - #region 公开属性 + #region 内部属性 /// /// 返回当前事务 /// - public static DBTrans Top + internal static DBTrans Top { get { @@ -113,6 +114,9 @@ public static DBTrans Top } } + #endregion + + #region 公开属性 /// /// 文档 @@ -182,11 +186,9 @@ public DBTrans(Database database, bool commit = true) /// 开图模式 /// 密码 /// 后台打开false;前台打开true(必须设置CommandFlags.Session) - public DBTrans(string fileName, - bool commit = true, + public DBTrans(string fileName, bool commit = true, FileOpenMode fileOpenMode = FileOpenMode.OpenForReadAndWriteNoShare, - string? password = null, - bool activeOpen = false) + string? password = null, bool activeOpen = false) { if (string.IsNullOrWhiteSpace(fileName)) throw new ArgumentNullException(nameof(fileName)); @@ -211,8 +213,7 @@ public DBTrans(string fileName, } else { - var doc = Acaop.DocumentManager - .Cast() + var doc = Acaop.DocumentManager.Cast() .FirstOrDefault(doc => !doc.IsDisposed && doc.Name == _fileName); if (activeOpen) @@ -223,7 +224,8 @@ public DBTrans(string fileName, { // 设置命令标记: CommandFlags.Session // 若没有设置: Open()之后的会进入中断状态(不会执行,直到切换文档ctrl+tab或者关闭文档) - doc = Acaop.DocumentManager.Open(fileName, fileOpenMode == FileOpenMode.OpenForReadAndReadShare, password); + doc = Acaop.DocumentManager.Open(fileName, + fileOpenMode == FileOpenMode.OpenForReadAndReadShare, password); } catch (Exception e) { @@ -295,7 +297,8 @@ public static implicit operator Transaction(DBTrans tr) /// /// 块表 /// - public SymbolTable BlockTable => _blockTable ??= new(this, Database.BlockTableId); + public SymbolTable BlockTable => + _blockTable ??= new(this, Database.BlockTableId); private SymbolTable? _blockTable; @@ -319,72 +322,82 @@ public BlockTableRecord CurrentSpace private ObjectId _lastCurrentSpaceId = ObjectId.Null; private BlockTableRecord? _currentSpace; - /// /// 模型空间 /// - public BlockTableRecord ModelSpace => _modelSpace ??= BlockTable.GetRecord(BlockTable.CurrentSymbolTable[BlockTableRecord.ModelSpace])!; + public BlockTableRecord ModelSpace => + _modelSpace ??= + BlockTable.GetRecord(BlockTable.CurrentSymbolTable[BlockTableRecord.ModelSpace])!; private BlockTableRecord? _modelSpace; /// /// 图纸空间 /// - public BlockTableRecord PaperSpace => BlockTable.GetRecord(BlockTable.CurrentSymbolTable[BlockTableRecord.PaperSpace])!; + public BlockTableRecord PaperSpace => + BlockTable.GetRecord(BlockTable.CurrentSymbolTable[BlockTableRecord.PaperSpace])!; /// /// 层表 /// - public SymbolTable LayerTable => _layerTable ??= new(this, Database.LayerTableId); + public SymbolTable LayerTable => + _layerTable ??= new(this, Database.LayerTableId); private SymbolTable? _layerTable; /// /// 文字样式表 /// - public SymbolTable TextStyleTable => _textStyleTable ??= new(this, Database.TextStyleTableId); + public SymbolTable TextStyleTable => + _textStyleTable ??= new(this, Database.TextStyleTableId); private SymbolTable? _textStyleTable; /// /// 注册应用程序表 /// - public SymbolTable RegAppTable => _regAppTable ??= new(this, Database.RegAppTableId); + public SymbolTable RegAppTable => + _regAppTable ??= new(this, Database.RegAppTableId); private SymbolTable? _regAppTable; /// /// 标注样式表 /// - public SymbolTable DimStyleTable => _dimStyleTable ??= new(this, Database.DimStyleTableId); + public SymbolTable DimStyleTable => + _dimStyleTable ??= new(this, Database.DimStyleTableId); private SymbolTable? _dimStyleTable; /// /// 线型表 /// - public SymbolTable LinetypeTable => _linetypeTable ??= new(this, Database.LinetypeTableId); + public SymbolTable LinetypeTable => + _linetypeTable ??= new(this, Database.LinetypeTableId); private SymbolTable? _linetypeTable; /// /// 用户坐标系表 /// - public SymbolTable UcsTable => _ucsTable ??= new(this, Database.UcsTableId); + public SymbolTable UcsTable => + _ucsTable ??= new(this, Database.UcsTableId); private SymbolTable? _ucsTable; /// /// 视图表 /// - public SymbolTable ViewTable => _viewTable ??= new(this, Database.ViewTableId); + public SymbolTable ViewTable => + _viewTable ??= new(this, Database.ViewTableId); private SymbolTable? _viewTable; /// /// 视口表 /// - public SymbolTable ViewportTable => _viewportTable ??= new(this, Database.ViewportTableId); + public SymbolTable ViewportTable => + _viewportTable ??= new(this, Database.ViewportTableId); private SymbolTable? _viewportTable; @@ -395,7 +408,8 @@ public BlockTableRecord CurrentSpace /// /// 命名对象字典 /// - public DBDictionary NamedObjectsDict => GetObject(Database.NamedObjectsDictionaryId)!; + public DBDictionary NamedObjectsDict => + GetObject(Database.NamedObjectsDictionaryId)!; /// /// 组字典 @@ -405,7 +419,8 @@ public BlockTableRecord CurrentSpace /// /// 多重引线样式字典 /// - public DBDictionary MLeaderStyleDict => GetObject(Database.MLeaderStyleDictionaryId)!; + public DBDictionary MLeaderStyleDict => + GetObject(Database.MLeaderStyleDictionaryId)!; /// /// 多线样式字典 @@ -426,7 +441,8 @@ public BlockTableRecord CurrentSpace /// /// 视觉样式字典 /// - public DBDictionary VisualStyleDict => GetObject(Database.VisualStyleDictionaryId)!; + public DBDictionary VisualStyleDict => + GetObject(Database.VisualStyleDictionaryId)!; /// /// 颜色字典 @@ -436,12 +452,14 @@ public BlockTableRecord CurrentSpace /// /// 打印设置字典 /// - public DBDictionary PlotSettingsDict => GetObject(Database.PlotSettingsDictionaryId)!; + public DBDictionary PlotSettingsDict => + GetObject(Database.PlotSettingsDictionaryId)!; /// /// 打印样式表名字典 /// - public DBDictionary PlotStyleNameDict => GetObject(Database.PlotStyleNameDictionaryId)!; + public DBDictionary PlotStyleNameDict => + GetObject(Database.PlotStyleNameDictionaryId)!; /// /// 布局字典 @@ -457,12 +475,14 @@ public BlockTableRecord CurrentSpace /// /// 详细视图样式字典 /// - public DBDictionary DetailViewStyleDict => GetObject(Database.DetailViewStyleDictionaryId)!; + public DBDictionary DetailViewStyleDict => + GetObject(Database.DetailViewStyleDictionaryId)!; /// /// 剖面视图样式字典 /// - public DBDictionary SectionViewStyleDict => GetObject(Database.SectionViewStyleDictionaryId)!; + public DBDictionary SectionViewStyleDict => + GetObject(Database.SectionViewStyleDictionaryId)!; #endif @@ -478,10 +498,8 @@ public BlockTableRecord CurrentSpace /// 是否打开已删除对象,默认为不打开 /// 是否打开锁定图层对象,默认为不打开 /// 数据库DBObject对象 - public DBObject GetObject(ObjectId id, - OpenMode openMode = OpenMode.ForRead, - bool openErased = false, - bool openLockedLayer = false) + public DBObject GetObject(ObjectId id, OpenMode openMode = OpenMode.ForRead, + bool openErased = false, bool openLockedLayer = false) { return Transaction.GetObject(id, openMode, openErased, openLockedLayer); } @@ -495,10 +513,8 @@ public DBObject GetObject(ObjectId id, /// 是否打开已删除对象,默认为不打开 /// 是否打开锁定图层对象,默认为不打开 /// 图元对象 - public T? GetObject(ObjectId id, - OpenMode openMode = OpenMode.ForRead, - bool openErased = false, - bool openLockedLayer = false) where T : DBObject + public T? GetObject(ObjectId id, OpenMode openMode = OpenMode.ForRead, + bool openErased = false, bool openLockedLayer = false) where T : DBObject { return Transaction.GetObject(id, openMode, openErased, openLockedLayer) as T; } @@ -609,7 +625,8 @@ private void Dispose(bool disposing) */ // 不重复释放,并设置已经释放 - if (IsDisposed) return; + if (IsDisposed) + return; if (disposing) { @@ -660,15 +677,10 @@ public override string ToString() { List lines = [ - $"StackCount = {_dBTrans.Count}", - $"_fileName = \"{_fileName}\"", - $"_commit = {_commit}", - $"_documentLock = {_documentLock != null}", - - $"Document = {Document != null}", - $"Editor = {Editor != null}", - $"Transaction = {Transaction.UnmanagedObject}", - $"Database = {Database.Filename}" + $"StackCount = {_dBTrans.Count}", $"_fileName = \"{_fileName}\"", + $"_commit = {_commit}", $"_documentLock = {_documentLock != null}", + $"Document = {Document != null}", $"Editor = {Editor != null}", + $"Transaction = {Transaction.UnmanagedObject}", $"Database = {Database.Filename}" ]; return string.Join("\n", lines.ToArray()); -- Gitee From 4425222efc039c44ffdecdc040237cd690130ee8 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Wed, 20 Nov 2024 22:17:53 +0800 Subject: [PATCH 370/453] =?UTF-8?q?=E5=90=88=E5=B9=B6=E5=90=8E=E7=BB=A7?= =?UTF-8?q?=E7=BB=AD=E8=B0=83=E6=95=B4=E5=A2=9E=E5=8A=A0net8=E4=B9=8B?= =?UTF-8?q?=E5=90=8E=E7=9A=84=E5=86=B2=E7=AA=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/Runtime/DBTrans.cs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/CADShared/Runtime/DBTrans.cs b/CADShared/Runtime/DBTrans.cs index 9f3cbaa..6ce8375 100644 --- a/CADShared/Runtime/DBTrans.cs +++ b/CADShared/Runtime/DBTrans.cs @@ -1,5 +1,7 @@ namespace IFoxCAD.Cad; - +#if a2024 +using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; +#endif using System.Diagnostics; using System.IO; @@ -23,7 +25,7 @@ public sealed class DBTrans : IDisposable /// 事务对象 public static Transaction GetTopTransaction(Database database) { - ArgumentNullEx.ThrowIfNull(database); + ArgumentNullException.ThrowIfNull(database); return database.TransactionManager.TopTransaction ?? throw new Exception("没有顶层事务!"); } @@ -36,9 +38,9 @@ public static Transaction GetTopTransaction(Database database) public static DBTrans GetTop(Database? database = null) { database ??= HostApplicationServices.WorkingDatabase; - ArgumentNullEx.ThrowIfNull(database); + ArgumentNullException.ThrowIfNull(database); var trans = database.TransactionManager.TopTransaction; - ArgumentNullEx.ThrowIfNull(trans); + ArgumentNullException.ThrowIfNull(trans); foreach (var item in _dBTrans) { @@ -108,7 +110,7 @@ internal static DBTrans Top // 由于大量的函数依赖本属性,强迫用户先开启事务 if (_dBTrans.Count == 0) - throw new ArgumentNullException("事务栈没有任何事务,请在调用前创建:" + nameof(DBTrans)); + throw new System.ArgumentNullException("事务栈没有任何事务,请在调用前创建:" + nameof(DBTrans)); var trans = _dBTrans.Peek(); return trans; } @@ -191,7 +193,7 @@ public DBTrans(string fileName, bool commit = true, string? password = null, bool activeOpen = false) { if (string.IsNullOrWhiteSpace(fileName)) - throw new ArgumentNullException(nameof(fileName)); + throw new System.ArgumentNullException(nameof(fileName)); _fileName = fileName.Replace("/", "\\"); // doc.Name总是"D:\\JX.dwg" @@ -538,7 +540,7 @@ public DBObject GetObject(ObjectId id, OpenMode openMode = OpenMode.ForRead, // ReSharper disable once InconsistentNaming public void Task(Action action, bool handlingDBTextDeviation = true) { - ArgumentNullEx.ThrowIfNull(action); + ArgumentNullException.ThrowIfNull(action); // 前台开图 || 后台直接处理 if (Document != null || !handlingDBTextDeviation) { -- Gitee From d4524642972c9c18186b9ced9642e0b12c84b1b0 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Sun, 24 Nov 2024 22:03:08 +0800 Subject: [PATCH 371/453] =?UTF-8?q?=E5=A2=9E=E5=8A=A0zwcad=E6=94=AF?= =?UTF-8?q?=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/Algorithms/QuadTree/Rect.cs | 2 +- CADShared/Assoc/AssocUtils.cs | 7 +- CADShared/Basal/Nullable/ArgumentNullEx.cs | 2 +- .../CallerArgumentExpressionAttribute.cs | 2 +- CADShared/Basal/Win/WindowsAPI.cs | 2 +- CADShared/ExtensionMethod/DatabaseEx.cs | 2 +- .../Entity/BlockReferenceEx.cs | 2 +- CADShared/ExtensionMethod/Entity/CurveEx.cs | 2 +- CADShared/ExtensionMethod/Entity/RegionEx.cs | 7 +- CADShared/ExtensionMethod/Geomerty/PointEx.cs | 2 +- .../ExtensionMethod/Hatch/HatchConverter.cs | 2 +- CADShared/ExtensionMethod/Hatch/HatchInfo.cs | 2 +- CADShared/ExtensionMethod/Jig/JigEx.cs | 2 +- CADShared/ExtensionMethod/SelectionSetEx.cs | 2 +- .../ExtensionMethod/SymbolTableRecordEx.cs | 2 +- CADShared/ExtensionMethod/XrefEx.cs | 2 +- CADShared/Initialize/AutoRegAssem.cs | 2 +- CADShared/Initialize/MethodInfoHelper.cs | 2 +- CADShared/Runtime/DBTrans.cs | 2 +- CADShared/Runtime/Env.cs | 2 +- CADShared/Runtime/SymbolTable.cs | 2 +- IFoxCAD.ZwCad/GlobalUsings.cs | 52 ++++++++++++ IFoxCAD.ZwCad/IFoxCAD.ZwCad.csproj | 83 +++++++++++++++++++ IFoxCAD.sln | 6 ++ 24 files changed, 171 insertions(+), 22 deletions(-) create mode 100644 IFoxCAD.ZwCad/GlobalUsings.cs create mode 100644 IFoxCAD.ZwCad/IFoxCAD.ZwCad.csproj diff --git a/CADShared/Algorithms/QuadTree/Rect.cs b/CADShared/Algorithms/QuadTree/Rect.cs index 939e8b4..1366442 100644 --- a/CADShared/Algorithms/QuadTree/Rect.cs +++ b/CADShared/Algorithms/QuadTree/Rect.cs @@ -1,6 +1,6 @@ using System.Diagnostics; using System.Runtime.CompilerServices; -#if a2024 +#if a2024 || zcad using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif namespace IFoxCAD.Cad; diff --git a/CADShared/Assoc/AssocUtils.cs b/CADShared/Assoc/AssocUtils.cs index 8781c07..c8c4001 100644 --- a/CADShared/Assoc/AssocUtils.cs +++ b/CADShared/Assoc/AssocUtils.cs @@ -1,4 +1,9 @@ -using ErrorStatus = Autodesk.AutoCAD.Runtime.ErrorStatus; +#if acad +using ErrorStatus = Autodesk.AutoCAD.Runtime.ErrorStatus; +#elif zcad +using ErrorStatus = ZwSoft.ZwCAD.Runtime.ErrorStatus; +#endif + namespace IFoxCAD.Cad.Assoc; diff --git a/CADShared/Basal/Nullable/ArgumentNullEx.cs b/CADShared/Basal/Nullable/ArgumentNullEx.cs index 7d9ba56..7fb7763 100644 --- a/CADShared/Basal/Nullable/ArgumentNullEx.cs +++ b/CADShared/Basal/Nullable/ArgumentNullEx.cs @@ -1,5 +1,5 @@  -#if a2024 +#if a2024 || zcad namespace IFoxCAD.Basal; /// diff --git a/CADShared/Basal/Nullable/CallerArgumentExpressionAttribute.cs b/CADShared/Basal/Nullable/CallerArgumentExpressionAttribute.cs index 583d458..e6f5660 100644 --- a/CADShared/Basal/Nullable/CallerArgumentExpressionAttribute.cs +++ b/CADShared/Basal/Nullable/CallerArgumentExpressionAttribute.cs @@ -1,5 +1,5 @@  -#if a2024 +#if a2024 || zcad namespace System.Runtime.CompilerServices; /// /// 指示参数将为另一个参数传递的表达式捕获为字符串。 diff --git a/CADShared/Basal/Win/WindowsAPI.cs b/CADShared/Basal/Win/WindowsAPI.cs index 657b5d1..5125d47 100644 --- a/CADShared/Basal/Win/WindowsAPI.cs +++ b/CADShared/Basal/Win/WindowsAPI.cs @@ -1,6 +1,6 @@ #pragma warning disable CS1591 // 缺少对公共可见类型或成员的 XML 注释 #define Marshal -#if a2024 +#if a2024 || zcad using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif namespace IFoxCAD.Basal; diff --git a/CADShared/ExtensionMethod/DatabaseEx.cs b/CADShared/ExtensionMethod/DatabaseEx.cs index c3bf399..d4b5350 100644 --- a/CADShared/ExtensionMethod/DatabaseEx.cs +++ b/CADShared/ExtensionMethod/DatabaseEx.cs @@ -120,7 +120,7 @@ public static void SaveFile(this Database db, DwgVersion version = DwgVersion.AC #endif #if zcad // 中望这里没有测试 - db.DxfOut(saveAsFile, 7, version, true); + db.DxfOut(saveAsFile, 7, version); #endif return; } diff --git a/CADShared/ExtensionMethod/Entity/BlockReferenceEx.cs b/CADShared/ExtensionMethod/Entity/BlockReferenceEx.cs index 4fb23ac..39ad840 100644 --- a/CADShared/ExtensionMethod/Entity/BlockReferenceEx.cs +++ b/CADShared/ExtensionMethod/Entity/BlockReferenceEx.cs @@ -1,4 +1,4 @@ -#if a2024 +#if a2024 || zcad using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif diff --git a/CADShared/ExtensionMethod/Entity/CurveEx.cs b/CADShared/ExtensionMethod/Entity/CurveEx.cs index 2694186..14a5113 100644 --- a/CADShared/ExtensionMethod/Entity/CurveEx.cs +++ b/CADShared/ExtensionMethod/Entity/CurveEx.cs @@ -1,6 +1,6 @@ // ReSharper disable ForCanBeConvertedToForeach -#if a2024 +#if a2024 || zcad using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif diff --git a/CADShared/ExtensionMethod/Entity/RegionEx.cs b/CADShared/ExtensionMethod/Entity/RegionEx.cs index c78753b..6cb3c0d 100644 --- a/CADShared/ExtensionMethod/Entity/RegionEx.cs +++ b/CADShared/ExtensionMethod/Entity/RegionEx.cs @@ -1,5 +1,8 @@ -using Autodesk.AutoCAD.BoundaryRepresentation; - +#if acad +using Autodesk.AutoCAD.BoundaryRepresentation; +#elif zcad +using ZwSoft.ZwCAD.BoundaryRepresentation; +#endif namespace IFoxCAD.Cad; /// diff --git a/CADShared/ExtensionMethod/Geomerty/PointEx.cs b/CADShared/ExtensionMethod/Geomerty/PointEx.cs index 19acd78..f920a3c 100644 --- a/CADShared/ExtensionMethod/Geomerty/PointEx.cs +++ b/CADShared/ExtensionMethod/Geomerty/PointEx.cs @@ -1,4 +1,4 @@ -#if a2024 +#if a2024 || zcad using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif diff --git a/CADShared/ExtensionMethod/Hatch/HatchConverter.cs b/CADShared/ExtensionMethod/Hatch/HatchConverter.cs index e49793c..fe79a62 100644 --- a/CADShared/ExtensionMethod/Hatch/HatchConverter.cs +++ b/CADShared/ExtensionMethod/Hatch/HatchConverter.cs @@ -1,7 +1,7 @@ // ReSharper disable CompareOfFloatsByEqualityOperator // ReSharper disable ForCanBeConvertedToForeach -#if a2024 +#if a2024 || zcad using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif diff --git a/CADShared/ExtensionMethod/Hatch/HatchInfo.cs b/CADShared/ExtensionMethod/Hatch/HatchInfo.cs index b66c3e2..f836615 100644 --- a/CADShared/ExtensionMethod/Hatch/HatchInfo.cs +++ b/CADShared/ExtensionMethod/Hatch/HatchInfo.cs @@ -1,6 +1,6 @@  -#if a2024 +#if a2024 || zcad using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif diff --git a/CADShared/ExtensionMethod/Jig/JigEx.cs b/CADShared/ExtensionMethod/Jig/JigEx.cs index 1a22827..0e6b1af 100644 --- a/CADShared/ExtensionMethod/Jig/JigEx.cs +++ b/CADShared/ExtensionMethod/Jig/JigEx.cs @@ -1,4 +1,4 @@ -#if a2024 +#if a2024 || zcad using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif diff --git a/CADShared/ExtensionMethod/SelectionSetEx.cs b/CADShared/ExtensionMethod/SelectionSetEx.cs index 6c4b99c..3d152fb 100644 --- a/CADShared/ExtensionMethod/SelectionSetEx.cs +++ b/CADShared/ExtensionMethod/SelectionSetEx.cs @@ -1,4 +1,4 @@ -#if a2024 +#if a2024 || zcad using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif diff --git a/CADShared/ExtensionMethod/SymbolTableRecordEx.cs b/CADShared/ExtensionMethod/SymbolTableRecordEx.cs index 56b7e8b..4aa3a5a 100644 --- a/CADShared/ExtensionMethod/SymbolTableRecordEx.cs +++ b/CADShared/ExtensionMethod/SymbolTableRecordEx.cs @@ -1,5 +1,5 @@  -#if a2024 +#if a2024 || zcad using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif diff --git a/CADShared/ExtensionMethod/XrefEx.cs b/CADShared/ExtensionMethod/XrefEx.cs index df6f3ed..39f7889 100644 --- a/CADShared/ExtensionMethod/XrefEx.cs +++ b/CADShared/ExtensionMethod/XrefEx.cs @@ -1,6 +1,6 @@ // ReSharper disable ForCanBeConvertedToForeach -#if a2024 +#if a2024 || zcad using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif diff --git a/CADShared/Initialize/AutoRegAssem.cs b/CADShared/Initialize/AutoRegAssem.cs index d379434..7d092c5 100644 --- a/CADShared/Initialize/AutoRegAssem.cs +++ b/CADShared/Initialize/AutoRegAssem.cs @@ -1,4 +1,4 @@ -#if a2024 +#if a2024 || zcad using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif diff --git a/CADShared/Initialize/MethodInfoHelper.cs b/CADShared/Initialize/MethodInfoHelper.cs index 26affa2..79bede7 100644 --- a/CADShared/Initialize/MethodInfoHelper.cs +++ b/CADShared/Initialize/MethodInfoHelper.cs @@ -1,4 +1,4 @@ -#if a2024 +#if a2024 || zcad using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif diff --git a/CADShared/Runtime/DBTrans.cs b/CADShared/Runtime/DBTrans.cs index 6ce8375..a1a4cb4 100644 --- a/CADShared/Runtime/DBTrans.cs +++ b/CADShared/Runtime/DBTrans.cs @@ -1,5 +1,5 @@ namespace IFoxCAD.Cad; -#if a2024 +#if a2024 || zcad using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif using System.Diagnostics; diff --git a/CADShared/Runtime/Env.cs b/CADShared/Runtime/Env.cs index 5841a42..3f88e36 100644 --- a/CADShared/Runtime/Env.cs +++ b/CADShared/Runtime/Env.cs @@ -1,5 +1,5 @@ using System.Security; -#if a2024 +#if a2024 || zcad using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif diff --git a/CADShared/Runtime/SymbolTable.cs b/CADShared/Runtime/SymbolTable.cs index 9b6f702..ad73274 100644 --- a/CADShared/Runtime/SymbolTable.cs +++ b/CADShared/Runtime/SymbolTable.cs @@ -1,6 +1,6 @@ // ReSharper disable RedundantNameQualifier -#if a2024 +#if a2024 || zcad using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif diff --git a/IFoxCAD.ZwCad/GlobalUsings.cs b/IFoxCAD.ZwCad/GlobalUsings.cs new file mode 100644 index 0000000..a3365f5 --- /dev/null +++ b/IFoxCAD.ZwCad/GlobalUsings.cs @@ -0,0 +1,52 @@ +global using ZwSoft.ZwCAD.ApplicationServices; +global using ZwSoft.ZwCAD.DatabaseServices; +global using ZwSoft.ZwCAD.EditorInput; +global using ZwSoft.ZwCAD.Geometry; +global using ZwSoft.ZwCAD.GraphicsInterface; +global using ZwSoft.ZwCAD.Runtime; +global using ZwSoft.ZwCAD.Windows; +global using ZwSoft.ZwCAD.Colors; +global using ZwSoft.ZwCAD.DatabaseServices.Filters; +global using ZwSoft.ZwCAD.GraphicsSystem; +global using LineWeight = ZwSoft.ZwCAD.DatabaseServices.LineWeight; +global using Viewport = ZwSoft.ZwCAD.DatabaseServices.Viewport; +global using Color = ZwSoft.ZwCAD.Colors.Color; +global using Acap = ZwSoft.ZwCAD.ApplicationServices.Application; +global using Acaop = ZwSoft.ZwCAD.ApplicationServices.Core.Application; +global using Polyline = ZwSoft.ZwCAD.DatabaseServices.Polyline; +global using Group = ZwSoft.ZwCAD.DatabaseServices.Group; +global using CursorType = ZwSoft.ZwCAD.EditorInput.CursorType; +global using ColorDialog = ZwSoft.ZwCAD.Windows.ColorDialog; +global using StatusBar = ZwSoft.ZwCAD.Windows.StatusBar; +global using Utils = ZwSoft.ZwCAD.Internal.Utils; +global using SystemVariableChangedEventArgs = ZwSoft.ZwCAD.ApplicationServices.SystemVariableChangedEventArgs; +global using AcException = ZwSoft.ZwCAD.Runtime.Exception; +global using System; +global using System.Reflection; +global using System.Collections; +global using System.Collections.Generic; +global using System.IO; +global using System.Linq; +global using System.Threading; +global using System.Text; +global using System.Runtime.InteropServices; +global using System.ComponentModel; +global using Exception = System.Exception; +global using DrawingColor = System.Drawing.Color; +global using Registry = Microsoft.Win32.Registry; +global using RegistryKey = Microsoft.Win32.RegistryKey; +global using Region = ZwSoft.ZwCAD.DatabaseServices.Region; +global using Microsoft.Win32; +global using System.Linq.Expressions; +global using System.Collections.ObjectModel; +// 系统引用 +global using System.Text.RegularExpressions; +global using System.Runtime.CompilerServices; +global using System.Windows.Input; +global using System.Globalization; +global using System.Diagnostics; + +// global using System.Windows.Data; +global using System.Net; +global using System.Diagnostics.CodeAnalysis; +global using IFoxCAD.Basal; \ No newline at end of file diff --git a/IFoxCAD.ZwCad/IFoxCAD.ZwCad.csproj b/IFoxCAD.ZwCad/IFoxCAD.ZwCad.csproj new file mode 100644 index 0000000..3429c1d --- /dev/null +++ b/IFoxCAD.ZwCad/IFoxCAD.ZwCad.csproj @@ -0,0 +1,83 @@ + + + net48 + Preview + enable + x64 + IFoxCAD.CAD + true + true + true + + + + + + 0.9.1.10 + 修复region同环曲线不闭合的问题 + + true + true + IFox.CAD.ZCAD + IFox.CAD.ZCAD + IFox.CAD.ZCAD + xsfhlzh, vicwjb, liuqihong, DYH + 基于.NET的二次开发基本类库. + https://www.nuget.org/packages/IFox.CAD.ZCAD/ + https://gitee.com/inspirefunction/ifoxcad + git + IFox,Cad,ZwCad,C#,NET, + InspireFunction + readme.md + LICENSE + + + + none + True + + + + + none + false + + bin\Release\IFoxCAD.ZwCad.xml + + + + $(Configuration);zcad;z2025 + + + + + + + + + + + True + \ + + + True + \ + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + diff --git a/IFoxCAD.sln b/IFoxCAD.sln index ed2cf93..dd5e78d 100644 --- a/IFoxCAD.sln +++ b/IFoxCAD.sln @@ -9,6 +9,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test", "Test\Test.csproj", EndProject Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "CADShared", "CADShared\CADShared.shproj", "{5178502E-9A78-4588-B849-33ED439976B2}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IFoxCAD.ZwCad", "IFoxCAD.ZwCad\IFoxCAD.ZwCad.csproj", "{738069A7-1153-4BD0-9C25-3AF52EABDD65}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -23,6 +25,10 @@ Global {0C01F295-0985-436B-A15D-228877C60F1D}.Debug|Any CPU.Build.0 = Debug|Any CPU {0C01F295-0985-436B-A15D-228877C60F1D}.Release|Any CPU.ActiveCfg = Release|Any CPU {0C01F295-0985-436B-A15D-228877C60F1D}.Release|Any CPU.Build.0 = Release|Any CPU + {738069A7-1153-4BD0-9C25-3AF52EABDD65}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {738069A7-1153-4BD0-9C25-3AF52EABDD65}.Debug|Any CPU.Build.0 = Debug|Any CPU + {738069A7-1153-4BD0-9C25-3AF52EABDD65}.Release|Any CPU.ActiveCfg = Release|Any CPU + {738069A7-1153-4BD0-9C25-3AF52EABDD65}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE -- Gitee From dc4d4a5d7efb6011854146795728aee5e7c69533 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Sun, 24 Nov 2024 23:24:04 +0800 Subject: [PATCH 372/453] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=B8=AD=E6=9C=9B?= =?UTF-8?q?=E6=89=BE=E4=B8=8D=E5=88=B0setsize=E5=87=BD=E6=95=B0=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/ExtensionMethod/WindowEx.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CADShared/ExtensionMethod/WindowEx.cs b/CADShared/ExtensionMethod/WindowEx.cs index 6d49aaa..bed5186 100644 --- a/CADShared/ExtensionMethod/WindowEx.cs +++ b/CADShared/ExtensionMethod/WindowEx.cs @@ -85,7 +85,8 @@ public static void SetSizeByScreenResolution(this PaletteSet paletteSet, int wid var newHeight = Convert.ToInt32(height * scale); if (newHeight > size.Height) newHeight = size.Height; - paletteSet.SetSize(new Size(newWidth, newHeight)); + // paletteSet.SetSize(new Size(newWidth, newHeight)); // 中望2025 这样调用报错找不到setsize函数 + WindowExtension.SetSize(paletteSet, new Size(newWidth, newHeight)); // 中望2025这样调用没有问题 } /// -- Gitee From 09d39aabc2aaa56e1521bc159c38512df4c2da65 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Mon, 25 Nov 2024 13:02:38 +0800 Subject: [PATCH 373/453] =?UTF-8?q?=E6=94=B9=E6=96=87=E4=BB=B6=E7=BB=84?= =?UTF-8?q?=E7=BB=87=E5=BD=A2=E5=BC=8F=EF=BC=8C=E6=B7=BB=E5=8A=A0=E5=A4=A7?= =?UTF-8?q?=E9=87=8F=E6=B5=8B=E8=AF=95=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IFoxCAD.sln | 56 +- Test/GlobalUsings.cs | 8 - Test/Test.csproj | 27 - .../Algorithms/QuadTree/QuadEntity.cs | 0 .../Algorithms/QuadTree/QuadTree.cs | 0 .../Algorithms/QuadTree/QuadTreeEvn.cs | 0 .../Algorithms/QuadTree/QuadTreeNode.cs | 0 .../Algorithms/QuadTree/QuadTreeSelectMode.cs | 0 .../CADShared}/Algorithms/QuadTree/Rect.cs | 0 .../Assoc/AssocPersSubentityIdPEEx.cs | 0 .../CADShared}/Assoc/AssocUtils.cs | 0 .../CADShared}/Basal/General/ArrayEx.cs | 0 .../CADShared}/Basal/General/DebugHelper.cs | 0 .../CADShared}/Basal/General/EnumEx.cs | 0 .../CADShared}/Basal/General/LinqEx.cs | 0 .../CADShared}/Basal/General/LoopList.cs | 0 .../CADShared}/Basal/General/LoopState.cs | 0 .../Basal/Nullable/ArgumentNullEx.cs | 0 .../CallerArgumentExpressionAttribute.cs | 0 .../CADShared}/Basal/Win/Enums.cs | 0 .../CADShared}/Basal/Win/PInvokeUser32.cs | 0 .../CADShared}/Basal/Win/SystemEx.cs | 0 .../CADShared}/Basal/Win/WindowsAPI.cs | 0 .../CADShared}/CADShared.projitems | 0 {CADShared => src/CADShared}/CADShared.shproj | 0 .../CADShared}/ExtensionMethod/BaseEx.cs | 0 .../ExtensionMethod/BulgeVertexWidth.cs | 0 .../ExtensionMethod/CollectionEx.cs | 0 .../ExtensionMethod/DBDictionaryEx.cs | 0 .../CADShared}/ExtensionMethod/DBObjectEx.cs | 0 .../CADShared}/ExtensionMethod/DBTransEx.cs | 0 .../CADShared}/ExtensionMethod/DatabaseEx.cs | 0 .../ExtensionMethod/DocumentLockManager.cs | 0 .../CADShared}/ExtensionMethod/DwgMark.cs | 0 .../CADShared}/ExtensionMethod/EditorEx.cs | 0 .../ExtensionMethod/Entity/ArcEx.cs | 0 .../Entity/BlockReferenceEx.cs | 0 .../ExtensionMethod/Entity/BoundingInfo.cs | 0 .../ExtensionMethod/Entity/CircleEx.cs | 0 .../ExtensionMethod/Entity/CurveEx.cs | 0 .../ExtensionMethod/Entity/DBTextEx.cs | 0 .../Entity/EntityBoundingInfo.cs | 0 .../ExtensionMethod/Entity/EntityEx.cs | 0 .../ExtensionMethod/Entity/MTextEx.cs | 0 .../ExtensionMethod/Entity/PolylineEx.cs | 0 .../ExtensionMethod/Entity/RegionEx.cs | 0 .../CADShared}/ExtensionMethod/Enums.cs | 0 .../CADShared}/ExtensionMethod/ErrorInfoEx.cs | 0 .../ExtensionMethod/Geomerty/Curve2dEx.cs | 0 .../ExtensionMethod/Geomerty/Curve3dEx.cs | 0 .../ExtensionMethod/Geomerty/GeometryEx.cs | 0 .../ExtensionMethod/Geomerty/PointEx.cs | 0 .../ExtensionMethod/Hatch/HatchConverter.cs | 0 .../ExtensionMethod/Hatch/HatchEx.cs | 0 .../ExtensionMethod/Hatch/HatchInfo.cs | 0 .../CADShared}/ExtensionMethod/IFoxUtils.cs | 0 .../CADShared}/ExtensionMethod/Jig/JigEx.cs | 0 .../ExtensionMethod/Jig/JigExTransient.cs | 0 .../CADShared}/ExtensionMethod/ObjectIdEx.cs | 0 .../CADShared}/ExtensionMethod/PaneEx.cs | 0 .../ExtensionMethod/PromptOptionsEx.cs | 0 .../CADShared}/ExtensionMethod/RandomEx.cs | 0 .../CADShared}/ExtensionMethod/RedrawEx.cs | 0 .../ExtensionMethod/SelectionSetEx.cs | 0 .../ExtensionMethod/SingleKeyWordHook.cs | 0 .../ExtensionMethod/SymbolTableEx.cs | 0 .../ExtensionMethod/SymbolTableRecordEx.cs | 0 .../CADShared}/ExtensionMethod/TangentEx.cs | 0 .../ExtensionMethod/TransactionEx.cs | 0 .../CADShared}/ExtensionMethod/WindowEx.cs | 0 .../CADShared}/ExtensionMethod/XrefEx.cs | 0 .../CADShared}/Initialize/AcadEMR.cs | 4 +- .../CADShared}/Initialize/AssemInfo.cs | 0 .../CADShared}/Initialize/AutoReg.cs | 0 .../CADShared}/Initialize/AutoRegAssem.cs | 2 + .../CADShared}/Initialize/CheckFactory.cs | 0 .../CADShared}/Initialize/IAutoGo.cs | 0 .../CADShared}/Initialize/MethodInfoHelper.cs | 0 {CADShared => src/CADShared}/PE/AcadPeInfo.cs | 0 {CADShared => src/CADShared}/PE/DBmod.cs | 0 {CADShared => src/CADShared}/PE/PostCmd.cs | 0 {CADShared => src/CADShared}/PE/ProgramPE.cs | 0 .../CADShared}/ResultData/LispList.cs | 0 .../CADShared}/ResultData/TypedValueList.cs | 0 .../CADShared}/ResultData/XDataList.cs | 0 .../CADShared}/ResultData/XRecordDataList.cs | 0 .../CADShared}/Runtime/AcPreferences.cs | 0 .../CADShared}/Runtime/DBTrans.cs | 0 {CADShared => src/CADShared}/Runtime/Env.cs | 0 .../CADShared}/Runtime/IdleAction.cs | 0 .../CADShared}/Runtime/IdleNoCommandAction.cs | 0 .../CADShared}/Runtime/SymbolTable.cs | 0 .../Runtime/SystemVariableManager.cs | 0 .../CADShared}/SelectionFilter/OpComp.cs | 0 .../CADShared}/SelectionFilter/OpEqual.cs | 0 .../CADShared}/SelectionFilter/OpFilter.cs | 0 .../CADShared}/SelectionFilter/OpList.cs | 0 .../CADShared}/SelectionFilter/OpLogi.cs | 0 .../IFoxCAD.AutoCad}/GlobalUsings.cs | 0 .../IFoxCAD.AutoCad}/IFoxCAD.AutoCad.csproj | 4 +- .../IFoxCAD.ZwCad}/GlobalUsings.cs | 0 .../IFoxCAD.ZwCad}/IFoxCAD.ZwCad.csproj | 6 +- tests/TestAcad2025/GlobalUsings.cs | 50 + tests/TestAcad2025/TestAcad2025.csproj | 32 + tests/TestShared/CmdINI.cs | 189 ++++ tests/TestShared/Copyclip.cs | 881 ++++++++++++++++++ tests/TestShared/TestAddEntity.cs | 109 +++ tests/TestShared/TestBlock.cs | 864 +++++++++++++++++ tests/TestShared/TestCadFilePath.cs | 30 + tests/TestShared/TestConvexHull.cs | 76 ++ tests/TestShared/TestCurve.cs | 324 +++++++ tests/TestShared/TestDBTrans.cs | 203 ++++ tests/TestShared/TestDBobject.cs | 27 + tests/TestShared/TestDwgFilerEx.cs | 161 ++++ tests/TestShared/TestDwgMark.cs | 11 + tests/TestShared/TestEditor.cs | 87 ++ .../TestShared/TestEntity}/TestAddEntity.cs | 13 +- tests/TestShared/TestEnv.cs | 184 ++++ tests/TestShared/TestExtents.cs | 108 +++ tests/TestShared/TestFileDatabase.cs | 28 + tests/TestShared/TestHatchinfo.cs | 18 + tests/TestShared/TestId.cs | 72 ++ tests/TestShared/TestJig.cs | 313 +++++++ tests/TestShared/TestJigExTransient.cs | 88 ++ tests/TestShared/TestJson.cs | 25 + {Test => tests/TestShared}/TestLayer.cs | 7 +- tests/TestShared/TestLisp.cs | 122 +++ tests/TestShared/TestLoop.cs | 25 + tests/TestShared/TestMarshal.cs | 123 +++ tests/TestShared/TestMirrorFile.cs | 73 ++ tests/TestShared/TestPoint.cs | 204 ++++ {Test => tests/TestShared}/TestPointEx.cs | 0 tests/TestShared/TestQuadTree.cs | 457 +++++++++ tests/TestShared/TestSelectfilter.cs | 58 ++ tests/TestShared/TestShared.projitems | 52 ++ tests/TestShared/TestShared.shproj | 13 + tests/TestShared/TestSingleKeyWordHook.cs | 48 + tests/TestShared/TestText.cs | 49 + tests/TestShared/TestXRecord.cs | 252 +++++ tests/TestShared/TestXdata.cs | 132 +++ tests/TestShared/TestXrefEx.cs | 24 + {Test => tests/TestShared}/Timer.cs | 0 {Test => tests/TestShared}/Tools.cs | 0 tests/TestShared/readme.md | 20 + tests/TestZcad2025/GlobalUsings.cs | 48 + tests/TestZcad2025/TestZcad2025.csproj | 33 + 146 files changed, 5672 insertions(+), 68 deletions(-) delete mode 100644 Test/GlobalUsings.cs delete mode 100644 Test/Test.csproj rename {CADShared => src/CADShared}/Algorithms/QuadTree/QuadEntity.cs (100%) rename {CADShared => src/CADShared}/Algorithms/QuadTree/QuadTree.cs (100%) rename {CADShared => src/CADShared}/Algorithms/QuadTree/QuadTreeEvn.cs (100%) rename {CADShared => src/CADShared}/Algorithms/QuadTree/QuadTreeNode.cs (100%) rename {CADShared => src/CADShared}/Algorithms/QuadTree/QuadTreeSelectMode.cs (100%) rename {CADShared => src/CADShared}/Algorithms/QuadTree/Rect.cs (100%) rename {CADShared => src/CADShared}/Assoc/AssocPersSubentityIdPEEx.cs (100%) rename {CADShared => src/CADShared}/Assoc/AssocUtils.cs (100%) rename {CADShared => src/CADShared}/Basal/General/ArrayEx.cs (100%) rename {CADShared => src/CADShared}/Basal/General/DebugHelper.cs (100%) rename {CADShared => src/CADShared}/Basal/General/EnumEx.cs (100%) rename {CADShared => src/CADShared}/Basal/General/LinqEx.cs (100%) rename {CADShared => src/CADShared}/Basal/General/LoopList.cs (100%) rename {CADShared => src/CADShared}/Basal/General/LoopState.cs (100%) rename {CADShared => src/CADShared}/Basal/Nullable/ArgumentNullEx.cs (100%) rename {CADShared => src/CADShared}/Basal/Nullable/CallerArgumentExpressionAttribute.cs (100%) rename {CADShared => src/CADShared}/Basal/Win/Enums.cs (100%) rename {CADShared => src/CADShared}/Basal/Win/PInvokeUser32.cs (100%) rename {CADShared => src/CADShared}/Basal/Win/SystemEx.cs (100%) rename {CADShared => src/CADShared}/Basal/Win/WindowsAPI.cs (100%) rename {CADShared => src/CADShared}/CADShared.projitems (100%) rename {CADShared => src/CADShared}/CADShared.shproj (100%) rename {CADShared => src/CADShared}/ExtensionMethod/BaseEx.cs (100%) rename {CADShared => src/CADShared}/ExtensionMethod/BulgeVertexWidth.cs (100%) rename {CADShared => src/CADShared}/ExtensionMethod/CollectionEx.cs (100%) rename {CADShared => src/CADShared}/ExtensionMethod/DBDictionaryEx.cs (100%) rename {CADShared => src/CADShared}/ExtensionMethod/DBObjectEx.cs (100%) rename {CADShared => src/CADShared}/ExtensionMethod/DBTransEx.cs (100%) rename {CADShared => src/CADShared}/ExtensionMethod/DatabaseEx.cs (100%) rename {CADShared => src/CADShared}/ExtensionMethod/DocumentLockManager.cs (100%) rename {CADShared => src/CADShared}/ExtensionMethod/DwgMark.cs (100%) rename {CADShared => src/CADShared}/ExtensionMethod/EditorEx.cs (100%) rename {CADShared => src/CADShared}/ExtensionMethod/Entity/ArcEx.cs (100%) rename {CADShared => src/CADShared}/ExtensionMethod/Entity/BlockReferenceEx.cs (100%) rename {CADShared => src/CADShared}/ExtensionMethod/Entity/BoundingInfo.cs (100%) rename {CADShared => src/CADShared}/ExtensionMethod/Entity/CircleEx.cs (100%) rename {CADShared => src/CADShared}/ExtensionMethod/Entity/CurveEx.cs (100%) rename {CADShared => src/CADShared}/ExtensionMethod/Entity/DBTextEx.cs (100%) rename {CADShared => src/CADShared}/ExtensionMethod/Entity/EntityBoundingInfo.cs (100%) rename {CADShared => src/CADShared}/ExtensionMethod/Entity/EntityEx.cs (100%) rename {CADShared => src/CADShared}/ExtensionMethod/Entity/MTextEx.cs (100%) rename {CADShared => src/CADShared}/ExtensionMethod/Entity/PolylineEx.cs (100%) rename {CADShared => src/CADShared}/ExtensionMethod/Entity/RegionEx.cs (100%) rename {CADShared => src/CADShared}/ExtensionMethod/Enums.cs (100%) rename {CADShared => src/CADShared}/ExtensionMethod/ErrorInfoEx.cs (100%) rename {CADShared => src/CADShared}/ExtensionMethod/Geomerty/Curve2dEx.cs (100%) rename {CADShared => src/CADShared}/ExtensionMethod/Geomerty/Curve3dEx.cs (100%) rename {CADShared => src/CADShared}/ExtensionMethod/Geomerty/GeometryEx.cs (100%) rename {CADShared => src/CADShared}/ExtensionMethod/Geomerty/PointEx.cs (100%) rename {CADShared => src/CADShared}/ExtensionMethod/Hatch/HatchConverter.cs (100%) rename {CADShared => src/CADShared}/ExtensionMethod/Hatch/HatchEx.cs (100%) rename {CADShared => src/CADShared}/ExtensionMethod/Hatch/HatchInfo.cs (100%) rename {CADShared => src/CADShared}/ExtensionMethod/IFoxUtils.cs (100%) rename {CADShared => src/CADShared}/ExtensionMethod/Jig/JigEx.cs (100%) rename {CADShared => src/CADShared}/ExtensionMethod/Jig/JigExTransient.cs (100%) rename {CADShared => src/CADShared}/ExtensionMethod/ObjectIdEx.cs (100%) rename {CADShared => src/CADShared}/ExtensionMethod/PaneEx.cs (100%) rename {CADShared => src/CADShared}/ExtensionMethod/PromptOptionsEx.cs (100%) rename {CADShared => src/CADShared}/ExtensionMethod/RandomEx.cs (100%) rename {CADShared => src/CADShared}/ExtensionMethod/RedrawEx.cs (100%) rename {CADShared => src/CADShared}/ExtensionMethod/SelectionSetEx.cs (100%) rename {CADShared => src/CADShared}/ExtensionMethod/SingleKeyWordHook.cs (100%) rename {CADShared => src/CADShared}/ExtensionMethod/SymbolTableEx.cs (100%) rename {CADShared => src/CADShared}/ExtensionMethod/SymbolTableRecordEx.cs (100%) rename {CADShared => src/CADShared}/ExtensionMethod/TangentEx.cs (100%) rename {CADShared => src/CADShared}/ExtensionMethod/TransactionEx.cs (100%) rename {CADShared => src/CADShared}/ExtensionMethod/WindowEx.cs (100%) rename {CADShared => src/CADShared}/ExtensionMethod/XrefEx.cs (100%) rename {CADShared => src/CADShared}/Initialize/AcadEMR.cs (99%) rename {CADShared => src/CADShared}/Initialize/AssemInfo.cs (100%) rename {CADShared => src/CADShared}/Initialize/AutoReg.cs (100%) rename {CADShared => src/CADShared}/Initialize/AutoRegAssem.cs (99%) rename {CADShared => src/CADShared}/Initialize/CheckFactory.cs (100%) rename {CADShared => src/CADShared}/Initialize/IAutoGo.cs (100%) rename {CADShared => src/CADShared}/Initialize/MethodInfoHelper.cs (100%) rename {CADShared => src/CADShared}/PE/AcadPeInfo.cs (100%) rename {CADShared => src/CADShared}/PE/DBmod.cs (100%) rename {CADShared => src/CADShared}/PE/PostCmd.cs (100%) rename {CADShared => src/CADShared}/PE/ProgramPE.cs (100%) rename {CADShared => src/CADShared}/ResultData/LispList.cs (100%) rename {CADShared => src/CADShared}/ResultData/TypedValueList.cs (100%) rename {CADShared => src/CADShared}/ResultData/XDataList.cs (100%) rename {CADShared => src/CADShared}/ResultData/XRecordDataList.cs (100%) rename {CADShared => src/CADShared}/Runtime/AcPreferences.cs (100%) rename {CADShared => src/CADShared}/Runtime/DBTrans.cs (100%) rename {CADShared => src/CADShared}/Runtime/Env.cs (100%) rename {CADShared => src/CADShared}/Runtime/IdleAction.cs (100%) rename {CADShared => src/CADShared}/Runtime/IdleNoCommandAction.cs (100%) rename {CADShared => src/CADShared}/Runtime/SymbolTable.cs (100%) rename {CADShared => src/CADShared}/Runtime/SystemVariableManager.cs (100%) rename {CADShared => src/CADShared}/SelectionFilter/OpComp.cs (100%) rename {CADShared => src/CADShared}/SelectionFilter/OpEqual.cs (100%) rename {CADShared => src/CADShared}/SelectionFilter/OpFilter.cs (100%) rename {CADShared => src/CADShared}/SelectionFilter/OpList.cs (100%) rename {CADShared => src/CADShared}/SelectionFilter/OpLogi.cs (100%) rename {IFoxCAD.AutoCad => src/IFoxCAD.AutoCad}/GlobalUsings.cs (100%) rename {IFoxCAD.AutoCad => src/IFoxCAD.AutoCad}/IFoxCAD.AutoCad.csproj (97%) rename {IFoxCAD.ZwCad => src/IFoxCAD.ZwCad}/GlobalUsings.cs (100%) rename {IFoxCAD.ZwCad => src/IFoxCAD.ZwCad}/IFoxCAD.ZwCad.csproj (96%) create mode 100644 tests/TestAcad2025/GlobalUsings.cs create mode 100644 tests/TestAcad2025/TestAcad2025.csproj create mode 100644 tests/TestShared/CmdINI.cs create mode 100644 tests/TestShared/Copyclip.cs create mode 100644 tests/TestShared/TestAddEntity.cs create mode 100644 tests/TestShared/TestBlock.cs create mode 100644 tests/TestShared/TestCadFilePath.cs create mode 100644 tests/TestShared/TestConvexHull.cs create mode 100644 tests/TestShared/TestCurve.cs create mode 100644 tests/TestShared/TestDBTrans.cs create mode 100644 tests/TestShared/TestDBobject.cs create mode 100644 tests/TestShared/TestDwgFilerEx.cs create mode 100644 tests/TestShared/TestDwgMark.cs create mode 100644 tests/TestShared/TestEditor.cs rename {Test => tests/TestShared/TestEntity}/TestAddEntity.cs (93%) create mode 100644 tests/TestShared/TestEnv.cs create mode 100644 tests/TestShared/TestExtents.cs create mode 100644 tests/TestShared/TestFileDatabase.cs create mode 100644 tests/TestShared/TestHatchinfo.cs create mode 100644 tests/TestShared/TestId.cs create mode 100644 tests/TestShared/TestJig.cs create mode 100644 tests/TestShared/TestJigExTransient.cs create mode 100644 tests/TestShared/TestJson.cs rename {Test => tests/TestShared}/TestLayer.cs (93%) create mode 100644 tests/TestShared/TestLisp.cs create mode 100644 tests/TestShared/TestLoop.cs create mode 100644 tests/TestShared/TestMarshal.cs create mode 100644 tests/TestShared/TestMirrorFile.cs create mode 100644 tests/TestShared/TestPoint.cs rename {Test => tests/TestShared}/TestPointEx.cs (100%) create mode 100644 tests/TestShared/TestQuadTree.cs create mode 100644 tests/TestShared/TestSelectfilter.cs create mode 100644 tests/TestShared/TestShared.projitems create mode 100644 tests/TestShared/TestShared.shproj create mode 100644 tests/TestShared/TestSingleKeyWordHook.cs create mode 100644 tests/TestShared/TestText.cs create mode 100644 tests/TestShared/TestXRecord.cs create mode 100644 tests/TestShared/TestXdata.cs create mode 100644 tests/TestShared/TestXrefEx.cs rename {Test => tests/TestShared}/Timer.cs (100%) rename {Test => tests/TestShared}/Tools.cs (100%) create mode 100644 tests/TestShared/readme.md create mode 100644 tests/TestZcad2025/GlobalUsings.cs create mode 100644 tests/TestZcad2025/TestZcad2025.csproj diff --git a/IFoxCAD.sln b/IFoxCAD.sln index dd5e78d..552aed5 100644 --- a/IFoxCAD.sln +++ b/IFoxCAD.sln @@ -3,13 +3,26 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.8.34309.116 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IFoxCAD.AutoCad", "IFoxCAD.AutoCad\IFoxCAD.AutoCad.csproj", "{6B29955A-5796-4035-9297-210FA15D3846}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{AE09C3B7-58AC-4A68-9884-1F93FDA5D785}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test", "Test\Test.csproj", "{0C01F295-0985-436B-A15D-228877C60F1D}" +Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "CADShared", "src\CADShared\CADShared.shproj", "{5178502E-9A78-4588-B849-33ED439976B2}" EndProject -Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "CADShared", "CADShared\CADShared.shproj", "{5178502E-9A78-4588-B849-33ED439976B2}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IFoxCAD.AutoCad", "src\IFoxCAD.AutoCad\IFoxCAD.AutoCad.csproj", "{9A0A144F-6820-4D15-9D39-43B7298195E3}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IFoxCAD.ZwCad", "IFoxCAD.ZwCad\IFoxCAD.ZwCad.csproj", "{738069A7-1153-4BD0-9C25-3AF52EABDD65}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IFoxCAD.ZwCad", "src\IFoxCAD.ZwCad\IFoxCAD.ZwCad.csproj", "{8546C2AC-815C-47A1-9D8C-A6470DF44AD9}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{46F3EDA8-A6D1-4707-8D03-731CADB41A56}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestAcad2025", "tests\TestAcad2025\TestAcad2025.csproj", "{47C42AB4-C2F4-475B-899C-71FDE57D926E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestZcad2025", "tests\TestZcad2025\TestZcad2025.csproj", "{0B4601B4-CBDA-4FD8-9B31-C1E292D03068}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{7145708C-A65B-470E-A8DA-ED79AC9A42D7}" + ProjectSection(SolutionItems) = preProject + docs\关于IFoxCAD的架构说明.md = docs\关于IFoxCAD的架构说明.md + EndProjectSection +EndProject +Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "TestShared", "tests\TestShared\TestShared.shproj", "{CED63D2D-0AF6-4831-806D-5E8E9B0D0A07}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -17,18 +30,22 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {6B29955A-5796-4035-9297-210FA15D3846}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6B29955A-5796-4035-9297-210FA15D3846}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6B29955A-5796-4035-9297-210FA15D3846}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6B29955A-5796-4035-9297-210FA15D3846}.Release|Any CPU.Build.0 = Release|Any CPU - {0C01F295-0985-436B-A15D-228877C60F1D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0C01F295-0985-436B-A15D-228877C60F1D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0C01F295-0985-436B-A15D-228877C60F1D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0C01F295-0985-436B-A15D-228877C60F1D}.Release|Any CPU.Build.0 = Release|Any CPU - {738069A7-1153-4BD0-9C25-3AF52EABDD65}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {738069A7-1153-4BD0-9C25-3AF52EABDD65}.Debug|Any CPU.Build.0 = Debug|Any CPU - {738069A7-1153-4BD0-9C25-3AF52EABDD65}.Release|Any CPU.ActiveCfg = Release|Any CPU - {738069A7-1153-4BD0-9C25-3AF52EABDD65}.Release|Any CPU.Build.0 = Release|Any CPU + {9A0A144F-6820-4D15-9D39-43B7298195E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9A0A144F-6820-4D15-9D39-43B7298195E3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9A0A144F-6820-4D15-9D39-43B7298195E3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9A0A144F-6820-4D15-9D39-43B7298195E3}.Release|Any CPU.Build.0 = Release|Any CPU + {8546C2AC-815C-47A1-9D8C-A6470DF44AD9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8546C2AC-815C-47A1-9D8C-A6470DF44AD9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8546C2AC-815C-47A1-9D8C-A6470DF44AD9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8546C2AC-815C-47A1-9D8C-A6470DF44AD9}.Release|Any CPU.Build.0 = Release|Any CPU + {47C42AB4-C2F4-475B-899C-71FDE57D926E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {47C42AB4-C2F4-475B-899C-71FDE57D926E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {47C42AB4-C2F4-475B-899C-71FDE57D926E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {47C42AB4-C2F4-475B-899C-71FDE57D926E}.Release|Any CPU.Build.0 = Release|Any CPU + {0B4601B4-CBDA-4FD8-9B31-C1E292D03068}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0B4601B4-CBDA-4FD8-9B31-C1E292D03068}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0B4601B4-CBDA-4FD8-9B31-C1E292D03068}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0B4601B4-CBDA-4FD8-9B31-C1E292D03068}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -40,4 +57,11 @@ Global CADShared\CADShared.projitems*{5178502e-9a78-4588-b849-33ed439976b2}*SharedItemsImports = 13 CADShared\CADShared.projitems*{6b29955a-5796-4035-9297-210fa15d3846}*SharedItemsImports = 5 EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {9A0A144F-6820-4D15-9D39-43B7298195E3} = {AE09C3B7-58AC-4A68-9884-1F93FDA5D785} + {8546C2AC-815C-47A1-9D8C-A6470DF44AD9} = {AE09C3B7-58AC-4A68-9884-1F93FDA5D785} + {47C42AB4-C2F4-475B-899C-71FDE57D926E} = {46F3EDA8-A6D1-4707-8D03-731CADB41A56} + {0B4601B4-CBDA-4FD8-9B31-C1E292D03068} = {46F3EDA8-A6D1-4707-8D03-731CADB41A56} + {CED63D2D-0AF6-4831-806D-5E8E9B0D0A07} = {46F3EDA8-A6D1-4707-8D03-731CADB41A56} + EndGlobalSection EndGlobal diff --git a/Test/GlobalUsings.cs b/Test/GlobalUsings.cs deleted file mode 100644 index 5431209..0000000 --- a/Test/GlobalUsings.cs +++ /dev/null @@ -1,8 +0,0 @@ -global using IFoxCAD.Cad; -global using Acap =Autodesk.AutoCAD.ApplicationServices.Application; -global using Autodesk.AutoCAD.DatabaseServices; -global using Autodesk.AutoCAD.Geometry; -global using Autodesk.AutoCAD.Runtime; -global using System.ComponentModel; -global using System.Runtime.InteropServices; -global using Autodesk.AutoCAD.Colors; \ No newline at end of file diff --git a/Test/Test.csproj b/Test/Test.csproj deleted file mode 100644 index 9ffaa05..0000000 --- a/Test/Test.csproj +++ /dev/null @@ -1,27 +0,0 @@ - - - - net48 - true - preview - enable - - - - x64 - - - - x64 - - - - - - - - - - - - diff --git a/CADShared/Algorithms/QuadTree/QuadEntity.cs b/src/CADShared/Algorithms/QuadTree/QuadEntity.cs similarity index 100% rename from CADShared/Algorithms/QuadTree/QuadEntity.cs rename to src/CADShared/Algorithms/QuadTree/QuadEntity.cs diff --git a/CADShared/Algorithms/QuadTree/QuadTree.cs b/src/CADShared/Algorithms/QuadTree/QuadTree.cs similarity index 100% rename from CADShared/Algorithms/QuadTree/QuadTree.cs rename to src/CADShared/Algorithms/QuadTree/QuadTree.cs diff --git a/CADShared/Algorithms/QuadTree/QuadTreeEvn.cs b/src/CADShared/Algorithms/QuadTree/QuadTreeEvn.cs similarity index 100% rename from CADShared/Algorithms/QuadTree/QuadTreeEvn.cs rename to src/CADShared/Algorithms/QuadTree/QuadTreeEvn.cs diff --git a/CADShared/Algorithms/QuadTree/QuadTreeNode.cs b/src/CADShared/Algorithms/QuadTree/QuadTreeNode.cs similarity index 100% rename from CADShared/Algorithms/QuadTree/QuadTreeNode.cs rename to src/CADShared/Algorithms/QuadTree/QuadTreeNode.cs diff --git a/CADShared/Algorithms/QuadTree/QuadTreeSelectMode.cs b/src/CADShared/Algorithms/QuadTree/QuadTreeSelectMode.cs similarity index 100% rename from CADShared/Algorithms/QuadTree/QuadTreeSelectMode.cs rename to src/CADShared/Algorithms/QuadTree/QuadTreeSelectMode.cs diff --git a/CADShared/Algorithms/QuadTree/Rect.cs b/src/CADShared/Algorithms/QuadTree/Rect.cs similarity index 100% rename from CADShared/Algorithms/QuadTree/Rect.cs rename to src/CADShared/Algorithms/QuadTree/Rect.cs diff --git a/CADShared/Assoc/AssocPersSubentityIdPEEx.cs b/src/CADShared/Assoc/AssocPersSubentityIdPEEx.cs similarity index 100% rename from CADShared/Assoc/AssocPersSubentityIdPEEx.cs rename to src/CADShared/Assoc/AssocPersSubentityIdPEEx.cs diff --git a/CADShared/Assoc/AssocUtils.cs b/src/CADShared/Assoc/AssocUtils.cs similarity index 100% rename from CADShared/Assoc/AssocUtils.cs rename to src/CADShared/Assoc/AssocUtils.cs diff --git a/CADShared/Basal/General/ArrayEx.cs b/src/CADShared/Basal/General/ArrayEx.cs similarity index 100% rename from CADShared/Basal/General/ArrayEx.cs rename to src/CADShared/Basal/General/ArrayEx.cs diff --git a/CADShared/Basal/General/DebugHelper.cs b/src/CADShared/Basal/General/DebugHelper.cs similarity index 100% rename from CADShared/Basal/General/DebugHelper.cs rename to src/CADShared/Basal/General/DebugHelper.cs diff --git a/CADShared/Basal/General/EnumEx.cs b/src/CADShared/Basal/General/EnumEx.cs similarity index 100% rename from CADShared/Basal/General/EnumEx.cs rename to src/CADShared/Basal/General/EnumEx.cs diff --git a/CADShared/Basal/General/LinqEx.cs b/src/CADShared/Basal/General/LinqEx.cs similarity index 100% rename from CADShared/Basal/General/LinqEx.cs rename to src/CADShared/Basal/General/LinqEx.cs diff --git a/CADShared/Basal/General/LoopList.cs b/src/CADShared/Basal/General/LoopList.cs similarity index 100% rename from CADShared/Basal/General/LoopList.cs rename to src/CADShared/Basal/General/LoopList.cs diff --git a/CADShared/Basal/General/LoopState.cs b/src/CADShared/Basal/General/LoopState.cs similarity index 100% rename from CADShared/Basal/General/LoopState.cs rename to src/CADShared/Basal/General/LoopState.cs diff --git a/CADShared/Basal/Nullable/ArgumentNullEx.cs b/src/CADShared/Basal/Nullable/ArgumentNullEx.cs similarity index 100% rename from CADShared/Basal/Nullable/ArgumentNullEx.cs rename to src/CADShared/Basal/Nullable/ArgumentNullEx.cs diff --git a/CADShared/Basal/Nullable/CallerArgumentExpressionAttribute.cs b/src/CADShared/Basal/Nullable/CallerArgumentExpressionAttribute.cs similarity index 100% rename from CADShared/Basal/Nullable/CallerArgumentExpressionAttribute.cs rename to src/CADShared/Basal/Nullable/CallerArgumentExpressionAttribute.cs diff --git a/CADShared/Basal/Win/Enums.cs b/src/CADShared/Basal/Win/Enums.cs similarity index 100% rename from CADShared/Basal/Win/Enums.cs rename to src/CADShared/Basal/Win/Enums.cs diff --git a/CADShared/Basal/Win/PInvokeUser32.cs b/src/CADShared/Basal/Win/PInvokeUser32.cs similarity index 100% rename from CADShared/Basal/Win/PInvokeUser32.cs rename to src/CADShared/Basal/Win/PInvokeUser32.cs diff --git a/CADShared/Basal/Win/SystemEx.cs b/src/CADShared/Basal/Win/SystemEx.cs similarity index 100% rename from CADShared/Basal/Win/SystemEx.cs rename to src/CADShared/Basal/Win/SystemEx.cs diff --git a/CADShared/Basal/Win/WindowsAPI.cs b/src/CADShared/Basal/Win/WindowsAPI.cs similarity index 100% rename from CADShared/Basal/Win/WindowsAPI.cs rename to src/CADShared/Basal/Win/WindowsAPI.cs diff --git a/CADShared/CADShared.projitems b/src/CADShared/CADShared.projitems similarity index 100% rename from CADShared/CADShared.projitems rename to src/CADShared/CADShared.projitems diff --git a/CADShared/CADShared.shproj b/src/CADShared/CADShared.shproj similarity index 100% rename from CADShared/CADShared.shproj rename to src/CADShared/CADShared.shproj diff --git a/CADShared/ExtensionMethod/BaseEx.cs b/src/CADShared/ExtensionMethod/BaseEx.cs similarity index 100% rename from CADShared/ExtensionMethod/BaseEx.cs rename to src/CADShared/ExtensionMethod/BaseEx.cs diff --git a/CADShared/ExtensionMethod/BulgeVertexWidth.cs b/src/CADShared/ExtensionMethod/BulgeVertexWidth.cs similarity index 100% rename from CADShared/ExtensionMethod/BulgeVertexWidth.cs rename to src/CADShared/ExtensionMethod/BulgeVertexWidth.cs diff --git a/CADShared/ExtensionMethod/CollectionEx.cs b/src/CADShared/ExtensionMethod/CollectionEx.cs similarity index 100% rename from CADShared/ExtensionMethod/CollectionEx.cs rename to src/CADShared/ExtensionMethod/CollectionEx.cs diff --git a/CADShared/ExtensionMethod/DBDictionaryEx.cs b/src/CADShared/ExtensionMethod/DBDictionaryEx.cs similarity index 100% rename from CADShared/ExtensionMethod/DBDictionaryEx.cs rename to src/CADShared/ExtensionMethod/DBDictionaryEx.cs diff --git a/CADShared/ExtensionMethod/DBObjectEx.cs b/src/CADShared/ExtensionMethod/DBObjectEx.cs similarity index 100% rename from CADShared/ExtensionMethod/DBObjectEx.cs rename to src/CADShared/ExtensionMethod/DBObjectEx.cs diff --git a/CADShared/ExtensionMethod/DBTransEx.cs b/src/CADShared/ExtensionMethod/DBTransEx.cs similarity index 100% rename from CADShared/ExtensionMethod/DBTransEx.cs rename to src/CADShared/ExtensionMethod/DBTransEx.cs diff --git a/CADShared/ExtensionMethod/DatabaseEx.cs b/src/CADShared/ExtensionMethod/DatabaseEx.cs similarity index 100% rename from CADShared/ExtensionMethod/DatabaseEx.cs rename to src/CADShared/ExtensionMethod/DatabaseEx.cs diff --git a/CADShared/ExtensionMethod/DocumentLockManager.cs b/src/CADShared/ExtensionMethod/DocumentLockManager.cs similarity index 100% rename from CADShared/ExtensionMethod/DocumentLockManager.cs rename to src/CADShared/ExtensionMethod/DocumentLockManager.cs diff --git a/CADShared/ExtensionMethod/DwgMark.cs b/src/CADShared/ExtensionMethod/DwgMark.cs similarity index 100% rename from CADShared/ExtensionMethod/DwgMark.cs rename to src/CADShared/ExtensionMethod/DwgMark.cs diff --git a/CADShared/ExtensionMethod/EditorEx.cs b/src/CADShared/ExtensionMethod/EditorEx.cs similarity index 100% rename from CADShared/ExtensionMethod/EditorEx.cs rename to src/CADShared/ExtensionMethod/EditorEx.cs diff --git a/CADShared/ExtensionMethod/Entity/ArcEx.cs b/src/CADShared/ExtensionMethod/Entity/ArcEx.cs similarity index 100% rename from CADShared/ExtensionMethod/Entity/ArcEx.cs rename to src/CADShared/ExtensionMethod/Entity/ArcEx.cs diff --git a/CADShared/ExtensionMethod/Entity/BlockReferenceEx.cs b/src/CADShared/ExtensionMethod/Entity/BlockReferenceEx.cs similarity index 100% rename from CADShared/ExtensionMethod/Entity/BlockReferenceEx.cs rename to src/CADShared/ExtensionMethod/Entity/BlockReferenceEx.cs diff --git a/CADShared/ExtensionMethod/Entity/BoundingInfo.cs b/src/CADShared/ExtensionMethod/Entity/BoundingInfo.cs similarity index 100% rename from CADShared/ExtensionMethod/Entity/BoundingInfo.cs rename to src/CADShared/ExtensionMethod/Entity/BoundingInfo.cs diff --git a/CADShared/ExtensionMethod/Entity/CircleEx.cs b/src/CADShared/ExtensionMethod/Entity/CircleEx.cs similarity index 100% rename from CADShared/ExtensionMethod/Entity/CircleEx.cs rename to src/CADShared/ExtensionMethod/Entity/CircleEx.cs diff --git a/CADShared/ExtensionMethod/Entity/CurveEx.cs b/src/CADShared/ExtensionMethod/Entity/CurveEx.cs similarity index 100% rename from CADShared/ExtensionMethod/Entity/CurveEx.cs rename to src/CADShared/ExtensionMethod/Entity/CurveEx.cs diff --git a/CADShared/ExtensionMethod/Entity/DBTextEx.cs b/src/CADShared/ExtensionMethod/Entity/DBTextEx.cs similarity index 100% rename from CADShared/ExtensionMethod/Entity/DBTextEx.cs rename to src/CADShared/ExtensionMethod/Entity/DBTextEx.cs diff --git a/CADShared/ExtensionMethod/Entity/EntityBoundingInfo.cs b/src/CADShared/ExtensionMethod/Entity/EntityBoundingInfo.cs similarity index 100% rename from CADShared/ExtensionMethod/Entity/EntityBoundingInfo.cs rename to src/CADShared/ExtensionMethod/Entity/EntityBoundingInfo.cs diff --git a/CADShared/ExtensionMethod/Entity/EntityEx.cs b/src/CADShared/ExtensionMethod/Entity/EntityEx.cs similarity index 100% rename from CADShared/ExtensionMethod/Entity/EntityEx.cs rename to src/CADShared/ExtensionMethod/Entity/EntityEx.cs diff --git a/CADShared/ExtensionMethod/Entity/MTextEx.cs b/src/CADShared/ExtensionMethod/Entity/MTextEx.cs similarity index 100% rename from CADShared/ExtensionMethod/Entity/MTextEx.cs rename to src/CADShared/ExtensionMethod/Entity/MTextEx.cs diff --git a/CADShared/ExtensionMethod/Entity/PolylineEx.cs b/src/CADShared/ExtensionMethod/Entity/PolylineEx.cs similarity index 100% rename from CADShared/ExtensionMethod/Entity/PolylineEx.cs rename to src/CADShared/ExtensionMethod/Entity/PolylineEx.cs diff --git a/CADShared/ExtensionMethod/Entity/RegionEx.cs b/src/CADShared/ExtensionMethod/Entity/RegionEx.cs similarity index 100% rename from CADShared/ExtensionMethod/Entity/RegionEx.cs rename to src/CADShared/ExtensionMethod/Entity/RegionEx.cs diff --git a/CADShared/ExtensionMethod/Enums.cs b/src/CADShared/ExtensionMethod/Enums.cs similarity index 100% rename from CADShared/ExtensionMethod/Enums.cs rename to src/CADShared/ExtensionMethod/Enums.cs diff --git a/CADShared/ExtensionMethod/ErrorInfoEx.cs b/src/CADShared/ExtensionMethod/ErrorInfoEx.cs similarity index 100% rename from CADShared/ExtensionMethod/ErrorInfoEx.cs rename to src/CADShared/ExtensionMethod/ErrorInfoEx.cs diff --git a/CADShared/ExtensionMethod/Geomerty/Curve2dEx.cs b/src/CADShared/ExtensionMethod/Geomerty/Curve2dEx.cs similarity index 100% rename from CADShared/ExtensionMethod/Geomerty/Curve2dEx.cs rename to src/CADShared/ExtensionMethod/Geomerty/Curve2dEx.cs diff --git a/CADShared/ExtensionMethod/Geomerty/Curve3dEx.cs b/src/CADShared/ExtensionMethod/Geomerty/Curve3dEx.cs similarity index 100% rename from CADShared/ExtensionMethod/Geomerty/Curve3dEx.cs rename to src/CADShared/ExtensionMethod/Geomerty/Curve3dEx.cs diff --git a/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs b/src/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs similarity index 100% rename from CADShared/ExtensionMethod/Geomerty/GeometryEx.cs rename to src/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs diff --git a/CADShared/ExtensionMethod/Geomerty/PointEx.cs b/src/CADShared/ExtensionMethod/Geomerty/PointEx.cs similarity index 100% rename from CADShared/ExtensionMethod/Geomerty/PointEx.cs rename to src/CADShared/ExtensionMethod/Geomerty/PointEx.cs diff --git a/CADShared/ExtensionMethod/Hatch/HatchConverter.cs b/src/CADShared/ExtensionMethod/Hatch/HatchConverter.cs similarity index 100% rename from CADShared/ExtensionMethod/Hatch/HatchConverter.cs rename to src/CADShared/ExtensionMethod/Hatch/HatchConverter.cs diff --git a/CADShared/ExtensionMethod/Hatch/HatchEx.cs b/src/CADShared/ExtensionMethod/Hatch/HatchEx.cs similarity index 100% rename from CADShared/ExtensionMethod/Hatch/HatchEx.cs rename to src/CADShared/ExtensionMethod/Hatch/HatchEx.cs diff --git a/CADShared/ExtensionMethod/Hatch/HatchInfo.cs b/src/CADShared/ExtensionMethod/Hatch/HatchInfo.cs similarity index 100% rename from CADShared/ExtensionMethod/Hatch/HatchInfo.cs rename to src/CADShared/ExtensionMethod/Hatch/HatchInfo.cs diff --git a/CADShared/ExtensionMethod/IFoxUtils.cs b/src/CADShared/ExtensionMethod/IFoxUtils.cs similarity index 100% rename from CADShared/ExtensionMethod/IFoxUtils.cs rename to src/CADShared/ExtensionMethod/IFoxUtils.cs diff --git a/CADShared/ExtensionMethod/Jig/JigEx.cs b/src/CADShared/ExtensionMethod/Jig/JigEx.cs similarity index 100% rename from CADShared/ExtensionMethod/Jig/JigEx.cs rename to src/CADShared/ExtensionMethod/Jig/JigEx.cs diff --git a/CADShared/ExtensionMethod/Jig/JigExTransient.cs b/src/CADShared/ExtensionMethod/Jig/JigExTransient.cs similarity index 100% rename from CADShared/ExtensionMethod/Jig/JigExTransient.cs rename to src/CADShared/ExtensionMethod/Jig/JigExTransient.cs diff --git a/CADShared/ExtensionMethod/ObjectIdEx.cs b/src/CADShared/ExtensionMethod/ObjectIdEx.cs similarity index 100% rename from CADShared/ExtensionMethod/ObjectIdEx.cs rename to src/CADShared/ExtensionMethod/ObjectIdEx.cs diff --git a/CADShared/ExtensionMethod/PaneEx.cs b/src/CADShared/ExtensionMethod/PaneEx.cs similarity index 100% rename from CADShared/ExtensionMethod/PaneEx.cs rename to src/CADShared/ExtensionMethod/PaneEx.cs diff --git a/CADShared/ExtensionMethod/PromptOptionsEx.cs b/src/CADShared/ExtensionMethod/PromptOptionsEx.cs similarity index 100% rename from CADShared/ExtensionMethod/PromptOptionsEx.cs rename to src/CADShared/ExtensionMethod/PromptOptionsEx.cs diff --git a/CADShared/ExtensionMethod/RandomEx.cs b/src/CADShared/ExtensionMethod/RandomEx.cs similarity index 100% rename from CADShared/ExtensionMethod/RandomEx.cs rename to src/CADShared/ExtensionMethod/RandomEx.cs diff --git a/CADShared/ExtensionMethod/RedrawEx.cs b/src/CADShared/ExtensionMethod/RedrawEx.cs similarity index 100% rename from CADShared/ExtensionMethod/RedrawEx.cs rename to src/CADShared/ExtensionMethod/RedrawEx.cs diff --git a/CADShared/ExtensionMethod/SelectionSetEx.cs b/src/CADShared/ExtensionMethod/SelectionSetEx.cs similarity index 100% rename from CADShared/ExtensionMethod/SelectionSetEx.cs rename to src/CADShared/ExtensionMethod/SelectionSetEx.cs diff --git a/CADShared/ExtensionMethod/SingleKeyWordHook.cs b/src/CADShared/ExtensionMethod/SingleKeyWordHook.cs similarity index 100% rename from CADShared/ExtensionMethod/SingleKeyWordHook.cs rename to src/CADShared/ExtensionMethod/SingleKeyWordHook.cs diff --git a/CADShared/ExtensionMethod/SymbolTableEx.cs b/src/CADShared/ExtensionMethod/SymbolTableEx.cs similarity index 100% rename from CADShared/ExtensionMethod/SymbolTableEx.cs rename to src/CADShared/ExtensionMethod/SymbolTableEx.cs diff --git a/CADShared/ExtensionMethod/SymbolTableRecordEx.cs b/src/CADShared/ExtensionMethod/SymbolTableRecordEx.cs similarity index 100% rename from CADShared/ExtensionMethod/SymbolTableRecordEx.cs rename to src/CADShared/ExtensionMethod/SymbolTableRecordEx.cs diff --git a/CADShared/ExtensionMethod/TangentEx.cs b/src/CADShared/ExtensionMethod/TangentEx.cs similarity index 100% rename from CADShared/ExtensionMethod/TangentEx.cs rename to src/CADShared/ExtensionMethod/TangentEx.cs diff --git a/CADShared/ExtensionMethod/TransactionEx.cs b/src/CADShared/ExtensionMethod/TransactionEx.cs similarity index 100% rename from CADShared/ExtensionMethod/TransactionEx.cs rename to src/CADShared/ExtensionMethod/TransactionEx.cs diff --git a/CADShared/ExtensionMethod/WindowEx.cs b/src/CADShared/ExtensionMethod/WindowEx.cs similarity index 100% rename from CADShared/ExtensionMethod/WindowEx.cs rename to src/CADShared/ExtensionMethod/WindowEx.cs diff --git a/CADShared/ExtensionMethod/XrefEx.cs b/src/CADShared/ExtensionMethod/XrefEx.cs similarity index 100% rename from CADShared/ExtensionMethod/XrefEx.cs rename to src/CADShared/ExtensionMethod/XrefEx.cs diff --git a/CADShared/Initialize/AcadEMR.cs b/src/CADShared/Initialize/AcadEMR.cs similarity index 99% rename from CADShared/Initialize/AcadEMR.cs rename to src/CADShared/Initialize/AcadEMR.cs index 18eac5a..3fcfc03 100644 --- a/CADShared/Initialize/AcadEMR.cs +++ b/src/CADShared/Initialize/AcadEMR.cs @@ -1,4 +1,5 @@ -#if true +#if true +#if acad namespace IFoxCAD.Cad; // 作者: [VB.net]福萝卜 莱昂纳多·胖子 @@ -148,4 +149,5 @@ static bool CheckFunc(ref IntPtr address, byte val, int len) return false; } } +#endif #endif \ No newline at end of file diff --git a/CADShared/Initialize/AssemInfo.cs b/src/CADShared/Initialize/AssemInfo.cs similarity index 100% rename from CADShared/Initialize/AssemInfo.cs rename to src/CADShared/Initialize/AssemInfo.cs diff --git a/CADShared/Initialize/AutoReg.cs b/src/CADShared/Initialize/AutoReg.cs similarity index 100% rename from CADShared/Initialize/AutoReg.cs rename to src/CADShared/Initialize/AutoReg.cs diff --git a/CADShared/Initialize/AutoRegAssem.cs b/src/CADShared/Initialize/AutoRegAssem.cs similarity index 99% rename from CADShared/Initialize/AutoRegAssem.cs rename to src/CADShared/Initialize/AutoRegAssem.cs index 7d092c5..eeecf3c 100644 --- a/CADShared/Initialize/AutoRegAssem.cs +++ b/src/CADShared/Initialize/AutoRegAssem.cs @@ -70,8 +70,10 @@ protected AutoRegAssem(AutoRegConfig autoRegConfig) AutoReg.RegApp(info); } +#if acad if ((autoRegConfig & AutoRegConfig.RemoveEMR) == AutoRegConfig.RemoveEMR) AcadEMR.Remove(); +#endif // 实例化了 AutoClass 之后会自动执行 IFoxAutoGo 接口下面的类, // 以及自动执行特性 [IFoxInitialize] diff --git a/CADShared/Initialize/CheckFactory.cs b/src/CADShared/Initialize/CheckFactory.cs similarity index 100% rename from CADShared/Initialize/CheckFactory.cs rename to src/CADShared/Initialize/CheckFactory.cs diff --git a/CADShared/Initialize/IAutoGo.cs b/src/CADShared/Initialize/IAutoGo.cs similarity index 100% rename from CADShared/Initialize/IAutoGo.cs rename to src/CADShared/Initialize/IAutoGo.cs diff --git a/CADShared/Initialize/MethodInfoHelper.cs b/src/CADShared/Initialize/MethodInfoHelper.cs similarity index 100% rename from CADShared/Initialize/MethodInfoHelper.cs rename to src/CADShared/Initialize/MethodInfoHelper.cs diff --git a/CADShared/PE/AcadPeInfo.cs b/src/CADShared/PE/AcadPeInfo.cs similarity index 100% rename from CADShared/PE/AcadPeInfo.cs rename to src/CADShared/PE/AcadPeInfo.cs diff --git a/CADShared/PE/DBmod.cs b/src/CADShared/PE/DBmod.cs similarity index 100% rename from CADShared/PE/DBmod.cs rename to src/CADShared/PE/DBmod.cs diff --git a/CADShared/PE/PostCmd.cs b/src/CADShared/PE/PostCmd.cs similarity index 100% rename from CADShared/PE/PostCmd.cs rename to src/CADShared/PE/PostCmd.cs diff --git a/CADShared/PE/ProgramPE.cs b/src/CADShared/PE/ProgramPE.cs similarity index 100% rename from CADShared/PE/ProgramPE.cs rename to src/CADShared/PE/ProgramPE.cs diff --git a/CADShared/ResultData/LispList.cs b/src/CADShared/ResultData/LispList.cs similarity index 100% rename from CADShared/ResultData/LispList.cs rename to src/CADShared/ResultData/LispList.cs diff --git a/CADShared/ResultData/TypedValueList.cs b/src/CADShared/ResultData/TypedValueList.cs similarity index 100% rename from CADShared/ResultData/TypedValueList.cs rename to src/CADShared/ResultData/TypedValueList.cs diff --git a/CADShared/ResultData/XDataList.cs b/src/CADShared/ResultData/XDataList.cs similarity index 100% rename from CADShared/ResultData/XDataList.cs rename to src/CADShared/ResultData/XDataList.cs diff --git a/CADShared/ResultData/XRecordDataList.cs b/src/CADShared/ResultData/XRecordDataList.cs similarity index 100% rename from CADShared/ResultData/XRecordDataList.cs rename to src/CADShared/ResultData/XRecordDataList.cs diff --git a/CADShared/Runtime/AcPreferences.cs b/src/CADShared/Runtime/AcPreferences.cs similarity index 100% rename from CADShared/Runtime/AcPreferences.cs rename to src/CADShared/Runtime/AcPreferences.cs diff --git a/CADShared/Runtime/DBTrans.cs b/src/CADShared/Runtime/DBTrans.cs similarity index 100% rename from CADShared/Runtime/DBTrans.cs rename to src/CADShared/Runtime/DBTrans.cs diff --git a/CADShared/Runtime/Env.cs b/src/CADShared/Runtime/Env.cs similarity index 100% rename from CADShared/Runtime/Env.cs rename to src/CADShared/Runtime/Env.cs diff --git a/CADShared/Runtime/IdleAction.cs b/src/CADShared/Runtime/IdleAction.cs similarity index 100% rename from CADShared/Runtime/IdleAction.cs rename to src/CADShared/Runtime/IdleAction.cs diff --git a/CADShared/Runtime/IdleNoCommandAction.cs b/src/CADShared/Runtime/IdleNoCommandAction.cs similarity index 100% rename from CADShared/Runtime/IdleNoCommandAction.cs rename to src/CADShared/Runtime/IdleNoCommandAction.cs diff --git a/CADShared/Runtime/SymbolTable.cs b/src/CADShared/Runtime/SymbolTable.cs similarity index 100% rename from CADShared/Runtime/SymbolTable.cs rename to src/CADShared/Runtime/SymbolTable.cs diff --git a/CADShared/Runtime/SystemVariableManager.cs b/src/CADShared/Runtime/SystemVariableManager.cs similarity index 100% rename from CADShared/Runtime/SystemVariableManager.cs rename to src/CADShared/Runtime/SystemVariableManager.cs diff --git a/CADShared/SelectionFilter/OpComp.cs b/src/CADShared/SelectionFilter/OpComp.cs similarity index 100% rename from CADShared/SelectionFilter/OpComp.cs rename to src/CADShared/SelectionFilter/OpComp.cs diff --git a/CADShared/SelectionFilter/OpEqual.cs b/src/CADShared/SelectionFilter/OpEqual.cs similarity index 100% rename from CADShared/SelectionFilter/OpEqual.cs rename to src/CADShared/SelectionFilter/OpEqual.cs diff --git a/CADShared/SelectionFilter/OpFilter.cs b/src/CADShared/SelectionFilter/OpFilter.cs similarity index 100% rename from CADShared/SelectionFilter/OpFilter.cs rename to src/CADShared/SelectionFilter/OpFilter.cs diff --git a/CADShared/SelectionFilter/OpList.cs b/src/CADShared/SelectionFilter/OpList.cs similarity index 100% rename from CADShared/SelectionFilter/OpList.cs rename to src/CADShared/SelectionFilter/OpList.cs diff --git a/CADShared/SelectionFilter/OpLogi.cs b/src/CADShared/SelectionFilter/OpLogi.cs similarity index 100% rename from CADShared/SelectionFilter/OpLogi.cs rename to src/CADShared/SelectionFilter/OpLogi.cs diff --git a/IFoxCAD.AutoCad/GlobalUsings.cs b/src/IFoxCAD.AutoCad/GlobalUsings.cs similarity index 100% rename from IFoxCAD.AutoCad/GlobalUsings.cs rename to src/IFoxCAD.AutoCad/GlobalUsings.cs diff --git a/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj b/src/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj similarity index 97% rename from IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj rename to src/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj index 7e1b83f..3f342cf 100644 --- a/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj +++ b/src/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj @@ -61,11 +61,11 @@ - + True \ - + True \ diff --git a/IFoxCAD.ZwCad/GlobalUsings.cs b/src/IFoxCAD.ZwCad/GlobalUsings.cs similarity index 100% rename from IFoxCAD.ZwCad/GlobalUsings.cs rename to src/IFoxCAD.ZwCad/GlobalUsings.cs diff --git a/IFoxCAD.ZwCad/IFoxCAD.ZwCad.csproj b/src/IFoxCAD.ZwCad/IFoxCAD.ZwCad.csproj similarity index 96% rename from IFoxCAD.ZwCad/IFoxCAD.ZwCad.csproj rename to src/IFoxCAD.ZwCad/IFoxCAD.ZwCad.csproj index 3429c1d..bbf2809 100644 --- a/IFoxCAD.ZwCad/IFoxCAD.ZwCad.csproj +++ b/src/IFoxCAD.ZwCad/IFoxCAD.ZwCad.csproj @@ -13,7 +13,7 @@ - 0.9.1.10 + 0.9.2-preview1 修复region同环曲线不闭合的问题 true @@ -56,11 +56,11 @@ - + True \ - + True \ diff --git a/tests/TestAcad2025/GlobalUsings.cs b/tests/TestAcad2025/GlobalUsings.cs new file mode 100644 index 0000000..045196f --- /dev/null +++ b/tests/TestAcad2025/GlobalUsings.cs @@ -0,0 +1,50 @@ +/// 系统引用 +global using System; +global using System.Collections; +global using System.Collections.Generic; +global using System.IO; +global using System.Linq; +global using System.Text; +global using System.Reflection; +global using System.Text.RegularExpressions; +global using Microsoft.Win32; +global using System.ComponentModel; +global using System.Runtime.InteropServices; +global using System.Collections.Specialized; +global using System.Threading; +global using Exception = System.Exception; + +global using Registry = Microsoft.Win32.Registry; +global using RegistryKey = Microsoft.Win32.RegistryKey; + +/// autocad 引用 +global using Autodesk.AutoCAD.ApplicationServices; +global using Autodesk.AutoCAD.EditorInput; +global using Autodesk.AutoCAD.Colors; +global using Autodesk.AutoCAD.DatabaseServices; +global using Autodesk.AutoCAD.Geometry; +global using Autodesk.AutoCAD.Runtime; +global using Acap = Autodesk.AutoCAD.ApplicationServices.Application; +global using Acaop = Autodesk.AutoCAD.ApplicationServices.Core.Application; +global using Acgi = Autodesk.AutoCAD.GraphicsInterface; + +global using Autodesk.AutoCAD.DatabaseServices.Filters; +global using Autodesk.AutoCAD; + +// jig命名空间会引起Viewport/Polyline等等重义,最好逐个引入 using Autodesk.AutoCAD.GraphicsInterface +global using WorldDraw = Autodesk.AutoCAD.GraphicsInterface.WorldDraw; +global using Manager = Autodesk.AutoCAD.GraphicsSystem.Manager; +global using Group = Autodesk.AutoCAD.DatabaseServices.Group; +global using Viewport = Autodesk.AutoCAD.DatabaseServices.Viewport; +global using Autodesk.AutoCAD.GraphicsInterface; +global using Polyline = Autodesk.AutoCAD.DatabaseServices.Polyline; +global using Cad_DwgFiler = Autodesk.AutoCAD.DatabaseServices.DwgFiler; +global using Cad_DxfFiler = Autodesk.AutoCAD.DatabaseServices.DxfFiler; +global using Cad_ErrorStatus = Autodesk.AutoCAD.Runtime.ErrorStatus; + + +/// ifoxcad +global using IFoxCAD.Cad; +global using IFoxCAD.Basal; + +global using Test; diff --git a/tests/TestAcad2025/TestAcad2025.csproj b/tests/TestAcad2025/TestAcad2025.csproj new file mode 100644 index 0000000..92786a6 --- /dev/null +++ b/tests/TestAcad2025/TestAcad2025.csproj @@ -0,0 +1,32 @@ + + + preview + enable + + NET48 + true + true + x64 + True + 1.0.0.* + 1.0.0.0 + false + + + + $(Configuration);acad + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/TestShared/CmdINI.cs b/tests/TestShared/CmdINI.cs new file mode 100644 index 0000000..c296a56 --- /dev/null +++ b/tests/TestShared/CmdINI.cs @@ -0,0 +1,189 @@ +//#define givePeopleTest +#if false +using System.Diagnostics; + +namespace Test; + +/// +/// 注册中心(自动执行接口): +/// +/// 继承虚函数后才能使用
    +/// 0x01 netload加载之后自动执行,写入启动注册表,下次就不需要netload了
    +/// 0x02 反射调用特性和接口
    +/// 启动cad后的执行顺序为:
    +/// 1:构造函数
    +/// 2:特性..多个
    +/// 3:接口..多个
    +/// 4:本类的构造函数
    +/// +/// **** 警告 **** +/// 如果不写一个 储存这个对象, +/// 而是直接写卸载命令在此, +/// 第一次加载的时候会初始化完成,然后这个类生命就结束了, +/// 第二次通过命令进入,会引发构造函数再次执行,留意构造函数的打印信息即可发现 +/// +///
    +///
    +public class AutoRegAssemEx : AutoRegAssem +{ + public AutoRegAssemEx() : base(AutoRegConfig.All) + { + CmdInit.AutoRegAssemEx = this; +#if givePeopleTest +#if Debug + // 此处用来反射本程序集,检查是否存在重复命令 + AutoReflection.DebugCheckCmdRecurrence(); +#endif + Env.Printl($"{nameof(AutoRegAssemEx)}构造函数,开始自动执行\r\n"); +#endif + } +} + + +public class CmdInit +{ + public static AutoRegAssemEx? AutoRegAssemEx; + + /// 如果netload之后用 删除注册表, + /// 由于不是也不能卸载dll,再netload是无法执行自动接口的, + /// 所以此时会产生无法再注册的问题...因此需要暴露此注册函数(硬来) + [CommandMethod(nameof(IFoxAddReg))] + public void IFoxAddReg() + { + Env.Printl($"加入注册表"); + + AutoRegAssemEx ??= new(); + AutoRegAssemEx.RegApp(); + } + + /// + /// 卸载注册表信息 + /// + [CommandMethod(nameof(IFoxRemoveReg))] + public void IFoxRemoveReg() + { + Env.Printl($"卸载注册表"); + + // 防止卸载两次,不然会报错的 + AutoRegAssemEx?.UnRegApp(); + AutoRegAssemEx = null; + } + + [CommandMethod(nameof(Debugx))] + public void Debugx() + { + var flag = Environment.GetEnvironmentVariable("debugx", EnvironmentVariableTarget.User); + if (flag == null || flag == "0") + { + Environment.SetEnvironmentVariable("debugx", "1", EnvironmentVariableTarget.User); + Env.Printl($"vs输出 -- 已启用"); + } + else + { + Environment.SetEnvironmentVariable("debugx", "0", EnvironmentVariableTarget.User); + Env.Printl($"vs输出 -- 已禁用"); + } + } +} + +#if givePeopleTest +/* + * 自动执行:特性 + */ +public class Cmd_IFoxInitialize +{ + int TestInt = 0; + + [IFoxInitialize] + public void Initialize() + { + Env.Printl($"开始自动执行,可以分开多个类和多个函数:{nameof(Cmd_IFoxInitialize)}.{nameof(Initialize)}+{TestInt}"); + } + + [IFoxInitialize] + public void Initialize2() + { + Env.Printl($"开始自动执行,可以分开多个类和多个函数,又一次测试:{nameof(Cmd_IFoxInitialize)}.{nameof(Initialize2)}"); + } + + //[IFoxInitialize(isInitialize: false)] + //public void Terminate() + //{ + // try + // { + // // 注意此时编辑器已经回收,所以此句引发错误 + // // 您可以写一些其他的释放动作,例如资源回收之类的 + // Env.Printl($"\n 结束自动执行 Terminate \r\n"); + // // 改用 + // Debugx.Printl($"\n 结束自动执行 Terminate \r\n"); + // } + // catch (System.Exception e) + // { + // System.Windows.Forms.MessageBox.Show(e.Message); + // } + //} + + [IFoxInitialize] + public static void StaticInitialize() + { + Env.Printl($"开始自动执行,静态调用:{nameof(Cmd_IFoxInitialize)}.{nameof(StaticInitialize)}"); + } +} + + +/* + * 自动执行:接口 + */ +public class Cmd_IFoxInitializeInterface : IFoxAutoGo +{ + int TestInt = 0; + public Cmd_IFoxInitializeInterface() + { + Env.Printl($"开始自动执行,{nameof(IFoxAutoGo)}接口调用:{nameof(Cmd_IFoxInitializeInterface)}::{TestInt}"); + } + + public Sequence SequenceId() + { + return Sequence.Last; + } + + public void Initialize() + { + Env.Printl($"开始自动执行,{nameof(IFoxAutoGo)}接口调用:{nameof(Initialize)}::{TestInt}"); + } + + public void Terminate() + { + Debugx.Printl($"开始自动执行,{nameof(IFoxAutoGo)}接口调用:{nameof(Terminate)}::{TestInt}"); + // try + // { + // // 注意此时编辑器已经回收,所以此句没用,并引发错误 + // Env.Printl($"结束自动执行 {nameof(Cmd_IFoxInitializeInterface)}.Terminate \r\n"); + // } + // catch (System.Exception e) + // { + // System.Windows.Forms.MessageBox.Show(e.Message); + // } + } +} +#endif + + +public class Init : AutoLoad +{ + public override void Initialize() + { + + Env.Print("loading..."); + // 将程序的目录加入信任路径 + // Env.AppendSupportPath(CurrentDirectory.FullName); + } + + public override void Terminate() + { + // 这里不能调用输出函数,因为这个函数执行的时候,已经没有editor对象了。 + // 所以如果不是想要在cad关闭的时候清理某些东西,这里不用写任何的代码。 + + } +} +#endif \ No newline at end of file diff --git a/tests/TestShared/Copyclip.cs b/tests/TestShared/Copyclip.cs new file mode 100644 index 0000000..370936c --- /dev/null +++ b/tests/TestShared/Copyclip.cs @@ -0,0 +1,881 @@ +#define test +#define COPYCLIP +#define PASTECLIP +#if false +namespace Test; +using System; +using System.Diagnostics; +using System.Drawing.Imaging; +using System.Threading; +using System.Windows; + +/* + * 0x01 (已完成) + * 跨cad复制,由于高版本会保存为当前dwg格式,所以我们将所有都保存为07格式(有动态块), + * 就可以多个版本cad相互复制粘贴了 + * + * 0x02 + * 设置一个粘贴板栈,用tmp.config储存(路径和粘贴基点), + * ctrl+shfit+v v v 就是三次前的剪贴板内容;也可以制作一个剪贴板窗口更好给用户交互 + * + * 0x03 + * 天正图元的复制粘贴出错原因 + * + * 引用技术贴: + * https://forums.autodesk.com/t5/net/paste-list-of-objects-from-clipboard-on-dwg-file-using-c-net/td-p/6797606 + */ +public class Copyclip +{ + #region 命令 +#if test + static bool _IsRunIFoxCopyClip = false; + [IFoxInitialize] // 惊惊: 遇到了高版本无法导出WMF,放弃此功能,等待有缘人 + public void Init() + { + Acap.DocumentManager.DocumentLockModeChanged += Dm_VetoCommand; + Env.Printl($"※剪贴板控制※\n{nameof(Copyclip_Switch)} - 切换开关\n"); + } + + [CommandMethod(nameof(Copyclip_Switch))] + public void Copyclip_Switch() + { + _IsRunIFoxCopyClip = !_IsRunIFoxCopyClip; + Env.Printl("已经 " + (_IsRunIFoxCopyClip ? "开启" : "禁用") + " 剪贴板+"); + } + + /// + /// 反应器->命令否决触发命令前(不可锁文档) + /// + /// + /// + void Dm_VetoCommand(object sender, DocumentLockModeChangedEventArgs e) + { + if (string.IsNullOrEmpty(e.GlobalCommandName) || e.GlobalCommandName == "#") + return; + if (!_IsRunIFoxCopyClip) + return; + + var up = e.GlobalCommandName.ToUpper(); + + string? cmd = null; +#if COPYCLIP + if (up == "COPYCLIP")// 复制 + { + e.Veto(); + cmd = nameof(IFoxCopyClip); + } + else if (up == "COPYBASE") //ctrl+shift+c 带基点复制 + { + e.Veto(); + cmd = nameof(IFoxCopyBase); + } + else if (up == "CUTCLIP") // 剪切 + { + e.Veto(); + cmd = nameof(IFoxCutclip); + } +#endif +#if PASTECLIP + if (up == "PASTECLIP")// 粘贴 + { + // === 完成之后此处将会移除 + // 粘贴文本的生成单行文字/多行文字,这些还需要自己去实现 + var getClip = ClipTool.GetClipboard(ClipboardEnv.CadVer, out TagClipboardInfo tag); + if (!getClip) + return; + //=== 完成之后此处将会移除 + + e.Veto(); + cmd = nameof(IFoxPasteClip); + } + else if (up == "PASTEBLOCK") //ctrl+shift+v 粘贴为块 + { + // === 完成之后此处将会移除 + var getClip = ClipTool.GetClipboard(ClipboardEnv.CadVer, out TagClipboardInfo tag); + if (!getClip) + return; + //=== 完成之后此处将会移除 + + e.Veto(); + cmd = nameof(IFoxPasteBlock); + } +#endif + if (cmd != null) + { + var dm = Acap.DocumentManager; + if (dm.Count == 0) + return; + var doc = dm.MdiActiveDocument; + // 发送命令是因为com导出WMF需要命令形式,否则将报错 + // 但是发送命令会导致选择集被取消了,那么就需要设置 CommandFlags.Redraw + doc.SendStringToExecute(cmd + "\n", true, false, false); + } + } + + + /// + /// 复制 + /// + [CommandMethod(nameof(IFoxCopyClip), CommandFlags.UsePickSet | CommandFlags.Redraw)] + public void IFoxCopyClip() + { + Copy(false); + } + /// + /// 带基点复制 + /// + [CommandMethod(nameof(IFoxCopyBase), CommandFlags.UsePickSet | CommandFlags.Redraw)] + public void IFoxCopyBase() + { + Copy(true); + } + /// + /// 剪切 + /// + [CommandMethod(nameof(IFoxCutclip), CommandFlags.UsePickSet | CommandFlags.Redraw)] + public void IFoxCutclip() + { + Copy(false, true); + } + + + /// + /// 粘贴 + /// + [CommandMethod(nameof(IFoxPasteClip))] + public void IFoxPasteClip() + { + Paste(false); + } + /// + /// 粘贴为块 + /// + [CommandMethod(nameof(IFoxPasteBlock))] + public void IFoxPasteBlock() + { + Paste(true); + } +#endif + #endregion + + // 想要重启cad之后还可以继续用剪贴板,那么就不要这个: + // [IFoxInitialize(isInitialize: false)] + // 会出现永远存在临时文件夹的情况: + // 0x01 复制的时候,无法删除占用中的, + // 0x02 调试期间直接退出 acad.exe + public void Terminate() + { + // 此处要先去删除tmp文件夹的上次剪贴板产生的dwg文件 + for (int i = _delFile.Count - 1; i >= 0; i--) + { + try + { + if (File.Exists(_delFile[i])) + File.Delete(_delFile[i]); + _delFile.RemoveAt(i); + } + catch { Env.Printl("无法删除(是否占用):" + _delFile[i]); } + } + } + + + /// + /// 读写锁,当资源处于写入模式时,
    + /// 其他线程写入需要等待本次写入结束之后才能继续写入 + /// 参考链接 + ///
    + static readonly ReaderWriterLockSlim _rwLock = new(); + + /// + /// 储存准备删除的文件 + /// 也可以用txt代替 + /// 如果删除出错(占用),将一直在这个集合中,直到cad关闭 + /// + readonly List _delFile = new(); + + /// + /// 复制 + /// + /// + void Copy(bool getPoint, bool isEraseSsget = false) + { + try + { + if (!_rwLock.IsWriteLockHeld) + _rwLock.EnterWriteLock(); // 进入写入锁 + + var dm = Acap.DocumentManager; + if (dm.Count == 0) + return; + var doc = dm.MdiActiveDocument; + if (doc == null) + return; + + ObjectId[] idArray; +#if true + var psr = doc.Editor.SelectImplied();// 预选 + if (psr.Status != PromptStatus.OK) + psr = doc.Editor.GetSelection();// 手选 + if (psr.Status != PromptStatus.OK) + return; + idArray = psr.Value.GetObjectIds(); +#endif + + // 设置基点 + Point3d pt = Point3d.Origin; + var tempFile = CreateTempFileName(); + while (File.Exists(tempFile) || + File.Exists(Path.ChangeExtension(tempFile, "wmf"))) + { + tempFile = CreateTempFileName(); + Thread.Sleep(1); + } + + using DBTrans tr = new(); + + + #region 写入 WMF 数据 + /* + * 通过cadCom导出wmf(免得自己转换每种图元), + * 再将wmf转为emf,然后才能写入剪贴板 + * wmf生成(win32api): https://www.cnblogs.com/5iedu/p/4706324.html + */ + IntPtr hMetaFile = IntPtr.Zero; + { + var wmf = Path.ChangeExtension(tempFile, "wmf"); + Env.Editor.ComExportWMF(wmf, idArray); + if (File.Exists(wmf)) + { + hMetaFile = PlaceableMetaHeader.Wmf2Emf(wmf);//emf文件句柄 + try { File.Delete(wmf); } + catch (Exception e) { Env.Printl(e); } + } + else + { + Env.Printl("没有创建wmf,失败"); + } + } + if (hMetaFile != IntPtr.Zero) + { + // 克隆一个,并写入描述...此处尚未完成 + // EmfTool.SetEnhMetaFileDescriptionEx(ref hMetaFile, "这是阿惊的emf"); + } + + // 保存文件 + //var emfsave = Path.ChangeExtension(cadClipType.File, ".emf"); + //EmfTool.Save(emf, emfsave); + #endregion + + #region 写入 AutoCAD.R17 数据 + if (getPoint) + { + var pr = doc.Editor.GetPoint("\n选择基点"); + if (pr.Status != PromptStatus.OK) + return; + pt = pr.Value; + } + else + { + // 遍历块内 + // 获取左下角点作为基点 + double minx = double.MaxValue; + double miny = double.MaxValue; + double minz = double.MaxValue; + foreach (var id in idArray) + { + var ent = tr.GetObject(id); + if (ent == null) + continue; + var info = ent.GetBoundingBoxEx(); + if (info != null) + { + if (ent is BlockReference brf) + info.Value.Move(brf.Position, Point3d.Origin); + minx = minx > info.Value.MinX ? info.Value.MinX : minx; + miny = miny > info.Value.MinY ? info.Value.MinY : miny; + minz = minz > info.Value.MinZ ? info.Value.MinZ : minz; + } + } + pt = new(minx, miny, minz); + } + + var cadClipType = new TagClipboardInfo(tempFile, pt); + + // 克隆到目标块表内 + using (DBTrans fileTr = new(cadClipType.File)) + { + fileTr.Task(() => { + using IdMapping map = new(); + using ObjectIdCollection ids = new(idArray); + tr.Database.WblockCloneObjects( + ids, + fileTr.ModelSpace.ObjectId, + map, + DuplicateRecordCloning.Replace, + false); + }); + + // 大于dwg07格式的,保存为07,以实现高低版本通用剪贴板 + // 小于dwg07格式的,本工程没有支持cad06dll + if ((int)DwgVersion.Current >= 27) + fileTr.Database.SaveFile((DwgVersion)27, false); + else + throw new ArgumentException($"版本过低,无法保存,版本号:{DwgVersion.Current}"); + } + #endregion + + // 必须一次性写入剪贴板,详见 OpenClipboardTask + var cadClipFormat = ClipTool.RegisterClipboardFormat(ClipboardEnv.CadVer); + + // 剪贴板需要的指针: 克隆一个新的,不释放内存,不锁定内存(否则高频触发时候卡死) + var cadClipData = cadClipType.CloneToPtr(); + + bool getFlag = ClipTool.OpenClipboardTask(true, () => { + // 写入剪贴板: cad图元 + ClipTool.SetClipboardData(cadClipFormat, cadClipData); + + // 写入剪贴板: wmf,使得在粘贴链接的时候可以用 + if (hMetaFile != IntPtr.Zero) + ClipTool.SetClipboardData((uint)ClipboardFormat.CF_ENHMETAFILE, hMetaFile); + }); + if (hMetaFile != IntPtr.Zero) + EmfTool.DeleteEnhMetaFile(hMetaFile); + + // 成功拷贝就删除上一次的临时文件 + if (getFlag) + Terminate(); + + // 加入删除队列,下次删除 + if (!_delFile.Contains(cadClipType.File)) + _delFile.Add(cadClipType.File); + + // 剪切时候删除 + if (isEraseSsget) + { + idArray.ForEach(id => { + id.Erase(); + }); + } + } + catch (Exception e) + { + Debugger.Break(); + throw e; + } + finally + { + if (_rwLock.IsWriteLockHeld) + _rwLock.ExitWriteLock(); // 退出写入锁 + } + } + + + /// + /// 粘贴 + /// + /// + void Paste(bool isBlock) + { + try + { + if (!_rwLock.IsWriteLockHeld) + _rwLock.EnterWriteLock(); // 进入写入锁 + + var dm = Acap.DocumentManager; + if (dm.Count == 0) + return; + + var getClip = ClipTool.GetClipboard(ClipboardEnv.CadVer, out TagClipboardInfo tag); + if (!getClip) + { + // 在没有安装插件的高版本cad中复制,此时剪贴板是当前版本的, + // 那么在安装了插件的cad中需要识别这个同版本的剪贴板内容 + // 例如天正只在某个启动的cad中加载插件,而不是全部 + getClip = ClipTool.GetClipboard(ClipboardEnv.CadCurrentVer, out tag); + if (!getClip) + return; + } + + var cadClipType = tag; + Env.Print("粘贴来源: " + cadClipType.File); + + if (!File.Exists(cadClipType.File)) + { + Env.Print("文件不存在"); + return; + } + + // 获取临时文件的图元id + List fileEntityIds = []; + using (DBTrans fileTr = new(cadClipType.File, commit: false, + fileOpenMode: FileOpenMode.OpenForReadAndAllShare)) + { + fileTr.ModelSpace.ForEach(id => { + if (id.IsOk()) + fileEntityIds.Add(id); + }); + } + if (fileEntityIds.Count == 0) + return; + + using DBTrans tr = new(); + tr.Editor?.SetImpliedSelection(new ObjectId[0]); // 清空选择集 + + // 新建块表记录 + var btr = CreateBlockTableRecord(tr, cadClipType.File); + if (btr == null) + return; + + /// 克隆进块表记录 + /// 动态块粘贴之后,用ctrl+z导致动态块特性无法恢复, + /// 是因为它: + using IdMapping map = new(); + using ObjectIdCollection idc = new(fileEntityIds.ToArray()); + tr.Task(() => { + tr.Database.WblockCloneObjects( + idc, + btr.ObjectId, // tr.Database.BlockTableId, // 粘贴目标 + map, + DuplicateRecordCloning.Ignore, + false); + }); + + // 移动块内,从基点到原点 + foreach (var id in btr) + { + if (!id.IsOk()) + { + Env.Printl("jig预览块内有克隆失败的脏东西,是否天正克隆期间导致?"); + continue; + } + var ent = tr.GetObject(id); + if (ent == null) + continue; + using (ent.ForWrite()) + ent.Move(cadClipType.Point, Point3d.Origin); + } + + // 预览并获取交互点 + // 天正此处可能存在失败:天正图元不给你jig接口调用之类的 + using var moveJig = new JigEx((mousePoint, drawEntitys) => { + var brf = new BlockReference(Point3d.Origin, btr.ObjectId); + brf.Move(Point3d.Origin, mousePoint); + drawEntitys.Enqueue(brf); + }); + var jppo = moveJig.SetOptions(cadClipType.Point); + jppo.Keywords.Add(" ", " ", "<空格取消>"); + jppo.Keywords.Add("A", "A", "引线点粘贴(A)"); + + var dr = moveJig.Drag(); + Point3d moveTo = Point3d.Origin; + if (dr.Status == PromptStatus.Keyword) + moveTo = cadClipType.Point; + else if (dr.Status == PromptStatus.OK) + moveTo = moveJig.MousePointWcsLast; + else + { + // 删除jig预览的块表记录 + using (btr.ForWrite()) + btr.Erase(); + return; + } + + if (isBlock) + { + PasteIsBlock(tr, moveJig.Entitys, moveJig.MousePointWcsLast, moveTo); + } + else + { + PasteNotBlock(tr, btr, Point3d.Origin, moveTo); + // 删除jig预览的块表记录 + using (btr.ForWrite()) + btr.Erase(); + } + + try + { + #region 读取剪贴板WMF + var msg = new StringBuilder(); + + int a3 = 0; + a3 = 2 | 4; + if ((a3 & 1) == 1) + { + // win32api 不成功 + ClipTool.OpenClipboardTask(false, () => { + // 剪贴板数据保存目标数据列表 + List _bytes = new(); + var cf = (uint)ClipboardFormat.CF_ENHMETAFILE; + var clipTypeData = ClipTool.GetClipboardData(cf); + if (clipTypeData == IntPtr.Zero) + { + Env.Printl("失败:粘贴剪贴板emf1"); + return; + } + + // 无法锁定剪贴板emf内存,也无法获取GlobalSize + bool locked = WindowsAPI.GlobalLockTask(clipTypeData, prt => { + uint size = WindowsAPI.GlobalSize(prt); + if (size > 0) + { + var buffer = new byte[size]; + Marshal.Copy(prt, buffer, 0, buffer.Length); + _bytes.Add(buffer); + } + }); + if (!locked) + Env.Printl("锁定内存失败"); + }); + } + if ((a3 & 2) == 2) + { + ClipTool.OpenClipboardTask(false, () => { + // 无法锁定剪贴板emf内存,也无法获取GlobalSize + // 需要直接通过指针跳转到指定emf结构位置 + var cf = (uint)ClipboardFormat.CF_ENHMETAFILE; + var clipTypeData = ClipTool.GetClipboardData(cf); + if (clipTypeData == IntPtr.Zero) + { + Env.Printl("失败:粘贴剪贴板emf2"); + return; + } + + int a4 = 1; + //int a4 = 1 | 2 | 4; + if ((a4 & 1) == 1) + { + // 获取描述 + var desc = EmfTool.GetEnhMetaFileDescriptionEx(clipTypeData); + if (!string.IsNullOrEmpty(desc)) + msg.AppendLine("DescriptionEx::" + desc); + } + if ((a4 & 2) == 2) + { + // 获取文件信息 + var obj = EnhMetaHeader.Create(clipTypeData); + msg.AppendLine("EnhMetaHeader::" + obj.ToString()); + } + if ((a4 & 4) == 4) + { + // 保存文件 + //var emfsave = Path.ChangeExtension(cadClipType.File, ".emf"); + //EmfTool.Save(clipTypeData, emfsave); + } + }); + } + if ((a3 & 4) == 4) + { + // c# 读取成功,win32直接读取剪贴板的话是不成功的 + if (Clipboard.ContainsData(DataFormats.EnhancedMetafile)) + { + var iData = Clipboard.GetDataObject();//从剪切板获取数据 + if (!iData.GetDataPresent(DataFormats.EnhancedMetafile)) + return; + var metafile = (Metafile)iData.GetData(DataFormats.EnhancedMetafile); + /* + // 为什么序列化失败了呢 + var formatter = new BinaryFormatter(); + //using MemoryStream stream = new(); + Stream stream = new FileStream("MyFile.bin", FileMode.Create, FileAccess.Write, FileShare.None); + formatter.Serialize(stream, metafile); + stream.Close(); + //Metafile obj = (Metafile)formatter.Deserialize(stream); + */ + msg.AppendLine($"c# Metafile::{metafile.Size}"); + } + } + + if (msg.Length != 0) + Env.Printl(msg); + #endregion + } + catch (Exception e) + { + Debugger.Break(); + DebugEx.Printl(e); + } + } + catch (Exception e)//{"剪贴板上的数据无效 (异常来自 HRESULT:0x800401D3 (CLIPBRD_E_BAD_DATA))"} + { + Debugger.Break(); + DebugEx.Printl(e); + } + finally + { + if (_rwLock.IsWriteLockHeld) + _rwLock.ExitWriteLock(); // 退出写入锁 + } + } + + /// + /// 粘贴为块 + /// + /// + /// + /// + /// + static void PasteIsBlock(DBTrans tr, Entity[] entitys, Point3d move, Point3d moveTo) + { + if (!move.IsEqualTo(moveTo, new Tolerance(1e-6, 1e-6))) + { + entitys.ForEach(ent => { + ent.Move(move, moveTo); + }); + } + tr.CurrentSpace.AddEntity(entitys); + } + + /// + /// 直接粘贴(不为块参照) + /// + /// + /// + /// 它总是为 + /// 目标点 + static void PasteNotBlock(DBTrans tr, BlockTableRecord btr, Point3d move, Point3d moveTo) + { + using ObjectIdCollection ids = new(); + foreach (var id in btr) + { + if (!id.IsOk()) + continue; + ids.Add(id); + } + + // 深度克隆,然后平移到当前目标点位置 + using IdMapping map = new(); + tr.CurrentSpace.DeepCloneEx(ids, map); + + map.GetValues().ForEach(id => { + if (!id.IsOk()) + return; + var ent = tr.GetObject(id); + if (ent == null) + return; + using (ent.ForWrite()) + ent.Move(move, moveTo); + }); + } + + /// + /// 创建块表记录 + /// + /// + /// 此名称若已在块表存在,就会自动用时间名称代替 + /// + BlockTableRecord? CreateBlockTableRecord(DBTrans tr, string tempFile) + { + var blockNameNew = Path.GetFileNameWithoutExtension(tempFile); + while (tr.BlockTable.Has(blockNameNew)) + { + tempFile = CreateTempFileName(); + blockNameNew = Path.GetFileNameWithoutExtension(tempFile); + Thread.Sleep(1); + } + var btrIdNew = tr.BlockTable.Add(blockNameNew); + return tr.GetObject(btrIdNew); + } + + /// + /// 创建临时路径的时间文件名 + /// + /// 格式,X是16进制 + /// + static string CreateTempFileName(string format = "X") + { + var t1 = DateTime.Now.ToString("yyyyMMddHHmmssfffffff"); + t1 = Convert.ToInt32(t1.GetHashCode()).ToString(format); + var t2 = Convert.ToInt32(t1.GetHashCode()).ToString(format);// 这里是为了满足长度而做的 + return Path.GetTempPath() + "A$" + t1 + t2[0] + ".DWG"; + } +} + + +public class TestImageFormat +{ + public ImageFormat GetFormat(string filename) + { + string ext = Path.GetExtension(filename).ToLower(); + var imf = ext switch + { + ".bmp" => ImageFormat.Bmp, + ".gif" => ImageFormat.Gif, + ".jpg" => ImageFormat.Jpeg, + ".tif" => ImageFormat.Tiff, + ".wmf" => ImageFormat.Wmf, + ".png" => ImageFormat.Png, + _ => throw new NotImplementedException(), + }; + return imf; + } + + // 此处相当于截图,后台没有doc不可用 + // https://www.cnblogs.com/shangdishijiao/p/15166499.html + [CommandMethod(nameof(CreatePreviewImage))] + public void CreatePreviewImage() + { + using DBTrans tr = new(); + if (tr.Document == null) + return; + + var doc = tr.Document; + + var size = doc.Window.DeviceIndependentSize; + using var bmp = doc.CapturePreviewImage( + Convert.ToUInt32(size.Width), + Convert.ToUInt32(size.Height)); + + //保存wmf会变png,看二进制签名 + var outFile = Path.ChangeExtension(tr.Database.Filename, ".bmp"); + bmp.Save(outFile, GetFormat(outFile)); + Env.Printl($"保存文件:{outFile}"); + Env.Printl($"保存后缀:{GetFormat(outFile)}"); + + // 利用winAPI截图 + bool getFlag = ClipTool.OpenClipboardTask(true, () => { + BitmapTool.CaptureWndImage(doc.Window.Handle, bitmapHandle => { + // 写入剪贴板: BMP位图,这是截图,不是WMF转BMP,不对 + ClipTool.SetClipboardData((uint)ClipboardFormat.CF_BITMAP, bitmapHandle); + }); + }); + } +} + + +public class OleTestClass +{ + // https://adndevblog.typepad.com/autocad/2012/04/update-linked-ole-object-from-net.html + + /// + /// 更新ole链接 + /// 如果 OLE 对象在另一个应用程序中打开,则上面的代码似乎不会更新该对象 + /// 例如,位图在 Microsoft 画图中打开 + /// + /// + /// + [DllImport("mfc90u.dll", CallingConvention = CallingConvention.ThisCall, + EntryPoint = "#6766")] + public static extern int COleClientItem_UpdateLink(IntPtr thisClientItem); + + [DllImport("acdb18.dll", CallingConvention = CallingConvention.ThisCall, + EntryPoint = "?getOleClientItem@AcDbOle2Frame@@QBEPAVCOleClientItem@@XZ")] + public static extern IntPtr AcDbOle2Frame_getOleClientItem(IntPtr thisOle2Frame); + + [CommandMethod(nameof(UpdateOleClient))] + public void UpdateOleClient() + { + var per = Env.Editor.GetEntity("\n选择OLE更新链接"); + if (per.Status != PromptStatus.OK) + return; + + using DBTrans tr = new(); + var ole2frame = tr.GetObject(per.ObjectId); + if (ole2frame == null) + return; + using (ole2frame.ForWrite()) + { + IntPtr ptrClientItem = AcDbOle2Frame_getOleClientItem(ole2frame.UnmanagedObject); + COleClientItem_UpdateLink(ptrClientItem); + } + } + + + // https://adndevblog.typepad.com/autocad/2012/06/iterating-ole-linked-entities.html + // 获取OLE路径 + [CommandMethod(nameof(GetOlePath))] + public void GetOlePath() + { + using DBTrans tr = new(); + foreach (ObjectId id in tr.CurrentSpace) + { + if (!id.IsOk()) + continue; + + var ole2frame = tr.GetObject(id); + if (ole2frame == null) + continue; + switch (ole2frame.Type) + { + case Ole2Frame.ItemType.Static: + Env.Editor.WriteMessage("\n" + "Static"); + break; + case Ole2Frame.ItemType.Embedded: + Env.Editor.WriteMessage("\n" + "Embedded"); + break; + case Ole2Frame.ItemType.Link: + Env.Editor.WriteMessage("\n" + "Link"); + Env.Editor.WriteMessage("\n" + ole2frame.LinkPath); + break; + } + } + } + + [CommandMethod(nameof(SetOle))] + public void SetOle() + { + //var pr = Env.Editor.GetPoint("\n选择基点"); + //if (pr.Status != PromptStatus.OK) + // return; + //var pt = pr.Value; + + using DBTrans tr = new(); + + // https://forums.autodesk.com/t5/net/how-to-create-an-ole-object-with-ole2frame/td-p/3203222 + var oo = new Ole2Frame(); + oo.SetDatabaseDefaults(); + //oo.CopyFrom() + oo.Position2d = new(0, 0, 100, 100); + + // 打印质量? https://learn.microsoft.com/zh-cn/dotnet/api/system.printing.outputquality?view=windowsdesktop-6.0 + //oo.OutputQuality = + //oo.AutoOutputQuality = + oo.Rotation = 0.0; + //oo.WcsWidth = ; + //oo.WcsHeight = ; + //oo.ScaleWidth = ; + //oo.ScaleHeight = ; + + //宽高比锁定 + oo.LockAspect = true; + } + +#if true2 + // https://forums.autodesk.com/t5/net/how-can-i-read-data-from-ole2frame-object-excel-through-api/td-p/7944241 + public void GetOleForOffice() + { + using DBTrans tr = new(); + foreach (ObjectId id in tr.CurrentSpace) + { + if (!id.IsOk()) + continue; + + var ole2frame = tr.GetObject(id); + if (ole2frame == null) + continue; + + var wb = (Microsoft.Office.Interop.Excel.Workbook)ole2frame.OleObject; + var ws = (Microsoft.Office.Interop.Excel.Worksheet)wb.ActiveSheet; + var range = (Microsoft.Office.Interop.Excel.Range)ws.UsedRange; + + tb.SetSize(range.Rows.Count, range.Columns.Count); + tb.SetRowHeight(range.RowHeight); + tb.SetColumnWidth(range.ColumnWidth); + tb.Position = new Point3d(ole2frame.Location.X, ole2frame.Location.Y, ole2frame.Location.Z); + for (int row = 0; row < range.Rows.Count; row++) + { + for (int col = 0; col < range.Columns.Count; col++) + { + tb.Cells[row, col].TextHeight = 1; + var aa = (Microsoft.Office.Interop.Excel.Range)range.Cells[row + 1, col + 1]; + var bb = Convert.ToString(aa.Value2); + tb.SetTextString(row, col, bb ?? ""); + tb.Cells[row, col].Alignment = CellAlignment.MiddleCenter; + } + } + tb.GenerateLayout(); + } + } +#endif +} + +#endif \ No newline at end of file diff --git a/tests/TestShared/TestAddEntity.cs b/tests/TestShared/TestAddEntity.cs new file mode 100644 index 0000000..123ba77 --- /dev/null +++ b/tests/TestShared/TestAddEntity.cs @@ -0,0 +1,109 @@ +namespace Test; + +public partial class Test +{ + + + + + + + + + + + + + [CommandMethod(nameof(Test_Rec))] + public void Test_Rec() + { + Point2d p1 = new(10000.2, 100000.5); + Point2d p2 = new(15000.9, 100000.5); + Point2d p3 = new(15000.9, 105000.7); + Point2d p4 = new(10000.2, 105000.7); + + var p12 = p2 - p1; + var p23 = p3 - p2; + var p34 = p4 - p3; + var p41 = p1 - p4; + var p13 = p3 - p1; + var p24 = p4 - p2; + + + const double pi90 = Math.PI / 2; + pi90.Print(); + + Tools.TestTimes(1000000, "对角线", () => { + var result = false; + if (Math.Abs(p13.Length - p24.Length) <= 1e8) + { + result = p41.IsParallelTo(p12); + } + }); + +#pragma warning disable CS0219 // 变量已被赋值,但从未使用过它的值 + Tools.TestTimes(1000000, "三次点乘", () => { + bool result = Math.Abs(p12.DotProduct(p23)) < 1e8 && + Math.Abs(p23.DotProduct(p34)) < 1e8 && + Math.Abs(p34.DotProduct(p41)) < 1e8; + }); + + Tools.TestTimes(1000000, "三次垂直", () => { + bool result = p12.IsParallelTo(p23) && + p23.IsParallelTo(p34) && + p34.IsParallelTo(p41); + }); +#pragma warning restore CS0219 // 变量已被赋值,但从未使用过它的值 + } + + + + + [CommandMethod(nameof(Test_EntRoration))] + public void Test_EntRoration() + { + var line = new Line(new(0, 0, 0), new(100, 0, 0)); + + using DBTrans tr = new(); + tr.CurrentSpace.AddEntity(line); + var line2 = (Line)line.Clone(); + tr.CurrentSpace.AddEntity(line2); + line2.Rotation(new(100, 0, 0), Math.PI / 2); + } + + [CommandMethod(nameof(Test_TypeSpeed))] + public void Test_TypeSpeed() + { + var line = new Line(); + var line1 = line as Entity; + Tools.TestTimes(100000, "is 匹配:", () => { + var t = line1 is Line; + }); + Tools.TestTimes(100000, "name 匹配:", () => { + // var t = line.GetType().Name; + var tt = line1.GetType().Name == nameof(Line); + }); + Tools.TestTimes(100000, "dxfname 匹配:", () => { + // var t = line.GetType().Name; + var tt = line1.GetRXClass().DxfName == nameof(Line); + }); + } + + [CommandMethod(nameof(Test_sleeptrans))] + public static void Test_sleeptrans() + { + using var tr = new DBTrans(); + for (int i = 0; i < 100; i++) + { + var cir = CircleEx.CreateCircle(new Point3d(i, i, 0), 0.5); + if (cir is null) + { + return; + } + cir.ColorIndex = i; + tr.CurrentSpace.AddEntity(cir); + tr.Editor?.Redraw(cir); + System.Threading.Thread.Sleep(10); + } + } +} \ No newline at end of file diff --git a/tests/TestShared/TestBlock.cs b/tests/TestShared/TestBlock.cs new file mode 100644 index 0000000..20baa82 --- /dev/null +++ b/tests/TestShared/TestBlock.cs @@ -0,0 +1,864 @@ + +namespace Test; + +public class TestBlock +{ + // 一个命令就把块编辑搞定,减少用户记忆命令 + [CommandMethod(nameof(Test_Refedit), CommandFlags.Redraw | CommandFlags.Session)] + public void Test_Refedit() + { + Env.Printl($"{nameof(Test_Refedit)}-在位编辑块/在位保存块"); + + // 全部用lisp发送命令是为了空格还是本命令 + // 打开了块编辑器,就关闭掉,保存提示 + if ((short)Env.GetVar("BlockEditor") == 1) + { + Env.Editor.RunLisp("(command \"_.bclose\")"); + return; + } + // 0x01 非在位编辑状态: 先选择块参照,然后在位编辑 + // 0x02 在位编辑状态: 关闭并保存 + if (Env.GetVar("RefEditName").ToString() == "")//显示正在编辑的参照名称 + Env.Editor.RunLisp("(command \"_.refedit\")");//直接点选可以有嵌套层次 + else + Env.Editor.RunLisp("(command \"_.refclose\" \"s\")"); + } + + [CommandMethod(nameof(Test_GetBoundingBoxEx))] + public void Test_GetBoundingBoxEx() + { + using DBTrans tr = new(); + var ents = Env.Editor.SSGet().Value?.GetEntities(); + if (ents == null) + return; + foreach (var item in ents) + { + var box = item?.GetBoundingBoxEx(); + Env.Print("min:" + box?.BottomLeft + ";max" + box?.TopRight); + if (box != null) + tr.CurrentSpace.AddEntity(new Line(box.Value.BottomLeft, box.Value.TopRight)); + } + } + + // 前台块定义 + [CommandMethod(nameof(Test_BlockDef))] + public void Test_BlockDef() + { + using DBTrans tr = new(); + // var line = new Line(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); + tr.BlockTable.Add("test", + btr => + { + btr.Origin = new Point3d(0, 0, 0); + }, + () => // 图元 + new List { new Line(new Point3d(0, 0, 0), new Point3d(1, 1, 0)) }, + () => // 属性定义 + { + var id1 = new AttributeDefinition() { Position = new Point3d(0, 0, 0), Tag = "start", Height = 0.2 }; + var id2 = new AttributeDefinition() { Position = new Point3d(1, 1, 0), Tag = "end", Height = 0.2 }; + return new List { id1, id2 }; + } + ); + // ObjectId objectId = tr.BlockTable.Add("a");// 新建块 + // objectId.GetObject().AddEntity();// 测试添加空实体 + tr.BlockTable.Add("test1", + btr => + { + btr.Origin = new Point3d(0, 0, 0); + }, + () => + { + var line = new Line(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); + var acText = DBTextEx.CreateDBText(Point3d.Origin, "123", 2.5); + return new List { line, acText }; + }); + } + + // 后台块定义 + [CommandMethod(nameof(Test_BlockDefbehind))] + public void Test_BlockDefbehind() + { + using DBTrans tr = new(@"C:\Users\vic\Desktop\test.dwg"); + // var line = new Line(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); + tr.BlockTable.Add("test", + btr => + { + btr.Origin = new Point3d(0, 0, 0); + }, + () => // 图元 + { + return new List { new Line(new Point3d(0, 0, 0), new Point3d(1, 1, 0)) }; + }, + () => // 属性定义 + { + var id1 = new AttributeDefinition() { Position = new Point3d(0, 0, 0), Tag = "start", Height = 0.2 }; + var id2 = new AttributeDefinition() { Position = new Point3d(1, 1, 0), Tag = "end", Height = 0.2 }; + return new List { id1, id2 }; + } + ); + // ObjectId objectId = tr.BlockTable.Add("a");// 新建块 + // objectId.GetObject().AddEntity();// 测试添加空实体 + tr.BlockTable.Add("test1", + btr => + { + btr.Origin = new Point3d(0, 0, 0); + }, + () => + { + var line = new Line(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); + var acText = DBTextEx.CreateDBText(Point3d.Origin, "12345", 2.5); + + return new List { line, acText }; + }); + tr.Database.SaveDwgFile(); + } + + + + // 修改块定义 + [CommandMethod(nameof(Test_BlockDefChange))] + public void Test_BlockDefChange() + { + using DBTrans tr = new(); + // var line = new Line(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); + // tr.BlockTable.Change("test", btr => + // { + // btr.Origin = new Point3d(5, 5, 0); + // btr.AddEntity(new Circle(new Point3d(0, 0, 0), Vector3d.ZAxis, 2)); + // btr.GetEntities() + // .ToList() + // .ForEach(e => e.Flush()); // 刷新块显示 + + // }); + + + tr.BlockTable.Change("test", btr => + { + foreach (var id in btr) + { + var ent = tr.GetObject(id); + using (ent!.ForWrite()) + { + switch (ent) + { + case Dimension dBText: + dBText.DimensionText = "234"; + dBText.RecomputeDimensionBlock(true); + break; + case Hatch hatch: + hatch.ColorIndex = 0; + break; + } + } + } + }); + tr.Editor?.Regen(); + } + + [CommandMethod(nameof(Test_InsertBlockDef))] + public void Test_InsertBlockDef() + { + using DBTrans tr = new(); + var line1 = new Line(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); + var line2 = new Line(new Point3d(0, 0, 0), new Point3d(-1, 1, 0)); + var att1 = new AttributeDefinition() { Position = new Point3d(10, 10, 0), Tag = "tagTest1", Height = 1, TextString = "valueTest1" }; + var att2 = new AttributeDefinition() { Position = new Point3d(10, 12, 0), Tag = "tagTest2", Height = 1, TextString = "valueTest2" }; + tr.BlockTable.Add("test1", line1, line2, att1, att2); + + + List ents = []; + var line5 = new Line(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); + var line6 = new Line(new Point3d(0, 0, 0), new Point3d(-1, 1, 0)); + ents.Add(line5); + ents.Add(line6); + tr.BlockTable.Add("test44", ents); + + + var line3 = new Line(new Point3d(5, 5, 0), new Point3d(6, 6, 0)); + var line4 = new Line(new Point3d(5, 5, 0), new Point3d(-6, 6, 0)); + var att3 = new AttributeDefinition() { Position = new Point3d(10, 14, 0), Tag = "tagTest3", Height = 1, TextString = "valueTest3" }; + var att4 = new AttributeDefinition() { Position = new Point3d(10, 16, 0), Tag = "tagTest4", Height = 1, TextString = "valueTest4" }; + tr.BlockTable.Add("test2", new List { line3, line4 }, new List { att3, att4 }); + // tr.CurrentSpace.InsertBlock(new Point3d(4, 4, 0), "test1"); // 测试默认 + // tr.CurrentSpace.InsertBlock(new Point3d(4, 4, 0), "test2"); + // tr.CurrentSpace.InsertBlock(new Point3d(4, 4, 0), "test3"); // 测试插入不存在的块定义 + // tr.CurrentSpace.InsertBlock(new Point3d(0, 0, 0), "test1", new Scale3d(2)); // 测试放大2倍 + // tr.CurrentSpace.InsertBlock(new Point3d(4, 4, 0), "test1", new Scale3d(2), Math.PI / 4); // 测试放大2倍,旋转45度 + + var def1 = new Dictionary + { + { "tagTest1", "1" }, + { "tagTest2", "2" } + }; + tr.CurrentSpace.InsertBlock(new Point3d(0, 0, 0), "test1", atts: def1); + var def2 = new Dictionary + { + { "tagTest3", "1" }, + { "tagTest4", "" } + }; + tr.CurrentSpace.InsertBlock(new Point3d(10, 10, 0), "test2", atts: def2); + tr.CurrentSpace.InsertBlock(new Point3d(20, 20, 0), "test2"); + tr.CurrentSpace.InsertBlock(new Point3d(-10, 0, 0), "test44"); + } + + [CommandMethod(nameof(Test_InsertBlockWithDoubleDatabase))] + public void Test_InsertBlockWithDoubleDatabase() + { + using var tr = new DBTrans(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "test.dwg")); + using var trans = new DBTrans(); + + tr.BlockTable.Add("test456", + btr => + { + btr.Origin = new(0, 0, 0); + }, + () => + { + var line = new Line(new(0, 0, 0), new(1, 1, 0)); + var actext = DBTextEx.CreateDBText(Point3d.Origin, "123", 2.5, database: tr.Database); + + return new List { line, actext }; + + }); + tr.CurrentSpace.InsertBlock(Point3d.Origin, "test456"); + tr.Database.SaveDwgFile(); + } + + + + [CommandMethod(nameof(Test_AddAttsDef))] + public void Test_AddAttsDef() + { + using DBTrans tr = new(); + var blockid = Env.Editor.GetEntity("pick block:").ObjectId; + var btf = tr.GetObject(blockid); + if (btf is null) + return; + var att1 = new AttributeDefinition() { Position = new Point3d(20, 20, 0), Tag = "addtagTest1", Height = 1, TextString = "valueTest1" }; + var att2 = new AttributeDefinition() { Position = new Point3d(10, 12, 0), Tag = "tagTest2", Height = 1, TextString = "valueTest2" }; + tr.BlockTable.AddAttsToBlocks(btf.BlockTableRecord, new() { att1, att2 }); + } + + [CommandMethod(nameof(Test_BlockNullBug))] + public void Test_BlockNullBug() + { + using DBTrans tr = new(); + + List ents = []; + var line5 = new Line(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); + var line6 = new Line(new Point3d(0, 0, 0), new Point3d(-1, 1, 0)); + ents.Add(line5); + ents.Add(line6); + tr.BlockTable.Add("test44", ents); + tr.CurrentSpace.InsertBlock(new Point3d(0, 0, 0), "test44"); + } + + [CommandMethod(nameof(Test_BlockFile))] + public void Test_BlockFile() + { + using DBTrans tr = new(); + var id = tr.BlockTable.GetBlockFrom(@"C:\Users\vic\Desktop\test.dwg", false); + tr.CurrentSpace.InsertBlock(Point3d.Origin, id); + } + + [CommandMethod(nameof(Test_BlockFiledxf))] + public void Test_BlockFiledxf() + { + string [] files; + var folder= new System.Windows.Forms.FolderBrowserDialog(); + if (folder.ShowDialog() == System.Windows.Forms.DialogResult.OK) + { + files = Directory.GetFiles(folder.SelectedPath,"*.dxf",SearchOption.AllDirectories); + using DBTrans tr = new(); + foreach (var item in files) + { + var id = tr.BlockTable.GetBlockFrom(item, false); + var pt = Env.Editor.GetPoint("pick pt"); + if (pt.Status == PromptStatus.OK) + { + tr.CurrentSpace.InsertBlock(pt.Value, id); + Env.Editor.Redraw(); + } + + } + + } + + + } + + [CommandMethod(nameof(Test_ClipBlock))] + public void Test_ClipBlock() + { + using DBTrans tr = new(); + tr.BlockTable.Add("test1", btr => + { + btr.Origin = new Point3d(0, 0, 0); + btr.AddEntity(new Line(new Point3d(0, 0, 0), new Point3d(10, 10, 0)), + new Line(new Point3d(10, 10, 0), new Point3d(10, 0, 0))); + }); + // tr.BlockTable.Add("hah"); + var id = tr.CurrentSpace.InsertBlock(new Point3d(0, 0, 0), "test1"); + var brf1 = tr.GetObject(id)!; + var pts = new List { new Point3d(3, 3, 0), new Point3d(7, 3, 0), new Point3d(7, 7, 0), new Point3d(3, 7, 0) }; + brf1.XClip(pts); + + var id1 = tr.CurrentSpace.InsertBlock(new Point3d(20, 20, 0), "test1"); + var brf2 = tr.GetObject(id); + brf2?.XClip(new Point3d(13, 13, 0), new Point3d(17, 17, 0)); + } + + + [CommandMethod(nameof(Test_ClipBlock1))] + public void Test_ClipBlock1() + { + using DBTrans tr = new(); + var ent = Env.Editor.GetEntity("pick block"); + if (ent.Status != PromptStatus.OK) return; + + var brf1 = tr.GetObject(ent.ObjectId)!; + var pts = new List { new Point3d(3, 3, 0), new Point3d(7, 3, 0), new Point3d(7, 7, 0), new Point3d(3, 7, 0) }; + brf1.XClip(pts); + + } + + + + // 给用户的测试程序,不知道对错 + [CommandMethod(nameof(Test_Block_ej))] + public void Test_Block_ej() + { + using (DBTrans tr = new()) + { + // Point3d.Origin.AddBellowToModelSpace(100, 100, 5, 3, 30);// 画波纹管 + + // Database db2 = new Database(false, true); + // string fullFileName = @".\MyBlockDwgFile\001.dwg"; + // db2.ReadDwgFile(fullFileName, System.IO.FileShare.Read, true, null); + // db2.CloseInput(true); + // string blockName = "test"; + // if (!tr.BlockTable.Has(blockName)) + // { + // // tr.Database.Insert(blockName, db2, false);// 插入块 + // db.Insert(blockName, db2, false); + + // } + + string fullFileName = @"C:\Users\vic\Desktop\001.dwg"; + var blockdef = tr.BlockTable.GetBlockFrom(fullFileName, false); + + tr.Database.Clayer = tr.LayerTable["0"];// 当前图层切换为0图层 + tr.LayerTable.Change(tr.Database.Clayer, ltr => + { + ltr.Color = Color.FromColorIndex(ColorMethod.ByAci, 2); // ColorMethod.ByAci可以让我们使用AutoCAD ACI颜色索引……这里为2(表示黄色) + }); + + var id = tr.ModelSpace.InsertBlock(Point3d.Origin, blockdef);// 插入块参照 + var brf = tr.GetObject(id); + brf?.Draw(); + } + + using DBTrans tr2 = new(); + PromptEntityOptions peo = new("\n请选择一个块"); + peo.SetRejectMessage("\n对象必须是块"); + peo.AddAllowedClass(typeof(BlockReference), true); + + var per = Env.Editor.GetEntity(peo); + if (per.Status != PromptStatus.OK) + return; + + var brf2 = tr2.GetObject(per.ObjectId)!; + // var BTR = tr.GetObject(Bref.BlockTableRecord, OpenMode.ForWrite); + //// 如果知道块名字BTRName + // BlockTableRecord BTR = tr.GetObject(tr.BlockTable[blockName], OpenMode.ForWrite); + + var btr = tr2.BlockTable[brf2.Name]; + + tr2.BlockTable.Change(btr, ltr => + { + foreach (ObjectId oid in ltr) + { + var ent = tr2.GetObject(oid); + if (ent is MText mText) + { + using (ent.ForWrite()) + switch (mText.Text) + { + case "$$A": + mText.Contents = "hahaha"; + break; + case "$$B": + break; + default: + break; + } + } + else if (ent is DBText dBText) + { + using (ent.ForWrite()) + dBText.TextString = "haha"; + } + else if (ent is Dimension dimension) + { + using (ent.ForWrite()) + switch (dimension.DimensionText) + { + case "$$pipeLen": + dimension.DimensionText = "350"; + dimension.RecomputeDimensionBlock(true); + break; + default: + break; + } + } + } + }); + tr2.Editor?.Regen(); + } + + [CommandMethod(nameof(Test_QuickBlockDef2))] + public void Test_QuickBlockDef2() + { + // Database db = HostApplicationServices.WorkingDatabase; + Editor ed = Acap.DocumentManager.MdiActiveDocument.Editor; + PromptSelectionOptions promptOpt = new() + { + MessageForAdding = "请选择需要快速制作块的对象" + }; + string blockName = "W_BLOCK_" + DateTime.Now.ToString("yyyyMMdd_HHmmss"); + // var rss = ed.GetSelection(promptOpt); + var rss = Env.Editor.GetSelection(promptOpt); + using DBTrans tr = new(); + if (rss.Status == PromptStatus.OK) + { + // SelectionSet ss = rss.Value; + // ObjectId[] ids = ss.GetObjectIds(); + // List> ents = []; + // var extents = new Extents3d(); + // foreach (var id in ids) + // { + // Entity ent = tr.GetObject(id); + // if (ent is null) + // continue; + // try + // { + // extents.AddExtents(ent.GeometricExtents); + // var order = id.Handle.Value; + // var newEnt = ent.Clone() as Entity; + // ents.Add(new KeyValuePair(newEnt, order)); + // ent.UpgradeOpen(); + // ent.Erase(); + // ent.DowngradeOpen(); + // } + // catch (System.Exception exc) + // { + // ed.WriteMessage(exc.Message); + // } + // } + // ents = ents.OrderBy(x => x.Value).ToList(); + var ents = rss.Value.GetEntities(); + // ents.ForEach(ent => extents.AddExtents(ent.GeometricExtents)); + var extents = ents!.GetExtents(); + Point3d pt = extents.MinPoint; + Matrix3d matrix = Matrix3d.Displacement(Point3d.Origin - pt); + // List newEnts = []; + // foreach (var ent in ents) + // { + // var newEnt = ent.Key; + // newEnt.TransformBy(matrix); + // newEnts.Add(newEnt); + // } + // if (tr.BlockTable.Has(blockName)) + // { + // Acap.ShowAlertDialog(Environment.NewLine + "块名重复,程序退出!"); + // return; + // } + ents.ForEach(ent => + ent?.ForWrite(e => e?.TransformBy(matrix))); + // var newents = ents.Select(ent => + // { + // var maping = new IdMapping(); + // return ent.DeepClone(ent, maping, true) as Entity; + // }); + var newents = ents.Select(ent => ent?.Clone() as Entity); + + // ents.ForEach(ent => ent.ForWrite(e => e.Erase(true))); // 删除实体就会卡死,比较奇怪,估计是Clone()函数的问题 + // 经过测试不是删除的问题 + var btrId = tr.BlockTable.Add(blockName, newents!); + ents.ForEach(ent => ent?.ForWrite(e => e?.Erase(true))); + var bId = tr.CurrentSpace.InsertBlock(pt, blockName); + // tr.GetObject(bId, OpenMode.ForWrite).Move(Point3d.Origin, Point3d.Origin); + // var ed = Acap.DocumentManager.MdiActiveDocument.Editor; + // ed.Regen(); + // tr.Editor.Regen(); + // 调用regen() 卡死 + } + // tr.Editor.Regen(); + // ed.Regen(); + // using (var tr = new DBTrans()) + // { + // tr.CurrentSpace.InsertBlock(Point3d.Origin, blockName); + // tr.Editor.Regen(); + // } + } + + [CommandMethod(nameof(Test_QuickBlockDef1))] + public void Test_QuickBlockDef1() + { + var dm = Acap.DocumentManager; + var doc = dm.MdiActiveDocument; + var db = doc.Database; + var ed = doc.Editor; + + PromptSelectionOptions promptOpt = new() + { + MessageForAdding = "请选择需要快速制作块的对象" + }; + string blockName = "W_BLOCK_" + DateTime.Now.ToString("yyyyMMdd_HHmmss"); + var rss = Env.Editor.GetSelection(promptOpt); + if (rss.Status != PromptStatus.OK) + return; + + using var tr = db.TransactionManager.StartTransaction(); + var ids = rss.Value.GetObjectIds(); + var bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable; + var btr = new BlockTableRecord + { + Name = blockName + }; + foreach (var item in ids) + { + var ent = tr.GetObject(item, OpenMode.ForRead) as Entity; + btr.AppendEntity(ent!.Clone() as Entity); + ent.ForWrite(e => e.Erase(true)); + } + bt!.UpgradeOpen(); + bt.Add(btr); + tr.AddNewlyCreatedDBObject(btr, true); + bt.DowngradeOpen(); + // tr.Commit(); + // } + + // using (var tr1 = db.TransactionManager.StartTransaction()) + // { + // var bt = tr1.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable; + var btr1 = tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord; + var brf = new BlockReference(Point3d.Origin, bt[blockName]) + { + ScaleFactors = default + }; + btr1!.AppendEntity(brf); + tr.AddNewlyCreatedDBObject(brf, true); + btr1.DowngradeOpen(); + ed.Regen(); + tr.Commit(); + // ed.Regen(); + } + + void Wblock() + { + var curdb = HostApplicationServices.WorkingDatabase; + PromptSelectionOptions opts = new() + { + MessageForAdding = "选择对象" + }; + var ss = Env.Editor.GetSelection(opts).Value; + using ObjectIdCollection ids = new(ss.GetObjectIds()); + var db = curdb.Wblock(ids, Point3d.Origin); + db.SaveAs(@"c:\test.dwg", DwgVersion.Current); + } + [CommandMethod(nameof(ChangeDynameicBlock))] + public void ChangeDynameicBlock() + { + var pro = new Dictionary + { + { "haha", 1 } + }; + var blockid = Env.Editor.GetEntity("选择个块").ObjectId; + using DBTrans tr = new(); + var brf = tr.GetObject(blockid)!; + brf.ChangeBlockProperty(pro); + // 这是第一个函数的用法 + } + [CommandMethod(nameof(ChangeBlockProperty))] + public void ChangeBlockProperty() + { + Dictionary? pro = new() + { + { "haha", "1" } + }; + var blockid = Env.Editor.GetEntity("选择个块").ObjectId; + using DBTrans tr = new(); + var brf = tr.GetObject(blockid)!; + brf.ChangeBlockProperty(pro); + // 这是第一个函数的用法 + } + + [CommandMethod(nameof(Test_Back))] + public void Test_Back() + { + string dir = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory); + string dwg = dir + "\\test.dwg"; + if (!File.Exists(dwg)) + { + System.Windows.Forms.MessageBox.Show(dwg, "你还没有创建此文件"); + return; + } + + using DBTrans tr = new(dwg); + tr.ModelSpace.GetEntities().ForEach(ent => + { + ent.ForWrite(e => e.ColorIndex = 3); + }); + tr.Database.SaveAs(dwg, DwgVersion.Current); + + tr.ModelSpace.GetEntities().ForEach(ent => + { + ent.ForWrite(e => e.ColorIndex = 4); + }); + tr.Database.SaveAs(dwg, DwgVersion.Current); + } + + [CommandMethod(nameof(Test_ExplodeBlock))] + public void Test_ExplodeBlock() + { + var r1 = Env.Editor.GetEntity("pick block"); + if (r1.Status != PromptStatus.OK) + return; + using var tr = new DBTrans(); + if (tr.GetObject(r1.ObjectId, OpenMode.ForWrite) is not BlockReference brf) + return; + var dboc = new DBObjectCollection(); + // brf.Explode(dboc); + brf.ExplodeToOwnerSpace(); + // foreach (Entity item in dboc) + // { + // tr.CurrentSpace.AddEntity(item); + // } + using (brf.ForWrite()) + { + brf.Erase(); + } + } +} + + + +public static class Blocks +{ + + [CommandMethod("TestExplodeToOwnerSpace3")] + public static void TestExplodeToOwnerSpace3_Method() + { + Editor ed = Application.DocumentManager.MdiActiveDocument.Editor; + try + { + PromptEntityOptions prEntOpt = new PromptEntityOptions("\nSelect an INSERT:"); + prEntOpt.SetRejectMessage("\nIt is not an INSERT!"); + prEntOpt.AddAllowedClass(typeof(BlockReference), true); + PromptEntityResult selRes = ed.GetEntity(prEntOpt); + if (selRes.Status == PromptStatus.OK) + { + ObjectIdCollection ids = ExplodeToOwnerSpace3(selRes.ObjectId); + ed.WriteMessage("{0} entities were added into database.", ids.Count); + } + else + { + ed.WriteMessage("\nEntity Selection failed!"); + } + } + catch (System.Exception ex) + { + ed.WriteMessage(ex.Message); + } + } + + public static void ExplodeToOwnerSpace2(ObjectId id, bool erase = true) + { + ExplodeToOwnerSpace3(id, erase); + } + + public static void ExplodeToOwnerSpace2(this BlockReference br) + { + ExplodeToOwnerSpace3(br); + } + + public static ObjectIdCollection ExplodeToOwnerSpace3(ObjectId id, bool erase = true) + { + ObjectIdCollection ids; + + using (Transaction tr = id.Database.TransactionManager.StartTransaction()) + { + BlockReference br = (BlockReference)tr.GetObject(id, OpenMode.ForRead); + ids = br.ExplodeToOwnerSpace3(); + + if (erase) + { + br.UpgradeOpen(); + br.Erase(); + } + + tr.Commit(); + } + + return ids; + } + + private static ObjectIdCollection idsAdded = []; + public static ObjectIdCollection ExplodeToOwnerSpace3(this BlockReference br) + { + idsAdded = new ObjectIdCollection(); + + Transaction tr = br.Database.TransactionManager.TopTransaction; + BlockTableRecord spaceBtr = (BlockTableRecord)tr.GetObject(br.BlockId, OpenMode.ForWrite); + LoopThroughInsertAndAddEntity2n3(br.BlockTransform, br, spaceBtr); + + return idsAdded; + } + // 不能用于非等比 + public static void LoopThroughInsertAndAddEntity2n3(Matrix3d mat, BlockReference br, BlockTableRecord space) + { + Transaction tr = space.Database.TransactionManager.TopTransaction; + BlockTableRecord btr = (BlockTableRecord)tr.GetObject(br.BlockTableRecord, OpenMode.ForRead); + + foreach (ObjectId id in btr) + { + DBObject obj = tr.GetObject(id, OpenMode.ForRead); + Entity? ent = obj.Clone() as Entity; + if (ent is BlockReference) + { + BlockReference br1 = (BlockReference)ent; + LoopThroughInsertAndAddEntity2n3(br1.BlockTransform.PreMultiplyBy(mat), br1, space); + } + else + { + ent?.TransformBy(mat); + space.AppendEntity(ent); + tr.AddNewlyCreatedDBObject(ent, true); + + idsAdded.Add(ent!.ObjectId); + } + } + } + +} + + +public class BlockImportClass +{ + [CommandMethod(nameof(Test_Cbll))] + public void Test_Cbll() + { + string filename = @"C:\Users\vic\Desktop\Drawing1.dwg"; + using DBTrans tr = new(); + using DBTrans tr1 = new(filename); + // tr.BlockTable.GetBlockFrom(filename, true); + string blkdefname = SymbolUtilityServices.RepairSymbolName(SymbolUtilityServices.GetSymbolNameFromPathName(filename, "dwg"), false); + tr.Database.Insert(blkdefname, tr1.Database, false); // 插入了块定义,未插入块参照 + } + + + [CommandMethod(nameof(Test_CombineBlocksIntoLibrary))] + public void Test_CombineBlocksIntoLibrary() + { + Document doc = Acap.DocumentManager.MdiActiveDocument; + Editor ed = doc.Editor; + Database destDb = doc.Database; + + PromptResult pr = ed.GetString("\nEnter the folder of source drawings: "); + + if (pr.Status != PromptStatus.OK) + return; + string pathName = pr.StringResult; + if (!Directory.Exists(pathName)) + { + ed.WriteMessage("\nDirectory does not exist: {0}", pathName); + return; + } + string[] fileNames = Directory.GetFiles(pathName, "*.dwg"); + int imported = 0, failed = 0; + foreach (string fileName in fileNames) + { + if (fileName.EndsWith(".dwg", + StringComparison.InvariantCultureIgnoreCase)) + { + // Catch exceptions at the file level to allow skipping + try + { + // Suggestion from Thorsten Meinecke... + + string destName = + SymbolUtilityServices.GetSymbolNameFromPathName( + fileName, "dwg" + ); + + // And from Dan Glassman... + + destName = + SymbolUtilityServices.RepairSymbolName( + destName, false + ); + + // Create a source database to load the DWG into + + using Database db = new(false, true); + // Read the DWG into our side database + + db.ReadDwgFile(fileName, FileShare.Read, true, ""); + bool isAnno = db.AnnotativeDwg; + + // Insert it into the destination database as + // a named block definition + + ObjectId btrId = destDb.Insert( + destName, + db, + false + ); + + if (isAnno) + { + // If an annotative block, open the resultant BTR + // and set its annotative definition status + + Transaction tr = + destDb.TransactionManager.StartTransaction(); + using (tr) + { + BlockTableRecord btr = + (BlockTableRecord)tr.GetObject( + btrId, + OpenMode.ForWrite + ); + btr.Annotative = AnnotativeStates.True; + tr.Commit(); + } + } + + // Print message and increment imported block counter + + ed.WriteMessage("\nImported from \"{0}\".", fileName); + imported++; + } + catch (System.Exception ex) + { + ed.WriteMessage( + "\nProblem importing \"{0}\": {1} - file skipped.", + fileName, ex.Message + ); + failed++; + } + } + } + + ed.WriteMessage( + "\nImported block definitions from {0} files{1} in " + + "\"{2}\" into the current drawing.", + imported, + failed > 0 ? " (" + failed + " failed)" : "", + pathName + ); + } + +} \ No newline at end of file diff --git a/tests/TestShared/TestCadFilePath.cs b/tests/TestShared/TestCadFilePath.cs new file mode 100644 index 0000000..4a32dd5 --- /dev/null +++ b/tests/TestShared/TestCadFilePath.cs @@ -0,0 +1,30 @@ + +namespace Test; + +public class TestCadFilePath +{ + [CommandMethod("TestCadFilePath")] + public void TestCadFilePathfun() + { + string key = HostApplicationServices.Current.UserRegistryProductRootKey; + // 计算机\HKEY_CURRENT_USER\SOFTWARE\Autodesk\AutoCAD\R24.0\ACAD-4101:804 + RegistryKey ackey = Registry.CurrentUser.OpenSubKey(key); + var profileskey = ackey.OpenSubKey("Profiles"); + + var listkey = profileskey.GetSubKeyNames(); + foreach (var item in listkey) + { + var acadkey = profileskey.OpenSubKey($@"{item}\General",true); + var name = "ACAD"; + var str = acadkey.GetValue(name)?.ToString(); + if (str is not null && !str.Contains("nihao")) + { + Env.Print(str); + acadkey.SetValue(name, $@"{str}\nihao;", RegistryValueKind.String); + } + + + } + + } +} diff --git a/tests/TestShared/TestConvexHull.cs b/tests/TestShared/TestConvexHull.cs new file mode 100644 index 0000000..03692ae --- /dev/null +++ b/tests/TestShared/TestConvexHull.cs @@ -0,0 +1,76 @@ +namespace Test; + + +public class TestConvexHull +{ + [CommandMethod(nameof(Test_ConvexHull))] + public void Test_ConvexHull() + { + // using DBTrans tr = new(); + // List pts = []; + // var flag = true; + // while (flag) + // { + // var pt = tr.Editor.GetPoint("qudian"); + // if (pt.Status == PromptStatus.OK) + // { + // pts.Add(pt.Value); + // tr.CurrentSpace.AddEntity(new DBPoint(pt.Value)); + // } + // else + // { + // flag = false; + // } + + // } + + // var ptt = ConvexHull.GetConvexHull(pts); + + // Polyline pl = new Polyline(); + // for (int i = 0; i < ptt.Count; i++) + // { + // pl.AddVertexAt(i, ptt[i].Point2d(), 0, 0, 0); + // } + //// pl.AddVertexAt(0, new Point2d(0, 0), 0, 0, 0); + //// pl.AddVertexAt(1, new Point2d(10, 10), 0, 0, 0); + //// pl.AddVertexAt(2, new Point2d(20, 20), 0, 0, 0); + //// pl.AddVertexAt(3, new Point2d(30, 30), 0, 0, 0); + //// pl.AddVertexAt(4, new Point2d(40, 40), 0, 0, 0); + // pl.Closed = true; + // pl.Color = Color.FromColorIndex(ColorMethod.ByColor, 6); + // tr.CurrentSpace.AddEntity(pl); + + // var a1 = GeometryEx.GetArea(new Point2d(0, 0), new Point2d(1, 0), new Point2d(1, 1)); + // var a2 = ConvexHull.cross(new Point3d(0, 0, 0), new Point3d(1, 0, 0), new Point3d(1, 1, 0)); + // tr.Editor.WriteMessage(a1.ToString()); + // tr.Editor.WriteMessage(a2.ToString()); + + + // var vec1 = new Vector2d(1, 1); + // var vec2 = new Vector2d(-1, 1); + + // var vec3 = vec1.GetPerpendicularVector(); + // var vec4 = vec2.GetPerpendicularVector(); + + // var area1 = vec2.DotProduct(vec1.GetPerpendicularVector()); + // var area2 = vec1.DotProduct(vec2.GetPerpendicularVector()); + + // var area3 = vec2.DotProduct(vec1); + // var area4 = vec1.DotProduct(vec2); + + var area5 = GeometryEx.GetArea(new List { new Point2d(0, 0), new Point2d(1, 1), new Point2d(-1, 1) }); + + var area6 = GeometryEx.GetArea(new List { new Point2d(0, 0), new Point2d(-1, 1), new Point2d(1, 1) }); + // Env.Editor.WriteMessage($"vec1 的法向量= {vec3} \n"); + // Env.Editor.WriteMessage($"vec2 的法向量= {vec4} \n"); + + // Env.Editor.WriteMessage($"vec2 点乘 vec1的法向量= {area1} \n"); + // Env.Editor.WriteMessage($"vec1 点乘 vec2的法向量= {area2} \n"); + + // Env.Editor.WriteMessage($"vec2 点乘 vec1= {area3} \n"); + // Env.Editor.WriteMessage($"vec1 点乘 vec2= {area4} \n"); + + Env.Editor.WriteMessage($"点集的有向面积:{area5} \n"); + Env.Editor.WriteMessage($"点集的有向面积:{area6} \n"); + } +} \ No newline at end of file diff --git a/tests/TestShared/TestCurve.cs b/tests/TestShared/TestCurve.cs new file mode 100644 index 0000000..fd75698 --- /dev/null +++ b/tests/TestShared/TestCurve.cs @@ -0,0 +1,324 @@ +namespace Test; + +public class TestGraph +{ + [CommandMethod(nameof(Test_PointInDict))] + public void Test_PointInDict() + { + var pt1 = new Point3d(0.0255, 0.452, 0); + var pt2 = new Point3d(0.0255001, 0.452003, 0); + var pt3 = new Point3d(0.0255002, 0.4520001, 0); + var pt4 = new Point3d(0.0255450, 0.45287893, 0); + var pt5 = new Point3d(0.02554935, 0.452092375, 0); + var dict = new Dictionary + { + { pt1, 1 }, + { pt2, 2 }, + { pt3, 3 }, + { pt4, 4 }, + { pt5, 5 } + }; + Env.Print(dict[pt1]); + } + +#if false + [CommandMethod(nameof(Test_Graph1))] + public void Test_Graph1() + { + using DBTrans tr = new(); + var ents = Env.Editor.SSGet()?.Value?.GetEntities(); + if (ents == null) + return; + Tools.TestTimes2(1, "new", () => { + var res = ents!.GetAllCycle(); + + // res.ForEach((i, t) => t.ForWrite(e => e.ColorIndex = i + 1)); + Env.Print(res.Count()); + tr.CurrentSpace.AddEntity(res); + }); + } + + + [CommandMethod(nameof(Test_Graphspeed))] + public void Test_Graphspeed() + { + using DBTrans tr = new(); + var ents = Env.Editor.SSGet()?.Value?.GetEntities(); + if (ents == null) + return; + + var graph = new IFoxCAD.Cad.Graph(); // 为了调试先把图的访问改为internal + foreach (var curve in ents) + { + graph.AddEdge(curve!.GetGeCurve()); + } + + // 新建 dfs + var dfs = new DepthFirst(); +#if true + Tools.TestTimes2(100, "new", () => { + // 查询全部的 闭合环 + dfs.FindAll(graph); + }); + Tools.TestTimes2(1000, "new", () => { + // 查询全部的 闭合环 + dfs.FindAll(graph); + }); +#else + Tools.TestTimes2(100, "old", () => { + // 查询全部的 闭合环 + dfs.FindAll(graph); + }); + Tools.TestTimes2(1000, "old", () => { + // 查询全部的 闭合环 + dfs.FindAll(graph); + }); +#endif + // res.ForEach((i, t) => t.ForWrite(e => e.ColorIndex = i + 1)); + + // tr.CurrentSpace.AddEntity(res); + } +#endif +} + + + +public partial class TestCurve +{ + [CommandMethod(nameof(Test_CurveExtend))] + public void Test_CurveExtend() + { + using var tr = new DBTrans(); + var ent = Env.Editor.GetEntity("pick curve").ObjectId.GetObject(); + if (ent is Curve curve) + curve.ForWrite(e => e.Extend(e.EndParam + 1)); + + } + + + private Arc ToArc1(CircularArc2d a2d) + { + double startangle, endangle; + double refangle = a2d.ReferenceVector.Angle; + + if (a2d.IsClockWise) + { + startangle = -a2d.EndAngle + refangle; + endangle = -a2d.StartAngle + refangle; + } + else + { + startangle = a2d.StartAngle + refangle; + endangle = a2d.EndAngle + refangle; + } + + return + new Arc( + new Point3d(new Plane(), a2d.Center), + Vector3d.ZAxis, + a2d.Radius, + startangle, + endangle); + } + + +#if false + [CommandMethod(nameof(Test_Curve_ToArc))] + public void Test_Curve_ToArc() + { + using var tr = new DBTrans(); + var gearc = new CircularArc2d(new Point2d(0,0),new Point2d(0.5,0.5),new Point2d(1,0)); + var dbarc = gearc.ToArc(); + var dbarc1 = ToArc1(gearc); + dbarc.ColorIndex = 1; + tr.CurrentSpace.AddEntity(dbarc); + dbarc1.ColorIndex = 2; + tr.CurrentSpace.AddEntity(dbarc1); + + var gearc3 = new CircularArc3d(new(0,0,0),new(0.5,0.5,0),new Point3d(1,0,0)); + var dbarc3 = (Arc)Curve.CreateFromGeCurve(gearc3); + dbarc3.ColorIndex = 3; + tr.CurrentSpace.AddEntity(dbarc3); + + + + Polyline pl0 = new();//创建有圆弧的多段线 + + pl0.AddVertexAt(0, new(-520, 200), -0.74, 0, 0); + pl0.AddVertexAt(1, new(-100, 140), 0.52, 0, 0); + pl0.AddVertexAt(2, new(16, -120), -0.27, 0, 0); + pl0.AddVertexAt(3, new(400, -130), 0.75, 0, 0); + pl0.AddVertexAt(4, new(450, 200), -0.69, 0, 0); + tr.CurrentSpace.AddEntity(pl0); + + + for (int FFF = 0; FFF < pl0.NumberOfVertices; FFF++) + { + if (pl0.GetSegmentType(FFF) == SegmentType.Arc) + { + var bulge = pl0.GetBulgeAt(FFF); + + //将 CircularArc2d 转为Arc 颜色为红 + CircularArc2d arc2d = pl0.GetArcSegment2dAt(FFF); + + Arc arc = arc2d.ToArc(); + if (bulge < 0) arc.ReverseCurve(); + arc.ColorIndex = 1; + tr.CurrentSpace.AddEntity(arc); + Env.Printl($"arc的ge:ReferenceVector:{MathEx.ConvertRadToDeg(arc2d.ReferenceVector.Angle)}"); + Env.Printl($"arc的ge:顺时针:{arc2d.IsClockWise}"); + Env.Printl($"arc的ge:起点角度:{MathEx.ConvertRadToDeg(arc2d.StartAngle)},终点角度:{MathEx.ConvertRadToDeg(arc2d.EndAngle)}"); + Env.Printl($"arc的db:起点角度:{MathEx.ConvertRadToDeg(arc.StartAngle)},终点角度:{MathEx.ConvertRadToDeg(arc.EndAngle)}"); + + //将 CircularArc2d 转为Arc 颜色为黄 + CircularArc2d arc2d1 = pl0.GetArcSegment2dAt(FFF); + Arc arc1 = ToArc1(arc2d1); + if (bulge < 0) arc1.ReverseCurve(); + arc1.ColorIndex = 2; + tr.CurrentSpace.AddEntity(arc1); + Env.Printl($"arc1的ge:ReferenceVector:{MathEx.ConvertRadToDeg(arc2d1.ReferenceVector.Angle)}"); + Env.Printl($"arc的ge:顺时针:{arc2d1.IsClockWise}"); + Env.Printl($"arc1的ge:起点角度:{MathEx.ConvertRadToDeg(arc2d1.StartAngle)} ,终点角度: {MathEx.ConvertRadToDeg(arc2d1.EndAngle)}"); + Env.Printl($"arc1的db:起点角度:{MathEx.ConvertRadToDeg(arc1.StartAngle)} ,终点角度: {MathEx.ConvertRadToDeg(arc1.EndAngle)}"); + + //将 CircularArc3d 转为Arc 颜色为黄色 + CircularArc3d arc3d = pl0.GetArcSegmentAt(FFF); + Arc arc2 = arc3d.ToArc(); + + arc2.ColorIndex = 3; + tr.CurrentSpace.AddEntity(arc2); + Env.Printl($"arc2的ge:ReferenceVector:{MathEx.ConvertRadToDeg(arc3d.ReferenceVector.AngleOnPlane(new Plane()))}"); + Env.Printl($"arc2的ge:起点角度:{MathEx.ConvertRadToDeg(arc3d.StartAngle)} ,终点角度: {MathEx.ConvertRadToDeg(arc3d.EndAngle)}"); + Env.Printl($"arc2的db:起点角度:{MathEx.ConvertRadToDeg(arc2.StartAngle)} ,终点角度: {MathEx.ConvertRadToDeg(arc2.EndAngle)}"); + +/* + + +arc的ge: ReferenceVector:154.872779886857 +arc的ge: 顺时针:True +arc的ge:起点角度:0,终点角度:146.005764482025 +arc的db: 起点角度:334.872779886857,终点角度:120.878544368882 +arc1的ge: ReferenceVector:154.872779886857 +arc的ge: 顺时针:True +arc1的ge:起点角度:0 ,终点角度: 146.005764482025 +arc1的db: 起点角度:334.872779886857 ,终点角度: 120.878544368882 +arc2的ge: ReferenceVector:154.872779886857 +arc2的ge: 起点角度:0 ,终点角度: 146.005764482025 +arc2的db: 起点角度:25.1272201131434 ,终点角度: 171.132984595169 + + +arc的ge: ReferenceVector:149.095360016814 +arc的ge: 顺时针:False +arc的ge:起点角度:0,终点角度:109.897726505109 +arc的db: 起点角度:149.095360016814,终点角度:258.993086521922 +arc1的ge: ReferenceVector:149.095360016814 +arc的ge: 顺时针:False +arc1的ge:起点角度:0 ,终点角度: 109.897726505109 +arc1的db: 起点角度:149.095360016814 ,终点角度: 258.993086521922 +arc2的ge: ReferenceVector:149.095360016814 +arc2的ge: 起点角度:0 ,终点角度: 109.897726505109 +arc2的db: 起点角度:149.095360016814 ,终点角度: 258.993086521922 + + +arc的ge: ReferenceVector:118.727409809308 +arc的ge: 顺时针:True +arc的ge:起点角度:0,终点角度:60.4383004893619 +arc的db: 起点角度:298.727409809308,终点角度:359.16571029867 +arc1的ge: ReferenceVector:118.727409809308 +arc的ge: 顺时针:True +arc1的ge:起点角度:0 ,终点角度: 60.4383004893619 +arc1的db: 起点角度:298.727409809308 ,终点角度: 359.16571029867 +arc2的ge: ReferenceVector:118.727409809308 +arc2的ge: 起点角度:0 ,终点角度: 60.4383004893619 +arc2的db: 起点角度:61.2725901906918 ,终点角度: 121.710890680054 + + +arc的ge: ReferenceVector:277.644556524148 +arc的ge: 顺时针:False +arc的ge:起点角度:0,终点角度:147.479590583376 +arc的db: 起点角度:277.644556524148,终点角度:65.124147107524 +arc1的ge: ReferenceVector:277.644556524148 +arc的ge: 顺时针:False +arc1的ge:起点角度:0 ,终点角度: 147.479590583376 +arc1的db: 起点角度:277.644556524148 ,终点角度: 65.124147107524 +arc2的ge: ReferenceVector:277.644556524148 +arc2的ge: 起点角度:0 ,终点角度: 147.479590583376 +arc2的db: 起点角度:277.644556524148 ,终点角度: 65.124147107524 + + + + + + +*/ + } + } + + } +#endif +} + + +public partial class TestCurve +{ + [CommandMethod(nameof(Test_BreakCurve))] + public void Test_BreakCurve() + { + using DBTrans tr = new(); + var ents = Env.Editor.SSGet()?.Value.GetEntities(); + if (ents is null) + return; + var tt = CurveEx.BreakCurve(ents.ToList()!); + tt.ForEach(t => t.ForWrite(e => e.ColorIndex = 1)); + tr.CurrentSpace.AddEntity(tt); + } + + [CommandMethod(nameof(Test_CurveCurveIntersector3d))] + public void Test_CurveCurveIntersector3d() + { + using DBTrans tr = new(); + var ents = Env.Editor.SSGet()? + .Value.GetEntities() + .Select(e => e?.ToCompositeCurve3d()).ToList(); + if (ents == null) + return; + + var cci3d = new CurveCurveIntersector3d(); + for (int i = 0; i < ents.Count; i++) + { + var gc1 = ents[i]; + var int1 = gc1?.GetInterval(); + // var pars1 = paramss[i]; + for (int j = i; j < ents.Count; j++) + { + var gc2 = ents[j]; + // var pars2 = paramss[j]; + var int2 = gc2?.GetInterval(); + cci3d.Set(gc1, gc2, int1, int2, Vector3d.ZAxis); + var d = cci3d.OverlapCount(); + var a = cci3d.GetIntersectionRanges(); + Env.Print($"{a[0].LowerBound}-{a[0].UpperBound} and {a[1].LowerBound}-{a[1].UpperBound}"); + for (int m = 0; m < d; m++) + { + var b = cci3d.GetOverlapRanges(m); + Env.Print($"{b[0].LowerBound}-{b[0].UpperBound} and {b[1].LowerBound}-{b[1].UpperBound}"); + } + + for (int k = 0; k < cci3d.NumberOfIntersectionPoints; k++) + { + // var a = cci3d.GetOverlapRanges(k); + // var b = cci3d.IsTangential(k); + // var c = cci3d.IsTransversal(k); + // var d = cci3d.OverlapCount(); + // var e = cci3d.OverlapDirection(); + var pt = cci3d.GetIntersectionParameters(k); + var pts = cci3d.GetIntersectionPoint(k); + Env.Print(pts); + } + } + } + // var tt = CurveEx.Topo(ents.ToList()); + // tt.ForEach(t => t.ForWrite(e => e.ColorIndex = 1)); + // tr.CurrentSpace.AddEntity(tt); + } +} \ No newline at end of file diff --git a/tests/TestShared/TestDBTrans.cs b/tests/TestShared/TestDBTrans.cs new file mode 100644 index 0000000..41eb67d --- /dev/null +++ b/tests/TestShared/TestDBTrans.cs @@ -0,0 +1,203 @@ +namespace Test; + +public class TestTrans +{ + [CommandMethod(nameof(Test_DBTrans))] + public void Test_DBTrans() + { + using DBTrans tr = new(); + if (tr.Editor is null) + return; + tr.Editor.WriteMessage("\n测试 Editor 属性是否工作!"); + tr.Editor.WriteMessage("\n----------开始测试--------------"); + tr.Editor.WriteMessage("\n测试document属性是否工作"); + if (tr.Document == Getdoc()) + { + tr.Editor.WriteMessage("\ndocument 正常"); + } + tr.Editor.WriteMessage("\n测试database属性是否工作"); + if (tr.Database == Getdb()) + { + tr.Editor.WriteMessage("\ndatabase 正常"); + } + } + + private static Database Getdb() + { + var db = Acaop.DocumentManager.MdiActiveDocument.Database; + return db; + } + + private static Document Getdoc() + { + var doc = Acaop.DocumentManager.MdiActiveDocument; + return doc; + } + + + + + [CommandMethod(nameof(CmdTest_DBTransActiveOpenDwg), CommandFlags.Session)] + public static void CmdTest_DBTransActiveOpenDwg() + { + using DBTrans tr = new(@"D:\桌面\AA.dwg", activeOpen: true); + } + + [CommandMethod(nameof(CmdTest_ForEachDemo))] + public static void CmdTest_ForEachDemo() + { + using DBTrans tr = new(); + + // 泛型扩展(用变量名来使用它) + tr.BlockTable.ForEach(action: (id) => { + //Debugger.Break();// 为什么cad工程不能断点进入呢? + id.Print(); + Console.WriteLine(id); + }); + + //tr.BlockTable.ForEach(asdad); + //void asdad(object id) + //{ + // id.Print(); + //} + + tr.BlockTable.ForEach(action: (id) => { + id.Print(); + }); + tr.BlockTable.ForEach(action: (id, state, index) => { + id.Print(); + }); + + // 符号表扩展(会顶替泛型扩展) + tr.BlockTable.ForEach((btr) => { // 预处理设置不进入ForEach函数体内 + btr.Print();// 此处可以设置断点 + }, OpenMode.ForRead, checkIdOk: true); + tr.BlockTable.ForEach((btr, state) => {// 预处理设置不进入ForEach函数体内 + btr.Print();// 此处可以设置断点 + }, OpenMode.ForRead, checkIdOk: true); + tr.BlockTable.ForEach((btr, state, index) => { // 预处理设置不进入ForEach函数体内 + btr.Print();// 此处可以设置断点 + }, OpenMode.ForRead, checkIdOk: true); + + // 修改:此处有缺陷:cad08会获取已经删除的块表记录,需要检查id.IsOk(),用ForEach代替 + // tr.BlockTable.Change("块表记录", btr => { + // }); + + // 修改:此处无缺陷 + tr.BlockTable.Change(tr.ModelSpace.ObjectId, modelSpace => { // 特性设置不进入函数体内 + var ents = modelSpace.GetEntities(); // 此处不会检查id.IsOk() + + modelSpace.ForEach(id => { // 利用遍历检查id.IsOk() + if (id.IsOk()) + id.Print(); + }); + }); + } + + + + // 后台:不存在路径的dwg会在桌面进行临时保存 + [CommandMethod(nameof(FileNotExist))] + public void FileNotExist() + { + using DBTrans tr = new("test.dwg"); + tr.Database.SaveFile((DwgVersion)24, false); + } + + // 前台:由于是弹出面板,此时路径不会起任何作用 + [CommandMethod(nameof(FileNotExist2))] + public void FileNotExist2() + { + using DBTrans tr = new(); + tr.Database.SaveFile(saveAsFile: "D:\\"); + } + + // 后台:只有路径,没有文件名 + [CommandMethod(nameof(FileNotExist3))] + public void FileNotExist3() + { + using DBTrans tr = new("D:\\"); + tr.Database.SaveDwgFile(); + + using DBTrans tr2 = new("D:\\"); + tr2.Database.SaveFile(saveAsFile: "D:\\"); + } + + + [CommandMethod(nameof(Test_SaveDwgFile))] + public void Test_SaveDwgFile() + { + string filename = @"C:\Users\vic\Desktop\test.dwg"; + using DBTrans tr = new(filename); + var circle = CircleEx.CreateCircle(new Point3d(10, 10, 0), 20)!; + tr.ModelSpace.AddEntity(circle); + // tr.Database.SaveAs(filename,DwgVersion.Current); + tr.Database.SaveDwgFile(); + } + [CommandMethod(nameof(Test_DBTransAbort))] + public void Test_DBTransAbort() + { + using DBTrans tr = new(); + var circle = CircleEx.CreateCircle(new Point3d(10, 10, 0), 20)!; + tr.ModelSpace.AddEntity(circle); + tr.Abort(); + // tr.Commit(); + } + + // AOP 应用 预计示例: + // 1. 无参数 + // [AOP] + // [CommandMethod(nameof(Test_AOP1))] + // public void TestAOP1() + // { + // // 不用 using DBTrans tr = new(); + // var tr = DBTrans.Top; + // tr.ModelSpace.AddCircle(new Point3d(0, 0, 0), 20); + // } + + // 2. 有参数 + // [AOP("file")] + // [CommandMethod(nameof(Test_AOP2))] + // public void TestAOP2() + // { + // // 不用 using var tr = new DBTrans(file); + // var tr = DBTrans.Top; + // tr.ModelSpace.AddCircle(new Point3d(0, 0, 0), 20); + // } + + + [CommandMethod(nameof(Test_TopTransaction))] + public void Test_TopTransaction() + { + // var pt = Env.Editor.GetPoint("pick pt:").Value; + // var pl = Env.Editor.GetEntity("pick pl").ObjectId; + + var tr1 = HostApplicationServices.WorkingDatabase.TransactionManager.TopTransaction; + using DBTrans tr2 = new(); + var tr3 = HostApplicationServices.WorkingDatabase.TransactionManager.TopTransaction; + var tr6 = Acaop.DocumentManager.MdiActiveDocument.TransactionManager.TopTransaction; + Env.Print(tr2.Transaction == tr3); + Env.Print(tr3 == tr6); + using DBTrans tr4 = new(); + var tr5 = HostApplicationServices.WorkingDatabase.TransactionManager.TopTransaction; + var tr7 = Acaop.DocumentManager.MdiActiveDocument.TransactionManager.TopTransaction; + Env.Print(tr4.Transaction == tr5); + Env.Print(tr5 == tr7); + var trm = HostApplicationServices.WorkingDatabase.TransactionManager; + + } + + [CommandMethod(nameof(Test_DBTrans_BlockCount))] + public void Test_DBTrans_BlockCount() + { + using var tr = new DBTrans(); + var i = tr.CurrentSpace + .GetEntities() + .Where(ent => ent.GetBlockName() == "自定义块"); + + var block = i.ToList()[0]; + Env.Print(i.Count()); + } + + +} \ No newline at end of file diff --git a/tests/TestShared/TestDBobject.cs b/tests/TestShared/TestDBobject.cs new file mode 100644 index 0000000..f0cb142 --- /dev/null +++ b/tests/TestShared/TestDBobject.cs @@ -0,0 +1,27 @@ + + +namespace TestShared +{ + public static class TestDBobject + { + [CommandMethod(nameof(TestForWrite))] + public static void TestForWrite() + { + using var tr = new DBTrans(); + var ent = Env.Editor.GetEntity("\npick entity"); + if (ent.Status is not PromptStatus.OK) return; + var entid = ent.ObjectId.GetObject()!; + Tools.TestTimes3(100000, "using:", i => { + using (entid.ForWrite()) + { + entid.ColorIndex = i % 7; + } + }); + Tools.TestTimes3(100000, "action:", i => { + entid.ForWrite(e => { + e.ColorIndex = i % 7; + }); + }); + } + } +} diff --git a/tests/TestShared/TestDwgFilerEx.cs b/tests/TestShared/TestDwgFilerEx.cs new file mode 100644 index 0000000..6513cda --- /dev/null +++ b/tests/TestShared/TestDwgFilerEx.cs @@ -0,0 +1,161 @@ +#if false +namespace Test; + +using DxfFiler = IFoxCAD.Cad.DxfFiler; + +public class CmdTestDwgFilerEx +{ + [CommandMethod(nameof(CmdTest_DwgFilerEx))] + public static void CmdTest_DwgFilerEx() + { + var dm = Acap.DocumentManager; + var doc = dm.MdiActiveDocument; + var db = doc.Database; + var ed = doc.Editor; + ed.WriteMessage("\n****测试,序列化图元"); + + var ssPsr = ed.SelectImplied();// 预选 + if (ssPsr.Status != PromptStatus.OK) + { + ssPsr = ed.GetSelection();// 手选 这里输入al会变成all,无法删除ssget的all关键字 + if (ssPsr.Status != PromptStatus.OK) + return; + } + + using DBTrans tr = new(); + var ids = ssPsr.Value.GetObjectIds(); + foreach (var id in ids) + { + if (!id.IsOk()) + continue; + var ent = tr.GetObject(id, OpenMode.ForRead); + if (ent is null) + continue; + var dwgFilerEx = new DwgFilerEx(ent); + ed.WriteMessage(Environment.NewLine + dwgFilerEx.ToString()); + } + } + + [CommandMethod(nameof(CmdTest_EntDxfout))] + public static void CmdTest_EntDxfout() + { + var dm = Acap.DocumentManager; + var doc = dm.MdiActiveDocument; + var db = doc.Database; + var ed = doc.Editor; + + // 定义选择集选项 + var pso = new PromptSelectionOptions + { + RejectObjectsOnLockedLayers = true, // 不选择锁定图层对象 + AllowDuplicates = true, // 不允许重复选择 + }; + var ssPsr = ed.GetSelection(pso);// 手选 这里输入al会变成all,无法删除ssget的all关键字 + if (ssPsr.Status != PromptStatus.OK) + return; + + using DBTrans tr = new(); + var ids = ssPsr.Value.GetObjectIds(); + foreach (var id in ids) + { + if (!id.IsOk()) + continue; + var ent = tr.GetObject(id, OpenMode.ForRead); + if (ent is null) + continue; + // ResultBuffer rbDxf = new(); + var filer = new DxfFiler(ent.UnmanagedObject, true);/// 这里有问题 + ent.DxfOut(filer); + } + } + + + [CommandMethod(nameof(CmdTest_TextOut))] + public static void CmdTest_TextOut() + { + var dm = Acap.DocumentManager; + var doc = dm.MdiActiveDocument; + var db = doc.Database; + var ed = doc.Editor; + +#if true + var peo1 = new PromptEntityOptions(Environment.NewLine + "点选源TCH_WIREDIM2:") + { + AllowObjectOnLockedLayer = false, + AllowNone = false + }; + var gt1 = ed.GetEntity(peo1); + if (gt1.Status != PromptStatus.OK) + return; +#else + var peo2 = new PromptEntityOptions(Environment.NewLine + "点选目标TCH_WIREDIM2:") + { + AllowObjectOnLockedLayer = false, + AllowNone = false + }; + var gt2 = ed.GetEntity(peo2); + if (gt2.Status != PromptStatus.OK) + return; +#endif + + using DBTrans tr = new(); + var dwgFilerEx = new DwgFilerEx(); + var bText = tr.GetObject(gt1.ObjectId, OpenMode.ForRead); + if (bText is null) + return; + + // DwgFilerEx.StringList[0] = "1@2@3@4@5@6@7@"; + // 复制 TCH_WIREDIM2 不行,TEXT 也不行,直接崩溃。line等线就没事 + bText.DwgOut(dwgFilerEx.DwgFiler); + + int testNum = 1 | 2 | 4 | 8; + + if ((testNum & 1) == 1) + { + // 错误,原地克隆也是不行的,它会生成在了模型中. + var sIds = new List + { + bText.ObjectId + }; + // 克隆到目标块表内 + using ObjectIdCollection bindIds = new(sIds.ToArray()); + using IdMapping map = new(); + + tr.CurrentSpace.DeepCloneEx(bindIds, map); + var newTexts = map.GetValues().GetObject(); + newTexts.ForEach(nText => { + if (nText == null) + return; + // 通过上面的克隆就已经在块表上面了.所以下面的设置也跟设置到已有图元上一样报错. + nText.UpgradeOpen(); + nText.DwgIn(dwgFilerEx); + tr.CurrentSpace.AddEntity(nText); + nText.DowngradeOpen(); + }); + } + if ((testNum & 2) == 2) + { + // 出错 + // 直接设置 + bText.DwgIn(dwgFilerEx); + } + if ((testNum & 4) == 4) + { + // 出错 + // 此时是内存中对象.... + var nText = (DBText)bText.Clone(); + nText.DwgIn(dwgFilerEx); + tr.CurrentSpace.AddEntity(nText); + } + if ((testNum & 8) == 8) + { + // 新对象相当于克隆,是ok的 + DBText nText = new(); + nText.SetDatabaseDefaults(); + nText.DwgIn(dwgFilerEx); + tr.CurrentSpace.AddEntity(nText); + } + } +} + +#endif \ No newline at end of file diff --git a/tests/TestShared/TestDwgMark.cs b/tests/TestShared/TestDwgMark.cs new file mode 100644 index 0000000..cf0d712 --- /dev/null +++ b/tests/TestShared/TestDwgMark.cs @@ -0,0 +1,11 @@ +namespace Test; +using IFoxCAD.Cad; +public class TestDwgMark { + [CommandMethod(nameof(DwgMarktest))] + public void DwgMarktest() { + FileInfo file = new FileInfo(@"D:\TEST\1.dwg"); + DwgMark.AddMark(file, 0x4D); + DwgMark.RemoveMark(file); + int A = DwgMark.GetMark(file); + } +} \ No newline at end of file diff --git a/tests/TestShared/TestEditor.cs b/tests/TestShared/TestEditor.cs new file mode 100644 index 0000000..5f83345 --- /dev/null +++ b/tests/TestShared/TestEditor.cs @@ -0,0 +1,87 @@ +namespace Test; + +public class Testeditor +{ + [CommandMethod(nameof(Test_Editor))] + public void Test_Editor() + { + var pts = new List + { + new Point2d(0,0), + new Point2d(0,1), + new Point2d(1,1), + new Point2d(1,0) + }; + var res = EditorEx.GetLines(pts, false); + var res1 = EditorEx.GetLines(pts, true); + var res2 = pts.Select(pt => new TypedValue((int)LispDataType.Point2d, pt)).ToList(); + + Editor ed = Acap.DocumentManager.MdiActiveDocument.Editor; + var pt = ed.GetPoint("qudiam", new Point3d(0, 0, 0)); + var d = ed.GetDouble("qudoule"); + var i = ed.GetInteger("quint"); + var s = ed.GetString("qustr"); + Env.Editor.WriteMessage(""); + } + [CommandMethod(nameof(Test_Zoom))] + public void Test_Zoom() + { + using DBTrans tr = new(); + var res = Env.Editor.GetEntity("\npick ent:"); + if (res.Status == PromptStatus.OK) + Env.Editor.ZoomObject(res.ObjectId.GetObject()!); + } + [CommandMethod(nameof(Test_ZoomExtents))] + public void Test_ZoomExtents() + { + // using DBTrans tr = new(); + // var res = Env.Editor.GetEntity("\npick ent:"); + // if (res.Status == PromptStatus.OK) + // { + // Env.Editor.ZoomObject(res.ObjectId.GetObject()); + // } + + Env.Editor.ZoomExtents(); + } + + [CommandMethod(nameof(Test_Zoom_1))] + public void Test_Zoom_1() + { + Env.Editor.Zoom(new(0, 0, 0),200,200); + } + [CommandMethod(nameof(Test_Zoom_2))] + public void Test_Zoom_2() + { + Env.Editor.ZoomWindow(new Point3d(-100,-100,0),new(100,100,0)); + } + + [CommandMethod(nameof(Test_Ssget))] + public void Test_Ssget() + { + + var keyword = new Dictionary + { + { "D", ("你好", () => { Env.Print("this is c"); }) }, + { "B", ("hello", () => { Env.Print("this is b"); }) } + }; + + var ss = Env.Editor.SSGet(/*":S", */ messages: ("get", "del" ), + keywords: keyword); + Env.Print(ss!); + } + + [CommandMethod(nameof(Test_ExportWMF), CommandFlags.Modal | CommandFlags.UsePickSet)] + public void Test_ExportWMF() + { + var psr = Env.Editor.SelectImplied();// 预选 + if (psr.Status != PromptStatus.OK) + psr = Env.Editor.GetSelection();// 手选 + if (psr.Status != PromptStatus.OK) + return; + + var ids = psr.Value.GetObjectIds(); + // acad21(acad08没有)先选择再执行..会让你再选择一次 + // 而且只发生在启动cad之后第一次执行. + Env.Editor.ComExportWMF(@"C:\Users\vic\Desktop\aaa.dwg", ids); + } +} \ No newline at end of file diff --git a/Test/TestAddEntity.cs b/tests/TestShared/TestEntity/TestAddEntity.cs similarity index 93% rename from Test/TestAddEntity.cs rename to tests/TestShared/TestEntity/TestAddEntity.cs index df868d1..920e6e0 100644 --- a/Test/TestAddEntity.cs +++ b/tests/TestShared/TestEntity/TestAddEntity.cs @@ -1,5 +1,4 @@ -namespace Test; - +namespace Test; public class TestAddEntity { @@ -40,14 +39,14 @@ public void Test_AddEntities() Line line1 = new(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); Line line2 = new(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); Line line3 = new(new Point3d(1, 1, 0), new Point3d(3, 3, 0)); - var circle = CircleEx.CreateCircle(new(0,0,0),10); + Circle circle = new(); // 一次性添加到当前空间 tr.CurrentSpace.AddEntity(line2, line2, line3, circle); // 或者可以传入个列表 List lines = [line1, line2, line3]; tr.CurrentSpace.AddEntity(lines); // 或者可以传入个数组 - Entity[] lines1 = [line1, line2, line3]; + Line[] lines1 = [line1, line2, line3]; tr.CurrentSpace.AddEntity(lines1); // 图元数组 Entity[] lines2 = [line1, line2, line3, circle]; @@ -81,9 +80,9 @@ public void Test_AddCircle() public void Test_AddArc() { using DBTrans tr = new(); - var arc1 = ArcEx.CreateArcSCE(new Point3d(2, 0, 0), new Point3d(0, 0, 0), new Point3d(0, 2, 0));// 起点,圆心,终点 - var arc2 = ArcEx.CreateArc(new Point3d(4, 0, 0), new Point3d(0, 0, 0), Math.PI / 2); // 起点,圆心,弧度 - var arc3 = ArcEx.CreateArc(new Point3d(1, 0, 0), new Point3d(0, 0, 0), new Point3d(0, 1, 0)); // 起点,圆上一点,终点 + Arc arc1 = ArcEx.CreateArcSCE(new Point3d(2, 0, 0), new Point3d(0, 0, 0), new Point3d(0, 2, 0));// 起点,圆心,终点 + Arc arc2 = ArcEx.CreateArc(new Point3d(4, 0, 0), new Point3d(0, 0, 0), Math.PI / 2); // 起点,圆心,弧度 + Arc arc3 = ArcEx.CreateArc(new Point3d(1, 0, 0), new Point3d(0, 0, 0), new Point3d(0, 1, 0)); // 起点,圆上一点,终点 tr.CurrentSpace.AddEntity(arc1, arc2, arc3); } diff --git a/tests/TestShared/TestEnv.cs b/tests/TestShared/TestEnv.cs new file mode 100644 index 0000000..d1df3b8 --- /dev/null +++ b/tests/TestShared/TestEnv.cs @@ -0,0 +1,184 @@ +namespace Test; + +public class Testenv +{ + [CommandMethod(nameof(Test_Enum))] + public void Test_Enum() + { + Env.CmdEcho = true; + } + [CommandMethod(nameof(Test_Enum1))] + public void Test_Enum1() + { + Env.CmdEcho = false; + } + + [CommandMethod(nameof(Test_Dimblk))] + public void Test_Dimblk() + { + Env.Dimblk = Env.DimblkType.Dot; + Env.Print(Env.Dimblk); + Env.Print(Env.GetDimblkId(Env.DimblkType.Dot)); + Env.Dimblk = Env.DimblkType.Default; + Env.Print(Env.Dimblk); + Env.Print(Env.GetDimblkId(Env.DimblkType.Default)); + Env.Dimblk = Env.DimblkType.Oblique; + Env.Print(Env.Dimblk); + Env.Print(Env.GetDimblkId(Env.DimblkType.Oblique)); + Env.Dimblk = Env.DimblkType.ArchTick; + Env.Print(Env.Dimblk); + Env.Print(Env.GetDimblkId(Env.DimblkType.ArchTick)); + } + [CommandMethod(nameof(Test_Dimblk1))] + public void Test_Dimblk1() + { + var dim = Env.Dimblk; + Env.Editor.WriteMessage(dim.ToString()); + } + + [CommandMethod(nameof(Test_Osmode))] + public void Test_Osmode() + { + // 设置osmode变量,多个值用逻辑或 + Env.OSMode = Env.OSModeType.End | Env.OSModeType.Middle; + // 也可以直接写数值,进行强转 + Env.OSMode = (Env.OSModeType)5179; + // 追加模式 + Env.OSMode |= Env.OSModeType.Center; + // 检查是否有某个模式 + var os = Env.OSMode.Include(Env.OSModeType.Center); + // 取消某个模式 + Env.OSMode ^= Env.OSModeType.Center; + Env.Editor.WriteMessage(Env.OSMode.ToString()); + } + [CommandMethod(nameof(Test_Osmode1))] + public void Test_Osmode1() + { + var dim = Env.OSMode; + Env.Editor.WriteMessage(dim.ToString()); + } +#if false + [CommandMethod(nameof(Test_Cadver))] + public void Test_Cadver() + { + // Env.Print(AcadVersion.Versions); + AcadVersion.Versions.ForEach(v => Env.Print(v)); + AcadVersion.FromApp(Acap.AcadApplication)?.Print(); + 1.Print(); + "1".Print(); + } +#endif + [CommandMethod(nameof(Test_GetVar))] + public void Test_GetVar() + { + // test getvar + var a = Env.GetVar("dbmod"); + a.Print(); + Env.SetVar("dbmod1", 1); + } + + + + //[CommandMethod(nameof(Test_DwgVersion))] + //public void TestDwgVersion() + //{ + // string filename = @"C:\Users\vic\Desktop\test.dwg"; + // var a = Helper.GetCadFileVersion(filename); + // a.Print(); + // ((DwgVersion)a).Print(); + //} + + +#if !zcad + // 通过此功能获取全部变量,尚不清楚此处如何设置,没有通过测试 + [CommandMethod(nameof(Test_GetvarAll))] + public static void Test_GetvarAll() + { + GetvarAll(); + } + + public static Dictionary GetvarAll() + { + var dict = new Dictionary(); + var en = new SystemVariableEnumerator(); + while (en.MoveNext()) + { + Console.WriteLine(en.Current.Name + "-----" + en.Current.Value);// Value会出现异常 + dict.Add(en.Current.Name, en.Current.Value); + } + return dict; + } +#endif + + [CommandMethod(nameof(Test_GetEnv))] + public static void Test_GetEnv() + { + var dir = Env.GetEnv("PrinterConfigDir"); + Env.Printl("pc3打印机位置:" + dir); + + Env.SetEnv("abc", "656"); + + var obj = Env.GetEnv("abc"); + Env.Printl("GetEnv:" + obj); + + Env.Printl("GetEnv:" + Env.GetEnv("abc")); + Env.Printl("GetEnv PATH:" + Env.GetEnv("PATH")); + + Env.Printl($"getenv-acad: {Env.GetEnv("ACAD")}"); + Env.Printl($"getvar-acad: {Env.GetVar("TRUSTEDPATHS")}"); + Env.Printl($"getenv-TRUSTEDPATHS: {Env.GetEnv("TRUSTEDPATHS")}"); + Env.Printl($"getenv-osmode: {Env.GetEnv("osmode")}"); + Env.Printl($"getvar-osmode: {Env.GetVar("osmode")}"); + } + [CommandMethod(nameof(Test_AppendPath))] + public static void Test_AppendPath() + { + Directory.Exists(@"C:\Folder4").Print(); + Env.AppendSupportPath(@"C:\Folder4", @"C:\Folder5", @"C:\Folder6"); + // Env.AppendTrustedPath(@"c:\a\x",@"c:\a\c"); + // AppendSupportPath(@"c:\a\c"); + Env.GetEnv("ACAD").Print(); + // Env.SetEnv("ACAD", @"C:\Folder1;"+Env.GetEnv("ACAD")); + Env.GetEnv("ACAD").Contains(@"C:\Folder1").Print(); + + } + + [CommandMethod(nameof(Test_RemovePath))] + public static void Test_RemovePath() + { + // var acad = Acaop.TryGetSystemVariable("ACAD").ToString(); + // acad.Print(); + // Acaop.SetSystemVariable("ACAD", acad + @";c:\a\x"); + Env.GetEnv("ACAD").Print(); + Env.RemoveSupportPath(); + // Env.RemoveTrustedPath(@"c:\a\x"); + Env.GetEnv("ACAD").Print(); + } + + public static void AppendSupportPath(string path) + { + + string key = HostApplicationServices.Current.UserRegistryProductRootKey; + // 计算机\HKEY_CURRENT_USER\SOFTWARE\Autodesk\AutoCAD\R24.0\ACAD-4101:804 + var ackey = Registry.CurrentUser.OpenSubKey($@"{key}\Profiles") ?? null; + + if (ackey != null) + { + var listkey = ackey.GetSubKeyNames(); + foreach (var item in listkey) + { + var acadkey = ackey.OpenSubKey($@"{item}\General", true); + const string name = "ACAD"; + var str = acadkey?.GetValue(name)?.ToString(); + if (str != null && !str.ToLower().Contains(path.ToLower())) + { + acadkey?.SetValue(name, $@"{str}{path};"); + } + } + } + + ackey?.Close(); + } + + +} \ No newline at end of file diff --git a/tests/TestShared/TestExtents.cs b/tests/TestShared/TestExtents.cs new file mode 100644 index 0000000..96c04db --- /dev/null +++ b/tests/TestShared/TestExtents.cs @@ -0,0 +1,108 @@ +namespace TestShared; + +public class TestExtents +{ + [CommandMethod(nameof(Test_BlockExtents))] + public void Test_BlockExtents() + { + using var tr = new DBTrans(); + var ent = Env.Editor.GetEntity("pick the entity"); + if (ent.Status != PromptStatus.OK ) + { + return; + } + + var block = ent.ObjectId.GetObject(); + if (block != null && block.Bounds.HasValue) + { + var extent = block.GeometricExtents; + List pts = [ + extent.MinPoint, + new Point3d(extent.MinPoint.X,extent.MaxPoint.Y,0), + extent.MaxPoint, + new Point3d(extent.MaxPoint.X,extent.MinPoint.Y,0), + + ]; + + tr.CurrentSpace.AddEntity(pts.CreatePolyline(action: e => e.ColorIndex = 1)); + + if (block is BlockReference block1) + { + var extents = block1.GeometryExtentsBestFit(); + List pts1 = + [ + extents.MinPoint, + new Point3d(extents.MinPoint.X, extents.MaxPoint.Y, 0), + extents.MaxPoint, + new Point3d(extents.MaxPoint.X, extents.MinPoint.Y, 0), + ]; + tr.CurrentSpace.AddEntity(pts.CreatePolyline(action: e => e.ColorIndex = 2)); + + var extents2 = block1.GetBoundingBoxEx(); + tr.CurrentSpace.AddEntity(pts.CreatePolyline(action: e => e.ColorIndex = 3)); + + // 此处是计算块定义的包围盒,不是块参照的,所以一般情况下不需要使用。 + var ext = new Extents3d(); + ext.AddBlockExtents(block1.BlockTableRecord.GetObject()); + tr.CurrentSpace.AddEntity(ext.CreatePolyline(action: e => e.ColorIndex = 4)); + } + + + } + } + + [CommandMethod(nameof(Test_entextents))] + public void Test_entextents() + { + using var tr = new DBTrans(); + var a = Env.Editor.GetSelection().Value. + GetEntities(OpenMode.ForWrite); + foreach (var e in a) + { + var b = e.Bounds.HasValue; //获取是否有包围盒 + var name = e.ObjectId.ObjectClass.DxfName; + Env.Print($"{name}是否有包围盒-" + b); + if (b) + { + tr.CurrentSpace.AddEntity(e.Bounds!.Value.CreatePolyline(action: e => + { + e.ColorIndex = 4; + e.Closed = true; + })); + var ext = e.GetBoundingBoxEx(); + if (ext.HasValue) + { + tr.CurrentSpace.AddEntity( + ext.Value.Extents3d.CreatePolyline(action: e => + { + e.ColorIndex = 5; + e.Closed = true; + })); + } + + if (e is Curve spline) + { + var ge = spline.GetGeCurve(); + var box = ge.BoundBlock; + List lst = + [ + box.BasePoint, + box.BasePoint + box.Direction1, + box.BasePoint + box.Direction2, + box.BasePoint + box.Direction3, + ]; + tr.CurrentSpace.AddEntity(lst.CreatePolyline(action: e => + { + e.ColorIndex = 6; + e.Closed = true; + })); + } + + } + + + + + } + } +} \ No newline at end of file diff --git a/tests/TestShared/TestFileDatabase.cs b/tests/TestShared/TestFileDatabase.cs new file mode 100644 index 0000000..e5c58c3 --- /dev/null +++ b/tests/TestShared/TestFileDatabase.cs @@ -0,0 +1,28 @@ +namespace Test; + +/************************************************************** +*作者:Leon +*创建时间:2022/2/11 9:55:32 +**************************************************************/ + +public class TestFileDatabase +{ + [CommandMethod(nameof(Test_FileDatabaseInit))] + public void Test_FileDatabaseInit() + { + try + { + var fileName = @"C:\Users\Administrator\Desktop\合并详图测试BUG.dwg"; + using DBTrans trans = new(fileName); + trans.ModelSpace.AddEntity(new Line(new(0, 0, 0), new(1000, 1000, 0))); + if (trans.Document is not null && trans.Document.IsActive) + trans.Document.SendStringToExecute("_qsave\n", false, true, true); + else + trans.Database.SaveAs(fileName, (DwgVersion)27); + } + catch (System.Exception e) + { + System.Windows.MessageBox.Show(e.Message); + } + } +} \ No newline at end of file diff --git a/tests/TestShared/TestHatchinfo.cs b/tests/TestShared/TestHatchinfo.cs new file mode 100644 index 0000000..1b765e5 --- /dev/null +++ b/tests/TestShared/TestHatchinfo.cs @@ -0,0 +1,18 @@ +namespace Test; + +public class TestHatchinfo +{ + [CommandMethod(" TestHatchInfo")] + public void TestHatchInfo() + { + using var tr = new DBTrans(); + var sf = new SelectionFilter(new TypedValue[] { new TypedValue(0, "*line,circle,arc") }); + var ids = Env.Editor.SSGet(null, sf).Value?.GetObjectIds(); + if (ids.Count() > 0) + { + HatchInfo hf = new HatchInfo(ids!, false, null, 1, 0).Mode2UserDefined(); + hf.Build(tr.CurrentSpace); + } + } +} + diff --git a/tests/TestShared/TestId.cs b/tests/TestShared/TestId.cs new file mode 100644 index 0000000..57f19cf --- /dev/null +++ b/tests/TestShared/TestId.cs @@ -0,0 +1,72 @@ +namespace Test; + +public class Testid +{ + [CommandMethod(nameof(Test_Id))] + public void Test_Id() + { + using DBTrans tr = new(); + Line line = new(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); + tr.CurrentSpace.AddEntity(line); + tr.Dispose(); + + var res = Env.Editor.GetEntity("\npick ent:"); + if (res.Status == PromptStatus.OK) + { + res.ObjectId.Erase(); + } + // using (var tr = new DBTrans()) + // { + // var res = Env.Editor.GetEntity("\npick ent:"); + // if(res.Status == PromptStatus.OK) + // { + // res.ObjectId.Erase(); + // } + + // } + } + + [CommandMethod(nameof(Test_MyCommand))] + public void Test_MyCommand() + { + using DBTrans dbtrans = new(Env.Document, true, false); + using var trans = Env.Database.TransactionManager.StartTransaction(); + + var l1 = new Line(new Point3d(0, 0, 0), new Point3d(100, 100, 0)); + var blkred = trans.GetObject(Env.Database.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord; + blkred?.AppendEntity(l1); + trans.AddNewlyCreatedDBObject(l1, true); + trans.Commit(); + // dbtrans.Dispose(); + } + [CommandMethod(nameof(Test_TextStyle))] + public void Test_TextStyle() + { + using DBTrans tr = new(); + tr.TextStyleTable.Add("宋体", "宋体.ttf", 0.8); + + tr.TextStyleTable.Add("宋体1", FontTTF.宋体, 0.8); + tr.TextStyleTable.Add("仿宋体", FontTTF.仿宋, 0.8); + tr.TextStyleTable.Add("fsgb2312", FontTTF.仿宋GB2312, 0.8); + tr.TextStyleTable.Add("arial", FontTTF.Arial, 0.8); + tr.TextStyleTable.Add("romas", FontTTF.Romans, 0.8); + + + + tr.TextStyleTable.Add("daziti", ttr => { + ttr.FileName = "ascii.shx"; + ttr.BigFontFileName = "gbcbig.shx"; + }); + } + + [CommandMethod(nameof(Test_TextStyleChange))] + public void Test_TextStyleChange() + { + using DBTrans tr = new(); + + + tr.TextStyleTable.AddWithChange("宋体1", "simfang.ttf", height: 5); + tr.TextStyleTable.AddWithChange("仿宋体", "宋体.ttf"); + tr.TextStyleTable.AddWithChange("fsgb2312", "Romans", "gbcbig"); + } +} \ No newline at end of file diff --git a/tests/TestShared/TestJig.cs b/tests/TestShared/TestJig.cs new file mode 100644 index 0000000..7a2b5f5 --- /dev/null +++ b/tests/TestShared/TestJig.cs @@ -0,0 +1,313 @@ +namespace Test; + +using System.Windows.Forms; + +public class Commands_Jig +{ + // 已在数据库的图元如何进入jig + [CommandMethod(nameof(Test_Jig33))] + public static void Test_Jig33() + { + using DBTrans tr = new(); + var per = tr.Editor?.GetEntity("\n点选圆形:"); + if (per?.Status != PromptStatus.OK) + return; + var cir = tr.GetObject(per.ObjectId, OpenMode.ForWrite); + if (cir == null) + return; + var oldSp = cir.StartPoint; + JigEx? moveJig = null; + moveJig = new JigEx((mousePoint, drawEntitys) => { + moveJig!.SetOptions(oldSp);// 回调过程中也可以修改基点 + // cir.UpgradeOpen();// 已经提权了,所以这里不需要提权 + cir.Move(cir.StartPoint, mousePoint); + // cir.DowngradeOpen(); + + // 此处会Dispose图元, + // 所以此处不加入已经在数据库的图元,而是加入new Entity的. + // drawEntitys.Enqueue(cir); + }); + moveJig.SetOptions(cir.GeometricExtents.MinPoint); + + // 此处详见方法注释 + moveJig.DatabaseEntityDraw(draw => { + draw.RawGeometry.Draw(cir); + }); + + while (true) + { + var prDrag = moveJig.Drag(); + if (prDrag.Status == PromptStatus.OK) + break; + } + moveJig.Dispose(); + } + + + // 不在数据库的图元如何进入jig + [CommandMethod(nameof(Test_Jig44))] + public void Test_Jig44() + { + using DBTrans tr = new(); + var per = Env.Editor.GetEntity("\n请选择一条多段线:"); + if (per.Status != PromptStatus.OK) + return; + var ent = tr.GetObject(per.ObjectId, OpenMode.ForWrite); + if (ent is not Polyline pl) + return; + + /* + * 鼠标采样器执行时修改鼠标基点 + * 原因: 多段线与鼠标垂直点作为 BasePoint,jig鼠标点为确定点 + * 所以需要先声明再传入指针,但是我发现null也可以. + */ + JigPromptPointOptions? options = null; + using var jig = new JigEx((mousePoint, drawEntitys) => { + var closestPt = pl.GetClosestPointTo(mousePoint, false); + + // 回调过程中SetOptions会覆盖配置,所以如果想增加关键字或者修改基点, + // 不要这样做: jig.SetOptions(closestPt) 而是使用底层暴露 + options!.BasePoint = closestPt; + + // 允许在循环中替换关键字,需要避免重复加入同一个关键字 + if (!options.Keywords.Contains("A")) + options.Keywords.Add("A"); + + // 生成文字 + var dictString = (pl.GetDistAtPoint(closestPt) * 0.001).ToString("0.00"); + var acText = DBTextEx.CreateDBText(closestPt, dictString, 200); + + // 加入刷新队列 + drawEntitys.Enqueue(acText); + }); + + options = jig.SetOptions(per.PickedPoint); + + // 在这里加入关键字 + // 如果没有这个,那么空格只会是 PromptStatus.None 而不是 PromptStatus.Keyword + // options.Keywords.Add(" ", " ", "空格结束啊"); + // jig.SetSpaceIsKeyword(); + options.Keywords.Add("A","A","A"); + + + bool flag = true; + while (flag) + { + var pr = jig.Drag(); + if (pr.Status == PromptStatus.Keyword) + { + switch (pr.StringResult) + { + case "A": + tr.Editor?.WriteMessage($"\n 您触发了关键字{pr.StringResult}"); + flag = false; + break; + case " ": + tr.Editor?.WriteMessage("\n 触发关键字空格"); + flag = false; + break; + } + } + else if (pr.Status != PromptStatus.OK)// PromptStatus.None == 右键,空格,回车,都在这里结束 + { + tr.Editor?.WriteMessage(Environment.NewLine + pr.Status.ToString()); + return; + } + else + flag = false; + } + tr.CurrentSpace.AddEntity(jig.Entities); + } + + [CommandMethod(nameof(Test_MessageFilter))] + public void Test_MessageFilter() + { + var dm = Acap.DocumentManager; + var ed = dm.MdiActiveDocument.Editor; + + // Create and add our message filter + MyMessageFilter filter = new(); + System.Windows.Forms.Application.AddMessageFilter(filter); + // Start the loop + while (true) + { + // Check for user input events + System.Windows.Forms.Application.DoEvents(); + // Check whether the filter has set the flag + if (filter.bCanceled == true) + { + ed.WriteMessage("\nLoop cancelled."); + break; + } + ed.WriteMessage($"\nInside while loop...and {filter.Key}"); + } + // We're done - remove the message filter + System.Windows.Forms.Application.RemoveMessageFilter(filter); + } + // Our message filter class + public class MyMessageFilter : IMessageFilter + { + public const int WM_KEYDOWN = 0x0100; + public bool bCanceled = false; + public Keys Key { get; private set; } + public bool PreFilterMessage(ref Message m) + { + if (m.Msg == WM_KEYDOWN) + { + // Check for the Escape keypress + Keys kc = (Keys)(int)m.WParam & Keys.KeyCode; + if (m.Msg == WM_KEYDOWN && kc == Keys.Escape) + bCanceled = true; + Key = kc; + // Return true to filter all keypresses + return true; + } + // Return false to let other messages through + return false; + } + } + + + [CommandMethod(nameof(Test_QuickText))] + static public void Test_QuickText() + { + var dm = Acap.DocumentManager; + var doc = dm.MdiActiveDocument; + var db = doc.Database; + var ed = doc.Editor; + + PromptStringOptions pso = new("\nEnter text string") + { + AllowSpaces = true + }; + var pr = ed.GetString(pso); + if (pr.Status != PromptStatus.OK) + return; + + using var tr = doc.TransactionManager.StartTransaction(); + var btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite); + // Create the text object, set its normal and contents + + var acText = DBTextEx.CreateDBText(Point3d.Origin, pr.StringResult, 200); + + acText.Normal = ed.CurrentUserCoordinateSystem.CoordinateSystem3d.Zaxis; + btr.AppendEntity(acText); + tr.AddNewlyCreatedDBObject(acText, true); + + // Create our jig + var pj = new TextPlacementJig(tr, db, acText); + // Loop as we run our jig, as we may have keywords + var state = PromptStatus.Keyword; + while (state == PromptStatus.Keyword) + { + var res = ed.Drag(pj); + state = res.Status; + if (state != PromptStatus.OK && state != PromptStatus.Keyword) + return; + } + tr.Commit(); + } + +#if true + class TextPlacementJig : EntityJig + { + // Declare some internal state + readonly Database _db; + readonly Transaction _tr; + + Point3d _position; + double _angle, _txtSize; + + // Constructor + public TextPlacementJig(Transaction tr, Database db, Entity ent) : base(ent) + { + _db = db; + _tr = tr; + _angle = 0; + _txtSize = 1; + } + + protected override SamplerStatus Sampler(JigPrompts jp) + { + // We acquire a point but with keywords + JigPromptPointOptions po = new("\nPosition of text") + { + UserInputControls = + UserInputControls.Accept3dCoordinates | + UserInputControls.NullResponseAccepted | + UserInputControls.NoNegativeResponseAccepted | + UserInputControls.GovernedByOrthoMode + }; + po.SetMessageAndKeywords( + "\nSpecify position of text or " + + "[Bold/Italic/LArger/Smaller/" + + "ROtate90/LEft/Middle/RIght]: ", + "Bold Italic LArger Smaller " + + "ROtate90 LEft Middle RIght" + ); + + PromptPointResult ppr = jp.AcquirePoint(po); + if (ppr.Status == PromptStatus.Keyword) + { + switch (ppr.StringResult) + { + case "Bold": + break; + case "Italic": + break; + case "LArger": + { + // Multiple the text size by two + _txtSize *= 2; + break; + } + case "Smaller": + { + // Divide the text size by two + _txtSize /= 2; + break; + } + case "ROtate90": + { + // To rotate clockwise we subtract 90 degrees and + // then normalise the angle between 0 and 360 + _angle -= Math.PI / 2; + while (_angle < Math.PI * 2) + { + _angle += Math.PI * 2; + } + break; + } + case "LEft": + break; + case "RIght": + break; + case "Middle": + break; + } + return SamplerStatus.OK; + } + else if (ppr.Status == PromptStatus.OK) + { + // Check if it has changed or not (reduces flicker) + if (_position.DistanceTo(ppr.Value) < Tolerance.Global.EqualPoint) + return SamplerStatus.NoChange; + + _position = ppr.Value; + return SamplerStatus.OK; + } + return SamplerStatus.Cancel; + } + + protected override bool Update() + { + // Set properties on our text object + DBText txt = (DBText)Entity; + txt.Position = _position; + txt.Height = _txtSize; + txt.Rotation = _angle; + return true; + } + } +#endif +} \ No newline at end of file diff --git a/tests/TestShared/TestJigExTransient.cs b/tests/TestShared/TestJigExTransient.cs new file mode 100644 index 0000000..52eb3f4 --- /dev/null +++ b/tests/TestShared/TestJigExTransient.cs @@ -0,0 +1,88 @@ + +namespace Test; + +public partial class Test +{ + [CommandMethod(nameof(Test_JigExTransient))] + public void Test_JigExTransient() + { + // 先取1点,建2个圆 + var getpt = Env.Editor.GetPoint("\n选择点"); + if (getpt.Status != PromptStatus.OK) + return; + var pt = getpt.Value.Ucs2Wcs(); + + var c1 = new Circle(pt, Vector3d.ZAxis, 100); + var c2 = new Circle(pt.Polar(0, 300), Vector3d.ZAxis, 100); + + // 创建瞬态容器 + using JigExTransient jet = new(); + + // 将c1以默认模式,c2以亮显模式加到瞬态容器,即在图纸上显示 + jet.Add(c1); + jet.Add(c2, Acgi.TransientDrawingMode.Highlight); + + // 再取一点,再建一个圆c3 + var r2 = Env.Editor.GetPoint("\n选择下一点"); + if (r2.Status != PromptStatus.OK) + return; + var pt2 = r2.Value.Ucs2Wcs(); + + // 将c1从瞬态容器中移除,将c2修改颜色,c3加入瞬态容器 + jet.Remove(c1); + + c2.ColorIndex = 1; + var c3 = new Circle(pt2, Vector3d.ZAxis, 150); + jet.Add(c3); + + // 由于c2进行了修改,所以需要更新, + // 可以单个更新或更新整个瞬态容器 + jet.Update(c2); + // jet.UpdateAll(); + + Env.Editor.GetPoint("\n此拾取无意义,仅为了暂停查看"); + + // 加到图纸中,为测试瞬态容器可以自行dispose消失,所以未全部加入 + using DBTrans tr = new(); + tr.CurrentSpace.AddEntity(c3); + + // 若想将容器中所有图元全部加入提供了Entities属性 + // tr.CurrentSpace.AddEntity(jet.Entities); + } + + [CommandMethod(nameof(Test_JigExTransentDim))] + public static void Test_JigExTransentDim() + { + PromptPointOptions ppo = new("") + { + AppendKeywordsToMessage = false, + }; + List pts = new(); + for (int i = 0; i < 3; i++) + { + ppo.Message = $"\n选择标注点{i + 1}"; + var ppr = Env.Editor.GetPoint(ppo); + if (ppr.Status != PromptStatus.OK) + return; + pts.Add(ppr.Value); + } + + using DBTrans tr = new(); + + using RotatedDimension dimension = new(); + dimension.SetDatabaseDefaults();// cad16没有这个不显示 + dimension.Rotation = 0; + dimension.XLine1Point = pts[0]; + dimension.XLine2Point = pts[1]; + dimension.DimLinePoint = pts[2]; + dimension.DimensionText = "<>"; + dimension.DimensionStyle = tr.Database.Dimstyle; + + using JigExTransient jet = new(); + jet.Add(dimension, TransientDrawingMode.Highlight); + jet.UpdateAll(); + + Env.Editor.GetPoint("\n此拾取无意义,仅为了暂停查看"); + tr.CurrentSpace.AddEntity(dimension); + } +} diff --git a/tests/TestShared/TestJson.cs b/tests/TestShared/TestJson.cs new file mode 100644 index 0000000..9e48561 --- /dev/null +++ b/tests/TestShared/TestJson.cs @@ -0,0 +1,25 @@ +namespace TestShared; + +public class TestJson +{ + /* + * 需要引入: + * + * + * + * + */ + [CommandMethod(nameof(JavaScriptSerializer))] + public void JavaScriptSerializer() + { + List RegisteredUsers = []; + RegisteredUsers.Add(0); + RegisteredUsers.Add(1); + RegisteredUsers.Add(2); + RegisteredUsers.Add(3); + + var serializer = new System.Web.Script.Serialization.JavaScriptSerializer(); + var serializedResult = serializer.Serialize(RegisteredUsers); + var deserializedResult = serializer.Deserialize>(serializedResult); + } +} \ No newline at end of file diff --git a/Test/TestLayer.cs b/tests/TestShared/TestLayer.cs similarity index 93% rename from Test/TestLayer.cs rename to tests/TestShared/TestLayer.cs index c976fd8..62df5e1 100644 --- a/Test/TestLayer.cs +++ b/tests/TestShared/TestLayer.cs @@ -1,5 +1,4 @@ -namespace Test; - +namespace Test; public class TestLayer { @@ -13,7 +12,7 @@ public void Test_LayerAdd0() lt.LineWeight = LineWeight.LineWeight030; }); tr.LayerTable.Remove("3"); - tr.LayerTable.Remove("0"); + tr.LayerTable.Delete("0"); tr.LayerTable.Change("4", lt => { lt.Color = Color.FromColorIndex(ColorMethod.ByColor, 2); }); @@ -45,7 +44,7 @@ public void Test_LayerDel() tr.LayerTable.Remove("Defpoints");// 删除图层 Defpoints tr.LayerTable.Remove("1"); // 删除不存在的图层 1 tr.LayerTable.Remove("2"); // 删除有图元的图层 2 - tr.LayerTable.Remove("3"); // 删除图层 3 + tr.LayerTable.Remove("3"); // 删除图层 3 // 删除图层 3 tr.LayerTable.Remove("2"); // 测试是否能强制删除 } diff --git a/tests/TestShared/TestLisp.cs b/tests/TestShared/TestLisp.cs new file mode 100644 index 0000000..4bd7b19 --- /dev/null +++ b/tests/TestShared/TestLisp.cs @@ -0,0 +1,122 @@ +namespace Test; + +public class TestLisp +{ + // 定义lisp函数 + [LispFunction(nameof(LispTest_RunLisp))] + public static object LispTest_RunLisp(ResultBuffer rb) + { + CmdTest_RunLisp(); + return null!; + } + + // 模态命令,只有当CAD发出命令提示或当前没有其他的命令或程序活动的时候才可以被触发 + [CommandMethod("CmdTest_RunLisp1")] + // 透明命令,可以在一个命令提示输入的时候触发例如正交切换,zoom等 + [CommandMethod("CmdTest_RunLisp2", CommandFlags.Transparent)] + // 选择图元之后执行命令将可以从 获取图元 + [CommandMethod("CmdTest_RunLisp3", CommandFlags.UsePickSet)] + // 命令执行前已选中部分实体.在命令执行过程中这些标记不会被清除 + [CommandMethod("CmdTest_RunLisp4", CommandFlags.Redraw)] + // 命令不能在透视图中使用 + [CommandMethod("CmdTest_RunLisp5", CommandFlags.NoPerspective)] + // 命令不能通过 MULTIPLE命令 重复触发 + [CommandMethod("CmdTest_RunLisp6", CommandFlags.NoMultiple)] + // 不允许在模型空间使用命令 + [CommandMethod("CmdTest_RunLisp7", CommandFlags.NoTileMode)] + // 不允许在布局空间使用命令 + [CommandMethod("CmdTest_RunLisp8", CommandFlags.NoPaperSpace)] + // 命令不能在OEM产品中使用 + [CommandMethod("CmdTest_RunLisp9", CommandFlags.NoOem)] + // 不能直接使用命令名调用,必须使用 组名.全局名 调用 + [CommandMethod("CmdTest_RunLisp10", CommandFlags.Undefined)] + // 定义lisp方法.已废弃 请使用lispfunction + [CommandMethod("CmdTest_RunLisp11", CommandFlags.Defun)] + // 命令不会被存储在新的命令堆上 + [CommandMethod("CmdTest_RunLisp12", CommandFlags.NoNewStack)] + // 命令不能被内部锁定(命令锁) + [CommandMethod("CmdTest_RunLisp13", CommandFlags.NoInternalLock)] + // 调用命令的文档将会被锁定为只读 + [CommandMethod("CmdTest_RunLisp14", CommandFlags.DocReadLock)] + // 调用命令的文档将会被锁定,类似document.lockdocument + [CommandMethod("CmdTest_RunLisp15", CommandFlags.DocExclusiveLock)] + // 命令在CAD运行期间都能使用,而不只是在当前文档 + [CommandMethod("CmdTest_RunLisp16", CommandFlags.Session)] + // 获取用户输入时,可以与属性面板之类的交互 + [CommandMethod("CmdTest_RunLisp17", CommandFlags.Interruptible)] + // 命令不会被记录在命令历史记录 + [CommandMethod("CmdTest_RunLisp18", CommandFlags.NoHistory)] +#if (!zcad) + // 命令不会被 UNDO取消 + [CommandMethod("CmdTest_RunLisp19", CommandFlags.NoUndoMarker)] + // 不能在参照块中使用命令 + [CommandMethod("CmdTest_RunLisp20", CommandFlags.NoBlockEditor)] + + // acad09增,不会被动作录制器 捕捉到 + [CommandMethod("CmdTest_RunLisp21", CommandFlags.NoActionRecording)] + // acad09增,会被动作录制器捕捉 + [CommandMethod("CmdTest_RunLisp22", CommandFlags.ActionMacro)] + + + // 推断约束时不能使用命令 + [CommandMethod("CmdTest_RunLisp23", CommandFlags.NoInferConstraint)] + // 命令允许在选择图元时临时显示动态尺寸 + [CommandMethod("CmdTest_RunLisp24", CommandFlags.TempShowDynDimension)] +#endif + public static void CmdTest_RunLisp() + { + // 测试方法1: (command "CmdTest_RunLisp1") + // 测试方式2: (LispTest_RunLisp) + var dm = Acap.DocumentManager; + var doc = dm.MdiActiveDocument; + var ed = doc.Editor; + + var sb = new StringBuilder(); + foreach (var item in Enum.GetValues(typeof(EditorEx.RunLispFlag))) + { + sb.Append((byte)item); + sb.Append(','); + } + sb.Remove(sb.Length - 1, 1); + var option = new PromptIntegerOptions($"\n输入RunLispFlag枚举值:[{sb}]"); + var ppr = ed.GetInteger(option); + + if (ppr.Status != PromptStatus.OK) + return; + var flag = (EditorEx.RunLispFlag)ppr.Value; + + if (flag == EditorEx.RunLispFlag.AdsQueueexpr) + { + // 同步 + Env.Editor.RunLisp("(setq a 10)(princ)", + EditorEx.RunLispFlag.AdsQueueexpr); + Env.Editor.RunLisp("(princ a)", + EditorEx.RunLispFlag.AdsQueueexpr);// 成功输出 + } + else if (flag == EditorEx.RunLispFlag.AcedEvaluateLisp) + { + // 使用(command "CmdTest_RunLisp1")发送,然后 !b 查看变量,acad08是有值的,高版本是null + var strlisp0 = "(setq b 20)"; + var res0 = Env.Editor.RunLisp(strlisp0, + EditorEx.RunLispFlag.AcedEvaluateLisp); // 有lisp的返回值 + + var strlisp1 = "(defun f1( / )(princ \"aa\"))"; + var res1 = Env.Editor.RunLisp(strlisp1, + EditorEx.RunLispFlag.AcedEvaluateLisp); // 有lisp的返回值 + + var strlisp2 = "(defun f2( / )(command \"line\"))"; + var res2 = Env.Editor.RunLisp(strlisp2, + EditorEx.RunLispFlag.AcedEvaluateLisp); // 有lisp的返回值 + } + else if (flag == EditorEx.RunLispFlag.SendStringToExecute) + { + // 测试异步 + // (command "CmdTest_RunLisp1")和(LispTest_RunLisp)4都是异步 + var str = "(setq c 40)(princ)"; + Env.Editor.RunLisp(str, + EditorEx.RunLispFlag.SendStringToExecute); // 异步,后发送 + Env.Editor.RunLisp("(princ c)", + EditorEx.RunLispFlag.AdsQueueexpr); // 同步,先发送了,输出是null + } + } +} \ No newline at end of file diff --git a/tests/TestShared/TestLoop.cs b/tests/TestShared/TestLoop.cs new file mode 100644 index 0000000..438253a --- /dev/null +++ b/tests/TestShared/TestLoop.cs @@ -0,0 +1,25 @@ +namespace Test; +public class TestLoop +{ + [CommandMethod(nameof(Test_LoopList))] + public void Test_LoopList() + { + var loop = new LoopList + { + 0, + 1, + 2, + 3, + 4, + 5 + }; + + Env.Print(loop); + + loop.SetFirst(loop.Last!); + Env.Print(loop); + Env.Print(loop.Min()); + loop.SetFirst(new LoopListNode(loop.Min(), loop)); + Env.Print(loop); + } +} \ No newline at end of file diff --git a/tests/TestShared/TestMarshal.cs b/tests/TestShared/TestMarshal.cs new file mode 100644 index 0000000..7beb84b --- /dev/null +++ b/tests/TestShared/TestMarshal.cs @@ -0,0 +1,123 @@ +using System.Diagnostics; +using static IFoxCAD.Basal.WindowsAPI; + +namespace TestShared; + +public class TestMarshal +{ + [CommandMethod(nameof(TestToBytes))] + public void TestToBytes() + { + var ptA = new Point3d(123, 456, 789); + var bytes = StructToBytes(ptA); + var ptB = BytesToStruct(bytes); + Env.Printl(ptB); + } + + [CommandMethod(nameof(Test_ChangeLinePoint))] + public void Test_ChangeLinePoint() + { + var prs = Env.Editor.SSGet("\n 选择直线"); + if (prs.Status != PromptStatus.OK) + return; + + using DBTrans tr = new(); + + prs.Value.GetObjectIds().ForEach(id => { + var line = id.GetObject(); + if (line == null) + return; + using (line.ForWrite()) + unsafe + { + // 不允许直接 &这个表达式进行取址(因为它是属性,不是字段) + // 实际上就是默认拷贝一份副本出来 + var p1 = line.StartPoint; + ((Point3D*)&p1)->X = 0; + ((Point3D*)&p1)->Y = 0; + ((Point3D*)&p1)->Z = 0; + line.StartPoint = p1;// 又放回去,节省了一个变量 + + var p2 = line.EndPoint; + ((Point3D*)&p2)->X = 100; + ((Point3D*)&p2)->Y = 100; + ((Point3D*)&p2)->Z = 0; + line.EndPoint = p2; + } + }); + } + + [CommandMethod(nameof(Test_ImplicitPoint3D))] + public void Test_ImplicitPoint3D() + { + // 无法用指针转换类型,所以隐式转换是无法不new的, + // 貌似是因为 + // 如果发生了获取对象的成员引用指针,没有new的话,会发生引用不计数...造成GC释放失效... + // 而微软没有提供一种计数转移的方法...造成我无法实现此操作... + unsafe + { + Point3d pt1 = new(1, 56, 89); + var a1 = (Point3D*)&pt1; + DebugEx.Printl("指针类型转换,获取x::" + a1->X); + + var pt2 = Point3D.Create(new IntPtr(&pt1)); + DebugEx.Printl("pt1地址::" + (int)&pt1); + DebugEx.Printl("pt2地址::" + (int)&pt2); + Debug.Assert(&pt1 == &pt2);//不相等,是申请了新内存 + } + } + + [CommandMethod(nameof(Test_Marshal))] + public void Test_Marshal() + { + var dm = Acap.DocumentManager; + var doc = dm.MdiActiveDocument; + var ed = doc.Editor; + // 0x01 如何修改Point3d内容? + Point3d pt = new(100, 50, 0); + ed.WriteMessage("\n原始:" + pt.ToString()); + + // 0x02 最佳方法: + // 将Point3d内存转为Point3D,以此避开get保护,实现修改内部值 + // 为了避免在安全类型中转换,多了栈帧(无法内联),直接用指针处理 + unsafe + { + ((Point3D*)&pt)->X = 12345;//必须强转成这个指针类型,不然它为(Point3d*) + } + ed.WriteMessage("\n指针法:" + pt.ToString()); + + // 0x03 此方法仍然需要不安全操作,而且多了几个函数调用... + unsafe + { + var p = new IntPtr(&pt); + var result2 = Point3D.Create(p); + result2.X = 220; + result2.ToPtr(p); + } + "封送法:".Print(); + pt.Print(); + + // 拷贝到数组,还原指针到结构,最后将内存空间转换为目标结构体 + // 浪费内存,这不闹嘛~ + int typeSize = Marshal.SizeOf(pt); + byte[] bytes = new byte[typeSize]; + IntPtr structPtr = Marshal.AllocHGlobal(Marshal.SizeOf(pt)); + Marshal.StructureToPtr(pt, structPtr, true); + Marshal.Copy(structPtr, bytes, 0, typeSize); + var result = (Point3d)Marshal.PtrToStructure(structPtr, typeof(Point3d)); + "内存拷贝:".Print(); + result.Print(); + + //这个是不对的,会获取类型的指针,替换了就错误了 + //RuntimeTypeHandle handle = structObj.GetType().TypeHandle; + //IntPtr ptr = handle.Value; + //var result3 = (Point3D)Marshal.PtrToStructure(ptr, typeof(Point3D)); + //result3.SetX(330); + //Marshal.StructureToPtr(result3, ptr, true); + //"打印D:".Print(); + //structObj.Print(); + + // 释放内存 + Marshal.FreeHGlobal(structPtr); + } +} \ No newline at end of file diff --git a/tests/TestShared/TestMirrorFile.cs b/tests/TestShared/TestMirrorFile.cs new file mode 100644 index 0000000..76ac033 --- /dev/null +++ b/tests/TestShared/TestMirrorFile.cs @@ -0,0 +1,73 @@ +namespace Test; + +public class MirrorFile +{ + const string file = "D:/JX.dwg"; + const string fileSave = "D:/JX222.dwg"; + + /// + /// 测试:后台打开图纸,镜像文字是否存在文字偏移 + /// 答案:不存在 + /// + [CommandMethod(nameof(CmdTest_MirrorFile))] + public static void CmdTest_MirrorFile() + { + var yaxis = new Point3d(0, 1, 0); + using DBTrans tr = new(file, fileOpenMode: FileOpenMode.OpenForReadAndReadShare); + tr.BlockTable.Change(tr.ModelSpace.ObjectId, modelSpace => { + modelSpace.ForEach(entId => { + var dbText = tr.GetObject(entId, OpenMode.ForRead)!; + if (dbText is null) + return; + + dbText.UpgradeOpen(); + var pos = dbText.Position; + // text.Move(pos, Point3d.Origin); + // Y轴 + dbText.Mirror(Point3d.Origin, yaxis); + // text.Move(Point3d.Origin, pos); + dbText.DowngradeOpen(); + }); + }); + var ver = (DwgVersion)27;/*AC1021 AutoCAD 2007/2008/2009.*/ + tr.Database.SaveAs(fileSave, ver); + } + + /// + /// 测试:后台设置 dbText.IsMirroredInX 属性会令文字偏移 + /// 答案:存在,并提出解决方案 + /// + [CommandMethod(nameof(CmdTest_MirrorFile2))] + public static void CmdTest_MirrorFile2() + { + using DBTrans tr = new(file); + + tr.Task(() => { + var yaxis = new Point3d(0, 1, 0); + tr.BlockTable.Change(tr.ModelSpace.ObjectId, modelSpace => { + modelSpace.ForEach(entId => { + var entity = tr.GetObject(entId, OpenMode.ForWrite)!; + if (entity is DBText dbText) + { + dbText.Mirror(Point3d.Origin, yaxis); + dbText.IsMirroredInX = true; // 这句将导致文字偏移 + + // 指定文字的垂直对齐方式 + if (dbText.VerticalMode == TextVerticalMode.TextBase) + dbText.VerticalMode = TextVerticalMode.TextBottom; + + // 指定文字的水平对齐方式 + dbText.HorizontalMode = dbText.HorizontalMode switch + { + TextHorizontalMode.TextLeft => TextHorizontalMode.TextRight, + TextHorizontalMode.TextRight => TextHorizontalMode.TextLeft, + _ => dbText.HorizontalMode + }; + dbText.AdjustAlignment(tr.Database); + } + }); + }); + }); + tr.Database.SaveAs(fileSave, (DwgVersion)27 /*AC1021 AutoCAD 2007/2008/2009.*/); + } +} \ No newline at end of file diff --git a/tests/TestShared/TestPoint.cs b/tests/TestShared/TestPoint.cs new file mode 100644 index 0000000..b69afea --- /dev/null +++ b/tests/TestShared/TestPoint.cs @@ -0,0 +1,204 @@ +namespace Test; +public class TestPoint +{ +#if false + [CommandMethod(nameof(Test_GetAngle))] + public void Test_GetAngle() + { + var pt1 = new Point2d(0, 0); + var pt2 = new Point2d(1, 1); + var angle_pt1_pt2 = pt1.GetAngle(pt2); + var angle_pt2_pt1 = pt2.GetAngle(pt1); + Env.Printl($"pt1-pt2 angle is : {angle_pt1_pt2}, 角度是: {MathEx.ConvertRadToDeg(angle_pt1_pt2)}"); + Env.Printl($"pt2-pt1 angle is : {angle_pt2_pt1}, 角度是: {MathEx.ConvertRadToDeg(angle_pt2_pt1)}"); + + var polar = pt1.Polar(Math.PI / 2, 10); + Env.Printl($"pt1 90° 距离10的点是: {polar}"); + + } +#endif + [CommandMethod(nameof(Test_Endtoend))] + public void Test_Endtoend() + { + var pts = new Point2dCollection + { + new(0, 0), + new(0, 1), + new(1, 1), + new(1, 0) + }; + + + foreach (Point2d pt in pts) + { + Env.Printl($"X={pt.X},Y={pt.Y}"); + } + pts.End2End(); + Env.Printl("-------"); + foreach (Point2d pt in pts) + { + Env.Printl($"X={pt.X},Y={pt.Y}"); + } + Env.Printl("--------"); + var ptss = new Point3dCollection + { + new(0, 0,0), + new(0, 1,0), + new(1, 1,0), + new(1, 0,0) + }; + + foreach (Point3d pt in ptss) + { + Env.Printl($"X={pt.X},Y={pt.Y},Z={pt.Z}"); + } + ptss.End2End(); + Env.Printl("-------"); + foreach (Point3d pt in ptss) + { + Env.Printl($"X={pt.X},Y={pt.Y},Z={pt.Z}"); + } + + } + + /// + /// 红黑树排序点集 + /// + [CommandMethod(nameof(Test_PtSortedSet))] + public void Test_PtSortedSet() + { + var ss1 = new SortedSet + { + new Point2d(1, 1), + new Point2d(4.6, 2), + new Point2d(8, 3), + new Point2d(4, 3), + new Point2d(5, 40), + new Point2d(6, 5), + new Point2d(1, 6), + new Point2d(7, 6), + new Point2d(9, 6) + }; + + /*判断区间,超过就中断*/ + foreach (var item in ss1) + { + if (item.X > 3 && item.X < 7) + DebugEx.Printl(item); + else if (item.X >= 7) + break; + } + } + + + + [CommandMethod(nameof(Test_PtGethash))] + public void Test_PtGethash() + { + // test + var pt = Env.Editor.GetPoint("pick pt").Value; + // Tools.TestTimes2(1_000_000, "新语法", () => { + // pt.GetHashString2(); + // }); + Tools.TestTimes2(1_000_000, "旧语法", () => { + pt.GetHashString(); + }); + } + + [CommandMethod(nameof(Test_Point3dHash))] + public void Test_Point3dHash() + { + Env.Print($"4位小数的hash:{new Point3d(0.0_001, 0.0_002, 0.0).GetHashCode()}"); + Env.Print($"5位小数的hash:{new Point3d(0.00_001, 0.00_002, 0.0).GetHashCode()}"); + Env.Print($"6位小数的hash:{new Point3d(0.000_001, 0.000_002, 0.0).GetHashCode()}"); + Env.Print($"7位小数的hash:{new Point3d(0.000_0_001, 0.000_0_002, 0.0).GetHashCode()}"); + Env.Print($"8位小数的hash:{new Point3d(0.000_00_001, 0.000_00_002, 0.0).GetHashCode()}"); + Env.Print($"9位小数的hash:{new Point3d(0.000_000_001, 0.000_000_002, 0.0).GetHashCode()}"); + Env.Print($"10位小数的hash:{new Point3d(0.000_000_0001, 0.000_000_0002, 0.0).GetHashCode()}"); + Env.Print($"10位小数的hash:{new Point3d(0.000_000_0001, 0.000_000_0001, 0.0).GetHashCode()}"); + + Env.Print($"11位小数的hash:{new Point3d(0.000_000_000_01, 0.000_000_000_02, 0.0).GetHashCode()}"); + Env.Print($"11位小数的hash:{new Point3d(0.000_000_000_01, 0.000_000_000_01, 0.0).GetHashCode()}"); + + Env.Print($"12位小数的hash:{new Point3d(0.000_000_000_001, 0.000_000_000_002, 0.0).GetHashCode()}"); + Env.Print($"12位小数的hash:{new Point3d(0.000_000_000_001, 0.000_000_000_001, 0.0).GetHashCode()}"); + + Env.Print($"13位小数的hash:{new Point3d(0.000_000_000_0001, 0.000_000_000_0002, 0.0).GetHashCode()}"); + Env.Print($"13位小数的hash:{new Point3d(0.000_000_000_0001, 0.000_000_000_0001, 0.0).GetHashCode()}"); + + Env.Print($"14位小数的hash:{new Point3d(0.000_000_000_000_01, 0.000_000_000_000_02, 0.0).GetHashCode()}"); + Env.Print($"14位小数的hash:{new Point3d(0.000_000_000_000_01, 0.000_000_000_000_01, 0.0).GetHashCode()}"); + + Env.Print($"15位小数的hash:{new Point3d(0.000_000_000_000_001, 0.000_000_000_000_002, 0.0).GetHashCode()}"); + Env.Print($"15位小数的hash:{new Point3d(0.000_000_000_000_001, 0.000_000_000_000_001, 0.0).GetHashCode()}"); + + Env.Print($"16位小数的hash:{new Point3d(0.000_000_000_000_000_1, 0.000_000_000_000_000_2, 0.0).GetHashCode()}"); + Env.Print($"16位小数的hash:{new Point3d(0.000_000_000_000_000_1, 0.000_000_000_000_000_1, 0.0).GetHashCode()}"); + + Env.Print($"17位小数的hash:{new Point3d(0.000_000_000_000_000_01, 0.000_000_000_000_000_02, 0.0).GetHashCode()}"); + Env.Print($"17位小数的hash:{new Point3d(0.000_000_000_000_000_01, 0.000_000_000_000_000_01, 0.0).GetHashCode()}"); + + Env.Print($"18位小数的hash:{new Point3d(0.000_000_000_000_000_001, 0.000_000_000_000_000_002, 0.0).GetHashCode()}"); + Env.Print($"18位小数的hash:{new Point3d(0.000_000_000_000_000_001, 0.000_000_000_000_000_001, 0.0).GetHashCode()}"); + + Env.Print($"19位小数的hash:{new Point3d(0.000_000_000_000_000_000_1, 0.000_000_000_000_000_000_2, 0.0).GetHashCode()}"); + Env.Print($"19位小数的hash:{new Point3d(0.000_000_000_000_000_000_1, 0.000_000_000_000_000_000_1, 0.0).GetHashCode()}"); + + Env.Print($"20位小数的hash:{new Point3d(0.000_000_000_000_000_000_01, 0.000_000_000_000_000_000_02, 0.0).GetHashCode()}"); + Env.Print($"20位小数的hash:{new Point3d(0.000_000_000_000_000_000_01, 0.000_000_000_000_000_000_01, 0.0).GetHashCode()}"); + } + + [CommandMethod(nameof(Test_ListEqualspeed))] + public void Test_ListEqualspeed() + { + var lst1 = new List { 1, 2, 3, 4 }; + var lst2 = new List { 1, 2, 3, 4 }; + lst1.SequenceEqual(null!); + Tools.TestTimes2(1000000, "eqaulspeed:", () => { + lst1.SequenceEqual(lst2); + }); + } + + [CommandMethod(nameof(Test_Contains))] + public void Test_Contains() + { + // test list and dict contains speed + var lst = new List { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 }; + var hashset = new HashSet { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 }; + var dict = new Dictionary + { + { 1, 0 }, + { 2, 1 }, + { 3, 2 }, + { 4, 3 }, + { 5, 4 }, + { 6, 5 }, + { 7, 6 }, + { 8, 7 }, + { 9, 8 }, + { 10, 9 }, + { 11, 11 }, + { 12, 12 }, + { 13, 13 }, + { 14, 14 }, + { 15, 15 }, + { 16, 16 }, + { 17, 17 }, + { 18, 18 }, + { 19, 19 }, + { 20, 20 }, + }; + + Tools.TestTimes2(100_0000, "list:", () => { + lst.Contains(20); + }); + + Tools.TestTimes2(100_0000, "hashset:", () => { + hashset.Contains(20); + }); + + Tools.TestTimes2(100_0000, "dict:", () => { + dict.ContainsKey(20); + }); + } +} \ No newline at end of file diff --git a/Test/TestPointEx.cs b/tests/TestShared/TestPointEx.cs similarity index 100% rename from Test/TestPointEx.cs rename to tests/TestShared/TestPointEx.cs diff --git a/tests/TestShared/TestQuadTree.cs b/tests/TestShared/TestQuadTree.cs new file mode 100644 index 0000000..1c2e2a8 --- /dev/null +++ b/tests/TestShared/TestQuadTree.cs @@ -0,0 +1,457 @@ +namespace Test; + +/* + * 这里属于用户调用例子, + * 调用时候必须要继承它,再提供给四叉树 + * 主要是用户可以扩展属性 + */ +public class CadEntity : QuadEntity +{ + public ObjectId ObjectId; + // 这里加入其他字段 + public List? Link;// 碰撞链 + public System.Drawing.Color Color; + public double Angle; + public CadEntity(ObjectId objectId, Rect box) : base(box) + { + ObjectId = objectId; + } + public int CompareTo(CadEntity? other) + { + if (other == null) + return -1; + return GetHashCode() ^ other.GetHashCode(); + } + public override int GetHashCode() + { + return (base.GetHashCode(), ObjectId.GetHashCode()).GetHashCode(); + } +} + + + + + +public partial class TestQuadTree +{ + QuadTree? _quadTreeRoot; + #region 四叉树创建并加入 + [CommandMethod(nameof(Test_QuadTree))] + public void Test_QuadTree() + { + using DBTrans tr = new(); + + Rect dbExt; + // 使用数据库边界来进行 + var dbExtent = tr.Database.GetValidExtents3d(); + if (dbExtent == null) + { + // throw new ArgumentException("画一个矩形"); + + // 这个初始值的矩形是很有意义, + // 主要是四叉树分裂过程中产生多个Rect,Rect内有很多重复的double值,是否可以内存复用,以此减少内存大小? + // 接着想了一下,Rect可以是int,long,这样可以利用位运算它扩展和缩小, + // 最小就是1,并且可以控制四叉树深度,不至于无限递归. + // 而且指针长度跟值是一样的,所以就不需要复用了,毕竟跳转一个函数地址挺麻烦的. + // 但是因为啊惊懒的原因,并没有单独制作这样的矩形, + // 而且非常糟糕的是,c#不支持模板约束运算符,使得值类型之间需要通过一层接口来委婉处理,拉低了效率..引用类型倒是无所谓.. + // 要么忍着,要么换c++去搞四叉树吧 + dbExt = new Rect(0, 0, 1 << 10, 1 << 10); + } + else + { + var a = new Point2d(dbExtent.Value.MinPoint.X, dbExtent.Value.MinPoint.Y); + var b = new Point2d(dbExtent.Value.MaxPoint.X, dbExtent.Value.MaxPoint.Y); + dbExt = new Rect(a, b); + } + + // 创建四叉树 + _quadTreeRoot = new QuadTree(dbExt); + + // 数据库边界 + var pl = dbExt.ToPoints(); + var databaseBoundary = new List<(Point3d, double, double, double)> + { + (new Point3d(pl[0].X,pl[0].Y,0),0,0,0), + (new Point3d(pl[1].X,pl[1].Y,0),0,0,0), + (new Point3d(pl[2].X,pl[2].Y,0),0,0,0), + (new Point3d(pl[3].X,pl[3].Y,0),0,0,0), + }; + tr.CurrentSpace.AddEntity(databaseBoundary.CreatePolyline(action: e => e.Closed = true)); + + // 生成多少个图元,导致cad会令undo出错(八叉树深度过大 treemax) + // int maximumItems = 30_0000; + int maximumItems = 1000; + + // 随机图元生成 + List ces = new(); // 用于随机获取图元 + Tools.TestTimes(1, "画圆消耗时间:", () => { + // 生成外边界和随机圆形 + var grc = GenerateRandomCircle(maximumItems, dbExt); + foreach (var ent in grc) + { + // 初始化图元颜色 + ent!.ColorIndex = 1; // Color.FromRgb(0, 0, 0);// 黑色 + var edge = ent.GeometricExtents; + // 四叉树数据 + var entRect = new Rect(edge.MinPoint.X, edge.MinPoint.Y, edge.MaxPoint.X, edge.MaxPoint.Y); + var entId = tr.CurrentSpace.AddEntity(ent); + + var ce = new CadEntity(entId, entRect) + { + Color = RandomEx.NextColor() + }; + ces.Add(ce); + /*加入随机点*/ + var p = edge.MinPoint + new Vector3d(10, 10, 0); + entRect = new Rect(p.Point2d(), p.Point2d()); + entId = tr.CurrentSpace.AddEntity(new DBPoint(p)); + var dbPointCe = new CadEntity(entId, entRect); + ces.Add(dbPointCe); + } + });// 30万图元±3秒.cad2021 + + // 测试只加入四叉树的时间 + Tools.TestTimes(1, "插入四叉树时间:", () => { + for (int i = 0; i < ces.Count; i++) + _quadTreeRoot.Insert(ces[i]); + });// 30万图元±0.7秒.cad2021 + + tr.Editor?.WriteMessage($"\n加入图元数量:{maximumItems}"); + } + + /// + /// 创建随机圆形 + /// + /// 创建数量 + /// 数据库边界 + static IEnumerable GenerateRandomCircle(int createNumber, Rect dbExt) + { + var x1 = (int)dbExt.X; + var x2 = (int)(dbExt.X + dbExt.Width); + var y1 = (int)dbExt.Y; + var y2 = (int)(dbExt.Y + dbExt.Height); + + var rand = RandomEx.GetRandom(); + for (int i = 0; i < createNumber; i++) + { + var x = rand.Next(x1, x2) + rand.NextDouble(); + var y = rand.Next(y1, y2) + rand.NextDouble(); + yield return CircleEx.CreateCircle(new Point3d(x, y, 0), rand.Next(1, 100)); // 起点,终点 + } + } + + /* 啊惊: 有点懒不想改了*/ +#if true2 + + // 选择加入到四叉树 + [CommandMethod(nameof(CmdTest_QuadTree21))] + public void CmdTest_QuadTree21() + { + var dm = Acap.DocumentManager; + var doc = dm.MdiActiveDocument; + var db = doc.Database; + var ed = doc.Editor; + ed.WriteMessage("\n选择单个图元加入已有的四叉树"); + + var ss = ed.Ssget(); + if (ss.Count == 0) + return; + + AddQuadTreeRoot(db, ed, ss); + } + + // 自动加入全图到四叉树 + [CommandMethod(nameof(CmdTest_QuadTree20))] + public void CmdTest_QuadTree20() + { + var dm = Acap.DocumentManager; + var doc = dm.MdiActiveDocument; + var db = doc.Database; + var ed = doc.Editor; + ed.WriteMessage("\n自动加入全图到四叉树"); + + List ss = []; + int entnum = 0; + var time1 = Timer.RunTime(() => { + db.Action(tr => { + db.TraverseBlockTable(tr, btRec => { + if (!btRec.IsLayout)// 布局跳过 + return false; + + foreach (var item in btRec) + { + // var ent = item.ToEntity(tr); + ss.Add(item); + ++entnum;// 图元数量:100000, 遍历全图时间:0.216秒 CmdTest_QuadTree2 + } + return false; + }); + }); + }); + ed.WriteMessage($"\n图元数量:{entnum}, 遍历全图时间:{time1 / 1000.0}秒"); + + // 清空原有的 + _quadTreeRoot = null; + AddQuadTreeRoot(db, ed, ss); + } + + void AddQuadTreeRoot(Database db, Editor ed, List ss) + { + if (_quadTreeRoot is null) + { + ed.WriteMessage("\n四叉树是空的,重新初始化"); + + Rect dbExt; + // 使用数据库边界来进行 + var dbExtent = db.GetValidExtents3d(); + if (dbExtent == null) + { + // throw new ArgumentException("画一个矩形"); + + // 测试时候画个矩形,在矩形内画随机坐标的圆形 + dbExt = new Rect(0, 0, 32525, 32525); + } + else + { + dbExt = new Rect(dbExtent.Value.MinPoint.Point2d(), dbExtent.Value.MaxPoint.Point2d()); + } + _quadTreeRoot = new(dbExt); + } + + /* 测试: + * 为了测试删除内容释放了分支,再重复加入是否报错 + * 先创建 CmdTest_QuadTree1 + * 再减去 CmdTest_QuadTree0 + * 然后原有黑色边界,再生成边界 CmdTest_Create00,对比删除效果. + * 然后加入 CmdTest_QuadTree2 + * 然后原有黑色边界,再生成边界 CmdTest_Create00,对比删除效果. + */ + + List ces = new(); + db.Action(tr => { + ss.ForEach(entId => { + var ent = entId.ToEntity(tr); + if (ent is null) + return; + var edge = new EdgeEntity(ent); + // 四叉树数据 + var ce = new CadEntity(entId, edge.Edge) + { + Color = Utility.RandomColor + }; + ces.Add(ce); + + edge.Dispose(); + }); + }); + + var time2 = Timer.RunTime(() => { + _quadTreeRoot.Insert(ces); + }); + ed.WriteMessage($"\n图元数量:{ces.Count}, 加入四叉树时间:{time2 / 1000.0}秒"); + } +#endif + + #endregion + + /* 啊惊: 有点懒不想改了*/ +#if true2 + + #region 节点边界显示 + // 四叉树减去节点 + [CommandMethod(nameof(CmdTest_QuadTree0))] + public void CmdTest_QuadTree0() + { + var dm = Acap.DocumentManager; + var doc = dm.MdiActiveDocument; + // var db = doc.Database; + var ed = doc.Editor; + ed.WriteMessage("\n四叉树减区"); + + if (_quadTreeRoot is null) + { + ed.WriteMessage("\n四叉树是空的"); + return; + } + var rect = GetCorner(ed); + if (rect is null) + return; + _quadTreeRoot.Remove(rect); + } + + // 创建节点边界 + [CommandMethod(nameof(CmdTest_CreateNodesRect))] + public void CmdTest_CreateNodesRect() + { + var dm = Acap.DocumentManager; + var doc = dm.MdiActiveDocument; + var db = doc.Database; + var ed = doc.Editor; + ed.WriteMessage("\n创建边界"); + + if (_quadTreeRoot is null) + { + ed.WriteMessage("\n四叉树是空的"); + return; + } + + // 此处发现了一个事务处理的bug,提交数量过多的时候,会导致 ctrl+z 无法回滚, + // 需要把事务放在循环体内部 + // 报错: 0x6B00500A (msvcr80.dll)处(位于 acad.exe 中)引发的异常: 0xC0000005: 写入位置 0xFFE00000 时发生访问冲突。 + // 画出所有的四叉树节点边界,因为事务放在外面引起 + List nodeRects = []; + _quadTreeRoot.ForEach(node => { + nodeRects.Add(node); + return false; + }); + List rectIds = []; + foreach (var item in nodeRects)// Count = 97341 当数量接近这个量级 + { + db.Action(tr => { + var pts = item.ToPoints(); + var rec = EntityAdd.AddPolyLineToEntity(pts.ToPoint2d()); + rec.ColorIndex = 250; + rectIds.Add(tr.AddEntityToMsPs(db, rec)); + }); + } + db.Action(tr => { + db.CoverGroup(tr, rectIds); + }); + + // 获取四叉树深度 + int dep = 0; + _quadTreeRoot.ForEach(node => { + dep = dep > node.Depth ? dep : node.Depth; + return false; + }); + ed.WriteMessage($"\n四叉树深度是: {dep}"); + } + #endregion + +#endif + + #region 四叉树查询节点 + // 选择范围改图元颜色 + [CommandMethod(nameof(CmdTest_QuadTree3))] + public void CmdTest_QuadTree3() + { + Ssget(QuadTreeSelectMode.IntersectsWith); + } + + [CommandMethod(nameof(CmdTest_QuadTree4))] + public void CmdTest_QuadTree4() + { + Ssget(QuadTreeSelectMode.Contains); + } + + /// + /// 改颜色 + /// + /// + void Ssget(QuadTreeSelectMode mode) + { + if (_quadTreeRoot is null) + return; + + using DBTrans tr = new(); + if (tr.Editor is null) + return; + var rect = GetCorner(tr.Editor); + if (rect is null) + return; + + tr.Editor.WriteMessage("选择模式:" + mode); + + // 仿选择集 + var ces = _quadTreeRoot.Query(rect, mode); + ces.ForEach(item => { + var ent = tr.GetObject(item.ObjectId, OpenMode.ForWrite); + ent!.Color = Color.FromColor(item.Color); + ent.DowngradeOpen(); + ent.Dispose(); + }); + } + + /// + /// 交互获取 + /// + /// + /// + public static Rect? GetCorner(Editor ed) + { + var optionsA = new PromptPointOptions($"{Environment.NewLine}起点位置:"); + var pprA = ed.GetPoint(optionsA); + if (pprA.Status != PromptStatus.OK) + return null; + var optionsB = new PromptCornerOptions(Environment.NewLine + "输入矩形角点2:", pprA.Value) + { + UseDashedLine = true,// 使用虚线 + AllowNone = true,// 回车 + }; + var pprB = ed.GetCorner(optionsB); + if (pprB.Status != PromptStatus.OK) + return null!; + + return new Rect(new Point2d(pprA.Value.X, pprA.Value.Y), + new Point2d(pprB.Value.X, pprB.Value.Y), + true); + } + #endregion +} + +// public partial class TestQuadTree +// { +// public void Cmd_tt6() +// { +// using DBTrans tr = new(); +// var ed = tr.Editor; +// // 创建四叉树,默认参数无所谓 +// var TreeRoot = new QuadTree(new Rect(0, 0, 32525, 32525)); + +// var fil = OpFilter.Build(e => e.Dxf(0) == "LINE"); +// var psr = ed.SSGet("\n 选择需要连接的直线", fil); +// if (psr.Status != PromptStatus.OK) return; +// var LineEnts = new List(psr.Value.GetEntities(OpenMode.ForWrite)!); +// // 将实体插入到四岔树 +// foreach (var line in LineEnts) +// { +// var edge = line.GeometricExtents; +// var entRect = new Rect(edge.MinPoint.X, edge.MinPoint.Y, edge.MaxPoint.X, edge.MaxPoint.Y); +// var ce = new CadEntity(line.Id, entRect) +// { +// // 四叉树数据 +// Angle = line.Angle +// }; +// TreeRoot.Insert(ce); +// } + +// var ppo = new PromptPointOptions(Environment.NewLine + "\n指定标注点:<空格退出>") +// { +// AllowArbitraryInput = true,// 任意输入 +// AllowNone = true // 允许回车 +// }; +// var ppr = ed.GetPoint(ppo);// 用户点选 +// if (ppr.Status != PromptStatus.OK) +// return; +// var rect = new Rect(ppr.Value.Point2d(), 100, 100); +// tr.CurrentSpace.AddEntity(rect.ToPolyLine());// 显示选择靶标范围 + +// var nent = TreeRoot.FindNearEntity(rect);// 查询最近实体,按逆时针 +// var ent = tr.GetObject(nent.ObjectId, OpenMode.ForWrite);// 打开实体 +// ent.ColorIndex = Utility.GetRandom().Next(1, 256);// 1~256随机色 +// ent.DowngradeOpen();// 实体降级 +// ent.Dispose(); + +// var res = TreeRoot.Query(rect, QuadTreeSelectMode.IntersectsWith);// 查询选择靶标范围相碰的ID +// res.ForEach(item => { +// if (item.Angle == 0 || item.Angle == Math.PI) // 过滤直线角度为0或180的直线 +// { +// var ent = tr.GetObject(item.ObjectId, OpenMode.ForWrite); +// ent.ColorIndex = Utility.GetRandom().Next(1, 7); +// ent.DowngradeOpen(); +// ent.Dispose(); +// } +// }); +// } +// } \ No newline at end of file diff --git a/tests/TestShared/TestSelectfilter.cs b/tests/TestShared/TestSelectfilter.cs new file mode 100644 index 0000000..cab6c92 --- /dev/null +++ b/tests/TestShared/TestSelectfilter.cs @@ -0,0 +1,58 @@ +namespace Test; + +public class Testselectfilter +{ + [CommandMethod(nameof(Test_Filter))] + public void Test_Filter() + { + var p = new Point3d(10, 10, 0); + var f = OpFilter.Build( + e => !(e.Dxf(0) == "line" & e.Dxf(8) == "0") + | e.Dxf(0) != "circle" & e.Dxf(8) == "2" & e.Dxf(10) >= p); + + + var f2 = OpFilter.Build( + e => e.Or( + !e.And(e.Dxf(0) == "line", e.Dxf(8) == "0"), + e.And(e.Dxf(0) != "circle", e.Dxf(8) == "2", + e.Dxf(10) <= new Point3d(10, 10, 0)))); + + SelectionFilter f3 = f; + SelectionFilter f4 = f2; + + Env.Editor.WriteMessage(""); + } + + [CommandMethod(nameof(Test_Selectanpoint))] + public void Test_Selectanpoint() + { + var sel2 = Env.Editor.SelectAtPoint(new Point3d(0, 0, 0)); + Env.Editor.WriteMessage(""); + } +} + +public class TestSelectObjectType +{ + [CommandMethod(nameof(Test_Select_type))] + public void Test_Select_type() + { + var sel = Env.Editor.SSGet(); + if (sel.Status != PromptStatus.OK) return; + var ids = sel.Value.GetObjectIds(); + foreach (var item in ids) + { + item.Print(); + } + + var dxfName = RXObject.GetClass(typeof(Dimension)).DxfName; + dxfName.Print(); + var idss = sel.Value.GetObjectIds(); + foreach (var item in idss) + { + item.Print(); + item.ObjectClass.DxfName.Print(); + } + + } + +} \ No newline at end of file diff --git a/tests/TestShared/TestShared.projitems b/tests/TestShared/TestShared.projitems new file mode 100644 index 0000000..4ca3fc1 --- /dev/null +++ b/tests/TestShared/TestShared.projitems @@ -0,0 +1,52 @@ + + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + true + ced63d2d-0af6-4831-806d-5e8e9b0d0a07 + + + TestShared + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/TestShared/TestShared.shproj b/tests/TestShared/TestShared.shproj new file mode 100644 index 0000000..31ea779 --- /dev/null +++ b/tests/TestShared/TestShared.shproj @@ -0,0 +1,13 @@ + + + + ced63d2d-0af6-4831-806d-5e8e9b0d0a07 + 14.0 + + + + + + + + diff --git a/tests/TestShared/TestSingleKeyWordHook.cs b/tests/TestShared/TestSingleKeyWordHook.cs new file mode 100644 index 0000000..73fe216 --- /dev/null +++ b/tests/TestShared/TestSingleKeyWordHook.cs @@ -0,0 +1,48 @@ +namespace TestShared; +public static class TestSingleKeyWordHook +{ + [CommandMethod(nameof(TestSingleKeyWordHookDemo))] + public static void TestSingleKeyWordHookDemo() + { + var line1 = new Line(Point3d.Origin, new Point3d(100, 100, 0)); + line1.SetDatabaseDefaults(); + using var j1 = new JigEx((mpw, _) => { + line1.Move(line1.StartPoint, mpw); + }); + j1.DatabaseEntityDraw(wd => wd.Geometry.Draw(line1)); + var jppo = j1.SetOptions("\n选择位置或"); + jppo.Keywords.Add("A", "A", "旋转90°(A)"); + jppo.Keywords.Add("D", "D", "旋转45°(D)"); + // 创建关键字钩子 + using var skwh = new SingleKeyWordHook(); + // 添加关键字 + skwh.AddKeys(jppo.Keywords); + while (true) + { + // 循环开始时复位 + skwh.Reset(); + var r1 = Env.Editor.Drag(j1); + if (skwh.IsResponsed || r1.Status == PromptStatus.Keyword) + { + // 此钩子完整保留了原关键字的鼠标点击功能,所以要同时支持两种情况,也方便在已经写好的关键字功能上扩展 + // 如果响应了关键字 + switch (skwh.IsResponsed ? skwh.StringResult : r1.StringResult.ToUpper()) + { + case "A": + line1.Rotation(line1.StartPoint, Math.PI * 0.5, Vector3d.ZAxis); + break; + case "D": + line1.Rotation(line1.StartPoint, Math.PI * 0.25, Vector3d.ZAxis); + break; + } + continue; + } + if (r1.Status == PromptStatus.OK) + { + using var tr = new DBTrans(); + tr.CurrentSpace.AddEntity(line1); + } + return; + } + } +} diff --git a/tests/TestShared/TestText.cs b/tests/TestShared/TestText.cs new file mode 100644 index 0000000..b25dab6 --- /dev/null +++ b/tests/TestShared/TestText.cs @@ -0,0 +1,49 @@ + +namespace TestShared; + +public class TestText +{ + + [CommandMethod(nameof(TestDBText))] + public void TestDBText() + { + using var tr = new DBTrans(); + tr.CurrentSpace.AddEntity(DBTextEx.CreateDBText(new(-1, -1, 0), "123", 2.5, action:t=> t.ColorIndex = 1)); + + tr.CurrentSpace.AddEntity(DBTextEx.CreateDBText(new(-1, -1, 0), "123", 2.5, action: t => { + t.Justify = AttachmentPoint.BaseCenter; + t.AlignmentPoint = new(1, 1, 0); + t.ColorIndex = 2; + })); + } + + [CommandMethod(nameof(TestBackDBText))] + public void TestBackDBText() + { + using var tr = new DBTrans(@"C:\Users\vic\Desktop\test.dwg"); + tr.CurrentSpace.AddEntity(DBTextEx.CreateDBText(new(-1, -1, 0), "123", 2.5, action: t => t.ColorIndex = 1)); + + tr.CurrentSpace.AddEntity(DBTextEx.CreateDBText(new(-1, -1, 0), "123", 2.5, action: t => + { + t.Justify = AttachmentPoint.BaseCenter; + t.AlignmentPoint = new(1, 1, 0); + t.ColorIndex = 2; + })); + tr.Database.SaveDwgFile(); + } + + + + [CommandMethod(nameof(TestMText))] + public void TestMText() + { + using var tr = new DBTrans(); + tr.CurrentSpace.AddEntity(MTextEx.CreateMText(new(5, 5, 0), "123", 2.5, action: t => t.ColorIndex = 1)); + + tr.CurrentSpace.AddEntity(MTextEx.CreateMText(new(5, 5, 0), "123", 2.5, action: t => { + t.Attachment = AttachmentPoint.TopCenter; + t.ColorIndex = 2; + })); + } + +} diff --git a/tests/TestShared/TestXRecord.cs b/tests/TestShared/TestXRecord.cs new file mode 100644 index 0000000..1fcb85c --- /dev/null +++ b/tests/TestShared/TestXRecord.cs @@ -0,0 +1,252 @@ +//#define ExtendedDataBinaryChunk +#define XTextString + +#if NewtonsoftJson +using System.Diagnostics; +using Newtonsoft.Json; +using static IFoxCAD.Cad.WindowsAPI; + +namespace Test_XRecord; + +public class TestCmd_XRecord +{ + [CommandMethod(nameof(TestSerializeSetXRecord))] + public void TestSerializeSetXRecord() + { + var prs = Env.Editor.SSGet("\n 序列化,选择多段线:"); + if (prs.Status != PromptStatus.OK) + return; + + using var tr = new DBTrans(); + var pls = prs.Value.GetEntities(); + Tools.TestTimes(1, nameof(TestSerializeSetXRecord), () => { + foreach (var pl in pls) + { + if (pl == null) + continue; + + TestABCList datas = new(); + for (int i = 0; i < 1000; i++) + { + datas.Add(new() + { + AAA = i, + BBB = i.ToString(), + CCCC = i * 0.5, + DDDD = i % 2 != 0, + EEEE = new(0, i, 0) + }); + } + + using (pl.ForWrite()) + pl.SerializeToXRecord(datas); + } + }); + } + + [CommandMethod(nameof(TestDeserializeGetXRecord))] + public void TestDeserializeGetXRecord() + { + var prs = Env.Editor.GetEntity("\n 反序列化,选择多段线:"); + if (prs.Status != PromptStatus.OK) + return; + + using var tr = new DBTrans(); + + TestABCList? datas = null; + Tools.TestTimes(1, nameof(TestDeserializeGetXRecord), () => { + var pl = prs.ObjectId.GetObject(); + if (pl == null) + return; +#if XTextString + datas = pl.DeserializeToXRecord(); +#endif + +#if ExtendedDataBinaryChunk + // 这里有数据容量限制,而且很小 + var xd = pl.GetXDictionary(); + if (xd == null) + return; + if (xd.XData == null) + return; + + XDataList data = xd.XData; + var sb = new StringBuilder(); + data.ForEach(a => { + if (a.TypeCode == (short)DxfCode.ExtendedDataBinaryChunk) + if (a.Value is byte[] bytes) + sb.Append(Encoding.UTF8.GetString(bytes)); + }); + datas = JsonConvert.DeserializeObject(sb.ToString(), XRecordHelper._sset); +#endif + }); + if (datas == null) + { + Env.Printl("没有反序列的东西"); + return; + } + + var sb = new StringBuilder(); + for (int i = 0; i < datas.Count; i++) + sb.Append(datas[i]); + Env.Printl(sb); + } +} + +public static class XRecordHelper +{ + #region 序列化方式 + internal static JsonSerializerSettings _sset = new() + { + Formatting = Formatting.Indented, + TypeNameHandling = TypeNameHandling.Auto + }; + + /// + /// 设定信息 + /// + /// 储存对象 + /// 储存数据 + public static void SerializeToXRecord(this DBObject dbo, T data) + { + var xd = dbo.GetXDictionary(); + if (xd == null) + return; + + // XRecordDataList 不能超过2G大小 + const int GigaByte2 = 2147483647; + // 单条只能 16KiBit => 2048 * 16 == 32768 + const int KiBit16 = (2048 * 16) - 1; + + // 就算这个写法支持,计算机也不一定有那么多内存,所以遇到此情况最好换成内存拷贝 + var json = JsonConvert.SerializeObject(data, _sset);// 此时内存占用了2G + var buffer = Encoding.UTF8.GetBytes(json); // 此时内存又占用了2G.. + + BytesTask(buffer, GigaByte2, bts => { +#if XTextString + XRecordDataList datas = new(); + BytesTask(buffer, KiBit16, bts => { + datas.Add(DxfCode.XTextString, Encoding.UTF8.GetString(bts)); // 这对的 + // datas.Add(DxfCode.XTextString, bts);//这样 bts 变成 "System.Byte[]" + }); + xd.SetXRecord(typeof(T).FullName, datas); +#endif + +#if ExtendedDataBinaryChunk + // 这里有数据容量限制,而且很小 + var appname = typeof(T).FullName; + DBTrans.Top.RegAppTable.Add(appname); + + XDataList datas = new(); + datas.Add(DxfCode.ExtendedDataRegAppName, appname); + BytesTask(buffer, KiBit16, bts => { + datas.Add(DxfCode.ExtendedDataBinaryChunk, bts); + }); + using (xd.ForWrite()) + xd.XData = datas; // Autodesk.AutoCAD.Runtime.Exception:“eXdataSizeExceeded” +#endif + }); + } + + [DebuggerHidden] + static void BytesTask(byte[] buffer, int max, Action action) + { + int index = 0; + while (index < buffer.Length) + { + // 每次 max,然后末尾剩余就单独 + byte[] bts; + if (buffer.Length - index > max) + bts = new byte[max]; + else + bts = new byte[buffer.Length - index]; + + for (int i = 0; i < bts.Length; i++) + bts[i] = buffer[index++]; + + action.Invoke(bts); + } + } + + /// + /// 提取信息 + /// + /// 类型 + /// 储存对象 + /// 提取数据生成的对象 + public static T? DeserializeToXRecord(this DBObject dbo) + { + var xd = dbo.GetXDictionary(); + if (xd == null) + return default; + + var datas = xd.GetXRecord(typeof(T).FullName); + if (datas == null) + return default; + + var sb = new StringBuilder(); + for (int i = 0; i < datas.Count; i++) + sb.Append(datas[i].Value); + + return JsonConvert.DeserializeObject(sb.ToString(), _sset); + } + #endregion + + + /// + /// 设置描述(容量无限) + /// + /// + /// + /// + public static void SetSummaryInfoAtt(this Database db, string key, object value) + { + var info = new DatabaseSummaryInfoBuilder(db.SummaryInfo); + if (!info.CustomPropertyTable.Contains(key)) + info.CustomPropertyTable.Add(key, value); + else + info.CustomPropertyTable[key] = value; + db.SummaryInfo = info.ToDatabaseSummaryInfo(); + } + /// + /// 获取描述 + /// + /// + /// + /// + public static object? GetSummaryInfoAtt(this Database db, string key) + { + var info = new DatabaseSummaryInfoBuilder(db.SummaryInfo); + if (info.CustomPropertyTable.Contains(key)) + return info.CustomPropertyTable[key]; + return null; + } + +} + +public class TestABCList : List +{ +} + +[ComVisible(true)] +[Serializable] +[DebuggerDisplay("{DebuggerDisplay,nq}")] +[DebuggerTypeProxy(typeof(TestABC))] +[StructLayout(LayoutKind.Sequential, Pack = 4)] +public class TestABC +{ + [DebuggerBrowsable(DebuggerBrowsableState.Never)] + private string DebuggerDisplay => ToString(); + + public int AAA; + public string? BBB; + public double CCCC; + public bool DDDD; + public Point3D EEEE; + + public override string ToString() + { + return JsonConvert.SerializeObject(this, XRecordHelper._sset); + } +} +#endif \ No newline at end of file diff --git a/tests/TestShared/TestXdata.cs b/tests/TestShared/TestXdata.cs new file mode 100644 index 0000000..a0c10af --- /dev/null +++ b/tests/TestShared/TestXdata.cs @@ -0,0 +1,132 @@ +namespace Test; + +public class TestXdata +{ + // 测试扩展数据 + private const string Appname = "myapp2"; + + // 增 + [CommandMethod(nameof(Test_AddXdata))] + public void Test_AddXdata() + { + using DBTrans tr = new(); + + tr.RegAppTable.Add("myapp1"); + tr.RegAppTable.Add(Appname); // add函数会默认的在存在这个名字的时候返回这个名字的regapp的id,不存在就新建 + tr.RegAppTable.Add("myapp3"); + tr.RegAppTable.Add("myapp4"); + + var line = new Line(new Point3d(0, 0, 0), new Point3d(1, 1, 0)) + { + XData = new XDataList() + { + { DxfCode.ExtendedDataRegAppName, "myapp1" }, // 可以用dxfcode和int表示组码 + { DxfCode.ExtendedDataAsciiString, "xxxxxxx" }, + {1070, 12 }, + { DxfCode.ExtendedDataRegAppName, Appname }, // 可以用dxfcode和int表示组码,移除中间的测试 + { DxfCode.ExtendedDataAsciiString, "要移除的我" }, + { DxfCode.ExtendedDataAsciiString, "要移除的我" }, + { DxfCode.ExtendedDataAsciiString, "要移除的我" }, + { DxfCode.ExtendedDataAsciiString, "要移除的我" }, + {1070, 12 }, + { DxfCode.ExtendedDataRegAppName, "myapp3" }, // 可以用dxfcode和int表示组码 + { DxfCode.ExtendedDataAsciiString, "aaaaaaaaa" }, + {1070, 12 }, + { DxfCode.ExtendedDataRegAppName, "myapp4" }, // 可以用dxfcode和int表示组码 + { DxfCode.ExtendedDataAsciiString, "bbbbbbbbb" }, + {1070, 12 } + } + }; + + var line1 = new Line(new(0, 0, 0), new(2, 0, 0)); + line1.XData = new XDataList() + { + { DxfCode.ExtendedDataRegAppName, "myapp1" }, // 可以用dxfcode和int表示组码 + { DxfCode.ExtendedDataAsciiString, "xxxxxxx" }, + { 1070, 12 }, + { DxfCode.ExtendedDataRegAppName, Appname }, // 可以用dxfcode和int表示组码,移除中间的测试 + { DxfCode.ExtendedDataAsciiString, "要移除的我" }, + { DxfCode.ExtendedDataAsciiString, "要移除的我" }, + { DxfCode.ExtendedDataAsciiString, "要移除的我" }, + { DxfCode.ExtendedDataAsciiString, "要移除的我" }, + { 1070, 12 }, + { DxfCode.ExtendedDataRegAppName, "myapp3" }, // 可以用dxfcode和int表示组码 + { DxfCode.ExtendedDataAsciiString, "aaaaaaaaa" }, + { DxfCode.ExtendedDataAsciiString, "ccccccccc" }, + { 1070, 12 }, + { DxfCode.ExtendedDataRegAppName, "myapp4" }, // 可以用dxfcode和int表示组码 + { DxfCode.ExtendedDataAsciiString, "bbbbbbbbb" }, + { 1070, 12 } + }; + + tr.CurrentSpace.AddEntity(line,line1); + } + // 删 + [CommandMethod(nameof(Test_RemoveXdata))] + public void Test_RemoveXdata() + { + var res = Env.Editor.GetEntity("\n select the entity:"); + if (res.Status != PromptStatus.OK) return; + + using DBTrans tr = new(); + var ent = tr.GetObject(res.ObjectId); + if (ent == null || ent.XData == null) + return; + + Env.Printl("\n移除前:" + ent.XData); + + ent.RemoveXData(Appname, DxfCode.ExtendedDataAsciiString); + Env.Printl("\n移除成员后:" + ent.XData); + + ent.RemoveXData(Appname); + Env.Printl("\n移除appName后:" + ent.XData); + } + // 查 + [CommandMethod(nameof(Test_GetXdata))] + public void Test_GetXdata() + { + using DBTrans tr = new(); + tr.RegAppTable.ForEach(id => + id.GetObject()?.Name.Print()); + tr.RegAppTable.GetRecords().ForEach(rec => rec.Name.Print()); + tr.RegAppTable.GetRecordNames().ForEach(name => name.Print()); + tr.RegAppTable.ForEach(reg => reg.Name.Print(), checkIdOk: false); + + // 查询appName里面是否含有某个 + + var res = Env.Editor.GetEntity("\n select the entity:"); + if (res.Status != PromptStatus.OK) return; + + var ent = tr.GetObject(res.ObjectId); + if (ent == null || ent.XData == null) + return; + + XDataList data = ent.XData; + if (data.Contains(Appname)) + Env.Printl("含有appName:" + Appname); + else + Env.Printl("不含有appName:" + Appname); + + const string str = "要移除的我"; + if (data.Contains(Appname, str)) + Env.Printl("含有内容:" + str); + else + Env.Printl("不含有内容:" + str); + } + // 改 + [CommandMethod(nameof(Test_ChangeXdata))] + public void Test_ChangeXdata() + { + var res = Env.Editor.GetEntity("\n select the entity:"); + if (res.Status != PromptStatus.OK) return; + + using DBTrans tr = new(); + var data = tr.GetObject(res.ObjectId)!; + data.ChangeXData(Appname, DxfCode.ExtendedDataAsciiString, "change"); + + if (data.XData == null) + return; + Env.Printl(data.XData.ToString()); + } + +} \ No newline at end of file diff --git a/tests/TestShared/TestXrefEx.cs b/tests/TestShared/TestXrefEx.cs new file mode 100644 index 0000000..7fa7f3e --- /dev/null +++ b/tests/TestShared/TestXrefEx.cs @@ -0,0 +1,24 @@ +namespace Test; + +public class TestCmd_BindXrefs +{ + //后台绑定 + [CommandMethod(nameof(Test_Bind1))] + public static void Test_Bind1() + { + string fileName = @"D:\Test.dwg"; + using var tr = new DBTrans(fileName, + fileOpenMode: FileOpenMode.OpenForReadAndAllShare/*后台绑定特别注意*/); + tr.XrefFactory(XrefModes.Bind); + tr.Database.SaveDwgFile(); + } + + //前台绑定 + [CommandMethod(nameof(Test_Bind2))] + public static void Test_Bind2() + { + using var tr = new DBTrans(); + tr.XrefFactory(XrefModes.Bind); + tr.Database.SaveDwgFile(); + } +} \ No newline at end of file diff --git a/Test/Timer.cs b/tests/TestShared/Timer.cs similarity index 100% rename from Test/Timer.cs rename to tests/TestShared/Timer.cs diff --git a/Test/Tools.cs b/tests/TestShared/Tools.cs similarity index 100% rename from Test/Tools.cs rename to tests/TestShared/Tools.cs diff --git a/tests/TestShared/readme.md b/tests/TestShared/readme.md new file mode 100644 index 0000000..81b106f --- /dev/null +++ b/tests/TestShared/readme.md @@ -0,0 +1,20 @@ +# 测试项目文件结构 +- 图元类 - TestEntity + + TestAddEntity.cs + + TestRemoveEntity.cs + + .... +- 事务类 - TestDBtrans +- 符号表类 - TestSymTable + + TestLayer.cs + + TestTextStyle.cs + + ... +- 选择集类 +- 扩展数据类 +- editor类 +- 数据库对象类 +- env类 +- jig类 +- 数据交互类 +- lisp类 +- 算法类 +- \ No newline at end of file diff --git a/tests/TestZcad2025/GlobalUsings.cs b/tests/TestZcad2025/GlobalUsings.cs new file mode 100644 index 0000000..c3f2931 --- /dev/null +++ b/tests/TestZcad2025/GlobalUsings.cs @@ -0,0 +1,48 @@ +/// 系统引用 +global using System; +global using System.Collections; +global using System.Collections.Generic; +global using System.IO; +global using System.Linq; +global using System.Text; +global using System.Reflection; +global using System.Text.RegularExpressions; +global using Microsoft.Win32; +global using System.ComponentModel; +global using System.Runtime.InteropServices; +global using System.Collections.Specialized; +global using System.Threading; +global using Exception = System.Exception; + +global using Registry = Microsoft.Win32.Registry; +global using RegistryKey = Microsoft.Win32.RegistryKey; + +// cad 引用 +global using ZwSoft.ZwCAD.ApplicationServices; +global using ZwSoft.ZwCAD.EditorInput; +global using ZwSoft.ZwCAD.Colors; +global using ZwSoft.ZwCAD.DatabaseServices; +global using ZwSoft.ZwCAD.Geometry; +global using ZwSoft.ZwCAD.Runtime; +global using Acap = ZwSoft.ZwCAD.ApplicationServices.Application; +global using Acaop = ZwSoft.ZwCAD.ApplicationServices.Application; +global using AcException = ZwSoft.ZwCAD.Runtime.Exception; +global using ZwSoft.ZwCAD.DatabaseServices.Filters; +global using Acgi = ZwSoft.ZwCAD.GraphicsInterface; +// jig命名空间会引起Viewport/Polyline等等重义,最好逐个引入 using ZwSoft.ZwCAD.GraphicsInterface +global using ZwSoft.ZwCAD.GraphicsInterface; +global using WorldDraw = ZwSoft.ZwCAD.GraphicsInterface.WorldDraw; +global using Manager = ZwSoft.ZwCAD.GraphicsSystem.Manager; +global using Group = ZwSoft.ZwCAD.DatabaseServices.Group; +global using Viewport = ZwSoft.ZwCAD.DatabaseServices.Viewport; +global using Polyline = ZwSoft.ZwCAD.DatabaseServices.Polyline; +global using Cad_DwgFiler = ZwSoft.ZwCAD.DatabaseServices.DwgFiler; +global using Cad_DxfFiler = ZwSoft.ZwCAD.DatabaseServices.DxfFiler; +global using Cad_ErrorStatus = ZwSoft.ZwCAD.Runtime.ErrorStatus; + + +/// ifoxcad +global using IFoxCAD.Cad; +global using IFoxCAD.Basal; + +global using Test; \ No newline at end of file diff --git a/tests/TestZcad2025/TestZcad2025.csproj b/tests/TestZcad2025/TestZcad2025.csproj new file mode 100644 index 0000000..e0df6f3 --- /dev/null +++ b/tests/TestZcad2025/TestZcad2025.csproj @@ -0,0 +1,33 @@ + + + preview + enable + + NET48 + true + true + x64 + True + + + + $(Configuration);zcad + + + + + + + + + + + + + + + + + + + -- Gitee From 78009a97b7923609799a45faba66eec6d84ca0dd Mon Sep 17 00:00:00 2001 From: vicwjb Date: Mon, 25 Nov 2024 15:57:26 +0800 Subject: [PATCH 374/453] =?UTF-8?q?=E5=A2=9E=E5=8A=A0Directory.Build.props?= =?UTF-8?q?=E7=BB=9F=E4=B8=80=E7=AE=A1=E7=90=86=E5=A4=9A=E4=B8=AA=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E7=9A=84=E4=BF=A1=E6=81=AF=EF=BC=8C=E7=BB=9F=E4=B8=80?= =?UTF-8?q?=E8=BE=93=E5=87=BA=E7=9B=AE=E5=BD=95=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IFoxCAD.sln | 3 ++ src/Directory.Build.props | 39 ++++++++++++++++++++++ src/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj | 28 ++++------------ src/IFoxCAD.ZwCad/IFoxCAD.ZwCad.csproj | 31 +++++------------ 4 files changed, 57 insertions(+), 44 deletions(-) create mode 100644 src/Directory.Build.props diff --git a/IFoxCAD.sln b/IFoxCAD.sln index 552aed5..12007ff 100644 --- a/IFoxCAD.sln +++ b/IFoxCAD.sln @@ -4,6 +4,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00 VisualStudioVersion = 17.8.34309.116 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{AE09C3B7-58AC-4A68-9884-1F93FDA5D785}" + ProjectSection(SolutionItems) = preProject + src\Directory.Build.props = src\Directory.Build.props + EndProjectSection EndProject Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "CADShared", "src\CADShared\CADShared.shproj", "{5178502E-9A78-4588-B849-33ED439976B2}" EndProject diff --git a/src/Directory.Build.props b/src/Directory.Build.props new file mode 100644 index 0000000..36227b4 --- /dev/null +++ b/src/Directory.Build.props @@ -0,0 +1,39 @@ + + + + 0.9.2-preview1 + 增加net8支持,增加zwcad2025支持 + + + + preview + enable + true + true + true + True + True + x64 + IFoxCAD.CAD + true + true + ..\..\bin\$(Configuration)\ + + + + + InspireFunction + xsfhlzh;vicwjb;liuqihong;DYH + InspireFunction + 基于.NET的二次开发基本类库. + + true + https://gitee.com/inspirefunction/ifoxcad + https://gitee.com/inspirefunction/ifoxcad.git + git + IFox;cad;AutoCad;C#;NET;ZwCad + readme.md + LICENSE + + + \ No newline at end of file diff --git a/src/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj b/src/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj index 3f342cf..a68b7c8 100644 --- a/src/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj +++ b/src/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj @@ -2,35 +2,19 @@ net48;net8.0-windows - Preview - enable - x64 - IFoxCAD.CAD - true - true - true + + + - - 0.9.1.10 - 修复region同环曲线不闭合的问题 - - true - true + IFox.CAD.ACAD IFox.CAD.ACAD IFox.CAD.ACAD - xsfhlzh, vicwjb, liuqihong, DYH - 基于.NET的二次开发基本类库. - https://www.nuget.org/packages/IFox.CAD.ACAD/ - https://gitee.com/inspirefunction/ifoxcad - git - IFox,Cad,AutoCad,C#,NET, - InspireFunction - readme.md - LICENSE + + diff --git a/src/IFoxCAD.ZwCad/IFoxCAD.ZwCad.csproj b/src/IFoxCAD.ZwCad/IFoxCAD.ZwCad.csproj index bbf2809..d17f8fc 100644 --- a/src/IFoxCAD.ZwCad/IFoxCAD.ZwCad.csproj +++ b/src/IFoxCAD.ZwCad/IFoxCAD.ZwCad.csproj @@ -1,35 +1,22 @@  net48 - Preview - enable - x64 - IFoxCAD.CAD - true - true - true + + + - - 0.9.2-preview1 - 修复region同环曲线不闭合的问题 - - true - true + + + IFox.CAD.ZCAD IFox.CAD.ZCAD IFox.CAD.ZCAD - xsfhlzh, vicwjb, liuqihong, DYH - 基于.NET的二次开发基本类库. - https://www.nuget.org/packages/IFox.CAD.ZCAD/ - https://gitee.com/inspirefunction/ifoxcad - git - IFox,Cad,ZwCad,C#,NET, - InspireFunction - readme.md - LICENSE + + + -- Gitee From ff0eaecb4a1dddcf1587971010861242153afd72 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Mon, 25 Nov 2024 15:59:55 +0800 Subject: [PATCH 375/453] =?UTF-8?q?=E5=88=A0=E9=99=A4=E5=A4=9A=E4=BD=99?= =?UTF-8?q?=E7=A9=BA=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Directory.Build.props | 4 +--- src/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj | 17 +--------------- src/IFoxCAD.ZwCad/IFoxCAD.ZwCad.csproj | 23 +--------------------- 3 files changed, 3 insertions(+), 41 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 36227b4..a5a1f77 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -19,14 +19,12 @@ true ..\..\bin\$(Configuration)\ - - + InspireFunction xsfhlzh;vicwjb;liuqihong;DYH InspireFunction 基于.NET的二次开发基本类库. - true https://gitee.com/inspirefunction/ifoxcad https://gitee.com/inspirefunction/ifoxcad.git diff --git a/src/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj b/src/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj index a68b7c8..d2d9d1c 100644 --- a/src/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj +++ b/src/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj @@ -2,31 +2,23 @@ net48;net8.0-windows - - - - IFox.CAD.ACAD IFox.CAD.ACAD IFox.CAD.ACAD - - none True - none false - bin\Release\IFoxCAD.AutoCad.xml @@ -38,11 +30,6 @@ $(Configuration);acad;a2025 true - - - - - @@ -68,8 +55,6 @@ - - - + diff --git a/src/IFoxCAD.ZwCad/IFoxCAD.ZwCad.csproj b/src/IFoxCAD.ZwCad/IFoxCAD.ZwCad.csproj index d17f8fc..4b659be 100644 --- a/src/IFoxCAD.ZwCad/IFoxCAD.ZwCad.csproj +++ b/src/IFoxCAD.ZwCad/IFoxCAD.ZwCad.csproj @@ -1,34 +1,22 @@  net48 - - - - - - - IFox.CAD.ZCAD IFox.CAD.ZCAD IFox.CAD.ZCAD - - - none True - none false - bin\Release\IFoxCAD.ZwCad.xml @@ -36,12 +24,6 @@ $(Configuration);zcad;z2025 - - - - - - True @@ -62,9 +44,6 @@ - - - - + -- Gitee From 62a696710588b4afbf6d85afc623dcfede7e3510 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Tue, 26 Nov 2024 00:10:40 +0800 Subject: [PATCH 376/453] =?UTF-8?q?=E4=B8=AD=E6=9C=9B=E9=9C=80=E8=A6=81?= =?UTF-8?q?=E8=B0=83=E7=94=A8=20GetExecutingAssembly=20=E5=87=BD=E6=95=B0?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E6=AD=A3=E7=A1=AE=E7=9A=84=E7=A8=8B=E5=BA=8F?= =?UTF-8?q?=E9=9B=86=EF=BC=8C=E5=BE=85=E6=B5=8B=E8=AF=95acad=E6=98=AF?= =?UTF-8?q?=E5=90=A6=E6=AD=A3=E5=B8=B8=E3=80=82=20=E6=AD=A4=E9=97=AE?= =?UTF-8?q?=E9=A2=98=E4=B8=BA=E4=B8=AD=E6=9C=9B=E5=9C=A8release=E9=87=8C?= =?UTF-8?q?=E4=B8=8D=E8=83=BD=E6=AD=A3=E7=A1=AE=E7=9A=84=E9=80=9A=E8=BF=87?= =?UTF-8?q?GetCallingAssembly=E5=87=BD=E6=95=B0=E8=8E=B7=E5=8F=96=E7=A8=8B?= =?UTF-8?q?=E5=BA=8F=E9=9B=86=EF=BC=8C=E4=BD=86=E6=98=AFdebug=E5=8D=B4?= =?UTF-8?q?=E5=8F=AF=E4=BB=A5=E6=AD=A3=E5=B8=B8=E8=8E=B7=E5=8F=96=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IFoxCAD.sln | 1 + tests/TestAcad2025/TestAcad2025.csproj | 35 +++++++++++++++++++++++--- tests/TestShared/CmdINI.cs | 25 ++++++++++-------- tests/TestShared/TestJson.cs | 7 ++++++ tests/TestZcad2025/GlobalUsings.cs | 3 ++- tests/TestZcad2025/TestZcad2025.csproj | 7 ++++-- 6 files changed, 60 insertions(+), 18 deletions(-) diff --git a/IFoxCAD.sln b/IFoxCAD.sln index 12007ff..8b9d772 100644 --- a/IFoxCAD.sln +++ b/IFoxCAD.sln @@ -66,5 +66,6 @@ Global {47C42AB4-C2F4-475B-899C-71FDE57D926E} = {46F3EDA8-A6D1-4707-8D03-731CADB41A56} {0B4601B4-CBDA-4FD8-9B31-C1E292D03068} = {46F3EDA8-A6D1-4707-8D03-731CADB41A56} {CED63D2D-0AF6-4831-806D-5E8E9B0D0A07} = {46F3EDA8-A6D1-4707-8D03-731CADB41A56} + {5178502E-9A78-4588-B849-33ED439976B2} = {AE09C3B7-58AC-4A68-9884-1F93FDA5D785} EndGlobalSection EndGlobal diff --git a/tests/TestAcad2025/TestAcad2025.csproj b/tests/TestAcad2025/TestAcad2025.csproj index 92786a6..dce3589 100644 --- a/tests/TestAcad2025/TestAcad2025.csproj +++ b/tests/TestAcad2025/TestAcad2025.csproj @@ -1,9 +1,9 @@ - + preview enable - NET48 + net48;net8.0-windows true true x64 @@ -13,11 +13,39 @@ false + + none + false + + + + none + false + + - $(Configuration);acad + $(Configuration);acad;a2024 + + $(Configuration);acad;a2025 + true + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + @@ -26,7 +54,6 @@ - \ No newline at end of file diff --git a/tests/TestShared/CmdINI.cs b/tests/TestShared/CmdINI.cs index c296a56..0fa0c4b 100644 --- a/tests/TestShared/CmdINI.cs +++ b/tests/TestShared/CmdINI.cs @@ -169,21 +169,24 @@ public void Terminate() #endif -public class Init : AutoLoad + +#endif + +public class Init { - public override void Initialize() + [CommandMethod(nameof(Initialize))] + public void Initialize() { - Env.Print("loading..."); - // 将程序的目录加入信任路径 - // Env.AppendSupportPath(CurrentDirectory.FullName); + var assembly= Assembly.GetExecutingAssembly(); + Env.Printl(assembly.GetName().Name); + var info = new AssemInfo(assembly); + Env.Printl(info.ToString()); + AutoReg.RegApp(info); } - public override void Terminate() + public void Terminate() { - // 这里不能调用输出函数,因为这个函数执行的时候,已经没有editor对象了。 - // 所以如果不是想要在cad关闭的时候清理某些东西,这里不用写任何的代码。 - + } -} -#endif \ No newline at end of file +} \ No newline at end of file diff --git a/tests/TestShared/TestJson.cs b/tests/TestShared/TestJson.cs index 9e48561..41b3d38 100644 --- a/tests/TestShared/TestJson.cs +++ b/tests/TestShared/TestJson.cs @@ -18,8 +18,15 @@ public void JavaScriptSerializer() RegisteredUsers.Add(2); RegisteredUsers.Add(3); +#if a2024 || zcad var serializer = new System.Web.Script.Serialization.JavaScriptSerializer(); var serializedResult = serializer.Serialize(RegisteredUsers); var deserializedResult = serializer.Deserialize>(serializedResult); +#elif a2025 + var serializedResult = System.Text.Json.JsonSerializer.Serialize(RegisteredUsers); + var deserializedResult = System.Text.Json.JsonSerializer.Deserialize>(serializedResult); +#endif + + } } \ No newline at end of file diff --git a/tests/TestZcad2025/GlobalUsings.cs b/tests/TestZcad2025/GlobalUsings.cs index c3f2931..2c24797 100644 --- a/tests/TestZcad2025/GlobalUsings.cs +++ b/tests/TestZcad2025/GlobalUsings.cs @@ -12,8 +12,9 @@ global using System.Runtime.InteropServices; global using System.Collections.Specialized; global using System.Threading; +global using System.Diagnostics; global using Exception = System.Exception; - +global using System.Runtime.CompilerServices; global using Registry = Microsoft.Win32.Registry; global using RegistryKey = Microsoft.Win32.RegistryKey; diff --git a/tests/TestZcad2025/TestZcad2025.csproj b/tests/TestZcad2025/TestZcad2025.csproj index e0df6f3..f91d7fe 100644 --- a/tests/TestZcad2025/TestZcad2025.csproj +++ b/tests/TestZcad2025/TestZcad2025.csproj @@ -21,13 +21,16 @@
    - + + + - + + -- Gitee From 3aeb6627d90477f44dd3e77078980ffda378ebac Mon Sep 17 00:00:00 2001 From: vicwjb Date: Tue, 26 Nov 2024 11:01:21 +0800 Subject: [PATCH 377/453] =?UTF-8?q?fix=20#IB71CP,=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E4=B8=8D=E8=83=BD=E6=AD=A3=E7=A1=AE=E8=8E=B7=E5=8F=96=E7=A8=8B?= =?UTF-8?q?=E5=BA=8F=E9=9B=86=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CADShared/Initialize/AutoReg.cs | 4 ++-- tests/TestShared/CmdINI.cs | 11 ++++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/CADShared/Initialize/AutoReg.cs b/src/CADShared/Initialize/AutoReg.cs index b84d3f3..8e9b1f5 100644 --- a/src/CADShared/Initialize/AutoReg.cs +++ b/src/CADShared/Initialize/AutoReg.cs @@ -55,7 +55,7 @@ public static void RegApp(AssemInfo info) /// 程序集 public static void RegApp(Assembly? assembly = null) { - assembly ??= Assembly.GetCallingAssembly(); + assembly ??= Assembly.GetExecutingAssembly(); var info = new AssemInfo(assembly); RegApp(info); } @@ -81,7 +81,7 @@ public static bool UnRegApp(AssemInfo info) /// 程序集 public static void UnRegApp(Assembly? assembly = null) { - assembly ??= Assembly.GetCallingAssembly(); + assembly ??= Assembly.GetExecutingAssembly(); var info = new AssemInfo(assembly); UnRegApp(info); } diff --git a/tests/TestShared/CmdINI.cs b/tests/TestShared/CmdINI.cs index 0fa0c4b..e4deab7 100644 --- a/tests/TestShared/CmdINI.cs +++ b/tests/TestShared/CmdINI.cs @@ -178,11 +178,12 @@ public class Init public void Initialize() { - var assembly= Assembly.GetExecutingAssembly(); - Env.Printl(assembly.GetName().Name); - var info = new AssemInfo(assembly); - Env.Printl(info.ToString()); - AutoReg.RegApp(info); + // var assembly= Assembly.GetExecutingAssembly(); + // Env.Printl(assembly.GetName().Name); + // var info = new AssemInfo(assembly); + // Env.Printl(info.ToString()); + // AutoReg.RegApp(info); + AutoReg.RegApp(); } public void Terminate() -- Gitee From 4ba5611458d57b472fd8a25071b9f44c824f8c81 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Tue, 26 Nov 2024 13:22:40 +0800 Subject: [PATCH 378/453] =?UTF-8?q?net4.7.2=E4=BB=A5=E5=90=8E=E9=83=BD?= =?UTF-8?q?=E5=8F=AF=E4=BB=A5=E7=94=A8System.Text.Json=E6=9B=BF=E4=BB=A3Sy?= =?UTF-8?q?stem.Web.Script.Serialization?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...66\346\236\204\350\257\264\346\230\216.md" | 36 ++++++++++--------- tests/TestAcad2025/TestAcad2025.csproj | 11 +++--- tests/TestShared/TestCadFilePath.cs | 27 +++++++------- tests/TestShared/TestHatchinfo.cs | 8 ++--- tests/TestShared/TestJig.cs | 4 +-- tests/TestShared/TestJson.cs | 9 ++--- tests/TestShared/TestMarshal.cs | 2 +- tests/TestZcad2025/TestZcad2025.csproj | 10 +++--- 8 files changed, 51 insertions(+), 56 deletions(-) diff --git "a/docs/\345\205\263\344\272\216IFoxCAD\347\232\204\346\236\266\346\236\204\350\257\264\346\230\216.md" "b/docs/\345\205\263\344\272\216IFoxCAD\347\232\204\346\236\266\346\236\204\350\257\264\346\230\216.md" index b282930..ee3a985 100644 --- "a/docs/\345\205\263\344\272\216IFoxCAD\347\232\204\346\236\266\346\236\204\350\257\264\346\230\216.md" +++ "b/docs/\345\205\263\344\272\216IFoxCAD\347\232\204\346\236\266\346\236\204\350\257\264\346\230\216.md" @@ -72,22 +72,26 @@ IFoxCAD是基于NFOX类库的重制版,主要是提供一个最小化的内核 - IFoxCAD ``` - ├───CADShared -- 共享项目,所有的代码都在这里 - │ ├───Basal -- 一些基础类的函数 - │ │ ├───General - │ │ ├───Nullable - │ │ └───Win - │ ├───ExtensionMethod -- 扩展函数 - │ │ ├───Entity - │ │ ├───Geomerty - │ │ └───Jig - │ ├───Initialize -- 初始化 - │ ├───ResultData -- 扩展数据 - │ ├───Runtime -- 核心类 - │ └───SelectionFilter -- 选择集过滤器类 - ├───docs -- 架构及api定义说明文档 - ├───IFoxCAD.AutoCad -- AutoCAD的类库,内部除了globalusing外无其他代码 - └───Test -- 测试类 +├───bin -- 用于放置生成的nuget包和dll +├───docs -- 架构及api定义说明文档 +├───src -- 源码目录 +│ ├───CADShared -- 共享项目,所有的代码都在这里 +│ │ ├───Algorithms -- 基础算法和数据结构 +│ │ ├───Assoc -- 关联函数 +│ │ ├───Basal -- 一些基础类的函数 +│ │ ├───ExtensionMethod -- 扩展函数 +│ │ ├───Initialize -- 初始化 +│ │ ├───PE -- PE +│ │ ├───ResultData -- 扩展数据 +│ │ ├───Runtime -- 核心类 +│ │ └───SelectionFilter -- 选择集过滤器类 +│ ├───IFoxCAD.AutoCad -- AutoCAD的类库,内部除了globalusing外无其他代码 +│ └───IFoxCAD.ZwCad -- AutoCAD的类库,内部除了globalusing外无其他代码 +└───tests -- 测试类 + ├───TestAcad2025 -- autocad测试 + ├───TestShared -- 共享项目,所有的测试代码都在这里 + └───TestZcad2025 -- zwcad测试 + ``` ## 二、关于DBTrans类的说明 diff --git a/tests/TestAcad2025/TestAcad2025.csproj b/tests/TestAcad2025/TestAcad2025.csproj index dce3589..126352d 100644 --- a/tests/TestAcad2025/TestAcad2025.csproj +++ b/tests/TestAcad2025/TestAcad2025.csproj @@ -20,7 +20,7 @@ none - false + true @@ -36,6 +36,7 @@ + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -46,10 +47,10 @@ - - - - + + + + diff --git a/tests/TestShared/TestCadFilePath.cs b/tests/TestShared/TestCadFilePath.cs index 4a32dd5..c0354d5 100644 --- a/tests/TestShared/TestCadFilePath.cs +++ b/tests/TestShared/TestCadFilePath.cs @@ -6,25 +6,22 @@ public class TestCadFilePath [CommandMethod("TestCadFilePath")] public void TestCadFilePathfun() { - string key = HostApplicationServices.Current.UserRegistryProductRootKey; + var key = HostApplicationServices.Current.UserRegistryProductRootKey; // 计算机\HKEY_CURRENT_USER\SOFTWARE\Autodesk\AutoCAD\R24.0\ACAD-4101:804 - RegistryKey ackey = Registry.CurrentUser.OpenSubKey(key); - var profileskey = ackey.OpenSubKey("Profiles"); + var ackey = Registry.CurrentUser.OpenSubKey(key); + var profileskey = ackey?.OpenSubKey("Profiles"); - var listkey = profileskey.GetSubKeyNames(); + var listkey = profileskey?.GetSubKeyNames(); + if (listkey == null) return; foreach (var item in listkey) { - var acadkey = profileskey.OpenSubKey($@"{item}\General",true); - var name = "ACAD"; - var str = acadkey.GetValue(name)?.ToString(); - if (str is not null && !str.Contains("nihao")) - { - Env.Print(str); - acadkey.SetValue(name, $@"{str}\nihao;", RegistryValueKind.String); - } - - + if (profileskey == null) continue; + var acadkey = profileskey.OpenSubKey($@"{item}\General", true); + const string name = "ACAD"; + var str = acadkey?.GetValue(name)?.ToString(); + if (str == null || str.Contains("nihao")) continue; + Env.Print(str); + acadkey?.SetValue(name, $@"{str}\nihao;", RegistryValueKind.String); } - } } diff --git a/tests/TestShared/TestHatchinfo.cs b/tests/TestShared/TestHatchinfo.cs index 1b765e5..e241dfb 100644 --- a/tests/TestShared/TestHatchinfo.cs +++ b/tests/TestShared/TestHatchinfo.cs @@ -8,11 +8,9 @@ public void TestHatchInfo() using var tr = new DBTrans(); var sf = new SelectionFilter(new TypedValue[] { new TypedValue(0, "*line,circle,arc") }); var ids = Env.Editor.SSGet(null, sf).Value?.GetObjectIds(); - if (ids.Count() > 0) - { - HatchInfo hf = new HatchInfo(ids!, false, null, 1, 0).Mode2UserDefined(); - hf.Build(tr.CurrentSpace); - } + if (ids == null || ids.Count() <= 0) return; + var hf = new HatchInfo(ids!, false, null, 1, 0).Mode2UserDefined(); + hf.Build(tr.CurrentSpace); } } diff --git a/tests/TestShared/TestJig.cs b/tests/TestShared/TestJig.cs index 7a2b5f5..d0076f4 100644 --- a/tests/TestShared/TestJig.cs +++ b/tests/TestShared/TestJig.cs @@ -36,7 +36,7 @@ public static void Test_Jig33() while (true) { - var prDrag = moveJig.Drag(); + var prDrag = Env.Editor.Drag(moveJig); if (prDrag.Status == PromptStatus.OK) break; } @@ -93,7 +93,7 @@ public void Test_Jig44() bool flag = true; while (flag) { - var pr = jig.Drag(); + var pr = Env.Editor.Drag(jig); if (pr.Status == PromptStatus.Keyword) { switch (pr.StringResult) diff --git a/tests/TestShared/TestJson.cs b/tests/TestShared/TestJson.cs index 41b3d38..281e1b1 100644 --- a/tests/TestShared/TestJson.cs +++ b/tests/TestShared/TestJson.cs @@ -17,15 +17,10 @@ public void JavaScriptSerializer() RegisteredUsers.Add(1); RegisteredUsers.Add(2); RegisteredUsers.Add(3); - -#if a2024 || zcad - var serializer = new System.Web.Script.Serialization.JavaScriptSerializer(); - var serializedResult = serializer.Serialize(RegisteredUsers); - var deserializedResult = serializer.Deserialize>(serializedResult); -#elif a2025 + var serializedResult = System.Text.Json.JsonSerializer.Serialize(RegisteredUsers); var deserializedResult = System.Text.Json.JsonSerializer.Deserialize>(serializedResult); -#endif + } diff --git a/tests/TestShared/TestMarshal.cs b/tests/TestShared/TestMarshal.cs index 7beb84b..80398e2 100644 --- a/tests/TestShared/TestMarshal.cs +++ b/tests/TestShared/TestMarshal.cs @@ -104,7 +104,7 @@ public void Test_Marshal() IntPtr structPtr = Marshal.AllocHGlobal(Marshal.SizeOf(pt)); Marshal.StructureToPtr(pt, structPtr, true); Marshal.Copy(structPtr, bytes, 0, typeSize); - var result = (Point3d)Marshal.PtrToStructure(structPtr, typeof(Point3d)); + var result = (Point3d)(Marshal.PtrToStructure(structPtr, typeof(Point3d)) ?? throw new InvalidOperationException()); "内存拷贝:".Print(); result.Print(); diff --git a/tests/TestZcad2025/TestZcad2025.csproj b/tests/TestZcad2025/TestZcad2025.csproj index f91d7fe..89cf1ba 100644 --- a/tests/TestZcad2025/TestZcad2025.csproj +++ b/tests/TestZcad2025/TestZcad2025.csproj @@ -15,13 +15,13 @@ - - - - + + + + - + -- Gitee From d24faebfb29020425b65b1ac56aaa1683441f75f Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Wed, 27 Nov 2024 16:39:44 +0800 Subject: [PATCH 379/453] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=B8=80=E7=A7=8D?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=9B=BE=E5=B1=82=E7=9A=84=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/ExtensionMethod/IFoxUtils.cs | 68 +++++++++++++++++++++----- 1 file changed, 55 insertions(+), 13 deletions(-) diff --git a/CADShared/ExtensionMethod/IFoxUtils.cs b/CADShared/ExtensionMethod/IFoxUtils.cs index 5d08312..ada431f 100644 --- a/CADShared/ExtensionMethod/IFoxUtils.cs +++ b/CADShared/ExtensionMethod/IFoxUtils.cs @@ -10,8 +10,8 @@ public static class IFoxUtils /// /// 刷新图层状态,在修改图层的锁定或冻结状态后使用 /// - /// 图层id集合 - public static void RegenLayers(IEnumerable objectIds) + /// 图层id集合 + public static void RegenLayers(IEnumerable layerIds) { var type = Acaop.Version.Major >= 21 ? Assembly.Load("accoremgd")?.GetType("Autodesk.AutoCAD.Internal.CoreLayerUtilities") @@ -19,7 +19,47 @@ public static void RegenLayers(IEnumerable objectIds) var mi = type?.GetMethods().FirstOrDefault(e => e.Name == "RegenLayers"); var pi = type?.GetProperties().FirstOrDefault(e => e.Name == "RegenPending"); var regenPending = (int)(pi?.GetValue(null) ?? 0); - mi?.Invoke(null, [objectIds.ToArray(), regenPending]); + mi?.Invoke(null, [layerIds.ToArray(), regenPending]); + } + + /// + /// 刷新图层状态,在修改图层的锁定或冻结状态后使用 + /// + /// 图层id集合 + public static void RegenLayers2(IEnumerable layerIds) + { + var isOff = false; + var layerRxc = RXObject.GetClass(typeof(LayerTableRecord)); + var entityRxc = RXObject.GetClass(typeof(Entity)); + foreach (var group in layerIds.Where(e => e.IsOk() && e.ObjectClass.IsDerivedFrom(layerRxc)) + .GroupBy(e => e.Database)) + { + var db = group.Key; + var doc = Acap.DocumentManager.GetDocument(db); + if (doc is null) + continue; // 获取不到文档说明是后台开图,后台开图就不用刷新了 + using var dl = doc.LockDocument(); + using var tr = new DBTrans(db); + var layerIdSet = group.ToHashSet(); + layerIdSet.Count.Print(); + foreach (var ltr in layerIdSet.Select(id => tr.GetObject(id, OpenMode.ForWrite)) + .OfType()) + { + Volatile.Write(ref isOff, ltr.IsOff); + ltr.IsOff = Volatile.Read(ref isOff); + } + + for (var i = db.BlockTableId.Handle.Value; i < db.Handseed.Value; i++) + { + if (!db.TryGetObjectId(new Handle(i), out var id) || !id.IsOk() || + !id.ObjectClass.IsDerivedFrom(entityRxc)) + continue; + var ent = (Entity)tr.GetObject(id, OpenMode.ForWrite, false, true); + if (!layerIdSet.Contains(ent.LayerId)) + continue; + ent.RecordGraphicsModified(true); + } + } } /// @@ -32,7 +72,9 @@ public static void RegenLayers(IEnumerable objectIds) /// 链接 /// 链接地址 /// 内容2 - public static void ShowBubbleWindow(int second, string title, string text, IconType iconType = IconType.None, string? hyperText = null, string? hyperLink = null, string? text2 = null) + public static void ShowBubbleWindow(int second, string title, string text, + IconType iconType = IconType.None, string? hyperText = null, string? hyperLink = null, + string? text2 = null) { TrayItem? trayItem = null; const string name = "IFox"; @@ -40,25 +82,25 @@ public static void ShowBubbleWindow(int second, string title, string text, IconT for (var i = 0; i < num; i++) { var ti = Acap.StatusBar.TrayItems[i]; - if (ti.ToolTipText != name) continue; + if (ti.ToolTipText != name) + continue; trayItem = ti; break; } if (trayItem == null) { - trayItem = new() - { - ToolTipText = name, - Visible = true, - }; + trayItem = new() { ToolTipText = name, Visible = true, }; Acap.StatusBar.TrayItems.Add(trayItem); Acap.StatusBar.Update(); } - if (second <= 0) second = 0; - else if (second % 10 == 0) second = 10; - else second %= 10; + if (second <= 0) + second = 0; + else if (second % 10 == 0) + second = 10; + else + second %= 10; Acaop.SetSystemVariable("TrayTimeOut", second); var tibw = new TrayItemBubbleWindow { -- Gitee From 815b4990472f9fc45c85500a079d4f33035058ba Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Wed, 27 Nov 2024 16:39:44 +0800 Subject: [PATCH 380/453] =?UTF-8?q?=E5=88=A0=E9=99=A4=E5=A4=9A=E4=BD=99?= =?UTF-8?q?=E7=9A=84=E8=B0=83=E8=AF=95=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/ExtensionMethod/IFoxUtils.cs | 67 +++++++++++++++++++++----- 1 file changed, 54 insertions(+), 13 deletions(-) diff --git a/CADShared/ExtensionMethod/IFoxUtils.cs b/CADShared/ExtensionMethod/IFoxUtils.cs index 5d08312..3ab211a 100644 --- a/CADShared/ExtensionMethod/IFoxUtils.cs +++ b/CADShared/ExtensionMethod/IFoxUtils.cs @@ -10,8 +10,8 @@ public static class IFoxUtils /// /// 刷新图层状态,在修改图层的锁定或冻结状态后使用 /// - /// 图层id集合 - public static void RegenLayers(IEnumerable objectIds) + /// 图层id集合 + public static void RegenLayers(IEnumerable layerIds) { var type = Acaop.Version.Major >= 21 ? Assembly.Load("accoremgd")?.GetType("Autodesk.AutoCAD.Internal.CoreLayerUtilities") @@ -19,7 +19,46 @@ public static void RegenLayers(IEnumerable objectIds) var mi = type?.GetMethods().FirstOrDefault(e => e.Name == "RegenLayers"); var pi = type?.GetProperties().FirstOrDefault(e => e.Name == "RegenPending"); var regenPending = (int)(pi?.GetValue(null) ?? 0); - mi?.Invoke(null, [objectIds.ToArray(), regenPending]); + mi?.Invoke(null, [layerIds.ToArray(), regenPending]); + } + + /// + /// 刷新图层状态,在修改图层的锁定或冻结状态后使用 + /// + /// 图层id集合 + public static void RegenLayers2(IEnumerable layerIds) + { + var isOff = false; + var layerRxc = RXObject.GetClass(typeof(LayerTableRecord)); + var entityRxc = RXObject.GetClass(typeof(Entity)); + foreach (var group in layerIds.Where(e => e.IsOk() && e.ObjectClass.IsDerivedFrom(layerRxc)) + .GroupBy(e => e.Database)) + { + var db = group.Key; + var doc = Acap.DocumentManager.GetDocument(db); + if (doc is null) + continue; // 获取不到文档说明是后台开图,后台开图就不用刷新了 + using var dl = doc.LockDocument(); + using var tr = new DBTrans(db); + var layerIdSet = group.ToHashSet(); + foreach (var ltr in layerIdSet.Select(id => tr.GetObject(id, OpenMode.ForWrite)) + .OfType()) + { + Volatile.Write(ref isOff, ltr.IsOff); + ltr.IsOff = Volatile.Read(ref isOff); + } + + for (var i = db.BlockTableId.Handle.Value; i < db.Handseed.Value; i++) + { + if (!db.TryGetObjectId(new Handle(i), out var id) || !id.IsOk() || + !id.ObjectClass.IsDerivedFrom(entityRxc)) + continue; + var ent = (Entity)tr.GetObject(id, OpenMode.ForWrite, false, true); + if (!layerIdSet.Contains(ent.LayerId)) + continue; + ent.RecordGraphicsModified(true); + } + } } /// @@ -32,7 +71,9 @@ public static void RegenLayers(IEnumerable objectIds) /// 链接 /// 链接地址 /// 内容2 - public static void ShowBubbleWindow(int second, string title, string text, IconType iconType = IconType.None, string? hyperText = null, string? hyperLink = null, string? text2 = null) + public static void ShowBubbleWindow(int second, string title, string text, + IconType iconType = IconType.None, string? hyperText = null, string? hyperLink = null, + string? text2 = null) { TrayItem? trayItem = null; const string name = "IFox"; @@ -40,25 +81,25 @@ public static void ShowBubbleWindow(int second, string title, string text, IconT for (var i = 0; i < num; i++) { var ti = Acap.StatusBar.TrayItems[i]; - if (ti.ToolTipText != name) continue; + if (ti.ToolTipText != name) + continue; trayItem = ti; break; } if (trayItem == null) { - trayItem = new() - { - ToolTipText = name, - Visible = true, - }; + trayItem = new() { ToolTipText = name, Visible = true, }; Acap.StatusBar.TrayItems.Add(trayItem); Acap.StatusBar.Update(); } - if (second <= 0) second = 0; - else if (second % 10 == 0) second = 10; - else second %= 10; + if (second <= 0) + second = 0; + else if (second % 10 == 0) + second = 10; + else + second %= 10; Acaop.SetSystemVariable("TrayTimeOut", second); var tibw = new TrayItemBubbleWindow { -- Gitee From 52869053d98a53b83567aab7d0e820d9301e8e1a Mon Sep 17 00:00:00 2001 From: yupeng_dyp Date: Wed, 27 Nov 2024 10:32:07 +0000 Subject: [PATCH 381/453] =?UTF-8?q?update=20src/CADShared/ExtensionMethod/?= =?UTF-8?q?SingleKeyWordHook.cs.=20=E4=BC=98=E5=8C=96=E5=90=AF=E7=94=A8?= =?UTF-8?q?=E5=8A=A8=E6=80=81=E8=BE=93=E5=85=A5=E6=97=B6=E8=BE=93=E5=85=A5?= =?UTF-8?q?=E9=94=99=E8=AF=AF=E7=84=A6=E7=82=B9=E7=A7=BB=E5=88=B0=E5=8A=A8?= =?UTF-8?q?=E6=80=81=E8=BE=93=E5=85=A5=E6=A1=86=E7=9A=84=E6=83=85=E5=86=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: yupeng_dyp --- .../ExtensionMethod/SingleKeyWordHook.cs | 73 +++++++++---------- 1 file changed, 35 insertions(+), 38 deletions(-) diff --git a/src/CADShared/ExtensionMethod/SingleKeyWordHook.cs b/src/CADShared/ExtensionMethod/SingleKeyWordHook.cs index e774feb..0f1f84c 100644 --- a/src/CADShared/ExtensionMethod/SingleKeyWordHook.cs +++ b/src/CADShared/ExtensionMethod/SingleKeyWordHook.cs @@ -1,4 +1,4 @@ -using Keys = System.Windows.Forms.Keys; +using Keys = System.Windows.Forms.Keys; namespace IFoxCAD.Cad; @@ -84,11 +84,9 @@ public void AddKeys(KeywordCollection keywordCollection) { foreach (Keyword item in keywordCollection) { - if (item.LocalName.Length == 1) - { - var k = (Keys)item.LocalName[0]; - _keyWords.Add(k); - } + if (item.LocalName.Length != 1) continue; + var k = (Keys)item.LocalName[0]; + _keyWords.Add(k); } } @@ -108,6 +106,7 @@ public void AddKeys(KeywordCollection keywordCollection) /// public void Reset() { + _key = Keys.None; _isResponsed = false; } @@ -136,34 +135,32 @@ private void Acap_PreTranslateMessage(object sender, PreTranslateMessageEventArg if (!_working || e.Message.message != 256) return; var tempKey = IntPtr.Size == 4 ? (Keys)e.Message.wParam.ToInt32() : (Keys)e.Message.wParam.ToInt64(); var contains = _keyWords.Contains(tempKey); - if (contains) + if (!contains) return; + + // 标记为true,表示此按键已经被处理,Windows不会再进行处理 + if (_workType != SingleKeyWordWorkType.ENTER) + { + e.Handled = true; + } + + if (IsResponsed) return; //放 e.Handled 后是避免在非 ENTER 模式时长按造成动态输入框偶发性闪现关键字以至轻微卡顿问题 + + _key = tempKey; + _isResponsed = true; // 此bool是防止按键被长按时出错 + + switch (_workType) { - // 标记为true,表示此按键已经被处理,Windows不会再进行处理 - if (_workType != SingleKeyWordWorkType.ENTER) - { - e.Handled = true; - } - - if (contains) - _key = tempKey; - if (!_isResponsed) - { - // 此bool是防止按键被长按时出错 - _isResponsed = true; - switch (_workType) - { - case SingleKeyWordWorkType.ESCAPE: - // ESC稳妥一些,但是要判断promptResult的顺序 - KeyBoardSendKey(Keys.Escape); - break; - case SingleKeyWordWorkType.ENTER: - KeyBoardSendKey(Keys.Enter); - break; - case SingleKeyWordWorkType.WRITE_LINE: - Utils.WriteToCommandLine(Convert.ToChar(_key) + _enterStr); - break; - } - } + case SingleKeyWordWorkType.ESCAPE: + // ESC稳妥一些,但是要判断promptResult的顺序 + KeyBoardSendKey(Keys.Escape); + break; + case SingleKeyWordWorkType.ENTER: + KeyBoardSendKey(Keys.Enter); + break; + case SingleKeyWordWorkType.WRITE_LINE: + Utils.SetFocusToDwgView(); // 恢复焦点(如果前面关键字输入错误便会将焦点移至动态输入框) + Utils.WriteToCommandLine(Convert.ToChar(_key) + _enterStr); + break; } } @@ -177,7 +174,7 @@ private void Acap_PreTranslateMessage(object sender, PreTranslateMessageEventArg public bool IsDisposed { get; private set; } /// - /// + /// 拆除事件 /// /// private void Dispose(bool disposing) @@ -195,19 +192,19 @@ private void Dispose(bool disposing) } /// - /// 析够里把事件拆了 + /// 析构里把事件拆了 /// ~SingleKeyWordHook() { - Dispose(disposing: false); + Dispose(false); } /// - /// + /// 拆除事件并清空关键字 /// public void Dispose() { - Dispose(disposing: true); + Dispose(true); GC.SuppressFinalize(this); } -- Gitee From 9025396a05e95ca30c4ae0aa1a49e2fc0f0e600a Mon Sep 17 00:00:00 2001 From: yupeng_dyp Date: Sat, 30 Nov 2024 11:23:25 +0000 Subject: [PATCH 382/453] =?UTF-8?q?update=20src/CADShared/ExtensionMethod/?= =?UTF-8?q?Jig/JigEx.cs.=20=E5=BD=93=E8=AE=BE=E7=BD=AE=20UseBasePoint=20?= =?UTF-8?q?=3D=20true=20=E6=97=B6=EF=BC=8C=E6=8C=89=E4=B8=8B=E5=85=B3?= =?UTF-8?q?=E9=94=AE=E5=AD=97=E7=9A=84=E7=9E=AC=E9=97=B4=E4=BC=9A=E5=B0=86?= =?UTF-8?q?=E9=BC=A0=E6=A0=87=E5=9D=90=E6=A0=87=E7=A7=BB=E8=87=B3=E5=8E=9F?= =?UTF-8?q?=E7=82=B9=EF=BC=8C=E6=8C=89=E5=B8=B8=E8=A7=84=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E5=BA=94=E8=AF=A5=E4=BE=9D=E7=84=B6=E4=B8=BA=E5=BD=93=E5=89=8D?= =?UTF-8?q?=E9=BC=A0=E6=A0=87=E5=9D=90=E6=A0=87=EF=BC=9B=E4=B8=8D=E7=84=B6?= =?UTF-8?q?=E4=BC=9A=E6=9C=89=E9=97=AE=E9=A2=98=EF=BC=8C=E6=AF=94=E5=A6=82?= =?UTF-8?q?=E5=9C=A8=E6=8C=89=E4=B8=8B=E5=85=B3=E9=94=AE=E5=AD=97=E5=90=8E?= =?UTF-8?q?=E5=B0=86=E6=8B=96=E5=8A=A8=E5=AF=B9=E8=B1=A1=E5=A4=8D=E5=88=B6?= =?UTF-8?q?=E4=B8=80=E4=BB=BD=E5=B9=B6=E6=8C=89=E5=BD=93=E5=89=8D=E9=BC=A0?= =?UTF-8?q?=E6=A0=87=E4=BD=8D=E7=BD=AE=E6=B7=BB=E5=8A=A0=E5=88=B0=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E5=BA=93=E5=B0=B1=E4=BC=9A=E5=87=BA=E7=8E=B0=E9=94=99?= =?UTF-8?q?=E8=AF=AF=EF=BC=8C=E6=B7=BB=E5=8A=A0=E7=9A=84=E5=AF=B9=E8=B1=A1?= =?UTF-8?q?=E5=AE=9E=E9=99=85=E8=B7=91=E5=88=B0=E5=8E=9F=E7=82=B9=E5=8E=BB?= =?UTF-8?q?=E4=BA=86=EF=BC=9B=E4=BF=AE=E6=94=B9=E5=90=8E=E5=8F=AF=E4=BF=9D?= =?UTF-8?q?=E6=8C=81=E4=B8=8E=20UseBasePoint=20=3D=20false=20=E6=97=B6?= =?UTF-8?q?=E7=9B=B8=E5=90=8C=EF=BC=8C=E5=8D=B3=E4=BE=9D=E7=84=B6=E4=B8=BA?= =?UTF-8?q?=E5=BD=93=E5=89=8D=E9=BC=A0=E6=A0=87=E5=9D=90=E6=A0=87=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: yupeng_dyp --- src/CADShared/ExtensionMethod/Jig/JigEx.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CADShared/ExtensionMethod/Jig/JigEx.cs b/src/CADShared/ExtensionMethod/Jig/JigEx.cs index 0e6b1af..5a1995e 100644 --- a/src/CADShared/ExtensionMethod/Jig/JigEx.cs +++ b/src/CADShared/ExtensionMethod/Jig/JigEx.cs @@ -1,4 +1,4 @@ -#if a2024 || zcad +#if a2024 || zcad using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif @@ -111,7 +111,7 @@ protected override SamplerStatus Sampler(JigPrompts prompts) lastIsKw = pro.Status == PromptStatus.Keyword; // 上次鼠标点不同(一定要这句,不然图元刷新太快会看到奇怪的边线) - var mousePointWcs = pro.Value; + var mousePointWcs = LastIsKw ? MousePointWcsLast : pro.Value; // == 是比较类字段,但是最好转为哈希比较. // IsEqualTo 是方形判断(仅加法),但是cad是距离. -- Gitee From f6af49d0b2bea13f14962f693eeab4f1502f2302 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Mon, 2 Dec 2024 14:19:21 +0800 Subject: [PATCH 383/453] =?UTF-8?q?=E4=BF=AE=E5=A4=8Djig=E5=85=B3=E9=94=AE?= =?UTF-8?q?=E5=AD=97=E5=9D=90=E6=A0=87=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CADShared/ExtensionMethod/Jig/JigEx.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CADShared/ExtensionMethod/Jig/JigEx.cs b/src/CADShared/ExtensionMethod/Jig/JigEx.cs index 5a1995e..c985110 100644 --- a/src/CADShared/ExtensionMethod/Jig/JigEx.cs +++ b/src/CADShared/ExtensionMethod/Jig/JigEx.cs @@ -1,4 +1,4 @@ -#if a2024 || zcad +#if a2024 || zcad using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif @@ -111,7 +111,7 @@ protected override SamplerStatus Sampler(JigPrompts prompts) lastIsKw = pro.Status == PromptStatus.Keyword; // 上次鼠标点不同(一定要这句,不然图元刷新太快会看到奇怪的边线) - var mousePointWcs = LastIsKw ? MousePointWcsLast : pro.Value; + var mousePointWcs = lastIsKw ? MousePointWcsLast : pro.Value; // == 是比较类字段,但是最好转为哈希比较. // IsEqualTo 是方形判断(仅加法),但是cad是距离. -- Gitee From 1b73ebd7f080d4f25c007aed29e8e83f2714e9da Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Mon, 2 Dec 2024 14:23:15 +0800 Subject: [PATCH 384/453] =?UTF-8?q?=E5=8F=91=E5=B8=830.9.2.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Directory.Build.props | 48 +++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index a5a1f77..0e6a1c4 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,24 +1,24 @@ - - - 0.9.2-preview1 - 增加net8支持,增加zwcad2025支持 + + + 0.9.2-preview2 + 修复jig关键字坐标的问题 - - preview - enable - true - true - true - True - True - x64 - IFoxCAD.CAD - true - true - ..\..\bin\$(Configuration)\ - + + preview + enable + true + true + true + True + True + x64 + IFoxCAD.CAD + true + true + ..\..\bin\$(Configuration)\ + InspireFunction @@ -26,12 +26,12 @@ InspireFunction 基于.NET的二次开发基本类库. true - https://gitee.com/inspirefunction/ifoxcad - https://gitee.com/inspirefunction/ifoxcad.git - git - IFox;cad;AutoCad;C#;NET;ZwCad - readme.md - LICENSE + https://gitee.com/inspirefunction/ifoxcad + https://gitee.com/inspirefunction/ifoxcad.git + git + IFox;cad;AutoCad;C#;NET;ZwCad + readme.md + LICENSE \ No newline at end of file -- Gitee From 18bc6c43f89b613651897fc7a5c43fe9a20baa2c Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sat, 7 Dec 2024 22:28:49 +0800 Subject: [PATCH 385/453] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=85=8B=E9=9A=86Clo?= =?UTF-8?q?neEx=E5=87=BD=E6=95=B0=E7=9A=84=E8=BE=93=E5=85=A5=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=EF=BC=8C=E4=BC=98=E5=8C=96=E9=9D=A2=E5=9F=9F=E8=BD=AC?= =?UTF-8?q?=E6=9B=B2=E7=BA=BF=E7=94=B1=E4=BA=8E=E9=9D=A2=E5=9F=9F=E4=B8=BA?= =?UTF-8?q?=E7=A9=BA=E5=AF=BC=E8=87=B4=E6=9E=84=E5=BB=BAbrep=E6=8A=A5?= =?UTF-8?q?=E9=94=99=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CADShared/ExtensionMethod/DBObjectEx.cs | 9 +++++---- src/CADShared/ExtensionMethod/Entity/RegionEx.cs | 3 +++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/CADShared/ExtensionMethod/DBObjectEx.cs b/src/CADShared/ExtensionMethod/DBObjectEx.cs index 162575c..13c23ce 100644 --- a/src/CADShared/ExtensionMethod/DBObjectEx.cs +++ b/src/CADShared/ExtensionMethod/DBObjectEx.cs @@ -71,12 +71,12 @@ public static void RemoveXData(this DBObject obj, string appName) /// 克隆对象 /// /// 对象类型 - /// 对象 + /// 对象 /// 克隆后的对象 /// - public static T CloneEx(this T ent) where T : RXObject + public static T CloneEx(this T obj) where T : ICloneable { - return ent.Clone() is T tEnt ? tEnt : throw new ArgumentException(nameof(CloneEx) + "克隆出错"); + return obj.Clone() is T tObj ? tObj : throw new ArgumentException(nameof(CloneEx) + "克隆出错"); } /// @@ -86,7 +86,8 @@ public static T CloneEx(this T ent) where T : RXObject /// 应用程序名称 /// 要修改数据的组码 /// 新的数据 - public static void ChangeXData(this DBObject obj, string appName, DxfCode dxfCode, object newValue) + public static void ChangeXData(this DBObject obj, string appName, DxfCode dxfCode, + object newValue) { if (obj.XData is null) return; diff --git a/src/CADShared/ExtensionMethod/Entity/RegionEx.cs b/src/CADShared/ExtensionMethod/Entity/RegionEx.cs index 6cb3c0d..c832305 100644 --- a/src/CADShared/ExtensionMethod/Entity/RegionEx.cs +++ b/src/CADShared/ExtensionMethod/Entity/RegionEx.cs @@ -1,5 +1,6 @@ #if acad using Autodesk.AutoCAD.BoundaryRepresentation; + #elif zcad using ZwSoft.ZwCAD.BoundaryRepresentation; #endif @@ -17,6 +18,8 @@ public static class RegionEx /// 曲线集合 public static IEnumerable ToCurves(this Region region) { + if (region.IsNull) + yield break; using var brep = new Brep(region); var loops = brep.Complexes.SelectMany(complex => complex.Shells) .SelectMany(shell => shell.Faces) -- Gitee From 7f9f9830ee5a0fd586cdf2f2e36bae5beb24c9d5 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sat, 7 Dec 2024 22:29:29 +0800 Subject: [PATCH 386/453] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E9=A1=B9=E7=9B=AE?= =?UTF-8?q?=E5=AD=97=E5=85=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IFoxCAD.sln.DotSettings | 1 + 1 file changed, 1 insertion(+) diff --git a/IFoxCAD.sln.DotSettings b/IFoxCAD.sln.DotSettings index 4cfd0e2..fd6a739 100644 --- a/IFoxCAD.sln.DotSettings +++ b/IFoxCAD.sln.DotSettings @@ -4,6 +4,7 @@ OS True True + True True True True -- Gitee From aaeb969082cdd6577b5a605f58625ef24e9f922a Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sat, 7 Dec 2024 22:34:58 +0800 Subject: [PATCH 387/453] =?UTF-8?q?=E5=8F=91=E5=B8=830.9.2-preview3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 0e6a1c4..89bc874 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,7 +1,7 @@ - 0.9.2-preview2 + 0.9.2-preview3 修复jig关键字坐标的问题 -- Gitee From 29fba210671a8cf5c75ae93c57eca02cd97e7cf3 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Mon, 9 Dec 2024 12:13:51 +0800 Subject: [PATCH 388/453] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=A1=AB=E5=85=85?= =?UTF-8?q?=E9=80=89=E6=8B=A9=E7=AA=97=E5=8F=A3HatchDialog?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CADShared/CADShared.projitems | 1 + .../ExtensionMethod/Hatch/HatchDialog.cs | 52 +++++++++++++++++++ .../Runtime/SystemVariableManager.cs | 9 ++++ 3 files changed, 62 insertions(+) create mode 100644 src/CADShared/ExtensionMethod/Hatch/HatchDialog.cs diff --git a/src/CADShared/CADShared.projitems b/src/CADShared/CADShared.projitems index a1e20cb..c0c7ea9 100644 --- a/src/CADShared/CADShared.projitems +++ b/src/CADShared/CADShared.projitems @@ -56,6 +56,7 @@ + diff --git a/src/CADShared/ExtensionMethod/Hatch/HatchDialog.cs b/src/CADShared/ExtensionMethod/Hatch/HatchDialog.cs new file mode 100644 index 0000000..7c71d3f --- /dev/null +++ b/src/CADShared/ExtensionMethod/Hatch/HatchDialog.cs @@ -0,0 +1,52 @@ +#if acad + +namespace IFoxCAD.Cad; + +/// +/// 填充图案选择对话框
    +/// 只是为了保持和其他Cad内置Dialog的使用一致性,并非真正的Dialog +///
    +public class HatchDialog +{ + /// + /// 构造函数 + /// + public HatchDialog(string? name = null, bool showCustom = true) + { + // 默认填充图案名称为当前名称 + Name = name ?? SystemVariableManager.HPName; + ShowCustom = showCustom; + } + + /// + /// 填充图案名称 + /// + public string Name { get; set; } + + /// + /// 显示自定义图案 + /// + public bool ShowCustom { get; set; } + + /// + /// 模态显示图案选择对话框 + /// + /// 成功返回true + public bool ShowDialog() + { + var dr = ShowHatchPaletteDialog(Name, ShowCustom, out var newPattern); + if (dr) + { + Name = Marshal.PtrToStringAuto(newPattern) ?? ""; + } + + return dr; + } + + [DllImport("acad.exe", CharSet = CharSet.Auto, + EntryPoint = "?acedHatchPalletteDialog@@YA_NPEB_W_NAEAPEA_W@Z")] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool ShowHatchPaletteDialog(string currentPattern, + [MarshalAs(UnmanagedType.Bool)] bool showCustom, out IntPtr newPattern); +} +#endif \ No newline at end of file diff --git a/src/CADShared/Runtime/SystemVariableManager.cs b/src/CADShared/Runtime/SystemVariableManager.cs index a418ea7..f502c1d 100644 --- a/src/CADShared/Runtime/SystemVariableManager.cs +++ b/src/CADShared/Runtime/SystemVariableManager.cs @@ -248,6 +248,15 @@ public bool GridMode #region H + /// + /// 当前填充的名称 + /// + public static string HPName + { + get => Acaop.GetSystemVariable(nameof(HPName)).ToString()!; + set => Acaop.SetSystemVariable(nameof(HPName), value); + } + /// /// 填充比例 /// -- Gitee From 460c314e71af440cbf63b6b2b724f71684537594 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Mon, 9 Dec 2024 12:17:27 +0800 Subject: [PATCH 389/453] =?UTF-8?q?=E5=8F=91=E5=B8=830.9.2-preview4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Directory.Build.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 89bc874..faf83c7 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,8 +1,8 @@ - 0.9.2-preview3 - 修复jig关键字坐标的问题 + 0.9.2-preview4 + 添加填充选择窗口HatchDialog -- Gitee From 04dcf4a9ee83b7110366562d71239536901b24b9 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 12 Dec 2024 15:49:37 +0800 Subject: [PATCH 390/453] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=80=89=E6=8B=A9?= =?UTF-8?q?=E9=9B=86=E5=85=B3=E9=94=AE=E5=AD=97=E6=8F=90=E7=A4=BA=E8=AF=AD?= =?UTF-8?q?=E6=8B=BC=E6=8E=A5=E4=B8=8D=E6=AD=A3=E7=A1=AE=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CADShared/ExtensionMethod/PromptOptionsEx.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/CADShared/ExtensionMethod/PromptOptionsEx.cs b/src/CADShared/ExtensionMethod/PromptOptionsEx.cs index 45c5341..637cc7c 100644 --- a/src/CADShared/ExtensionMethod/PromptOptionsEx.cs +++ b/src/CADShared/ExtensionMethod/PromptOptionsEx.cs @@ -1,4 +1,5 @@ // ReSharper disable UnusedAutoPropertyAccessor.Global + namespace IFoxCAD.Cad; /// @@ -26,13 +27,13 @@ public static void AddKeywords(this PromptSelectionOptions pso, params string[] { for (var i = 0; i < keywords.Length / 2; i++) { - var key = keywords[i].ToUpper(); + var key = keywords[i * 2].ToUpper(); if (SsGetSaveKeywords.FirstOrDefault(e => e.StartsWith(key)) is { } saveKey) { throw new ArgumentException($"关键字{key}与选择集保留关键字{saveKey}冲突"); } - var message = keywords[i + 1]; + var message = keywords[i * 2 + 1]; var end = $"({key})"; if (!message.EndsWith(end)) { -- Gitee From 6e7fd38223badada2e401e7e00a7b7142d068583 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 12 Dec 2024 16:05:13 +0800 Subject: [PATCH 391/453] =?UTF-8?q?=E5=8F=91=E5=B8=830.9.2-preview5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Directory.Build.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index faf83c7..9c29f76 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,8 +1,8 @@ - 0.9.2-preview4 - 添加填充选择窗口HatchDialog + 0.9.2-preview5 + 修复选择集关键字提示语拼接不正确的问题 -- Gitee From ea73facda61fd47d87100f05067b35fa4995850f Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Fri, 13 Dec 2024 16:28:23 +0800 Subject: [PATCH 392/453] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=82=B9=E5=9C=A8?= =?UTF-8?q?=E5=A4=9A=E8=BE=B9=E5=BD=A2=E5=86=85=E7=9A=84=E5=88=A4=E6=96=AD?= =?UTF-8?q?=E9=80=BB=E8=BE=91=EF=BC=8C=E5=8F=91=E5=B8=830.9.2-preview6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/Geomerty/GeometryEx.cs | 243 +++++++++++------- src/Directory.Build.props | 4 +- src/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj | 2 +- tests/TestShared/TestPointOnRegion.cs | 24 ++ tests/TestShared/TestShared.projitems | 1 + 5 files changed, 175 insertions(+), 99 deletions(-) create mode 100644 tests/TestShared/TestPointOnRegion.cs diff --git a/src/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs b/src/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs index 3558994..5672631 100644 --- a/src/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs +++ b/src/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs @@ -21,17 +21,33 @@ public static class GeometryEx /// 点与多边形的关系 public static PointOnRegionType PointOnRegion(this IEnumerable pts, Point2d pt) { - // 遍历点集并生成首尾连接的多边形 - var ptlst = new LoopList(pts); - if (ptlst.Count < 3) + var ptList = pts.ToList(); + if (ptList.Count < 3) + return PointOnRegionType.Error; + if (ptList[0] == ptList[1]) + { + ptList.RemoveAt(ptList.Count - 1); + } + + if (ptList.Count < 3) return PointOnRegionType.Error; List ls2ds = []; - foreach (var node in ptlst.GetNodes()) + for (var i = 0; i < ptList.Count - 1; i++) + { + ls2ds.Add(new LineSegment2d(ptList[i], ptList[i + 1])); + } + + ls2ds.Add(new LineSegment2d(ptList[^1], ptList[0])); + using var cc2d = new CompositeCurve2d(ls2ds.ToArray()); + + // 释放资源 + foreach (var curve2d in ls2ds) { - ls2ds.Add(new LineSegment2d(node.Value, node.Next!.Value)); + using (curve2d) + { + } } - var cc2d = new CompositeCurve2d(ls2ds.ToArray()); // 在多边形上? if (cc2d.IsOn(pt)) @@ -42,25 +58,46 @@ public static PointOnRegionType PointOnRegion(this IEnumerable pts, Poi if (!bb2d.Contains(pt)) return PointOnRegionType.Outside; - // + #region 旧版疑似有问题的代码 + + // // + // var flag = false; + // foreach (var node in ptlst.GetNodes()) + // { + // var pt1 = node.Value; + // var pt2 = node.Next!.Value; + // if (pt.Y < pt1.Y && pt.Y < pt2.Y) + // continue; + // if (pt1.X < pt.X && pt2.X < pt.X) + // continue; + // var vec = pt2 - pt1; + // var t = (pt.X - pt1.X) / vec.X; + // var y = t * vec.Y + pt1.Y; + // if (y < pt.Y && t >= 0 && t <= 1) + // flag = !flag; + // } + // return + // flag ? + // PointOnRegionType.Inside : PointOnRegionType.Outside; + + #endregion + var flag = false; - foreach (var node in ptlst.GetNodes()) + var j = ptList.Count - 1; + for (var i = 0; i < ptList.Count; i++) { - var pt1 = node.Value; - var pt2 = node.Next!.Value; - if (pt.Y < pt1.Y && pt.Y < pt2.Y) - continue; - if (pt1.X < pt.X && pt2.X < pt.X) - continue; - var vec = pt2 - pt1; - var t = (pt.X - pt1.X) / vec.X; - var y = t * vec.Y + pt1.Y; - if (y < pt.Y && t >= 0 && t <= 1) - flag = !flag; + var pi = ptList[i]; + var pj = ptList[j]; + if ((pi.Y < pt.Y && pj.Y >= pt.Y || pj.Y < pt.Y && pi.Y >= pt.Y) && + (pi.X <= pt.X || pj.X <= pt.X)) + { + flag ^= pi.X + (pt.Y - pi.Y) / (pj.Y - pi.Y) * (pj.X - pi.X) < pt.X; + } + + j = i; } - return - flag ? - PointOnRegionType.Inside : PointOnRegionType.Outside; + + return flag ? PointOnRegionType.Inside : PointOnRegionType.Outside; } /// @@ -71,46 +108,60 @@ public static PointOnRegionType PointOnRegion(this IEnumerable pts, Poi /// 点与多边形的关系 public static PointOnRegionType PointOnRegion(this IEnumerable pts, Point3d pt) { - // 遍历点集并生成首尾连接的多边形 - var ptlst = new LoopList(pts); - if (ptlst.First!.Value == ptlst.Last!.Value) - ptlst.RemoveLast(); - if (ptlst.Count < 3) + var ptList = pts.ToList(); + if (ptList.Count < 3) + return PointOnRegionType.Error; + if (ptList[0] == ptList[1]) + { + ptList.RemoveAt(ptList.Count - 1); + } + + if (ptList.Count < 3) return PointOnRegionType.Error; List ls3ds = []; - foreach (var node in ptlst.GetNodes()) - ls3ds.Add(new LineSegment3d(node.Value, node.Next!.Value)); - var cc3d = new CompositeCurve3d(ls3ds.ToArray()); + for (var i = 0; i < ptList.Count - 1; i++) + { + ls3ds.Add(new LineSegment3d(ptList[i], ptList[i + 1])); + } + + ls3ds.Add(new LineSegment3d(ptList[^1], ptList[0])); + using var cc3d = new CompositeCurve3d(ls3ds.ToArray()); + + // 释放资源 + foreach (var curve3d in ls3ds) + { + using (curve3d) + { + } + } // 在多边形上? if (cc3d.IsOn(pt)) return PointOnRegionType.On; // 在最小包围矩形外? - var bb2d = cc3d.BoundBlock; - if (!bb2d.Contains(pt)) + var bb3d = cc3d.BoundBlock; + if (!bb3d.Contains(pt)) return PointOnRegionType.Outside; - // + var flag = false; - foreach (var node in ptlst.GetNodes()) + var j = ptList.Count - 1; + for (var i = 0; i < ptList.Count; i++) { - var pt1 = node.Value; - var pt2 = node.Next!.Value; - if (pt.Y < pt1.Y && pt.Y < pt2.Y) - continue; - if (pt1.X < pt.X && pt2.X < pt.X) - continue; - var vec = pt2 - pt1; - var t = (pt.X - pt1.X) / vec.X; - var y = t * vec.Y + pt1.Y; - if (y < pt.Y && t >= 0 && t <= 1) - flag = !flag; + var pi = ptList[i]; + var pj = ptList[j]; + if ((pi.Y < pt.Y && pj.Y >= pt.Y || pj.Y < pt.Y && pi.Y >= pt.Y) && + (pi.X <= pt.X || pj.X <= pt.X)) + { + flag ^= pi.X + (pt.Y - pi.Y) / (pj.Y - pi.Y) * (pj.X - pi.X) < pt.X; + } + + j = i; } - return - flag ? - PointOnRegionType.Inside : PointOnRegionType.Outside; + + return flag ? PointOnRegionType.Inside : PointOnRegionType.Outside; } /// @@ -123,12 +174,7 @@ public static PointOnRegionType PointOnRegion(this IEnumerable pts, Poi public static CircularArc2d GetMinCircle(Point2d pt1, Point2d pt2, out LoopList ptlst) { ptlst = [pt1, pt2]; - return - new CircularArc2d - ( - (pt1 + pt2.GetAsVector()) / 2, - pt1.GetDistanceTo(pt2) / 2 - ); + return new CircularArc2d((pt1 + pt2.GetAsVector()) / 2, pt1.GetDistanceTo(pt2) / 2); } /// @@ -139,21 +185,17 @@ public static CircularArc2d GetMinCircle(Point2d pt1, Point2d pt2, out LoopList< /// 基准点 /// 输出圆上的点 /// 解析类圆对象 - public static CircularArc2d GetMinCircle(Point2d pt1, Point2d pt2, Point2d pt3, out LoopList ptlst) + public static CircularArc2d GetMinCircle(Point2d pt1, Point2d pt2, Point2d pt3, + out LoopList ptlst) { ptlst = [pt1, pt2, pt3]; // 遍历各点与下一点的向量长度,找到距离最大的两个点 - var maxNode = - ptlst.GetNodes().FindByMax - ( - out _, - node => node.Value.GetDistanceTo(node.Next!.Value) - ); + var maxNode = ptlst.GetNodes() + .FindByMax(out _, node => node.Value.GetDistanceTo(node.Next!.Value)); // 以两点做最小包围圆 - var ca2d = - GetMinCircle(maxNode.Value, maxNode.Next!.Value, out var tptlst); + var ca2d = GetMinCircle(maxNode.Value, maxNode.Next!.Value, out var tptlst); // 如果另一点属于该圆 if (ca2d.IsIn(maxNode.Previous!.Value)) @@ -162,6 +204,7 @@ public static CircularArc2d GetMinCircle(Point2d pt1, Point2d pt2, Point2d pt3, ptlst = tptlst; return ca2d; } + // 否则按三点做圆 // ptlst.SetFirst(maxNode); ptlst = [maxNode.Value, maxNode.Next.Value, maxNode.Previous.Value]; @@ -179,7 +222,8 @@ public static CircularArc2d GetMinCircle(Point2d pt1, Point2d pt2, Point2d pt3, /// 基准点 /// 输出圆上的点 /// 解析类圆对象 - public static CircularArc2d? GetMinCircle(Point2d pt1, Point2d pt2, Point2d pt3, Point2d pt4, out LoopList? ptlst) + public static CircularArc2d? GetMinCircle(Point2d pt1, Point2d pt2, Point2d pt3, Point2d pt4, + out LoopList? ptlst) { var iniptlst = new LoopList() { pt1, pt2, pt3, pt4 }; ptlst = null; @@ -191,7 +235,8 @@ public static CircularArc2d GetMinCircle(Point2d pt1, Point2d pt2, Point2d pt3, // 获取各组合下三点的最小包围圆 var secondNode = firstNode.Next; var thirdNode = secondNode!.Next; - var tca2d = GetMinCircle(firstNode.Value, secondNode.Value, thirdNode!.Value, out var tptlst); + var tca2d = GetMinCircle(firstNode.Value, secondNode.Value, thirdNode!.Value, + out var tptlst); // 如果另一点属于该圆,并且半径小于当前值就把它做为候选解 if (!tca2d.IsIn(firstNode.Previous!.Value)) @@ -218,6 +263,7 @@ private static double CalArea(Point2d ptBase, Point2d pt1, Point2d pt2) { return (pt2 - ptBase).DotProduct((pt1 - ptBase).GetPerpendicularVector()) * 0.5; } + /// /// 计算三点围成的三角形的真实面积 /// @@ -311,6 +357,7 @@ private static double CalArea(IEnumerable pnts) area = (area + (p2.X * start.Y - start.X * p2.Y)) / 2.0; return area; } + /// /// 计算点集的真实面积 /// @@ -348,21 +395,21 @@ public static OrientationType IsClockWise(this IEnumerable pnts) switch (pnts.Count) { case 0: - ptlst = null; - return null; + ptlst = null; + return null; case 1: - ptlst = [pnts[0]]; - return new CircularArc2d(pnts[0], 0); + ptlst = [pnts[0]]; + return new CircularArc2d(pnts[0], 0); case 2: - return GetMinCircle(pnts[0], pnts[1], out ptlst); + return GetMinCircle(pnts[0], pnts[1], out ptlst); case 3: - return GetMinCircle(pnts[0], pnts[1], pnts[2], out ptlst); + return GetMinCircle(pnts[0], pnts[1], pnts[2], out ptlst); case 4: - return GetMinCircle(pnts[0], pnts[1], pnts[2], pnts[3], out ptlst); + return GetMinCircle(pnts[0], pnts[1], pnts[2], pnts[3], out ptlst); } // 按前三点计算最小包围圆 @@ -388,10 +435,9 @@ public static OrientationType IsClockWise(this IEnumerable pnts) { // 第三点取另两点中距离圆心较远的点 // 按算法中描述的任选其中一点的话,还是无法收敛...... - tpnts[2] = - tpnts.Except(ptlst) - .FindByMax(pnt => ca2d!.Center.GetDistanceTo(pnt)); + tpnts[2] = tpnts.Except(ptlst).FindByMax(pnt => ca2d!.Center.GetDistanceTo(pnt)); } + tpnts[0] = ptlst.First!.Value; tpnts[1] = ptlst.First.Next!.Value; @@ -418,13 +464,13 @@ public static List ConvexHull(this List points) int n = points.Count, k = 0; List H = [..new Point2d[2 * n]]; - points.Sort((a, b) => - a.X == b.X ? a.Y.CompareTo(b.Y) : a.X.CompareTo(b.X)); + points.Sort((a, b) => a.X == b.X ? a.Y.CompareTo(b.Y) : a.X.CompareTo(b.X)); // Build lower hull for (var i = 0; i < n; ++i) { - while (k >= 2 && IsClockWise(H[k - 2], H[k - 1], points[i]) == OrientationType.CounterClockWise) + while (k >= 2 && IsClockWise(H[k - 2], H[k - 1], points[i]) == + OrientationType.CounterClockWise) k--; H[k++] = points[i]; } @@ -432,14 +478,15 @@ public static List ConvexHull(this List points) // Build upper hull for (int i = n - 2, t = k + 1; i >= 0; i--) { - while (k >= t && IsClockWise(H[k - 2], H[k - 1], points[i]) == OrientationType.CounterClockWise) + while (k >= t && IsClockWise(H[k - 2], H[k - 1], points[i]) == + OrientationType.CounterClockWise) k--; H[k++] = points[i]; } + return H.Take(k - 1).ToList(); } - #endregion PointList #endregion Point&Circle @@ -493,7 +540,8 @@ public static Vector3d Wcs2Ucs(this Vector3d vec) /// 源坐标系 /// 目标坐标系 /// 变换后的点 - public static Point3d Trans(this Point3d point, CoordinateSystemCode from, CoordinateSystemCode to) + public static Point3d Trans(this Point3d point, CoordinateSystemCode from, + CoordinateSystemCode to) { return Env.Editor.GetMatrix(from, to) * point; } @@ -505,7 +553,8 @@ public static Point3d Trans(this Point3d point, CoordinateSystemCode from, Coord /// 源坐标系 /// 目标坐标系 /// 变换后的向量 - public static Vector3d Trans(this Vector3d vec, CoordinateSystemCode from, CoordinateSystemCode to) + public static Vector3d Trans(this Vector3d vec, CoordinateSystemCode from, + CoordinateSystemCode to) { return vec.TransformBy(Env.Editor.GetMatrix(from, to)); } @@ -518,11 +567,8 @@ public static Vector3d Trans(this Vector3d vec, CoordinateSystemCode from, Coord /// 变换后的点 public static Point3d Wcs2Dcs(this Point3d point, bool atPaperSpace) { - return - Trans( - point, - CoordinateSystemCode.Wcs, atPaperSpace ? CoordinateSystemCode.PDcs : CoordinateSystemCode.MDcs - ); + return Trans(point, CoordinateSystemCode.Wcs, + atPaperSpace ? CoordinateSystemCode.PDcs : CoordinateSystemCode.MDcs); } /// @@ -533,16 +579,12 @@ public static Point3d Wcs2Dcs(this Point3d point, bool atPaperSpace) /// 变换后的向量 public static Vector3d Wcs2Dcs(this Vector3d vec, bool atPaperSpace) { - return - Trans( - vec, - CoordinateSystemCode.Wcs, atPaperSpace ? CoordinateSystemCode.PDcs : CoordinateSystemCode.MDcs - ); + return Trans(vec, CoordinateSystemCode.Wcs, + atPaperSpace ? CoordinateSystemCode.PDcs : CoordinateSystemCode.MDcs); } #endregion Ucs - /// /// 返回不等比例变换矩阵 /// @@ -585,6 +627,7 @@ public static void Draw(this Geometry geometry, IEnumerable drawables) { drawables.ForEach(d => geometry.Draw(d)); } + /// /// 重绘 /// @@ -595,6 +638,7 @@ public static void Draw(this Geometry geometry, params Drawable[] drawables) drawables.ForEach(d => geometry.Draw(d)); } } + /// /// 向量扩展类 /// @@ -620,6 +664,7 @@ public static Vector3d Convert3d(this Vector2d vector2d, double z = 0) { return new Vector3d(vector2d.X, vector2d.Y, z); } + /// /// 2d叉乘 /// @@ -630,6 +675,7 @@ public static double Cross2d(this Vector3d a, Vector3d b) { return a.X * b.Y - b.X * a.Y; } + /// /// 2d叉乘 /// @@ -640,6 +686,7 @@ public static double Cross2d(this Vector2d a, Vector2d b) { return a.X * b.Y - b.X * a.Y; } + /// /// 向量Z值归零 /// @@ -649,6 +696,7 @@ public static Vector3d Z20(this Vector3d vector3d) { return new Vector3d(vector3d.X, vector3d.Y, 0); } + /// /// 向量在平面上的弧度 /// @@ -660,6 +708,7 @@ public static double AngleOnPlane(this Vector3d vector, Plane? plane = null) return vector.AngleOnPlane(plane ?? PlaneEx.Z); } } + /// /// 平面 /// @@ -668,13 +717,15 @@ public static class PlaneEx /// /// X /// - public static readonly Plane X = new (Point3d.Origin, Vector3d.XAxis); + public static readonly Plane X = new(Point3d.Origin, Vector3d.XAxis); + /// /// Y /// - public static readonly Plane Y = new (Point3d.Origin, Vector3d.YAxis); + public static readonly Plane Y = new(Point3d.Origin, Vector3d.YAxis); + /// /// Z /// - public static readonly Plane Z = new (Point3d.Origin, Vector3d.ZAxis); + public static readonly Plane Z = new(Point3d.Origin, Vector3d.ZAxis); } \ No newline at end of file diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 9c29f76..36d97ae 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,8 +1,8 @@ - 0.9.2-preview5 - 修复选择集关键字提示语拼接不正确的问题 + 0.9.2-preview6 + 优化点在多边形内的判断逻辑 diff --git a/src/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj b/src/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj index d2d9d1c..d6c0b91 100644 --- a/src/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj +++ b/src/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj @@ -1,7 +1,7 @@  - net48;net8.0-windows + net8.0-windows;net48 diff --git a/tests/TestShared/TestPointOnRegion.cs b/tests/TestShared/TestPointOnRegion.cs new file mode 100644 index 0000000..62996a7 --- /dev/null +++ b/tests/TestShared/TestPointOnRegion.cs @@ -0,0 +1,24 @@ +namespace TestAcad2025; + +public static class TestPointOnRegion +{ + [CommandMethod(nameof(TestPointOnRegionCommand))] + public static void TestPointOnRegionCommand() + { + var r1 = Env.Editor.GetEntity("\n选择多段线"); + if (r1.Status != PromptStatus.OK) + return; + using var tr = new DBTrans(); + if (tr.GetObject(r1.ObjectId) is not Polyline pl || pl.HasBulges) + return; + var stretchPoints = pl.GetStretchPoints(); + while (true) + { + var r2 = Env.Editor.GetPoint("\n选择点"); + if (r2.Status != PromptStatus.OK) + return; + var pt = r2.Value.Ucs2Wcs(); + stretchPoints.PointOnRegion(pt).Print(); + } + } +} \ No newline at end of file diff --git a/tests/TestShared/TestShared.projitems b/tests/TestShared/TestShared.projitems index 4ca3fc1..4dfb640 100644 --- a/tests/TestShared/TestShared.projitems +++ b/tests/TestShared/TestShared.projitems @@ -36,6 +36,7 @@ + -- Gitee From f2e29b95e64c18583b7e7e18179a0ac2dccad8dd Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 26 Dec 2024 08:55:37 +0800 Subject: [PATCH 393/453] =?UTF-8?q?=E8=A7=A3=E5=86=B3=E7=94=B1=E4=BA=8Epe?= =?UTF-8?q?=E5=AF=BC=E8=87=B4=E7=9A=84=E7=BC=96=E8=AF=91=E4=B8=8D=E9=80=9A?= =?UTF-8?q?=E8=BF=87=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CADShared/PE/ProgramPE.cs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/CADShared/PE/ProgramPE.cs b/src/CADShared/PE/ProgramPE.cs index fc9587d..d0d61bd 100644 --- a/src/CADShared/PE/ProgramPE.cs +++ b/src/CADShared/PE/ProgramPE.cs @@ -85,8 +85,8 @@ public class PeInfo /// public PeInfo(string fullName) { - if (fullName is null) - throw new ArgumentException(nameof(fullName)); + if (string.IsNullOrWhiteSpace(fullName)) + throw new ArgumentNullException(nameof(fullName)); FullName = fullName; FileStream? file = null; @@ -94,9 +94,7 @@ public PeInfo(string fullName) try { // 文件流 - file = new FileStream(fullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);// FileShare才能进c盘 - _PEFileByte = new byte[file.Length]; - file.Read(_PEFileByte, 0, _PEFileByte.Length); + _PEFileByte = File.ReadAllBytes(fullName); LoadFile(); OpenFile = true; } -- Gitee From e04e328b2e2b14cabd36a578208161f7e05f3252 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 26 Dec 2024 09:03:09 +0800 Subject: [PATCH 394/453] =?UTF-8?q?=E8=B0=83=E6=95=B4jig=E7=9A=84=E6=A0=BC?= =?UTF-8?q?=E5=BC=8F=EF=BC=8C=E8=A1=A5=E5=85=85=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CADShared/ExtensionMethod/Jig/JigEx.cs | 34 ++++++++++++---------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/src/CADShared/ExtensionMethod/Jig/JigEx.cs b/src/CADShared/ExtensionMethod/Jig/JigEx.cs index c985110..7289922 100644 --- a/src/CADShared/ExtensionMethod/Jig/JigEx.cs +++ b/src/CADShared/ExtensionMethod/Jig/JigEx.cs @@ -1,5 +1,9 @@ #if a2024 || zcad using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; + +// ReSharper disable ClassWithVirtualMembersNeverInherited.Global + +// ReSharper disable MemberCanBePrivate.Global #endif namespace IFoxCAD.Cad; @@ -17,13 +21,12 @@ namespace IFoxCAD.Cad; /// /// 重绘事件 /// -/// +/// worldDraw public delegate void WorldDrawEvent(WorldDraw draw); /// /// jig扩展类 /// -// ReSharper disable once ClassWithVirtualMembersNeverInherited.Global public class JigEx : DrawJig, IDisposable { #region 成员 @@ -31,7 +34,7 @@ public class JigEx : DrawJig, IDisposable /// /// 事件:亮显/暗显会被刷新冲刷掉,所以这个事件用于补充非刷新的工作 /// - event WorldDrawEvent? WorldDrawEvent; + private event WorldDrawEvent? WorldDrawEvent; /// /// 最后的鼠标点,用来确认长度 @@ -46,11 +49,12 @@ public class JigEx : DrawJig, IDisposable /// /// 鼠标移动时的委托 /// - readonly Action>? _mouseAction; - readonly Tolerance _tolerance; // 容差 + private readonly Action>? _mouseAction; + + private readonly Tolerance _tolerance; // 容差 - readonly Queue _drawEntities; // 委托内重复生成的图元,放在这里刷新 - JigPromptPointOptions? _options; // jig鼠标配置 + private readonly Queue _drawEntities; // 委托内重复生成的图元,放在这里刷新 + private JigPromptPointOptions? _options; // jig鼠标配置 private bool _worldDrawFlag; // 20220503 #endregion @@ -60,7 +64,7 @@ public class JigEx : DrawJig, IDisposable /// /// 在界面绘制图元 /// - JigEx() + private JigEx() { _drawEntities = new(); DimensionEntities = new(); @@ -248,7 +252,7 @@ public JigPromptPointOptions SetOptions(string msg, /// /// 鼠标配置:自定义 /// - /// + /// 拖拽设置委托 public void SetOptions(Action action) { _options = new JigPromptPointOptions(); @@ -270,7 +274,6 @@ public PromptResult Drag() return dr; } - #region 配置 /// @@ -278,7 +281,7 @@ public PromptResult Drag() /// 令jig.Drag().Status == /// /// Jig配置 - static JigPromptPointOptions JigPointOptions() + private static JigPromptPointOptions JigPointOptions() { return new JigPromptPointOptions() { @@ -300,7 +303,8 @@ public void SetSpaceIsKeyword() ArgumentNullException.ThrowIfNull(opt); if ((opt.UserInputControls & UserInputControls.NullResponseAccepted) == UserInputControls.NullResponseAccepted) opt.UserInputControls ^= UserInputControls.NullResponseAccepted; // 输入了鼠标右键,结束jig - if ((opt.UserInputControls & UserInputControls.AnyBlankTerminatesInput) == UserInputControls.AnyBlankTerminatesInput) + if ((opt.UserInputControls & UserInputControls.AnyBlankTerminatesInput) == + UserInputControls.AnyBlankTerminatesInput) opt.UserInputControls ^= UserInputControls.AnyBlankTerminatesInput; // 空格或回车,结束jig } @@ -331,7 +335,7 @@ protected override DynamicDimensionDataCollection GetDynamicDimensionData(double #region IDisposable接口相关函数 /// - /// + /// 已经销毁 /// public bool IsDisposed { get; private set; } @@ -353,9 +357,9 @@ public void Dispose() } /// - /// + /// 销毁 /// - /// + /// 正常销毁 protected virtual void Dispose(bool disposing) { // 不重复释放,并设置已经释放 -- Gitee From 943a6a134e12dd98383d607c78abf8419498079c Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 26 Dec 2024 09:35:57 +0800 Subject: [PATCH 395/453] =?UTF-8?q?=E8=A1=A5=E5=85=85=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CADShared/ExtensionMethod/EditorEx.cs | 97 +++++++++++------------ 1 file changed, 46 insertions(+), 51 deletions(-) diff --git a/src/CADShared/ExtensionMethod/EditorEx.cs b/src/CADShared/ExtensionMethod/EditorEx.cs index 9d2f6c8..bd18a46 100644 --- a/src/CADShared/ExtensionMethod/EditorEx.cs +++ b/src/CADShared/ExtensionMethod/EditorEx.cs @@ -1,4 +1,5 @@ using ArgumentNullException = System.ArgumentNullException; +// ReSharper disable MemberCanBePrivate.Global namespace IFoxCAD.Cad; @@ -17,9 +18,9 @@ public static class EditorEx /// 过滤器 /// 选择集结果类 public static PromptSelectionResult SelectAtPoint(this Editor editor, Point3d point, - SelectionFilter? filter = default) + SelectionFilter? filter = null) { - return editor.SelectCrossingWindow(point, point, filter); + return editor.SelectCrossingWindow(point, point, filter?? new SelectionFilter([])); } /// @@ -149,7 +150,6 @@ public static PromptSelectionResult SSGet(this Editor editor, string? mode = nul /// /// 选择集配置 /// 关键字,回调委托 - /// public static void SsgetAddKeys(this PromptSelectionOptions pso, Dictionary dicActions) { @@ -163,9 +163,8 @@ public static void SsgetAddKeys(this PromptSelectionOptions pso, if (keySp.Length < 2) continue; - for (var j = 0; j < keySp.Length; j++) + foreach (var item in keySp) { - var item = keySp[j]; // 防止多个后缀通过|符越过词典约束同名 // 后缀(key)含有,而且Action(value)不同,就把Action(value)累加到后面. if (dicActions.TryGetValue(item, out var value)) @@ -236,7 +235,6 @@ public static void SsgetAddKeys(this PromptSelectionOptions pso, // Env.Editor.SelectionAdded += SelectTest_SelectionAdded; // // 初始化坐标系 // Env.Editor.CurrentUserCoordinateSystem = Matrix3d.Identity; - // // 创建过滤器 // var sf = new OpEqual(0, "arc"); // var pso = new PromptSelectionOptions @@ -254,7 +252,6 @@ public static void SsgetAddKeys(this PromptSelectionOptions pso, // // 用户选择 // var psr = Env.Editor.GetSelection(pso, sf); // // 处理代码 - // } // catch (Exception ex)// 捕获关键字 // { @@ -478,28 +475,26 @@ public static bool Acceptable() /// public static List GetLines(IEnumerable pnts, bool isClosed) { - using var itor = pnts.GetEnumerator(); - if (!itor.MoveNext()) + using var enumerator = pnts.GetEnumerator(); + if (!enumerator.MoveNext()) return []; List values = []; - TypedValue tvFirst = new((int)LispDataType.Point2d, itor.Current); - TypedValue tv1; - var tv2 = tvFirst; + TypedValue first = new((int)LispDataType.Point2d, enumerator.Current); + var last = first; - while (itor.MoveNext()) + while (enumerator.MoveNext()) { - tv1 = tv2; - tv2 = new TypedValue((int)LispDataType.Point2d, itor.Current); - values.Add(tv1); - values.Add(tv2); + values.Add(last); + last = new TypedValue((int)LispDataType.Point2d, enumerator.Current); + values.Add(last); } if (isClosed) { - values.Add(tv2); - values.Add(tvFirst); + values.Add(last); + values.Add(first); } return values; @@ -592,14 +587,13 @@ public static void DrawCircle(this Editor editor, Point2d pnt, short colorIndex, public static void DrawLineVectors(this Editor editor, IEnumerable points, int colorIndex = 1, bool drawHighlighted = false) { - Point3d endPoint1, endPoint2; using var itor = points.GetEnumerator(); while (itor.MoveNext()) { - endPoint1 = itor.Current; + var endPoint1 = itor.Current; if (!itor.MoveNext()) return; - endPoint2 = itor.Current; + var endPoint2 = itor.Current; editor.DrawVector(endPoint1, endPoint2, colorIndex, drawHighlighted); } } @@ -610,13 +604,13 @@ public static void DrawLineVectors(this Editor editor, IEnumerable poin /// 用户交互对象 /// 点表 /// CAD颜色索引;默认:1为红色 - /// 是否闭合; 为闭合,默认: 为不闭合 + /// 是否闭合; 为闭合,默认: 为不闭合 /// 是否高亮显示;为高亮显示,默认:为不高亮显示 public static void DrawEndToEndVectors(this Editor editor, IEnumerable points, - int colorIndex = 1, bool isclose = false, bool drawHighlighted = false) + int colorIndex = 1, bool isClose = false, bool drawHighlighted = false) { using var itor = points.GetEnumerator(); - if (!points.Any() || !itor.MoveNext()) + if (!itor.MoveNext()) return; Point3d endPoint1 = itor.Current, endPoint2 = new(), firstEndPoint = endPoint1; while (itor.MoveNext()) @@ -626,7 +620,7 @@ public static void DrawEndToEndVectors(this Editor editor, IEnumerable endPoint1 = endPoint2; } - if (isclose) + if (isClose) editor.DrawVector(endPoint2, firstEndPoint, colorIndex, drawHighlighted); } @@ -655,7 +649,7 @@ public static Matrix3d GetMatrixFromWcsToUcs(this Editor editor) } /// - /// 获取MDCS(模型空间)到WCS的矩阵 + /// 获取MDcs(模型空间)到WCS的矩阵 /// /// 命令行对象 /// 变换矩阵 @@ -934,12 +928,12 @@ public static void ZoomObject(this Editor ed, Entity ent, double offsetDist = 0. /// 获取Point /// /// 命令行对象 - /// 提示信息 - /// 提示使用的基点 - /// - public static PromptPointResult GetPoint(this Editor ed, string Message, Point3d BasePoint) + /// 提示信息 + /// 提示使用的基点 + /// 交互结果 + public static PromptPointResult GetPoint(this Editor ed, string message, Point3d basePoint) { - PromptPointOptions ptOp = new(Message) { BasePoint = BasePoint, UseBasePoint = true }; + PromptPointOptions ptOp = new(message) { BasePoint = basePoint, UseBasePoint = true, AllowNone = true }; return ed.GetPoint(ptOp); } @@ -947,13 +941,13 @@ public static PromptPointResult GetPoint(this Editor ed, string Message, Point3d /// 获取double值 /// /// 命令行对象 - /// 提示信息 - /// double默认值 - /// - public static PromptDoubleResult GetDouble(this Editor ed, string Message, - double DefaultValue = 1.0) + /// 提示信息 + /// double默认值 + /// 交互结果 + public static PromptDoubleResult GetDouble(this Editor ed, string message, + double defaultValue = 1.0) { - PromptDoubleOptions douOp = new(Message) { DefaultValue = DefaultValue }; + PromptDoubleOptions douOp = new(message) { DefaultValue = defaultValue, AllowNone = true }; return ed.GetDouble(douOp); } @@ -961,13 +955,13 @@ public static PromptDoubleResult GetDouble(this Editor ed, string Message, /// 获取int值 /// /// 命令行对象 - /// 提示信息 - /// double默认值 - /// - public static PromptIntegerResult GetInteger(this Editor ed, string Message, - int DefaultValue = 1) + /// 提示信息 + /// 默认值 + /// 交互结果 + public static PromptIntegerResult GetInteger(this Editor ed, string message, + int defaultValue = 1) { - PromptIntegerOptions douOp = new(Message) { DefaultValue = DefaultValue }; + PromptIntegerOptions douOp = new(message) { DefaultValue = defaultValue, AllowNone = true }; return ed.GetInteger(douOp); } @@ -975,12 +969,13 @@ public static PromptIntegerResult GetInteger(this Editor ed, string Message, /// 获取string值 /// /// 命令行对象 - /// 提示信息 - /// string默认值 + /// 提示信息 + /// string默认值 /// - public static PromptResult GetString(this Editor ed, string Message, string DefaultValue = "") + public static PromptResult GetString(this Editor ed, string message, string defaultValue = "") { - PromptStringOptions strOp = new(Message) { DefaultValue = DefaultValue }; + PromptStringOptions strOp = new(message) + { DefaultValue = defaultValue, UseDefaultValue = !string.IsNullOrWhiteSpace(defaultValue) }; return ed.GetString(strOp); } @@ -990,17 +985,17 @@ public static PromptResult GetString(this Editor ed, string Message, string Defa [DllImport("accore.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "acedInvoke")] - static extern int AcedInvoke(IntPtr args, out IntPtr result); + private static extern int AcedInvoke(IntPtr args, out IntPtr result); // 高版本此接口不能使用lisp(command "xx"),但是可以直接在自动运行接口上 [DllImport("accore.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, EntryPoint = "?acedEvaluateLisp@@YAHPEB_WAEAPEAUresbuf@@@Z")] [System.Security.SuppressUnmanagedCodeSecurity] // 初始化默认值 - static extern int AcedEvaluateLisp(string lispLine, out IntPtr result); + private static extern int AcedEvaluateLisp(string lispLine, out IntPtr result); [DllImport("accore.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ads_queueexpr")] - static extern int Ads_queueexpr(string strExpr); + private static extern int Ads_queueexpr(string strExpr); /// /// 执行lisp的方式枚举 -- Gitee From 09fae6553160a0d1a4bc967fe78df0231a7fa5a5 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 26 Dec 2024 09:37:06 +0800 Subject: [PATCH 396/453] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E9=A1=B9=E7=9B=AE?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E5=AD=97=E5=85=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IFoxCAD.sln.DotSettings | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/IFoxCAD.sln.DotSettings b/IFoxCAD.sln.DotSettings index fd6a739..cda8b1a 100644 --- a/IFoxCAD.sln.DotSettings +++ b/IFoxCAD.sln.DotSettings @@ -2,7 +2,10 @@ API DB OS + SS + WMF True + True True True True @@ -21,5 +24,6 @@ True True True + True True True \ No newline at end of file -- Gitee From 7757616b446e4f0dc4f5a11604d940cf6942268a Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 2 Jan 2025 22:07:18 +0800 Subject: [PATCH 397/453] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=B3=A8=E5=86=8C?= =?UTF-8?q?=E8=A1=A8=E7=A8=8B=E5=BA=8F=E9=9B=86=E8=8E=B7=E5=8F=96=E9=94=99?= =?UTF-8?q?=E8=AF=AF=E7=9A=84=E9=97=AE=E9=A2=98=EF=BC=8C=E5=8F=91=E5=B8=83?= =?UTF-8?q?0.9.2-preview6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CADShared/Initialize/AutoReg.cs | 4 ++-- src/Directory.Build.props | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/CADShared/Initialize/AutoReg.cs b/src/CADShared/Initialize/AutoReg.cs index 8e9b1f5..b84d3f3 100644 --- a/src/CADShared/Initialize/AutoReg.cs +++ b/src/CADShared/Initialize/AutoReg.cs @@ -55,7 +55,7 @@ public static void RegApp(AssemInfo info) /// 程序集 public static void RegApp(Assembly? assembly = null) { - assembly ??= Assembly.GetExecutingAssembly(); + assembly ??= Assembly.GetCallingAssembly(); var info = new AssemInfo(assembly); RegApp(info); } @@ -81,7 +81,7 @@ public static bool UnRegApp(AssemInfo info) /// 程序集 public static void UnRegApp(Assembly? assembly = null) { - assembly ??= Assembly.GetExecutingAssembly(); + assembly ??= Assembly.GetCallingAssembly(); var info = new AssemInfo(assembly); UnRegApp(info); } diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 9c29f76..a53df46 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,8 +1,8 @@ - 0.9.2-preview5 - 修复选择集关键字提示语拼接不正确的问题 + 0.9.2-preview6 + 修复注册表程序集获取错误的问题 -- Gitee From 8b800c80e0197f6a2edfe9e92263bf7729fe4aa1 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 2 Jan 2025 22:12:21 +0800 Subject: [PATCH 398/453] =?UTF-8?q?=E5=8F=91=E5=B8=830.9.2-preview7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index a53df46..5991873 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,7 +1,7 @@ - 0.9.2-preview6 + 0.9.2-preview7 修复注册表程序集获取错误的问题 -- Gitee From 0a24427c249eabc02af3ae703bcb6eda0acbbb06 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 2 Jan 2025 23:02:56 +0800 Subject: [PATCH 399/453] =?UTF-8?q?=E5=85=81=E8=AE=B8=E4=B8=AD=E6=9C=9Bcad?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=E6=B0=94=E6=B3=A1=E9=80=9A=E7=9F=A5=EF=BC=8C?= =?UTF-8?q?=E5=8F=91=E5=B8=830.9.2-preview8=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CADShared/ExtensionMethod/IFoxUtils.cs | 2 +- src/Directory.Build.props | 2 +- tests/TestShared/TestBubbleWindow.cs | 10 ++++++++++ tests/TestShared/TestShared.projitems | 1 + 4 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 tests/TestShared/TestBubbleWindow.cs diff --git a/src/CADShared/ExtensionMethod/IFoxUtils.cs b/src/CADShared/ExtensionMethod/IFoxUtils.cs index 3ab211a..956af63 100644 --- a/src/CADShared/ExtensionMethod/IFoxUtils.cs +++ b/src/CADShared/ExtensionMethod/IFoxUtils.cs @@ -61,6 +61,7 @@ public static void RegenLayers2(IEnumerable layerIds) } } +#endif /// /// 发送气泡通知 /// @@ -136,5 +137,4 @@ public static Transparency CreateTransparency(int value) { return new Transparency(Convert.ToByte(Math.Floor((100 - value) * 2.55))); } -#endif } \ No newline at end of file diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 5991873..acc8b84 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,7 +1,7 @@ - 0.9.2-preview7 + 0.9.2-preview8 修复注册表程序集获取错误的问题 diff --git a/tests/TestShared/TestBubbleWindow.cs b/tests/TestShared/TestBubbleWindow.cs new file mode 100644 index 0000000..2edae8c --- /dev/null +++ b/tests/TestShared/TestBubbleWindow.cs @@ -0,0 +1,10 @@ +namespace TestAcad2025; + +public static class TestBubbleWindow +{ + [CommandMethod(nameof(TestBubbleWindow))] + public static void Run() + { + IFoxUtils.ShowBubbleWindow(5, "测试", "测试"); + } +} \ No newline at end of file diff --git a/tests/TestShared/TestShared.projitems b/tests/TestShared/TestShared.projitems index 4dfb640..3c6557b 100644 --- a/tests/TestShared/TestShared.projitems +++ b/tests/TestShared/TestShared.projitems @@ -13,6 +13,7 @@ + -- Gitee From a0b1012f4143e977fedaef7b350c06864f4f5c77 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 2 Jan 2025 23:43:45 +0800 Subject: [PATCH 400/453] =?UTF-8?q?=E7=82=B9=E5=9C=A8=E5=A4=9A=E8=BE=B9?= =?UTF-8?q?=E5=BD=A2=E5=86=85=E9=83=A8=EF=BC=8C=E6=8E=92=E9=99=A4=E4=B8=AD?= =?UTF-8?q?=E6=9C=9B=E7=9A=84ge=E6=9B=B2=E7=BA=BF=E9=83=A8=E5=88=86?= =?UTF-8?q?=EF=BC=8C=E5=8F=91=E5=B8=830.9.2-preview9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/Geomerty/GeometryEx.cs | 16 +++++++--------- src/Directory.Build.props | 2 +- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs b/src/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs index 5672631..cffdca2 100644 --- a/src/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs +++ b/src/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs @@ -24,7 +24,7 @@ public static PointOnRegionType PointOnRegion(this IEnumerable pts, Poi var ptList = pts.ToList(); if (ptList.Count < 3) return PointOnRegionType.Error; - if (ptList[0] == ptList[1]) + if (ptList[0] == ptList[^1]) { ptList.RemoveAt(ptList.Count - 1); } @@ -32,6 +32,7 @@ public static PointOnRegionType PointOnRegion(this IEnumerable pts, Poi if (ptList.Count < 3) return PointOnRegionType.Error; +#if !zcad List ls2ds = []; for (var i = 0; i < ptList.Count - 1; i++) { @@ -52,11 +53,11 @@ public static PointOnRegionType PointOnRegion(this IEnumerable pts, Poi // 在多边形上? if (cc2d.IsOn(pt)) return PointOnRegionType.On; - // 在最小包围矩形外? var bb2d = cc2d.BoundBlock; if (!bb2d.Contains(pt)) return PointOnRegionType.Outside; +#endif #region 旧版疑似有问题的代码 @@ -111,7 +112,7 @@ public static PointOnRegionType PointOnRegion(this IEnumerable pts, Poi var ptList = pts.ToList(); if (ptList.Count < 3) return PointOnRegionType.Error; - if (ptList[0] == ptList[1]) + if (ptList[0] == ptList[^1]) { ptList.RemoveAt(ptList.Count - 1); } @@ -402,14 +403,11 @@ public static OrientationType IsClockWise(this IEnumerable pnts) ptlst = [pnts[0]]; return new CircularArc2d(pnts[0], 0); - case 2: - return GetMinCircle(pnts[0], pnts[1], out ptlst); + case 2: return GetMinCircle(pnts[0], pnts[1], out ptlst); - case 3: - return GetMinCircle(pnts[0], pnts[1], pnts[2], out ptlst); + case 3: return GetMinCircle(pnts[0], pnts[1], pnts[2], out ptlst); - case 4: - return GetMinCircle(pnts[0], pnts[1], pnts[2], pnts[3], out ptlst); + case 4: return GetMinCircle(pnts[0], pnts[1], pnts[2], pnts[3], out ptlst); } // 按前三点计算最小包围圆 diff --git a/src/Directory.Build.props b/src/Directory.Build.props index acc8b84..e1de936 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,7 +1,7 @@ - 0.9.2-preview8 + 0.9.2-preview9 修复注册表程序集获取错误的问题 -- Gitee From 2c2392c849eef85be2b36d9937559afb74738d02 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Tue, 21 Jan 2025 09:18:34 +0800 Subject: [PATCH 401/453] =?UTF-8?q?=E5=8F=91=E5=B8=830.9.2=E6=AD=A3?= =?UTF-8?q?=E5=BC=8F=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index e1de936..370ec90 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,7 +1,7 @@ - 0.9.2-preview9 + 0.9.2 修复注册表程序集获取错误的问题 -- Gitee From 444d175e1c8e081aac4bf6903c441c7414e011b5 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Tue, 21 Jan 2025 11:23:04 +0800 Subject: [PATCH 402/453] =?UTF-8?q?=E8=A1=A5=E5=85=85IFoxDwgFilter?= =?UTF-8?q?=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CADShared/CADShared.projitems | 1 + .../ExtensionMethod/Filter/DwgFiler.cs | 474 ++++++++++++++++++ src/Directory.Build.props | 4 +- tests/TestAcad2025/TestAcad2025.csproj | 2 +- tests/TestShared/TestDwgFilerEx.cs | 270 +++++----- 5 files changed, 611 insertions(+), 140 deletions(-) create mode 100644 src/CADShared/ExtensionMethod/Filter/DwgFiler.cs diff --git a/src/CADShared/CADShared.projitems b/src/CADShared/CADShared.projitems index c0c7ea9..b6f36ff 100644 --- a/src/CADShared/CADShared.projitems +++ b/src/CADShared/CADShared.projitems @@ -52,6 +52,7 @@ + diff --git a/src/CADShared/ExtensionMethod/Filter/DwgFiler.cs b/src/CADShared/ExtensionMethod/Filter/DwgFiler.cs new file mode 100644 index 0000000..13288d0 --- /dev/null +++ b/src/CADShared/ExtensionMethod/Filter/DwgFiler.cs @@ -0,0 +1,474 @@ +// ReSharper disable InconsistentNaming + +#pragma warning disable CS1591 // 缺少对公共可见类型或成员的 XML 注释 + +#if acad +using ErrorStatus = Autodesk.AutoCAD.Runtime.ErrorStatus; + +namespace IFoxCAD.Cad; + +/* + Arx自定义实体类,加 读函数(assertReadEnabled)和写函数(assertWriteEnabled) + + 所有属性位置都不要改动位置,因为涉及序列化 + [Serializable] 设置类 可以序列化 + [Newtonsoft.Json.JsonIgnore] 设置成员 不可序列化 +*/ +// DYH 2025-01-21 取消序列化相关代码,因为无法打上json转换器,不想让ifox再多引一个json包 +// 如有此类需求自己继承并实现即可 +// #if false +// [JsonConverter(typeof(ObjectIdConverter))] +// #endif +[Serializable] +public class IFoxDwgFiler : DwgFiler +{ + public IFoxDwgFiler(FilerType filerType = FilerType.CopyFiler) + { + m_FilerType = filerType; + } + + public long m_Position = 0; + public FilerType m_FilerType; + public ErrorStatus m_FilerStatus = ErrorStatus.OK; + public List AddressList = new(); + public int AddressListPt; + public List BinaryChunkList = new(); + public int BinaryChunkListPt; + public List BooleanList = new(); + public int BooleanListPt; + public List ByteList = new(); + public int ByteListPt; + public List BytesList = new(); + public int BytesListPt; + public List DoubleList = new(); + public int DoubleListPt; + public List HandleList = new(); + + public int HandleListPt; + + //[NonSerialized] + //[ScriptIgnore] + public List HardOwnershipIdList = new(); + + public int HardOwnershipIdListPt; + + //[NonSerialized] + //[ScriptIgnore] + public List HardPointerIdList = new(); + public int HardPointerIdListPt; + public List Int16List = new(); + public int Int16ListPt; + public List Int32List = new(); + public int Int32ListPt; + + public List Int64List = new(); + public int Int64ListPt; + + public List Point2dList = new(); + public int Point2dListPt; + public List Point3dList = new(); + public int Point3dListPt; + public List Scale3dList = new(); + + public int Scale3dListPt; + + //[NonSerialized] + //[ScriptIgnore] + public List SoftOwnershipIdList = new(); + + public int SoftOwnershipIdListPt; + + //[NonSerialized] + //[ScriptIgnore] + public List SoftPointerIdList = new(); + public int SoftPointerIdListPt; + public List StringList = new(); + public int StringListPt; + public List Uint16List = new(); + public int uint16ListPt; + public List Uint32List = new(); + public int uint32ListPt; + + public List Uint64List = new(); + public int uint64ListPt; + + public List Vector2dList = new(); + public int Vector2dListPt; + public List Vector3dList = new(); + public int Vector3dListPt; + + public override long Position => m_Position; + public override FilerType FilerType => m_FilerType; + + public override ErrorStatus FilerStatus + { + get => m_FilerStatus; + set => m_FilerStatus = value; + } + + public override IntPtr ReadAddress() + { + if (AddressList.Count == 0) + return new(); + return AddressList[AddressListPt++]; + } + + public override byte[]? ReadBinaryChunk() + { + if (BinaryChunkList.Count == 0) + return null; + return BinaryChunkList[BinaryChunkListPt++]; + } + + public override bool ReadBoolean() + { + if (BooleanList.Count == 0) + return false; + return BooleanList[BooleanListPt++]; + } + + public override byte ReadByte() + { + if (ByteList.Count == 0) + return 0; + return ByteList[ByteListPt++]; + } + + public override void ReadBytes(byte[] value) + { + if (ByteList.Count == 0) + return; + value = new byte[BytesList[BytesListPt].Length]; + BytesList[BytesListPt++].CopyTo(value, 0); + } + + public override double ReadDouble() + { + if (DoubleList.Count == 0) + return 0; + return DoubleList[DoubleListPt++]; + } + + public override Handle ReadHandle() + { + if (HandleList.Count == 0) + return new(); + return HandleList[HandleListPt++]; + } + + public override ObjectId ReadHardOwnershipId() + { + if (HardOwnershipIdList.Count == 0) + return new(); + return HardOwnershipIdList[HardOwnershipIdListPt++]; + } + + public override ObjectId ReadHardPointerId() + { + if (HardPointerIdList.Count == 0) + return new(); + return HardPointerIdList[HardPointerIdListPt++]; + } + + public override short ReadInt16() + { + if (Int16List.Count == 0) + return 0; + return Int16List[Int16ListPt++]; + } + + public override int ReadInt32() + { + if (Int32List.Count == 0) + return 0; + return Int32List[Int32ListPt++]; + } + + public override long ReadInt64() + { + if (Int64List.Count == 0) + return 0; + return Int64List[Int64ListPt++]; + } + + public override Point2d ReadPoint2d() + { + if (Point2dList.Count == 0) + return new(); + return Point2dList[Point2dListPt++]; + } + + public override Point3d ReadPoint3d() + { + if (Point3dList.Count == 0) + return new(); + return Point3dList[Point3dListPt++]; + } + + public override Scale3d ReadScale3d() + { + if (Scale3dList.Count == 0) + return new(); + return Scale3dList[Scale3dListPt++]; + } + + public override ObjectId ReadSoftOwnershipId() + { + if (SoftOwnershipIdList.Count == 0) + return new(); + return SoftOwnershipIdList[SoftOwnershipIdListPt++]; + } + + public override ObjectId ReadSoftPointerId() + { + if (SoftPointerIdList.Count == 0) + return new(); + return SoftPointerIdList[SoftPointerIdListPt++]; + } + + public override string? ReadString() + { + if (StringList.Count == 0) + return null; + return StringList[StringListPt++]; + } + + public override ushort ReadUInt16() + { + if (Uint16List.Count == 0) + return 0; + return Uint16List[uint16ListPt++]; + } + + public override uint ReadUInt32() + { + if (Uint32List.Count == 0) + return 0; + return Uint32List[uint32ListPt++]; + } + + public override ulong ReadUInt64() + { + if (Uint64List.Count == 0) + return 0; + return Uint64List[uint64ListPt++]; + } + + public override Vector2d ReadVector2d() + { + if (Vector2dList.Count == 0) + return new(); + return Vector2dList[Vector2dListPt++]; + } + + public override Vector3d ReadVector3d() + { + if (Vector3dList.Count == 0) + return new(); + return Vector3dList[Vector3dListPt++]; + } + + public override void ResetFilerStatus() + { + AddressList.Clear(); + AddressListPt = 0; + BinaryChunkList.Clear(); + BinaryChunkListPt = 0; + BooleanList.Clear(); + BooleanListPt = 0; + ByteList.Clear(); + ByteListPt = 0; + BytesList.Clear(); + BytesListPt = 0; + DoubleList.Clear(); + DoubleListPt = 0; + HandleList.Clear(); + HandleListPt = 0; + HardOwnershipIdList.Clear(); + HardOwnershipIdListPt = 0; + HardPointerIdList.Clear(); + HardPointerIdListPt = 0; + Int16List.Clear(); + Int16ListPt = 0; + Int32List.Clear(); + Int32ListPt = 0; + + Int64List.Clear(); + Int64ListPt = 0; + + Point2dList.Clear(); + Point2dListPt = 0; + Point3dList.Clear(); + Point3dListPt = 0; + Scale3dList.Clear(); + Scale3dListPt = 0; + SoftOwnershipIdList.Clear(); + SoftOwnershipIdListPt = 0; + SoftPointerIdList.Clear(); + SoftPointerIdListPt = 0; + StringList.Clear(); + StringListPt = 0; + Uint16List.Clear(); + uint16ListPt = 0; + Uint32List.Clear(); + uint32ListPt = 0; + + Uint64List.Clear(); + uint64ListPt = 0; + + Vector2dList.Clear(); + Vector2dListPt = 0; + Vector3dList.Clear(); + Vector3dListPt = 0; + + m_FilerType = FilerType.CopyFiler; + } + +#if zcad // 中望官方的问题 + public override void Seek(int offset, int method) + { + var ed = Acap.DocumentManager.MdiActiveDocument.Editor; + ed.WriteMessage(MethodInfo.GetCurrentMethod().Name + " = " + " \n "); + } + public override void Seek(long offset, int method) + { + Seek((int)offset, method); + } +#endif + +#if acad || gcad + public override void Seek(long offset, int method) + { + var ed = Acap.DocumentManager.MdiActiveDocument.Editor; + ed.WriteMessage(MethodInfo.GetCurrentMethod()!.Name + " = " + " \n "); + } +#endif + + public override void WriteAddress(IntPtr value) + { + AddressList.Add(value); + } + + public override void WriteBinaryChunk(byte[] chunk) + { + BinaryChunkList.Add(chunk); + } + + public override void WriteBoolean(bool value) + { + BooleanList.Add(value); + } + + public override void WriteByte(byte value) + { + ByteList.Add(value); + } + + public override void WriteBytes(byte[] value) + { + BytesList.Add(value); + } + + public override void WriteDouble(double value) + { + DoubleList.Add(value); + } + + public override void WriteHandle(Handle handle) + { + HandleList.Add(handle); + } + + public override void WriteHardOwnershipId(ObjectId value) + { + HardOwnershipIdList.Add(value); + } + + public override void WriteHardPointerId(ObjectId value) + { + HardPointerIdList.Add(value); + } + + public override void WriteInt16(short value) + { + Int16List.Add(value); + } + + public override void WriteInt32(int value) + { + Int32List.Add(value); + } + + public override void WriteInt64(long value) + { + Int64List.Add(value); + } + + public override void WritePoint2d(Point2d value) + { + Point2dList.Add(value); + } + + public override void WritePoint3d(Point3d value) + { + Point3dList.Add(value); + } + + public override void WriteScale3d(Scale3d value) + { + Scale3dList.Add(value); + } + + public override void WriteSoftOwnershipId(ObjectId value) + { + SoftOwnershipIdList.Add(value); + } + + public override void WriteSoftPointerId(ObjectId value) + { + SoftPointerIdList.Add(value); + } + + public override void WriteString(string value) + { + StringList.Add(value); + } + + public override void WriteUInt16(ushort value) + { + Uint16List.Add(value); + } + + public override void WriteUInt32(uint value) + { + Uint32List.Add(value); + } + + public override void WriteUInt64(ulong value) + { + Uint64List.Add(value); + } + + public override void WriteVector2d(Vector2d value) + { + Vector2dList.Add(value); + } + + public override void WriteVector3d(Vector3d value) + { + Vector3dList.Add(value); + } + + // public override string ToString() + // { +// #if NewtonsoftJson +// return JsonConvert.SerializeObject(this, Formatting.Indented); +// #else +// JavaScriptSerializer serializer = new(); +// serializer.RegisterConverters(new[] { new ObjectIdConverter() }); +// return serializer.Serialize(this); +// #endif + // } +} + +#endif \ No newline at end of file diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 370ec90..d540818 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,8 +1,8 @@ - 0.9.2 - 修复注册表程序集获取错误的问题 + 0.9.3-preview1 + 补充IFoxDwgFilter类 diff --git a/tests/TestAcad2025/TestAcad2025.csproj b/tests/TestAcad2025/TestAcad2025.csproj index 126352d..e4e2def 100644 --- a/tests/TestAcad2025/TestAcad2025.csproj +++ b/tests/TestAcad2025/TestAcad2025.csproj @@ -14,7 +14,7 @@ - none + full false diff --git a/tests/TestShared/TestDwgFilerEx.cs b/tests/TestShared/TestDwgFilerEx.cs index 6513cda..851677b 100644 --- a/tests/TestShared/TestDwgFilerEx.cs +++ b/tests/TestShared/TestDwgFilerEx.cs @@ -1,56 +1,15 @@ -#if false +#if acad namespace Test; -using DxfFiler = IFoxCAD.Cad.DxfFiler; - public class CmdTestDwgFilerEx { - [CommandMethod(nameof(CmdTest_DwgFilerEx))] + [CommandMethod(nameof(CmdTest_DwgFilerEx), CommandFlags.UsePickSet)] public static void CmdTest_DwgFilerEx() { - var dm = Acap.DocumentManager; - var doc = dm.MdiActiveDocument; - var db = doc.Database; - var ed = doc.Editor; - ed.WriteMessage("\n****测试,序列化图元"); - - var ssPsr = ed.SelectImplied();// 预选 - if (ssPsr.Status != PromptStatus.OK) - { - ssPsr = ed.GetSelection();// 手选 这里输入al会变成all,无法删除ssget的all关键字 - if (ssPsr.Status != PromptStatus.OK) - return; - } - - using DBTrans tr = new(); - var ids = ssPsr.Value.GetObjectIds(); - foreach (var id in ids) - { - if (!id.IsOk()) - continue; - var ent = tr.GetObject(id, OpenMode.ForRead); - if (ent is null) - continue; - var dwgFilerEx = new DwgFilerEx(ent); - ed.WriteMessage(Environment.NewLine + dwgFilerEx.ToString()); - } - } - - [CommandMethod(nameof(CmdTest_EntDxfout))] - public static void CmdTest_EntDxfout() - { - var dm = Acap.DocumentManager; - var doc = dm.MdiActiveDocument; - var db = doc.Database; - var ed = doc.Editor; + var ed = Env.Editor; + // ed.WriteMessage("\n****测试,序列化图元"); - // 定义选择集选项 - var pso = new PromptSelectionOptions - { - RejectObjectsOnLockedLayers = true, // 不选择锁定图层对象 - AllowDuplicates = true, // 不允许重复选择 - }; - var ssPsr = ed.GetSelection(pso);// 手选 这里输入al会变成all,无法删除ssget的all关键字 + var ssPsr = ed.GetSelection(); if (ssPsr.Status != PromptStatus.OK) return; @@ -60,102 +19,139 @@ public static void CmdTest_EntDxfout() { if (!id.IsOk()) continue; - var ent = tr.GetObject(id, OpenMode.ForRead); + var ent = tr.GetObject(id); if (ent is null) continue; - // ResultBuffer rbDxf = new(); - var filer = new DxfFiler(ent.UnmanagedObject, true);/// 这里有问题 - ent.DxfOut(filer); - } - } - - - [CommandMethod(nameof(CmdTest_TextOut))] - public static void CmdTest_TextOut() - { - var dm = Acap.DocumentManager; - var doc = dm.MdiActiveDocument; - var db = doc.Database; - var ed = doc.Editor; - -#if true - var peo1 = new PromptEntityOptions(Environment.NewLine + "点选源TCH_WIREDIM2:") - { - AllowObjectOnLockedLayer = false, - AllowNone = false - }; - var gt1 = ed.GetEntity(peo1); - if (gt1.Status != PromptStatus.OK) - return; -#else - var peo2 = new PromptEntityOptions(Environment.NewLine + "点选目标TCH_WIREDIM2:") - { - AllowObjectOnLockedLayer = false, - AllowNone = false - }; - var gt2 = ed.GetEntity(peo2); - if (gt2.Status != PromptStatus.OK) - return; -#endif - - using DBTrans tr = new(); - var dwgFilerEx = new DwgFilerEx(); - var bText = tr.GetObject(gt1.ObjectId, OpenMode.ForRead); - if (bText is null) - return; - - // DwgFilerEx.StringList[0] = "1@2@3@4@5@6@7@"; - // 复制 TCH_WIREDIM2 不行,TEXT 也不行,直接崩溃。line等线就没事 - bText.DwgOut(dwgFilerEx.DwgFiler); - - int testNum = 1 | 2 | 4 | 8; - - if ((testNum & 1) == 1) - { - // 错误,原地克隆也是不行的,它会生成在了模型中. - var sIds = new List + var dwgFiler = new IFoxDwgFiler(); + ent.DwgOut(dwgFiler); + foreach (var objectId in dwgFiler.SoftPointerIdList) { - bText.ObjectId - }; - // 克隆到目标块表内 - using ObjectIdCollection bindIds = new(sIds.ToArray()); - using IdMapping map = new(); - - tr.CurrentSpace.DeepCloneEx(bindIds, map); - var newTexts = map.GetValues().GetObject(); - newTexts.ForEach(nText => { - if (nText == null) - return; - // 通过上面的克隆就已经在块表上面了.所以下面的设置也跟设置到已有图元上一样报错. - nText.UpgradeOpen(); - nText.DwgIn(dwgFilerEx); - tr.CurrentSpace.AddEntity(nText); - nText.DowngradeOpen(); - }); - } - if ((testNum & 2) == 2) - { - // 出错 - // 直接设置 - bText.DwgIn(dwgFilerEx); - } - if ((testNum & 4) == 4) - { - // 出错 - // 此时是内存中对象.... - var nText = (DBText)bText.Clone(); - nText.DwgIn(dwgFilerEx); - tr.CurrentSpace.AddEntity(nText); - } - if ((testNum & 8) == 8) - { - // 新对象相当于克隆,是ok的 - DBText nText = new(); - nText.SetDatabaseDefaults(); - nText.DwgIn(dwgFilerEx); - tr.CurrentSpace.AddEntity(nText); + objectId.ObjectClass.DxfName.Print(); + } + + ed.WriteMessage(Environment.NewLine + dwgFiler.ToString()); } } + + // [CommandMethod(nameof(CmdTest_EntDxfout))] + // public static void CmdTest_EntDxfout() + // { + // var dm = Acap.DocumentManager; + // var doc = dm.MdiActiveDocument; + // var db = doc.Database; + // var ed = doc.Editor; + // + // // 定义选择集选项 + // var pso = new PromptSelectionOptions + // { + // RejectObjectsOnLockedLayers = true, // 不选择锁定图层对象 + // AllowDuplicates = true, // 不允许重复选择 + // }; + // var ssPsr = ed.GetSelection(pso);// 手选 这里输入al会变成all,无法删除ssget的all关键字 + // if (ssPsr.Status != PromptStatus.OK) + // return; + // + // using DBTrans tr = new(); + // var ids = ssPsr.Value.GetObjectIds(); + // foreach (var id in ids) + // { + // if (!id.IsOk()) + // continue; + // var ent = tr.GetObject(id, OpenMode.ForRead); + // if (ent is null) + // continue; + // // ResultBuffer rbDxf = new(); + // var filer = new DxfFiler(ent.UnmanagedObject, true);/// 这里有问题 + // ent.DxfOut(filer); + // } + // } + +// [CommandMethod(nameof(CmdTest_TextOut))] +// public static void CmdTest_TextOut() +// { +// var dm = Acap.DocumentManager; +// var doc = dm.MdiActiveDocument; +// var db = doc.Database; +// var ed = doc.Editor; +// +// #if true +// var peo1 = new PromptEntityOptions(Environment.NewLine + "点选源TCH_WIREDIM2:") +// { +// AllowObjectOnLockedLayer = false, +// AllowNone = false +// }; +// var gt1 = ed.GetEntity(peo1); +// if (gt1.Status != PromptStatus.OK) +// return; +// #else +// var peo2 = new PromptEntityOptions(Environment.NewLine + "点选目标TCH_WIREDIM2:") +// { +// AllowObjectOnLockedLayer = false, +// AllowNone = false +// }; +// var gt2 = ed.GetEntity(peo2); +// if (gt2.Status != PromptStatus.OK) +// return; +// #endif +// +// using DBTrans tr = new(); +// var dwgFilerEx = new DwgFilerEx(); +// var bText = tr.GetObject(gt1.ObjectId, OpenMode.ForRead); +// if (bText is null) +// return; +// +// // DwgFilerEx.StringList[0] = "1@2@3@4@5@6@7@"; +// // 复制 TCH_WIREDIM2 不行,TEXT 也不行,直接崩溃。line等线就没事 +// bText.DwgOut(dwgFilerEx.DwgFiler); +// +// int testNum = 1 | 2 | 4 | 8; +// +// if ((testNum & 1) == 1) +// { +// // 错误,原地克隆也是不行的,它会生成在了模型中. +// var sIds = new List +// { +// bText.ObjectId +// }; +// // 克隆到目标块表内 +// using ObjectIdCollection bindIds = new(sIds.ToArray()); +// using IdMapping map = new(); +// +// tr.CurrentSpace.DeepCloneEx(bindIds, map); +// var newTexts = map.GetValues().GetObject(); +// newTexts.ForEach(nText => { +// if (nText == null) +// return; +// // 通过上面的克隆就已经在块表上面了.所以下面的设置也跟设置到已有图元上一样报错. +// nText.UpgradeOpen(); +// nText.DwgIn(dwgFilerEx); +// tr.CurrentSpace.AddEntity(nText); +// nText.DowngradeOpen(); +// }); +// } +// if ((testNum & 2) == 2) +// { +// // 出错 +// // 直接设置 +// bText.DwgIn(dwgFilerEx); +// } +// if ((testNum & 4) == 4) +// { +// // 出错 +// // 此时是内存中对象.... +// var nText = (DBText)bText.Clone(); +// nText.DwgIn(dwgFilerEx); +// tr.CurrentSpace.AddEntity(nText); +// } +// if ((testNum & 8) == 8) +// { +// // 新对象相当于克隆,是ok的 +// DBText nText = new(); +// nText.SetDatabaseDefaults(); +// nText.DwgIn(dwgFilerEx); +// tr.CurrentSpace.AddEntity(nText); +// } +// } } #endif \ No newline at end of file -- Gitee From 22fa79cac7089015c070dfb294af60c5f532de8a Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Wed, 22 Jan 2025 20:57:21 +0800 Subject: [PATCH 403/453] =?UTF-8?q?=E6=96=87=E5=AD=97=E5=AF=B9=E9=BD=90?= =?UTF-8?q?=E5=88=A4=E6=96=AD=E6=9B=B4=E6=8D=A2API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CADShared/ExtensionMethod/Entity/DBTextEx.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CADShared/ExtensionMethod/Entity/DBTextEx.cs b/src/CADShared/ExtensionMethod/Entity/DBTextEx.cs index 97a6511..ae3245e 100644 --- a/src/CADShared/ExtensionMethod/Entity/DBTextEx.cs +++ b/src/CADShared/ExtensionMethod/Entity/DBTextEx.cs @@ -39,7 +39,7 @@ public static DBText CreateDBText(Point3d position, string text, double height, action?.Invoke(acText); - if (acText.Justify != AttachmentPoint.BaseLeft) + if (!acText.IsDefaultAlignment) acText.AlignmentPoint = position; acText.AdjustAlignment(workingDatabase); -- Gitee From 9971cda6d0d4d9595955eec135a4ca5b5e461cf7 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Wed, 22 Jan 2025 20:58:46 +0800 Subject: [PATCH 404/453] =?UTF-8?q?=E5=88=A0=E9=99=A4=E5=A4=9A=E4=BD=99?= =?UTF-8?q?=E5=88=AB=E5=90=8D=E5=AE=9A=E4=B9=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CADShared/ExtensionMethod/Entity/DBTextEx.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/CADShared/ExtensionMethod/Entity/DBTextEx.cs b/src/CADShared/ExtensionMethod/Entity/DBTextEx.cs index ae3245e..0b198f8 100644 --- a/src/CADShared/ExtensionMethod/Entity/DBTextEx.cs +++ b/src/CADShared/ExtensionMethod/Entity/DBTextEx.cs @@ -1,6 +1,4 @@ -using ArgumentNullException = System.ArgumentNullException; - -namespace IFoxCAD.Cad; +namespace IFoxCAD.Cad; /// /// 单行文字扩展类 -- Gitee From bf4a8bdbca911a705a5d1e1f64ed9626f51c65f5 Mon Sep 17 00:00:00 2001 From: yupeng_dyp Date: Sun, 2 Feb 2025 12:01:47 +0000 Subject: [PATCH 405/453] =?UTF-8?q?update=20src/CADShared/ExtensionMethod/?= =?UTF-8?q?Geomerty/GeometryEx.cs.=20=E4=BF=AE=E5=A4=8D=E5=8E=9F=E5=87=BD?= =?UTF-8?q?=E6=95=B0=E4=BC=9A=E5=87=BA=E7=8E=B0=E5=85=B1=E7=BA=BF=E7=82=B9?= =?UTF-8?q?=E5=8F=8A=E4=BC=A0=E5=85=A5=E7=9A=84=E7=82=B9=E9=9B=86=E5=A6=82?= =?UTF-8?q?=E6=9E=9C=E6=9C=89=E9=87=8D=E7=82=B9=E6=97=B6=E7=94=9F=E6=88=90?= =?UTF-8?q?=E7=9A=84=E5=87=B8=E5=8C=85=E5=8F=AF=E8=83=BD=E4=BC=9A=E6=9C=89?= =?UTF-8?q?=E9=94=99=E8=AF=AF=E7=9A=84=E6=83=85=E5=86=B5=EF=BC=88=E5=85=B6?= =?UTF-8?q?=E5=AE=9E=E7=AE=97=E6=B3=95=E4=B8=8E=E5=8E=9F=E6=9D=A5=E7=9A=84?= =?UTF-8?q?=E4=B8=80=E6=A0=B7=EF=BC=8C=E6=B2=A1=E6=9C=89=E5=8E=BB=E6=B7=B1?= =?UTF-8?q?=E7=A9=B6=E5=8E=9F=E5=87=BD=E6=95=B0=E4=BC=9A=E6=9C=89=E5=89=8D?= =?UTF-8?q?=E9=9D=A2=E7=9A=84=E9=97=AE=E9=A2=98=E7=9A=84=E5=85=B7=E4=BD=93?= =?UTF-8?q?=E5=8E=9F=E5=9B=A0=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: yupeng_dyp --- .../ExtensionMethod/Geomerty/GeometryEx.cs | 53 +++++++++++-------- 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/src/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs b/src/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs index cffdca2..d21d818 100644 --- a/src/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs +++ b/src/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs @@ -449,40 +449,51 @@ public static OrientationType IsClockWise(this IEnumerable pnts) return ca2d; } + /// + /// 叉积,二维叉乘计算 + /// + /// 原点 + /// oa向量 + /// ob向量,此为判断点 + /// 返回值有正负,表示绕原点四象限的位置变换,也就是有向面积 + private static double Cross(Point2d o, Point2d a, Point2d b) + { + return (a.X - o.X) * (b.Y - o.Y) - (a.Y - o.Y) * (b.X - o.X); + } + /// /// 获取点集的凸包 /// /// 点集 /// 凸包 - public static List ConvexHull(this List points) + public static List? ConvexHull(this List points) { - if (points.Count <= 1) - return points; + if (points.Count < 3) return null; - int n = points.Count, k = 0; - List H = [..new Point2d[2 * n]]; + //坐标排序 + points = points.OrderBy(p => p.X).ThenBy(p => p.Y).ToList(); - points.Sort((a, b) => a.X == b.X ? a.Y.CompareTo(b.Y) : a.X.CompareTo(b.X)); + var hullPts = new List(); - // Build lower hull - for (var i = 0; i < n; ++i) - { - while (k >= 2 && IsClockWise(H[k - 2], H[k - 1], points[i]) == - OrientationType.CounterClockWise) - k--; - H[k++] = points[i]; + //构建下凸包 + foreach (var pt in points) { + while (hullPts.Count >= 2 && Cross(hullPts[^2], hullPts[^1], pt) <= 0) + hullPts.RemoveAt(hullPts.Count - 1); + hullPts.Add(pt); } - // Build upper hull - for (int i = n - 2, t = k + 1; i >= 0; i--) - { - while (k >= t && IsClockWise(H[k - 2], H[k - 1], points[i]) == - OrientationType.CounterClockWise) - k--; - H[k++] = points[i]; + //构建上凸包 + var lowerHullCount = hullPts.Count + 1; + for (var i = points.Count - 2; i >= 0; i--) { + while (hullPts.Count >= lowerHullCount && Cross(hullPts[^2], hullPts[^1], points[i]) <= 0) + hullPts.RemoveAt(hullPts.Count - 1); + hullPts.Add(points[i]); } - return H.Take(k - 1).ToList(); + //移除与起点重复的尾点 + hullPts.RemoveAt(hullPts.Count - 1); + + return hullPts.Count >= 3 ? hullPts : null; } #endregion PointList -- Gitee From f04696a1d64e2ec5cb9a490372ffc42da7f71938 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 6 Mar 2025 17:36:45 +0800 Subject: [PATCH 406/453] =?UTF-8?q?=E5=8F=91=E5=B8=830.9.3-preview3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CADShared/ExtensionMethod/IFoxUtils.cs | 31 +++++++++++++++++++--- src/Directory.Build.props | 4 +-- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/CADShared/ExtensionMethod/IFoxUtils.cs b/src/CADShared/ExtensionMethod/IFoxUtils.cs index 956af63..5834343 100644 --- a/src/CADShared/ExtensionMethod/IFoxUtils.cs +++ b/src/CADShared/ExtensionMethod/IFoxUtils.cs @@ -16,10 +16,27 @@ public static void RegenLayers(IEnumerable layerIds) var type = Acaop.Version.Major >= 21 ? Assembly.Load("accoremgd")?.GetType("Autodesk.AutoCAD.Internal.CoreLayerUtilities") : Assembly.Load("acmgd")?.GetType("Autodesk.AutoCAD.Internal.LayerUtilities"); - var mi = type?.GetMethods().FirstOrDefault(e => e.Name == "RegenLayers"); - var pi = type?.GetProperties().FirstOrDefault(e => e.Name == "RegenPending"); + if (type == null) + return; + var mi = type.GetMethods() + .FirstOrDefault(e => + { + if (e.Name != "RegenLayers") + return false; + var parameterInfos = e.GetParameters(); + if (parameterInfos.Length != 2) + return false; + if (parameterInfos[0].ParameterType != typeof(ObjectId[])) + return false; + if (parameterInfos[1].ParameterType != typeof(int)) + return false; + return true; + }); + if (mi == null) + return; + var pi = type.GetProperties().FirstOrDefault(e => e.Name == "RegenPending"); var regenPending = (int)(pi?.GetValue(null) ?? 0); - mi?.Invoke(null, [layerIds.ToArray(), regenPending]); + mi.Invoke(null, [layerIds.ToArray(), regenPending]); } /// @@ -57,6 +74,14 @@ public static void RegenLayers2(IEnumerable layerIds) if (!layerIdSet.Contains(ent.LayerId)) continue; ent.RecordGraphicsModified(true); + try + { + ent.TransformBy(Matrix3d.Identity); + } + catch (Exception) + { + // 某些类型如blockbegin blockend等不能进行矩阵转换 + } } } } diff --git a/src/Directory.Build.props b/src/Directory.Build.props index d540818..5221f29 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,8 +1,8 @@ - 0.9.3-preview1 - 补充IFoxDwgFilter类 + 0.9.3-preview3 + 修复某些类型如blockbegin blockend等不能进行矩阵转换而报错的问题 -- Gitee From e6490deb79a741cdc777f6b78e9a324a4afe3dd9 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Wed, 12 Mar 2025 16:36:27 +0800 Subject: [PATCH 407/453] =?UTF-8?q?=E5=8F=91=E5=B8=830.9.3-preview4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CADShared/ExtensionMethod/Filter/DwgFiler.cs | 10 +++++----- src/Directory.Build.props | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/CADShared/ExtensionMethod/Filter/DwgFiler.cs b/src/CADShared/ExtensionMethod/Filter/DwgFiler.cs index 13288d0..dfb0ec9 100644 --- a/src/CADShared/ExtensionMethod/Filter/DwgFiler.cs +++ b/src/CADShared/ExtensionMethod/Filter/DwgFiler.cs @@ -108,14 +108,14 @@ public override ErrorStatus FilerStatus public override IntPtr ReadAddress() { - if (AddressList.Count == 0) - return new(); + if (AddressListPt >= AddressList.Count) + return IntPtr.Zero; return AddressList[AddressListPt++]; } public override byte[]? ReadBinaryChunk() { - if (BinaryChunkList.Count == 0) + if (BinaryChunkListPt >= BinaryChunkList.Count) return null; return BinaryChunkList[BinaryChunkListPt++]; } @@ -228,7 +228,7 @@ public override ObjectId ReadSoftPointerId() public override string? ReadString() { - if (StringList.Count == 0) + if (StringListPt >= StringList.Count) return null; return StringList[StringListPt++]; } @@ -458,7 +458,7 @@ public override void WriteVector3d(Vector3d value) { Vector3dList.Add(value); } - + // public override string ToString() // { // #if NewtonsoftJson diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 5221f29..e974cca 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,8 +1,8 @@ - 0.9.3-preview3 - 修复某些类型如blockbegin blockend等不能进行矩阵转换而报错的问题 + 0.9.3-preview4 + 更新dwgfilter的null返回方式 -- Gitee From 774bbef2345bea76a344ab8e3ebdc804dd72a20f Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Mon, 17 Mar 2025 16:28:51 +0800 Subject: [PATCH 408/453] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/TestAcad2025/TestAcad2025.csproj | 8 +------- tests/TestZcad2025/TestZcad2025.csproj | 13 +------------ 2 files changed, 2 insertions(+), 19 deletions(-) diff --git a/tests/TestAcad2025/TestAcad2025.csproj b/tests/TestAcad2025/TestAcad2025.csproj index e4e2def..1109e94 100644 --- a/tests/TestAcad2025/TestAcad2025.csproj +++ b/tests/TestAcad2025/TestAcad2025.csproj @@ -2,7 +2,6 @@ preview enable - net48;net8.0-windows true true @@ -47,12 +46,7 @@ - - - - - - + diff --git a/tests/TestZcad2025/TestZcad2025.csproj b/tests/TestZcad2025/TestZcad2025.csproj index 89cf1ba..280480b 100644 --- a/tests/TestZcad2025/TestZcad2025.csproj +++ b/tests/TestZcad2025/TestZcad2025.csproj @@ -2,7 +2,6 @@ preview enable - NET48 true true @@ -14,23 +13,13 @@ $(Configuration);zcad - - - - - - - - - + - - -- Gitee From 5571ffb4c8e50f6e18b7c483de9b398e09c21853 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Tue, 8 Apr 2025 10:30:48 +0800 Subject: [PATCH 409/453] =?UTF-8?q?=E7=A7=BB=E9=99=A4=E4=BA=86=E6=9C=AA?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=E7=9A=84=20DelayUpdateLayLockFade=20?= =?UTF-8?q?=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CADShared/Runtime/Env.cs | 117 ++++++++++++++++------------------- 1 file changed, 55 insertions(+), 62 deletions(-) diff --git a/src/CADShared/Runtime/Env.cs b/src/CADShared/Runtime/Env.cs index 3f88e36..b379ad8 100644 --- a/src/CADShared/Runtime/Env.cs +++ b/src/CADShared/Runtime/Env.cs @@ -58,7 +58,6 @@ public static object GetCurrentProfileProperty(string subSectionName, string pro return ss.ReadProperty(propertyName, ""); } - /// /// 获取对话框配置的数据 /// @@ -88,7 +87,6 @@ public static IConfigurationSection GetGlobalSection(string propertyName) #endregion Preferences #region Enum - /// /// 控制在AutoLISP的command函数运行时AutoCAD是否回显提示和输入, 为显示, 为不显示 /// @@ -102,7 +100,6 @@ public static bool CmdEcho /// 获取Cad当前是否有活动命令 /// public static bool CmdActive => Convert.ToBoolean(Acaop.GetSystemVariable("CMDACTIVE")); - /// /// 控制在光标是否为正交模式, 为打开正交, 为关闭正交 /// @@ -251,7 +248,6 @@ public enum DimblkType { "基准三角形", DimblkType.DatumBlank }, { "完整标记", DimblkType.Integral }, { "建筑标记", DimblkType.ArchTick }, - { "", DimblkType.Default }, { "_DOT", DimblkType.Dot }, { "_DOTSMALL", DimblkType.DotSmall }, @@ -274,7 +270,6 @@ public enum DimblkType { "_ARCHTICK", DimblkType.ArchTick } }; - /// /// 标注箭头属性 /// @@ -299,10 +294,7 @@ public static DimblkType Dimblk /// 箭头名 public static string GetDimblkName(DimblkType dimblk) { - return - dimblk == DimblkType.Default - ? "." - : "_" + dimblk.GetName(); + return dimblk == DimblkType.Default ? "." : "_" + dimblk.GetName(); } /// @@ -402,7 +394,12 @@ public enum OSModeType /// /// 平行 /// - Parallel = 8192 + Parallel = 8192, + + /// + /// 禁用 + /// + Disabled = 16384, } /// @@ -428,7 +425,6 @@ public static bool Include(this OSModeType osm1, OSModeType osm2) #endregion OsMode - private static string? GetName(this T value) { return Enum.GetName(typeof(T), value!); @@ -488,12 +484,14 @@ public static void SetVar(string varName, object value, bool echo = true) #if gcad [System.Security.SuppressUnmanagedCodeSecurity] - [DllImport("gced.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, EntryPoint = + [DllImport("gced.dll", CharSet = CharSet.Auto, CallingConvention = + CallingConvention.Cdecl, EntryPoint = "gcedGetEnv")] static extern int AcedGetEnv(string? envName, StringBuilder ReturnValue); [System.Security.SuppressUnmanagedCodeSecurity] - [DllImport("gced.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, EntryPoint = + [DllImport("gced.dll", CharSet = CharSet.Auto, CallingConvention = + CallingConvention.Cdecl, EntryPoint = "gcedSetEnv")] static extern int AcedSetEnv(string? envName, StringBuilder NewValue); #endif @@ -501,12 +499,14 @@ public static void SetVar(string varName, object value, bool echo = true) // TODO: 中望没有测试,此处仅为不报错;本工程所有含有"中望"均存在问题 #if zcad [System.Security.SuppressUnmanagedCodeSecurity] - [DllImport("zced.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, EntryPoint = + [DllImport("zced.dll", CharSet = CharSet.Auto, CallingConvention = + CallingConvention.Cdecl, EntryPoint = "zcedGetEnv")] static extern int AcedGetEnv(string? envName, StringBuilder ReturnValue); [System.Security.SuppressUnmanagedCodeSecurity] - [DllImport("zced.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, EntryPoint = + [DllImport("zced.dll", CharSet = CharSet.Auto, CallingConvention = + CallingConvention.Cdecl, EntryPoint = "zcedSetEnv")] static extern int AcedSetEnv(string? envName, StringBuilder NewValue); #endif @@ -583,21 +583,21 @@ public static int SetEnv(string name, string var) /// 目录 public static void AppendSupportPath(params string[] folders) { - if (!folders.Any()) return; + if (!folders.Any()) + return; var acadPath = GetEnv("ACAD"); - var acadPathLowerArr = - acadPath - .ToLower() - .Split(';') - .Where(item => item != "") - .Select(item => - item[^1] == '\\' ? item.Remove(item.Length - 1) : item) - .ToHashSet(); + var acadPathLowerArr = acadPath.ToLower() + .Split(';') + .Where(item => item != "") + .Select(item => item[^1] == '\\' ? item.Remove(item.Length - 1) : item) + .ToHashSet(); foreach (var folder in folders) { - if (!Directory.Exists(folder)) continue; - var folderLower = - folder[^1] == '\\' ? folder.Remove(folder.Length - 1).ToLower() : folder.ToLower(); + if (!Directory.Exists(folder)) + continue; + var folderLower = folder[^1] == '\\' + ? folder.Remove(folder.Length - 1).ToLower() + : folder.ToLower(); if (!acadPathLowerArr.Contains(folderLower)) acadPath = folder + ";" + acadPath; //加到前面方便检查 } @@ -611,14 +611,17 @@ public static void AppendSupportPath(params string[] folders) /// 目录 public static void RemoveSupportPath(params string[] folders) { - if (!folders.Any()) return; + if (!folders.Any()) + return; var acadPathArr = GetEnv("ACAD").Split(';').ToList(); foreach (var folder in folders) { - var folderLower = - folder[^1] == '\\' ? folder.Remove(folder.Length - 1).ToLower() : folder.ToLower(); + var folderLower = folder[^1] == '\\' + ? folder.Remove(folder.Length - 1).ToLower() + : folder.ToLower(); acadPathArr.RemoveAll(item => - (item[^1] == '\\' ? item.Remove(item.Length - 1).ToLower() : item.ToLower()) == folderLower); + (item[^1] == '\\' ? item.Remove(item.Length - 1).ToLower() : item.ToLower()) == + folderLower); } SetEnv("ACAD", string.Join(";", acadPathArr)); @@ -630,21 +633,21 @@ public static void RemoveSupportPath(params string[] folders) /// 目录 public static void AppendTrustedPath(params string[] folders) { - if (folders.Length == 0) return; + if (folders.Length == 0) + return; var trustedPath = GetVar("TRUSTEDPATHS").ToString(); - var trustedPathLowerArr = - trustedPath! - .ToLower() - .Split(';') - .Where(item => item != "") - .Select(item => - item[^1] == '\\' ? item.Remove(item.Length - 1) : item) - .ToHashSet(); + var trustedPathLowerArr = trustedPath!.ToLower() + .Split(';') + .Where(item => item != "") + .Select(item => item[^1] == '\\' ? item.Remove(item.Length - 1) : item) + .ToHashSet(); foreach (var folder in folders) { - if (!Directory.Exists(folder)) continue; - var folderLower = - folder[^1] == '\\' ? folder.Remove(folder.Length - 1).ToLower() : folder.ToLower(); + if (!Directory.Exists(folder)) + continue; + var folderLower = folder[^1] == '\\' + ? folder.Remove(folder.Length - 1).ToLower() + : folder.ToLower(); if (!trustedPathLowerArr.Contains(folderLower)) trustedPath = folder + ";" + trustedPath; //加到前面方便检查 } @@ -658,14 +661,17 @@ public static void AppendTrustedPath(params string[] folders) /// 目录 public static void RemoveTrustedPath(params string[] folders) { - if (!folders.Any()) return; + if (!folders.Any()) + return; var trustedPathArr = GetVar("TRUSTEDPATHS").ToString()!.Split(';').ToList(); foreach (var folder in folders) { - var folderLower = - folder[^1] == '\\' ? folder.Remove(folder.Length - 1).ToLower() : folder.ToLower(); + var folderLower = folder[^1] == '\\' + ? folder.Remove(folder.Length - 1).ToLower() + : folder.ToLower(); trustedPathArr.RemoveAll(item => - (item[^1] == '\\' ? item.Remove(item.Length - 1).ToLower() : item.ToLower()) == folderLower); + (item[^1] == '\\' ? item.Remove(item.Length - 1).ToLower() : item.ToLower()) == + folderLower); } SetVar("TRUSTEDPATHS", string.Join(";", trustedPathArr)); @@ -703,7 +709,6 @@ public static bool IsUcs() return (short)GetVar("WORLDUCS") == 0; } - #region dwg版本号/cad版本号/年份 /// @@ -803,7 +808,6 @@ public static string GetAcapVersionDll(string str = "acdb") #endregion - #region cad变量功能延伸 /// @@ -834,7 +838,8 @@ public static string GetAcapVersionDll(string str = "acdb") return null; // 相同的参数进行设置会发生一次异常 - if (!string.Equals(currentVar.ToString(), valueType.ToString(), StringComparison.CurrentCultureIgnoreCase)) + if (!string.Equals(currentVar.ToString(), valueType.ToString(), + StringComparison.CurrentCultureIgnoreCase)) SetVar(key, valueType); return currentVar; @@ -871,17 +876,5 @@ public static Dictionary SaveCadVar(Dictionary a return dict; } - /// - /// 延迟更新图层锁定淡显状态 - /// 在有锁定或解锁图层的命令的末尾使用 - /// - public static void DelayUpdateLayLockFade() - { - const string lfName = "LAYLOCKFADECTL"; - var lf = Convert.ToInt32(Acaop.GetSystemVariable(lfName).ToString()); - Acaop.SetSystemVariable(lfName, -lf); - IdleAction.Add(() => Acaop.SetSystemVariable(lfName, lf)); - } - #endregion } \ No newline at end of file -- Gitee From 7c5dbaaa601a72aae60bd7aac35ff909de88a3b8 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Tue, 8 Apr 2025 10:36:17 +0800 Subject: [PATCH 410/453] =?UTF-8?q?=E5=B0=86=20SystemVariableManager=20?= =?UTF-8?q?=E7=B1=BB=E6=94=B9=E4=B8=BA=E9=9D=99=E6=80=81=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Runtime/SystemVariableManager.cs | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/CADShared/Runtime/SystemVariableManager.cs b/src/CADShared/Runtime/SystemVariableManager.cs index f502c1d..c16dd8c 100644 --- a/src/CADShared/Runtime/SystemVariableManager.cs +++ b/src/CADShared/Runtime/SystemVariableManager.cs @@ -5,14 +5,14 @@ namespace IFoxCAD.Cad; /// /// 系统变量管理器 /// -public class SystemVariableManager +public static class SystemVariableManager { #region A /// /// 打开或关闭自动捕捉靶框的显示 /// - public bool ApBox + public static bool ApBox { get => Convert.ToBoolean(Acaop.GetSystemVariable(nameof(ApBox))); set => Acaop.SetSystemVariable(nameof(ApBox), Convert.ToInt32(value)); @@ -21,7 +21,7 @@ public bool ApBox /// /// 对象捕捉靶框的大小,范围[1,50] /// - public int Aperture + public static int Aperture { get => Convert.ToInt32(Acaop.GetSystemVariable(nameof(Aperture))); set => Acaop.SetSystemVariable(nameof(Aperture), value); @@ -30,7 +30,7 @@ public int Aperture /// /// 图形单位-角度-类型,范围[0-十进制度数,1-度/分/秒,2-百分度,3-弧度,4-勘测单位] /// - public int Aunits + public static int Aunits { get => Convert.ToInt32(Acaop.GetSystemVariable(nameof(Aunits))); set => Acaop.SetSystemVariable(nameof(Aunits), value); @@ -39,7 +39,7 @@ public int Aunits /// /// 图形单位-角度-精度,范围[0,8] /// - public int Auprec + public static int Auprec { get => Convert.ToInt32(Acaop.GetSystemVariable(nameof(Auprec))); set => Acaop.SetSystemVariable(nameof(Auprec), value); @@ -52,7 +52,7 @@ public int Auprec /// /// 是否在块编辑器中 /// - public bool BlockEditor => Acaop.GetSystemVariable(nameof(BlockEditor)) is 1; + public static bool BlockEditor => Acaop.GetSystemVariable(nameof(BlockEditor)) is 1; #endregion @@ -238,7 +238,7 @@ public static bool DynPrompt /// /// 显示图形栅格 /// - public bool GridMode + public static bool GridMode { get => Acaop.GetSystemVariable(nameof(GridMode)) is 1; set => Acaop.SetSystemVariable(nameof(GridMode), Convert.ToInt32(value)); @@ -278,7 +278,7 @@ public static double HPScale /// /// 图形单位-插入时的缩放单位 /// - public UnitsValue Insunits + public static UnitsValue Insunits { get => (UnitsValue)Acaop.GetSystemVariable(nameof(Insunits)); set => Acaop.SetSystemVariable(nameof(Insunits), (int)value); @@ -291,7 +291,7 @@ public UnitsValue Insunits /// /// 储存所输入相对于当前用户坐标系统(UCS)的最后点的值 /// - public Point3d LastPoint + public static Point3d LastPoint { get => (Point3d)Acaop.GetSystemVariable(nameof(LastPoint)); set => Acaop.SetSystemVariable(nameof(LastPoint), value); @@ -300,7 +300,7 @@ public Point3d LastPoint /// /// 图形单位-长度-类型,范围[1-科学,2-小数,3-工程,4-建筑,5-分数] /// - public int Lunits + public static int Lunits { get => Convert.ToInt32(Acaop.GetSystemVariable(nameof(Lunits))); set => Acaop.SetSystemVariable(nameof(Lunits), value); @@ -309,7 +309,7 @@ public int Lunits /// /// 图形单位-长度-精度,范围[0,8] /// - public int Luprec + public static int Luprec { get => Convert.ToInt32(Acaop.GetSystemVariable(nameof(Luprec))); set => Acaop.SetSystemVariable(nameof(Luprec), value); @@ -322,7 +322,7 @@ public int Luprec /// /// 图形单位 /// - public MeasurementValue Measurement + public static MeasurementValue Measurement { get => (MeasurementValue)Acaop.GetSystemVariable(nameof(Measurement)); set => Acaop.SetSystemVariable(nameof(Measurement), Convert.ToInt32(value)); -- Gitee From fe3bd6f82e3be9d7973973855afd8a660f59d452 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Tue, 8 Apr 2025 10:38:36 +0800 Subject: [PATCH 411/453] =?UTF-8?q?=E5=B0=86DocumentLockManager=E6=94=B9?= =?UTF-8?q?=E4=B8=BA=E5=AF=86=E5=B0=81=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CADShared/ExtensionMethod/DocumentLockManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CADShared/ExtensionMethod/DocumentLockManager.cs b/src/CADShared/ExtensionMethod/DocumentLockManager.cs index 17a2928..6004065 100644 --- a/src/CADShared/ExtensionMethod/DocumentLockManager.cs +++ b/src/CADShared/ExtensionMethod/DocumentLockManager.cs @@ -3,7 +3,7 @@ /// /// 文档锁管理器,用于管理文档的锁定和解锁。 /// -public class DocumentLockManager : IDisposable +public sealed class DocumentLockManager : IDisposable { /// /// 用于存储文档锁的实例,如果文档未锁定则为null。 -- Gitee From e3c322fb3a86de9dc6bd2e093e8ae1c5cba282d8 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Tue, 8 Apr 2025 10:40:16 +0800 Subject: [PATCH 412/453] =?UTF-8?q?refactor(CADShared):=20=E9=87=8D?= =?UTF-8?q?=E5=91=BD=E5=90=8D=E6=9E=9A=E4=B8=BE=E5=80=BC=E5=B9=B6=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E4=BB=A3=E7=A0=81=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 KeywordName 枚举值重命名为大写,以符合常量命名惯例 -优化 ObjectIdEx.cs 中的方法定义格式,提高代码可读性 - 修复 Erase 方法,确保仅在 id 有效时执行擦除操作 --- src/CADShared/ExtensionMethod/CollectionEx.cs | 14 ++--- src/CADShared/ExtensionMethod/ObjectIdEx.cs | 56 ++++++++++--------- 2 files changed, 36 insertions(+), 34 deletions(-) diff --git a/src/CADShared/ExtensionMethod/CollectionEx.cs b/src/CADShared/ExtensionMethod/CollectionEx.cs index f015ecb..61415d3 100644 --- a/src/CADShared/ExtensionMethod/CollectionEx.cs +++ b/src/CADShared/ExtensionMethod/CollectionEx.cs @@ -185,17 +185,17 @@ public enum KeywordName /// /// 全局名字 /// - GlobalName, + GLOBAL, /// /// 本地名字 /// - LocalName, + LOCAL, /// /// 显示名字 /// - DisplayName, + DISPLAY, } /// @@ -207,12 +207,12 @@ public enum KeywordName /// true含有 [DebuggerStepThrough] public static bool Contains(this KeywordCollection collection, string name, - KeywordName keywordName = KeywordName.GlobalName) + KeywordName keywordName = KeywordName.GLOBAL) { var contains = false; switch (keywordName) { - case KeywordName.GlobalName: + case KeywordName.GLOBAL: for (var i = 0; i < collection.Count; i++) { var item = collection[i]; @@ -225,7 +225,7 @@ public static bool Contains(this KeywordCollection collection, string name, } break; - case KeywordName.LocalName: + case KeywordName.LOCAL: for (var i = 0; i < collection.Count; i++) { var item = collection[i]; @@ -238,7 +238,7 @@ public static bool Contains(this KeywordCollection collection, string name, } break; - case KeywordName.DisplayName: + case KeywordName.DISPLAY: for (var i = 0; i < collection.Count; i++) { var item = collection[i]; diff --git a/src/CADShared/ExtensionMethod/ObjectIdEx.cs b/src/CADShared/ExtensionMethod/ObjectIdEx.cs index b305350..ba790c2 100644 --- a/src/CADShared/ExtensionMethod/ObjectIdEx.cs +++ b/src/CADShared/ExtensionMethod/ObjectIdEx.cs @@ -15,14 +15,13 @@ public static class ObjectIdEx /// 是否打开已删除对象,默认为不打开 /// 是否打开锁定图层对象,默认为不打开 /// 指定类型对象 - public static DBObject GetObject(this ObjectId id, - OpenMode openMode = OpenMode.ForRead, - bool openErased = false, - bool openLockedLayer = false) + public static DBObject GetObject(this ObjectId id, OpenMode openMode = OpenMode.ForRead, + bool openErased = false, bool openLockedLayer = false) { var tr = DBTrans.GetTopTransaction(id.Database); return tr.GetObject(id, openMode, openErased, openLockedLayer); } + /// /// 获取指定类型对象 /// @@ -32,10 +31,8 @@ public static DBObject GetObject(this ObjectId id, /// 是否打开已删除对象,默认为不打开 /// 是否打开锁定图层对象,默认为不打开 /// 指定类型对象 - public static T? GetObject(this ObjectId id, - OpenMode openMode = OpenMode.ForRead, - bool openErased = false, - bool openLockedLayer = false) where T : DBObject + public static T? GetObject(this ObjectId id, OpenMode openMode = OpenMode.ForRead, + bool openErased = false, bool openLockedLayer = false) where T : DBObject { var tr = DBTrans.GetTopTransaction(id.Database); return tr.GetObject(id, openMode, openErased, openLockedLayer) as T; @@ -52,9 +49,8 @@ public static DBObject GetObject(this ObjectId id, /// 指定类型对象集合 [DebuggerStepThrough] public static IEnumerable GetObject(this IEnumerable ids, - OpenMode openMode = OpenMode.ForRead, - bool openErased = false, - bool openLockedLayer = false) where T : DBObject + OpenMode openMode = OpenMode.ForRead, bool openErased = false, bool openLockedLayer = false) + where T : DBObject { var rxc = RXObject.GetClass(typeof(T)); return ids.Where(id => id.ObjectClass.IsDerivedFrom(rxc)) @@ -73,9 +69,8 @@ public static IEnumerable GetObject(this IEnumerable ids, /// 指定类型对象集合 [DebuggerStepThrough] public static IEnumerable GetObject(this ObjectIdCollection ids, - OpenMode openMode = OpenMode.ForRead, - bool openErased = false, - bool openLockedLayer = false) where T : DBObject + OpenMode openMode = OpenMode.ForRead, bool openErased = false, bool openLockedLayer = false) + where T : DBObject { return ids.Cast().GetObject(openMode, openErased, openLockedLayer); } @@ -87,7 +82,8 @@ public static IEnumerable GetObject(this ObjectIdCollection ids, /// 对象id集合 /// 精确匹配 /// 对象id集合 - public static IEnumerable IsDerivedFrom(this IEnumerable ids, bool exactMatch = false) where T : DBObject + public static IEnumerable IsDerivedFrom(this IEnumerable ids, + bool exactMatch = false) where T : DBObject { var rxc = RXObject.GetClass(typeof(T)); if (exactMatch) @@ -120,7 +116,9 @@ public static ObjectId GetObjectId(this Database db, string handleString) /// 对象的ObjectId public static ObjectId GetObjectId(this Database db, Handle? handle) { - return handle is not null && db.TryGetObjectId(handle.Value, out var id) ? id : ObjectId.Null; + return handle is not null && db.TryGetObjectId(handle.Value, out var id) + ? id + : ObjectId.Null; } /// @@ -130,7 +128,9 @@ public static ObjectId GetObjectId(this Database db, Handle? handle) /// 句柄 public static Handle? ConvertToHandle(this string handleString) { - return long.TryParse(handleString, NumberStyles.HexNumber, null, out var l) ? new Handle(l) : null; + return long.TryParse(handleString, NumberStyles.HexNumber, null, out var l) + ? new Handle(l) + : null; } /// @@ -140,7 +140,14 @@ public static ObjectId GetObjectId(this Database db, Handle? handle) /// id有效返回 ,反之返回 public static bool IsOk(this ObjectId id) { - return id is { IsNull: false, IsValid: true, IsErased: false, IsEffectivelyErased: false, IsResident: true }; + return id is + { + IsNull: false, + IsValid: true, + IsErased: false, + IsEffectivelyErased: false, + IsResident: true + }; } /// @@ -149,14 +156,9 @@ public static bool IsOk(this ObjectId id) /// 对象id public static void Erase(this ObjectId id) { - if (id.IsOk()) - { - var ent = id.GetObject()!; - using (ent.ForWrite()) - { - ent.Erase(); - } // 第一种读写权限自动转换写法 - // Env.Editor.Regen(); - } + if (!id.IsOk()) + return; + var dbo = id.GetObject(OpenMode.ForWrite); + dbo.Erase(); } } \ No newline at end of file -- Gitee From efddc03635e2bbcf957985afb91c73726a5fd4eb Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Tue, 8 Apr 2025 10:42:09 +0800 Subject: [PATCH 413/453] =?UTF-8?q?=E7=A7=BB=E9=99=A4=20CheckFactory=20?= =?UTF-8?q?=E4=B8=AD=E7=9A=84=20#if=20DEBUG=20=E6=8C=87=E4=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CADShared/Initialize/CheckFactory.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/CADShared/Initialize/CheckFactory.cs b/src/CADShared/Initialize/CheckFactory.cs index ae66f98..d310854 100644 --- a/src/CADShared/Initialize/CheckFactory.cs +++ b/src/CADShared/Initialize/CheckFactory.cs @@ -1,5 +1,4 @@ -#if DEBUG -namespace IFoxCAD.Cad; +namespace IFoxCAD.Cad; /// /// 命令检查类 @@ -43,12 +42,10 @@ public static void CheckDuplicateCommand(Assembly? assembly = null) } } - var strings = dic - .Where(o => o.Value.Count() > 1) + var strings = dic.Where(o => o.Value.Count() > 1) .Select(o => o.Key + "命令重复,在类" + string.Join("和", o.Value) + "中"); var str = string.Join(Environment.NewLine, strings); if (!string.IsNullOrEmpty(str)) System.Windows.Forms.MessageBox.Show(str, @"错误:重复命令!"); } -} -#endif \ No newline at end of file +} \ No newline at end of file -- Gitee From e17662c6b408a8b677474cafb0f8e37089f3c8d6 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Tue, 8 Apr 2025 10:44:35 +0800 Subject: [PATCH 414/453] =?UTF-8?q?=E4=BC=98=E5=8C=96=20IAutoGo=20?= =?UTF-8?q?=E7=B1=BB=E7=9A=84=E8=AE=BF=E9=97=AE=E4=BF=AE=E9=A5=B0=E7=AC=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CADShared/Initialize/IAutoGo.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/CADShared/Initialize/IAutoGo.cs b/src/CADShared/Initialize/IAutoGo.cs index e9608be..cba370a 100644 --- a/src/CADShared/Initialize/IAutoGo.cs +++ b/src/CADShared/Initialize/IAutoGo.cs @@ -108,8 +108,8 @@ public class AutoReflection(string dllName, AutoRegConfig configInfo) private static List _initializeList = []; // 储存方法用于初始化 private static List _terminateList = []; // 储存方法用于结束释放 - readonly string _dllName = dllName; - readonly AutoRegConfig _autoRegConfig = configInfo; + private readonly string _dllName = dllName; + private readonly AutoRegConfig _autoRegConfig = configInfo; /// /// 启动cad的时候会自动执行 @@ -232,7 +232,7 @@ public static void AppDomainGetTypes(Action action, string? dllNameWithout /// /// /// - void GetInterfaceFunctions(List initializes, string initializeName, + private void GetInterfaceFunctions(List initializes, string initializeName, List terminates, string terminateName) { AppDomainGetTypes(type => @@ -301,7 +301,7 @@ void GetInterfaceFunctions(List initializes, string initializeName, /// /// 收集特性下的函数 /// - void GetAttributeFunctions(List initializes, + private void GetAttributeFunctions(List initializes, List terminates) { AppDomainGetTypes(type => @@ -340,7 +340,7 @@ void GetAttributeFunctions(List initializes, /// /// 执行收集到的函数 /// - static void RunFunctions(List runClassList) + private static void RunFunctions(List runClassList) { foreach (var t in runClassList) t.Run(); -- Gitee From e13eecd58995986775845548f9d46b828eb66724 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Tue, 8 Apr 2025 10:53:43 +0800 Subject: [PATCH 415/453] =?UTF-8?q?refactor(CADShared):=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=20RemoveXData=20=E6=96=B9=E6=B3=95=E7=9A=84=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修改了判断条件,使用 GetXDataForApplication 方法来检查特定应用的扩展数据是否存在 - 移除了不必要的 new XDataList() 中的括号,简化了代码 --- src/CADShared/ExtensionMethod/DBObjectEx.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CADShared/ExtensionMethod/DBObjectEx.cs b/src/CADShared/ExtensionMethod/DBObjectEx.cs index 13c23ce..9d1f9ab 100644 --- a/src/CADShared/ExtensionMethod/DBObjectEx.cs +++ b/src/CADShared/ExtensionMethod/DBObjectEx.cs @@ -59,12 +59,12 @@ public static void RemoveXData(this DBObject obj, string appName, DxfCode dxfCod /// 应用程序名称 public static void RemoveXData(this DBObject obj, string appName) { - if (obj.XData is null) + if (obj.GetXDataForApplication(appName) is null) return; // 直接赋值进去等于清空名称 using (obj.ForWrite()) - obj.XData = new XDataList() { { 1001, appName } }; + obj.XData = new XDataList { { 1001, appName } }; } /// -- Gitee From 8de5b7e1112ed0587c2da6e69c01374beb5ca3ad Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Tue, 8 Apr 2025 11:01:06 +0800 Subject: [PATCH 416/453] =?UTF-8?q?feat(CADShared):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=20RXClass=20=E6=89=A9=E5=B1=95=E7=B1=BB=E5=B9=B6=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E7=9B=B8=E5=85=B3=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 RXClassEx 类,用于缓存和快速获取 RXClass 对象 - 修改 DBTransEx 类中的 GetAllIds 方法,将内部实现设为 private - 更新 SelectionSetEx 类,使用 RXClassEx 以提高性能 --- src/CADShared/CADShared.projitems | 1 + src/CADShared/ExtensionMethod/DBTransEx.cs | 2 +- src/CADShared/ExtensionMethod/RXClassEx.cs | 28 +++++++++++++++++++ .../ExtensionMethod/SelectionSetEx.cs | 5 ++-- 4 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 src/CADShared/ExtensionMethod/RXClassEx.cs diff --git a/src/CADShared/CADShared.projitems b/src/CADShared/CADShared.projitems index b6f36ff..a9c5954 100644 --- a/src/CADShared/CADShared.projitems +++ b/src/CADShared/CADShared.projitems @@ -65,6 +65,7 @@ + diff --git a/src/CADShared/ExtensionMethod/DBTransEx.cs b/src/CADShared/ExtensionMethod/DBTransEx.cs index 8838267..f28d451 100644 --- a/src/CADShared/ExtensionMethod/DBTransEx.cs +++ b/src/CADShared/ExtensionMethod/DBTransEx.cs @@ -72,7 +72,7 @@ public static void Purge(this DBTrans tr, SymModes sym = SymModes.All, bool excl id.Erase(); } - static void GetAllIds(DBTrans tr, SymbolTable symbolTable, + private static void GetAllIds(DBTrans tr, SymbolTable symbolTable, ObjectIdCollection ids, bool excludeXref = true) where TTable : SymbolTable where TRecord : SymbolTableRecord, new() { diff --git a/src/CADShared/ExtensionMethod/RXClassEx.cs b/src/CADShared/ExtensionMethod/RXClassEx.cs new file mode 100644 index 0000000..a1175cf --- /dev/null +++ b/src/CADShared/ExtensionMethod/RXClassEx.cs @@ -0,0 +1,28 @@ +namespace IFoxCAD.CAD.ExtensionMethod; + +/// +/// RXClass扩展 +/// +public static class RXClassEx +{ + /// + /// 获取RXClass + /// + /// 类型 + /// + public static RXClass Get() where T : DBObject + { + var type = typeof(T); + if (!_dict.TryGetValue(type, out var rxClass)) + { + _dict[type] = rxClass = RXObject.GetClass(type); + } + + return rxClass; + } + + /// + /// 由于RXObject.GetClass速度极慢,采用内部字典优化速度 + /// + private static readonly Dictionary _dict = []; +} \ No newline at end of file diff --git a/src/CADShared/ExtensionMethod/SelectionSetEx.cs b/src/CADShared/ExtensionMethod/SelectionSetEx.cs index 3d152fb..cceecf0 100644 --- a/src/CADShared/ExtensionMethod/SelectionSetEx.cs +++ b/src/CADShared/ExtensionMethod/SelectionSetEx.cs @@ -1,4 +1,5 @@ -#if a2024 || zcad +using IFoxCAD.CAD.ExtensionMethod; +#if a2024 || zcad using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif @@ -20,7 +21,7 @@ public static class SelectionSetEx [DebuggerStepThrough] public static IEnumerable GetObjectIds(this SelectionSet ss) where T : Entity { - var rxc = RXObject.GetClass(typeof(T)); + var rxc = RXClassEx.Get(); return ss.GetObjectIds() .Where(id => id.ObjectClass.IsDerivedFrom(rxc)); -- Gitee From 897aec76452281691ec0e2494a984b6e69eb7e3e Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Tue, 8 Apr 2025 11:10:43 +0800 Subject: [PATCH 417/453] =?UTF-8?q?refactor(CADShared):=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=20GetRelativePath=20=E6=96=B9=E6=B3=95=E4=B8=AD?= =?UTF-8?q?=E7=9A=84=E5=8F=98=E9=87=8F=E5=A3=B0=E6=98=8E-=20=E5=B0=86=20st?= =?UTF-8?q?ring[]=20=E7=B1=BB=E5=9E=8B=E7=9A=84=E5=8F=98=E9=87=8F=E5=A3=B0?= =?UTF-8?q?=E6=98=8E=E6=94=B9=E4=B8=BA=E4=BD=BF=E7=94=A8=20var=20=E5=85=B3?= =?UTF-8?q?=E9=94=AE=E5=AD=97=20-=20=E6=8F=90=E9=AB=98=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E7=9A=84=E5=8F=AF=E8=AF=BB=E6=80=A7=E5=92=8C=E7=AE=80=E6=B4=81?= =?UTF-8?q?=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CADShared/ExtensionMethod/XrefEx.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CADShared/ExtensionMethod/XrefEx.cs b/src/CADShared/ExtensionMethod/XrefEx.cs index 39f7889..b23d94c 100644 --- a/src/CADShared/ExtensionMethod/XrefEx.cs +++ b/src/CADShared/ExtensionMethod/XrefEx.cs @@ -578,8 +578,8 @@ public static string GetRelativePath(string strDbPath, string strXrefPath) /// ]]> private static string GetRelativePath(string directory, string file) { - string[] directories = directory.Split('\\'); - string[] files = file.Split('\\'); + var directories = directory.Split('\\'); + var files = file.Split('\\'); // 获取两条路径中的最短路径 var getMinLength = directories.Length < files.Length ? directories.Length : files.Length; -- Gitee From 9b0a764c63c88a01ebf184be67138b133f6ec961 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Tue, 8 Apr 2025 11:17:27 +0800 Subject: [PATCH 418/453] =?UTF-8?q?build:=20=E6=9B=B4=E6=96=B0=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E5=8F=B7=E8=87=B3=200.9.3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index e974cca..e7e8311 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,7 +1,7 @@ - 0.9.3-preview4 + 0.9.3 更新dwgfilter的null返回方式 -- Gitee From ddeccf3beb264ba52d61a139b2e2ae7fec8b769e Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Tue, 8 Apr 2025 16:39:17 +0800 Subject: [PATCH 419/453] =?UTF-8?q?refactor(CAD):=20=E4=BF=AE=E6=94=B9=20R?= =?UTF-8?q?XClassEx.cs=20=E4=B8=AD=E7=9A=84=E5=91=BD=E5=90=8D=E7=A9=BA?= =?UTF-8?q?=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将命名空间从 IFoxCAD.CAD.ExtensionMethod 更改为 IFoxCAD.CAD --- src/CADShared/ExtensionMethod/RXClassEx.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CADShared/ExtensionMethod/RXClassEx.cs b/src/CADShared/ExtensionMethod/RXClassEx.cs index a1175cf..a6e299a 100644 --- a/src/CADShared/ExtensionMethod/RXClassEx.cs +++ b/src/CADShared/ExtensionMethod/RXClassEx.cs @@ -1,4 +1,4 @@ -namespace IFoxCAD.CAD.ExtensionMethod; +namespace IFoxCAD.CAD; /// /// RXClass扩展 -- Gitee From 4e944194c9a4e6f92771f7430336deecf08d78ed Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Tue, 8 Apr 2025 16:43:29 +0800 Subject: [PATCH 420/453] =?UTF-8?q?refactor(CADShared):=20=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=20SelectionSetEx.cs=20=E6=96=87=E4=BB=B6=E7=9A=84?= =?UTF-8?q?=E5=BC=95=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 using IFoxCAD.CAD.ExtensionMethod; 修改为 using IFoxCAD.CAD; --- src/CADShared/ExtensionMethod/SelectionSetEx.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CADShared/ExtensionMethod/SelectionSetEx.cs b/src/CADShared/ExtensionMethod/SelectionSetEx.cs index cceecf0..58d513a 100644 --- a/src/CADShared/ExtensionMethod/SelectionSetEx.cs +++ b/src/CADShared/ExtensionMethod/SelectionSetEx.cs @@ -1,4 +1,4 @@ -using IFoxCAD.CAD.ExtensionMethod; +using IFoxCAD.CAD; #if a2024 || zcad using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif -- Gitee From bc7a2429c144ab627fcfaddde05f20d2be07589e Mon Sep 17 00:00:00 2001 From: yupeng_dyp Date: Thu, 10 Apr 2025 14:23:39 +0000 Subject: [PATCH 421/453] =?UTF-8?q?=E5=A6=82=20jig=20=E5=B7=B2=E5=9C=A8?= =?UTF-8?q?=E5=A4=96=E9=9D=A2=E8=A2=AB=E9=87=8A=E6=94=BE=EF=BC=8C=E5=88=99?= =?UTF-8?q?=E5=86=85=E9=83=A8=E5=85=88=E5=88=A4=E6=96=AD=20ent.Database=20?= =?UTF-8?q?=E4=BC=9A=E5=AF=BC=E8=87=B4=E6=8A=A5=E9=94=99=EF=BC=81=20?= =?UTF-8?q?=E5=B0=86=20jig=20=E9=87=8A=E6=94=BE=E6=97=B6=E7=9A=84=E6=9D=A1?= =?UTF-8?q?=E4=BB=B6=E5=88=A4=E6=96=AD=E9=A1=BA=E5=BA=8F=E7=94=B1=20if=20(?= =?UTF-8?q?ent.Database=20=3D=3D=20null=20&&=20!ent.IsDisposed=20)=20?= =?UTF-8?q?=E6=94=B9=E4=B8=BA=20if=20(!ent.IsDisposed=20&&=20ent.Database?= =?UTF-8?q?=20=3D=3D=20null)=EF=BC=8C=E9=81=BF=E5=85=8D=E5=9B=A0=E5=9C=A8?= =?UTF-8?q?=E5=A4=96=E9=9D=A2=E9=87=8A=E6=94=BE=E5=90=8E=E5=86=85=E9=83=A8?= =?UTF-8?q?=E5=88=A4=E6=96=AD=E5=AF=BC=E8=87=B4=E9=94=99=E8=AF=AF=E8=80=8C?= =?UTF-8?q?=E9=80=80=E5=87=BACAD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: yupeng_dyp --- src/CADShared/ExtensionMethod/Jig/JigEx.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CADShared/ExtensionMethod/Jig/JigEx.cs b/src/CADShared/ExtensionMethod/Jig/JigEx.cs index 7289922..84fe249 100644 --- a/src/CADShared/ExtensionMethod/Jig/JigEx.cs +++ b/src/CADShared/ExtensionMethod/Jig/JigEx.cs @@ -1,4 +1,4 @@ -#if a2024 || zcad +#if a2024 || zcad using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; // ReSharper disable ClassWithVirtualMembersNeverInherited.Global @@ -371,7 +371,7 @@ protected virtual void Dispose(bool disposing) // 最后一次的图元如果没有加入数据库,就在此销毁,所以JigEx调用的时候加using _drawEntities.ForEach(ent => { - if (ent.Database == null && !ent.IsDisposed) + if (!ent.IsDisposed && ent.Database == null) ent.Dispose(); }); } -- Gitee From 14ac1ca745b276e92077f6d9e1ca6e85ed0705b5 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Wed, 16 Apr 2025 17:17:34 +0800 Subject: [PATCH 422/453] =?UTF-8?q?=E6=95=B4=E7=90=86=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E6=90=9C=E7=B4=A2=E8=B7=AF=E5=BE=84=E5=92=8C?= =?UTF-8?q?=E4=BF=A1=E4=BB=BB=E8=B7=AF=E5=BE=84=E7=9A=84=E6=89=A9=E5=B1=95?= =?UTF-8?q?=E6=96=B9=E6=B3=95=E5=B9=B6=E6=B7=BB=E5=8A=A0Get=E6=96=B9?= =?UTF-8?q?=E6=B3=95=EF=BC=8C=E5=8F=91=E5=B8=830.9.4=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CADShared/CADShared.projitems | 2 + src/CADShared/CADShared.shproj.DotSettings | 2 + .../ExtensionMethod/SupportPathEx.cs | 75 ++++++++++ .../ExtensionMethod/TrustedPathEx.cs | 75 ++++++++++ src/CADShared/Runtime/Env.cs | 135 ++++-------------- src/Directory.Build.props | 4 +- 6 files changed, 185 insertions(+), 108 deletions(-) create mode 100644 src/CADShared/CADShared.shproj.DotSettings create mode 100644 src/CADShared/ExtensionMethod/SupportPathEx.cs create mode 100644 src/CADShared/ExtensionMethod/TrustedPathEx.cs diff --git a/src/CADShared/CADShared.projitems b/src/CADShared/CADShared.projitems index a9c5954..48f9e01 100644 --- a/src/CADShared/CADShared.projitems +++ b/src/CADShared/CADShared.projitems @@ -68,11 +68,13 @@ + + diff --git a/src/CADShared/CADShared.shproj.DotSettings b/src/CADShared/CADShared.shproj.DotSettings new file mode 100644 index 0000000..ab0a621 --- /dev/null +++ b/src/CADShared/CADShared.shproj.DotSettings @@ -0,0 +1,2 @@ + + True \ No newline at end of file diff --git a/src/CADShared/ExtensionMethod/SupportPathEx.cs b/src/CADShared/ExtensionMethod/SupportPathEx.cs new file mode 100644 index 0000000..fa0803f --- /dev/null +++ b/src/CADShared/ExtensionMethod/SupportPathEx.cs @@ -0,0 +1,75 @@ +namespace IFoxCAD.Cad; + +internal static class SupportPathEx +{ + private const string kName = "ACAD"; + + /// + /// 获取支持路径 + /// + /// 路径列表 + public static List Get() + { + var str = Env.GetEnv(kName); + var set = str.ToLower() + .Split([";"], StringSplitOptions.RemoveEmptyEntries) + .Select(s => s.TrimEnd('\\')) + .ToHashSet(); + return set.ToList(); + } + + /// + /// 添加支持路径 + /// + /// 路径列表 + public static void Add(params IEnumerable dirs) + { + var dirSet = dirs.ToLowerDirSet(); + if (dirSet.Count == 0) + return; + var supportPaths = Get(); + foreach (var dir in dirSet) + { + if (!Directory.Exists(dir)) + continue; + if (supportPaths.Contains(dir)) + continue; + supportPaths.Insert(0, dir); + } + + Set(supportPaths); + } + + /// + /// 移除支持路径 + /// + /// 路径列表 + public static void Remove(params IEnumerable dirs) + { + var dirSet = dirs.ToLowerDirSet(); + var supportPaths = Get(); + supportPaths.RemoveAll(dirSet.Contains); + Set(supportPaths); + } + + /// + /// 设置支持路径 + /// + /// 路径列表 + private static void Set(IEnumerable dirs) + { + var set = dirs.Where(Directory.Exists).ToLowerDirSet(); + var str = string.Join(";", set); + Env.SetEnv(kName, str); + } + + /// + /// 转换为小写并去除尾部反斜杠的路径集合 + /// + /// 路径列表 + /// 路径集合 + private static HashSet ToLowerDirSet(this IEnumerable dirs) + { + return dirs.Select(dir => dir.ToLower().TrimEnd('\\')).ToHashSet(); + } +} \ No newline at end of file diff --git a/src/CADShared/ExtensionMethod/TrustedPathEx.cs b/src/CADShared/ExtensionMethod/TrustedPathEx.cs new file mode 100644 index 0000000..00c1ccd --- /dev/null +++ b/src/CADShared/ExtensionMethod/TrustedPathEx.cs @@ -0,0 +1,75 @@ +namespace IFoxCAD.Cad; + +internal static class TrustedPathEx +{ + private const string kName = "TRUSTEDPATHS"; + + /// + /// 获取信任路径 + /// + /// 路径列表 + public static List Get() + { + var str = Env.GetVar(kName).ToString(); + var set = str.ToLower() + .Split([";"], StringSplitOptions.RemoveEmptyEntries) + .Select(s => s.TrimEnd('\\')) + .ToHashSet(); + return set.ToList(); + } + + /// + /// 添加信任路径 + /// + /// 路径列表 + public static void Add(params IEnumerable dirs) + { + var dirSet = dirs.ToLowerDirSet(); + if (dirSet.Count == 0) + return; + var paths = Get(); + foreach (var dir in dirSet) + { + if (!Directory.Exists(dir)) + continue; + if (paths.Contains(dir)) + continue; + paths.Insert(0, dir); + } + + Set(paths); + } + + /// + /// 移除信任路径 + /// + /// 路径列表 + public static void Remove(params IEnumerable dirs) + { + var dirSet = dirs.ToLowerDirSet(); + var paths = Get(); + paths.RemoveAll(dirSet.Contains); + Set(paths); + } + + /// + /// 设置信任路径 + /// + /// 路径列表 + private static void Set(IEnumerable dirs) + { + var set = dirs.Where(Directory.Exists).ToLowerDirSet(); + var str = string.Join(";", set); + Env.SetVar(kName, str); + } + + /// + /// 转换为小写并去除尾部反斜杠的路径集合 + /// + /// 路径列表 + /// 路径集合 + private static HashSet ToLowerDirSet(this IEnumerable dirs) + { + return dirs.Select(dir => dir.ToLower().TrimEnd('\\')).ToHashSet(); + } +} \ No newline at end of file diff --git a/src/CADShared/Runtime/Env.cs b/src/CADShared/Runtime/Env.cs index b379ad8..cbf3974 100644 --- a/src/CADShared/Runtime/Env.cs +++ b/src/CADShared/Runtime/Env.cs @@ -87,6 +87,7 @@ public static IConfigurationSection GetGlobalSection(string propertyName) #endregion Preferences #region Enum + /// /// 控制在AutoLISP的command函数运行时AutoCAD是否回显提示和输入, 为显示, 为不显示 /// @@ -100,6 +101,7 @@ public static bool CmdEcho /// 获取Cad当前是否有活动命令 /// public static bool CmdActive => Convert.ToBoolean(Acaop.GetSystemVariable("CMDACTIVE")); + /// /// 控制在光标是否为正交模式, 为打开正交, 为关闭正交 /// @@ -499,15 +501,13 @@ public static void SetVar(string varName, object value, bool echo = true) // TODO: 中望没有测试,此处仅为不报错;本工程所有含有"中望"均存在问题 #if zcad [System.Security.SuppressUnmanagedCodeSecurity] - [DllImport("zced.dll", CharSet = CharSet.Auto, CallingConvention = - CallingConvention.Cdecl, EntryPoint = - "zcedGetEnv")] + [DllImport("zced.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, + EntryPoint = "zcedGetEnv")] static extern int AcedGetEnv(string? envName, StringBuilder ReturnValue); [System.Security.SuppressUnmanagedCodeSecurity] - [DllImport("zced.dll", CharSet = CharSet.Auto, CallingConvention = - CallingConvention.Cdecl, EntryPoint = - "zcedSetEnv")] + [DllImport("zced.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, + EntryPoint = "zcedSetEnv")] static extern int AcedSetEnv(string? envName, StringBuilder NewValue); #endif @@ -527,7 +527,6 @@ public static string GetEnv(string name) // GetEnv("Path")长度很长: // 可用内存 (最新格式) 1 MB (标准格式) // https://docs.microsoft.com/zh-cn/windows/win32/sysinfo/registry-element-size-limits - var sbRes = new StringBuilder(1 << 23); _ = AcedGetEnv(name, sbRes); return sbRes.ToString(); @@ -548,83 +547,33 @@ public static int SetEnv(string name, string var) #endregion - #region win环境变量/由于 Aced的 能够同时获取此变量与cad内的,所以废弃 - - // /// - // /// 获取系统环境变量 - // /// - // /// 变量名 - // /// 指定的环境变量的值;或者如果找不到环境变量,则返回 null - // public static string? GetEnv(string? var) - // { - // // 从当前进程或者从当前用户或本地计算机的 Windows 操作系统注册表项检索环境变量的值 - // // 用户: 计算机\HKEY_CURRENT_USER\Environment - // // 系统: 计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment - // return Environment.GetEnvironmentVariable(var); - // } - // /// - // /// 设置系统环境变量 - // /// - // /// 变量名 - // /// 变量值 - // public static void SetEnv(string? var, string? value) - // { - // // 创建、修改或删除当前进程中或者为当前用户或本地计算机保留的 Windows 操作系统注册表项中存储的环境变量 - // Environment.SetEnvironmentVariable(var, value); - // } - - #endregion - #region 支持文件目录 /// /// 添加目录至CAD支持搜索的路径 /// /// 目录 - public static void AppendSupportPath(params string[] folders) - { - if (!folders.Any()) - return; - var acadPath = GetEnv("ACAD"); - var acadPathLowerArr = acadPath.ToLower() - .Split(';') - .Where(item => item != "") - .Select(item => item[^1] == '\\' ? item.Remove(item.Length - 1) : item) - .ToHashSet(); - foreach (var folder in folders) - { - if (!Directory.Exists(folder)) - continue; - var folderLower = folder[^1] == '\\' - ? folder.Remove(folder.Length - 1).ToLower() - : folder.ToLower(); - if (!acadPathLowerArr.Contains(folderLower)) - acadPath = folder + ";" + acadPath; //加到前面方便检查 - } - - SetEnv("ACAD", acadPath); + public static void AppendSupportPath(params IEnumerable folders) + { + SupportPathEx.Add(folders); } /// /// 删除支持搜索文件目录 /// /// 目录 - public static void RemoveSupportPath(params string[] folders) + public static void RemoveSupportPath(params IEnumerable folders) { - if (!folders.Any()) - return; - var acadPathArr = GetEnv("ACAD").Split(';').ToList(); - foreach (var folder in folders) - { - var folderLower = folder[^1] == '\\' - ? folder.Remove(folder.Length - 1).ToLower() - : folder.ToLower(); - acadPathArr.RemoveAll(item => - (item[^1] == '\\' ? item.Remove(item.Length - 1).ToLower() : item.ToLower()) == - folderLower); - } + SupportPathEx.Remove(folders); + } - SetEnv("ACAD", string.Join(";", acadPathArr)); + /// + /// 获取支持搜索文件目录 + /// + /// 支持搜索文件目录列表 + public static List GetSupportPath() + { + return SupportPathEx.Get(); } /// @@ -633,26 +582,7 @@ public static void RemoveSupportPath(params string[] folders) /// 目录 public static void AppendTrustedPath(params string[] folders) { - if (folders.Length == 0) - return; - var trustedPath = GetVar("TRUSTEDPATHS").ToString(); - var trustedPathLowerArr = trustedPath!.ToLower() - .Split(';') - .Where(item => item != "") - .Select(item => item[^1] == '\\' ? item.Remove(item.Length - 1) : item) - .ToHashSet(); - foreach (var folder in folders) - { - if (!Directory.Exists(folder)) - continue; - var folderLower = folder[^1] == '\\' - ? folder.Remove(folder.Length - 1).ToLower() - : folder.ToLower(); - if (!trustedPathLowerArr.Contains(folderLower)) - trustedPath = folder + ";" + trustedPath; //加到前面方便检查 - } - - SetVar("TRUSTEDPATHS", trustedPath); + TrustedPathEx.Add(folders); } /// @@ -661,20 +591,16 @@ public static void AppendTrustedPath(params string[] folders) /// 目录 public static void RemoveTrustedPath(params string[] folders) { - if (!folders.Any()) - return; - var trustedPathArr = GetVar("TRUSTEDPATHS").ToString()!.Split(';').ToList(); - foreach (var folder in folders) - { - var folderLower = folder[^1] == '\\' - ? folder.Remove(folder.Length - 1).ToLower() - : folder.ToLower(); - trustedPathArr.RemoveAll(item => - (item[^1] == '\\' ? item.Remove(item.Length - 1).ToLower() : item.ToLower()) == - folderLower); - } + TrustedPathEx.Remove(folders); + } - SetVar("TRUSTEDPATHS", string.Join(";", trustedPathArr)); + /// + /// 获取受信任的位置 + /// + /// 受信任的位置列表 + public static List GetTrustedPath() + { + return TrustedPathEx.Get(); } #endregion @@ -823,7 +749,6 @@ public static string GetAcapVersionDll(string str = "acdb") public static object? SetVarEx(string key, string value) { var currentVar = GetVar(key); - object? valueType = currentVar.GetType().Name switch { "String" => value.Replace("\"", string.Empty), @@ -833,7 +758,6 @@ public static string GetAcapVersionDll(string str = "acdb") _ => null, // _ => throw new NotImplementedException() }; - if (valueType is null) return null; @@ -841,7 +765,6 @@ public static string GetAcapVersionDll(string str = "acdb") if (!string.Equals(currentVar.ToString(), valueType.ToString(), StringComparison.CurrentCultureIgnoreCase)) SetVar(key, valueType); - return currentVar; } diff --git a/src/Directory.Build.props b/src/Directory.Build.props index e7e8311..9a365f1 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,8 +1,8 @@ - 0.9.3 - 更新dwgfilter的null返回方式 + 0.9.4 + 整理支持文件搜索路径和信任路径的扩展方法并添加Get方法 -- Gitee From a6f4ca1ac382e7d325b0d7e16536e11b60a927b7 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Mon, 12 May 2025 17:14:02 +0800 Subject: [PATCH 423/453] =?UTF-8?q?=E6=B7=BB=E5=8A=A0EntGet=EF=BC=8C?= =?UTF-8?q?=E7=BB=84=E7=BB=87=E9=83=A8=E5=88=86=E7=B3=BB=E7=BB=9F=E5=8F=98?= =?UTF-8?q?=E9=87=8F=EF=BC=8C=E6=B7=BB=E5=8A=A0=E5=8F=AF=E8=A7=81=E6=80=A7?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=E8=8E=B7=E5=8F=96=E5=8A=9F=E8=83=BD=EF=BC=8C?= =?UTF-8?q?=E5=8F=91=E5=B8=830.9.5=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CADShared/CADShared.projitems | 1 + .../Entity/BlockReferenceEx.cs | 81 +++++++++++++++- .../ExtensionMethod/TrustedPathEx.cs | 2 +- src/CADShared/Runtime/Env.cs | 63 ++++++------- src/CADShared/Runtime/PInvokeCad.cs | 92 +++++++++++++++++++ .../Runtime/SystemVariableManager.cs | 6 +- src/Directory.Build.props | 4 +- tests/TestShared/TestBlkVisibility.cs | 20 ++++ tests/TestShared/TestEnv.cs | 6 +- tests/TestShared/TestShared.projitems | 1 + 10 files changed, 231 insertions(+), 45 deletions(-) create mode 100644 src/CADShared/Runtime/PInvokeCad.cs create mode 100644 tests/TestShared/TestBlkVisibility.cs diff --git a/src/CADShared/CADShared.projitems b/src/CADShared/CADShared.projitems index 48f9e01..ecde82d 100644 --- a/src/CADShared/CADShared.projitems +++ b/src/CADShared/CADShared.projitems @@ -100,6 +100,7 @@ + diff --git a/src/CADShared/ExtensionMethod/Entity/BlockReferenceEx.cs b/src/CADShared/ExtensionMethod/Entity/BlockReferenceEx.cs index 39ad840..fcd4041 100644 --- a/src/CADShared/ExtensionMethod/Entity/BlockReferenceEx.cs +++ b/src/CADShared/ExtensionMethod/Entity/BlockReferenceEx.cs @@ -23,7 +23,6 @@ public static void XClip(this BlockReference brf, IEnumerable pt3ds) { var mat = brf.BlockTransform.Inverse(); var pts = pt3ds.Select(p => p.TransformBy(mat).Point2d()).ToCollection(); - SpatialFilterDefinition sfd = new(pts, Vector3d.ZAxis, 0.0, double.PositiveInfinity, double.NegativeInfinity, true); using SpatialFilter sf = new(); @@ -43,13 +42,11 @@ public static void XClip(this BlockReference brf, Point3d pt1, Point3d pt2) var mat = brf.BlockTransform.Inverse(); pt1 = pt1.TransformBy(mat); pt2 = pt2.TransformBy(mat); - Point2dCollection pts = [ new Point2d(Math.Min(pt1.X, pt2.X), Math.Min(pt1.Y, pt2.Y)), new Point2d(Math.Max(pt1.X, pt2.X), Math.Max(pt1.Y, pt2.Y)) ]; - using SpatialFilter sf = new(); sf.Definition = new(pts, Vector3d.ZAxis, 0.0, double.PositiveInfinity, double.NegativeInfinity, true); @@ -223,9 +220,9 @@ public static string GetBlockName(this BlockReference blk) string nestedBlockName) { var tr = DBTrans.GetTopTransaction(parentBlockRef.Database); - var btr = tr.GetObject(parentBlockRef.BlockTableRecord); - if (btr == null) return null; + if (btr == null) + return null; foreach (var id in btr) { if (id.ObjectClass.Name == "AcDbBlockReference") @@ -323,4 +320,78 @@ public static void NestedForEach(this Entity blockReference, Action + /// 获取块可见性信息 + /// + /// 块参照 + /// 可见性信息 + public static BlockVisibilityInfo GetVisibilityInfo(this BlockReference blockReference) + { + var info = new BlockVisibilityInfo(); + if (blockReference.IsDynamicBlock) + { + var btr = (BlockTableRecord)blockReference.DynamicBlockTableRecord.GetObject(); + info = btr.GetVisibilityInfo(); + } + + return info; + } + + /// + /// 获取块可见性信息 + /// + /// 块表记录 + /// 可见性信息 + public static BlockVisibilityInfo GetVisibilityInfo(this BlockTableRecord btr) + { + var info = new BlockVisibilityInfo(); + if (btr.IsDynamicBlock && btr.ExtensionDictionary.IsOk()) + { + var dict = btr.GetXDictionary(); + if (dict.Contains("ACAD_ENHANCEDBLOCK")) + { + var idEnhancedBlock = dict.GetAt("ACAD_ENHANCEDBLOCK"); + var enhancedBlockTypedValues = Env.EntGet(idEnhancedBlock); + var parm = enhancedBlockTypedValues.FirstOrDefault(e => + e.TypeCode == 360 && e.Value is ObjectId id && id.IsOk() && + id.ObjectClass.DxfName == "BLOCKVISIBILITYPARAMETER") + .Value; + if (parm is ObjectId parmId) + { + info.Has = true; + var parmTypedValues = Env.EntGet(parmId); + info.PropertyName = parmTypedValues.FirstOrDefault(e => e.TypeCode == 301) + .Value?.ToString() ?? ""; + info.AllowedValues = parmTypedValues.Where(e => e.TypeCode == 303) + .Select(e => e.Value?.ToString() ?? "") + .Where(e => !string.IsNullOrWhiteSpace(e)) + .ToList(); + } + } + } + + return info; + } +} + +/// +/// 块可见性信息 +/// +public class BlockVisibilityInfo +{ + /// + /// 有无可见性 + /// + public bool Has { get; set; } + + /// + /// 属性名 + /// + public string PropertyName { get; set; } = ""; + + /// + /// 允许值 + /// + public List AllowedValues { get; set; } = []; } \ No newline at end of file diff --git a/src/CADShared/ExtensionMethod/TrustedPathEx.cs b/src/CADShared/ExtensionMethod/TrustedPathEx.cs index 00c1ccd..a5c37da 100644 --- a/src/CADShared/ExtensionMethod/TrustedPathEx.cs +++ b/src/CADShared/ExtensionMethod/TrustedPathEx.cs @@ -10,7 +10,7 @@ internal static class TrustedPathEx /// 路径列表 public static List Get() { - var str = Env.GetVar(kName).ToString(); + var str = Env.GetVar(kName).ToString()!; var set = str.ToLower() .Split([";"], StringSplitOptions.RemoveEmptyEntries) .Select(s => s.TrimEnd('\\')) diff --git a/src/CADShared/Runtime/Env.cs b/src/CADShared/Runtime/Env.cs index cbf3974..d50ae0a 100644 --- a/src/CADShared/Runtime/Env.cs +++ b/src/CADShared/Runtime/Env.cs @@ -1,10 +1,14 @@ +#if zcad +using Marshaler = ZwSoft.ZwCAD.Runtime.Marshaler; +#else using System.Security; +using Marshaler = Autodesk.AutoCAD.Runtime.Marshaler; +#endif #if a2024 || zcad using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif // ReSharper disable StringLiteralTypo - namespace IFoxCAD.Cad; /// @@ -88,15 +92,6 @@ public static IConfigurationSection GetGlobalSection(string propertyName) #region Enum - /// - /// 控制在AutoLISP的command函数运行时AutoCAD是否回显提示和输入, 为显示, 为不显示 - /// - public static bool CmdEcho - { - get => Convert.ToInt16(Acaop.GetSystemVariable("cmdecho")) == 1; - set => Acaop.SetSystemVariable("cmdecho", Convert.ToInt16(value)); - } - /// /// 获取Cad当前是否有活动命令 /// @@ -111,15 +106,6 @@ public static bool OrthoMode set => Acaop.SetSystemVariable("ORTHOMODE", Convert.ToInt16(value)); } - /// - /// 读写系统变量LastPoint的坐标(UCS) - /// - public static Point3d LastPoint - { - get => (Point3d)Acaop.GetSystemVariable("LASTPOINT"); - set => Acaop.SetSystemVariable("LASTPOINT", value); - } - #region Dimblk /// @@ -414,17 +400,6 @@ public static OSModeType OSMode set => Acaop.SetSystemVariable("osmode", (int)value); } - /// - /// 捕捉模式osm1是否包含osm2 - /// - /// 原模式 - /// 要比较的模式 - /// 包含时返回 ,不包含时返回 - public static bool Include(this OSModeType osm1, OSModeType osm2) - { - return (osm1 & osm2) == osm2; - } - #endregion OsMode private static string? GetName(this T value) @@ -483,7 +458,6 @@ public static void SetVar(string varName, object value, bool echo = true) EntryPoint = "acedSetEnv")] private static extern int AcedSetEnv(string? envName, StringBuilder newValue); #endif - #if gcad [System.Security.SuppressUnmanagedCodeSecurity] [DllImport("gced.dll", CharSet = CharSet.Auto, CallingConvention = @@ -800,4 +774,31 @@ public static Dictionary SaveCadVar(Dictionary a } #endregion + + #region EntGet功能 + + /// + /// EntGet + /// + public static TypedValue[] EntGet(ObjectId objectId) + { + var adsName = GetAdsName(objectId); + var intPtr = PInvokeCad.AcdbEntGet(ref adsName); + var typedValues = Marshaler.ResbufToTypedValues(intPtr); + return typedValues; + } + + /// + /// GetAdsName + /// + /// ObjectId + /// ads_name + public static ads_name GetAdsName(ObjectId objectId) + { + var adsName = new ads_name(); + _ = PInvokeCad.GetAdsName(ref adsName, objectId); + return adsName; + } + + #endregion } \ No newline at end of file diff --git a/src/CADShared/Runtime/PInvokeCad.cs b/src/CADShared/Runtime/PInvokeCad.cs new file mode 100644 index 0000000..9a4ae25 --- /dev/null +++ b/src/CADShared/Runtime/PInvokeCad.cs @@ -0,0 +1,92 @@ +// ReSharper disable InconsistentNaming + +namespace IFoxCAD.Cad; + +/// +/// cad相关的PInvoke +/// +public static class PInvokeCad +{ + /// + /// Entget + /// + [DllImport("accore.dll", CallingConvention = CallingConvention.Cdecl, + EntryPoint = "acdbEntGet")] + public static extern IntPtr AcdbEntGet(ref ads_name adsName); + + /// + /// EntMod + /// + [DllImport("accore.dll", CallingConvention = CallingConvention.Cdecl, + EntryPoint = "acdbEntMod")] + public static extern void AcdbEndMod(IntPtr intPtr); + + [DllImport("acdb25.dll", CallingConvention = CallingConvention.Cdecl, + EntryPoint = "?acdbGetAdsName@@YA?AW4ErrorStatus@Acad@@AEAY01_JVAcDbObjectId@@@Z")] + private static extern int AcdbGetAdsName25(ref ads_name adsName, ObjectId objectId); + + [DllImport("acdb24.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl, + EntryPoint = "?acdbGetAdsName@@YA?AW4ErrorStatus@Acad@@AEAY01_JVAcDbObjectId@@@Z")] + private static extern int AcdbGetAdsName24(ref ads_name adsName, ObjectId objectId); + + [DllImport("acdb23.dll", CallingConvention = CallingConvention.Cdecl, + EntryPoint = "?acdbGetAdsName@@YA?AW4ErrorStatus@Acad@@AEAY01_JVAcDbObjectId@@@Z")] + private static extern int AcdbGetAdsName23(ref ads_name adsName, ObjectId objectId); + + [DllImport("acdb22.dll", CallingConvention = CallingConvention.Cdecl, + EntryPoint = "?acdbGetAdsName@@YA?AW4ErrorStatus@Acad@@AEAY01_JVAcDbObjectId@@@Z")] + private static extern int AcdbGetAdsName22(ref ads_name adsName, ObjectId objectId); + + [DllImport("acdb21.dll", CallingConvention = CallingConvention.Cdecl, + EntryPoint = "?acdbGetAdsName@@YA?AW4ErrorStatus@Acad@@AEAY01_JVAcDbObjectId@@@Z")] + private static extern int AcdbGetAdsName21(ref ads_name adsName, ObjectId objectId); + + [DllImport("acdb20.dll", CallingConvention = CallingConvention.Cdecl, + EntryPoint = "?acdbGetAdsName@@YA?AW4ErrorStatus@Acad@@AEAY01_JVAcDbObjectId@@@Z")] + private static extern int AcdbGetAdsName20(ref ads_name adsName, ObjectId objectId); + + [DllImport("acdb19.dll", CallingConvention = CallingConvention.Cdecl, + EntryPoint = "?acdbGetAdsName@@YA?AW4ErrorStatus@Acad@@AEAY01_JVAcDbObjectId@@@Z")] + private static extern int AcdbGetAdsName19(ref ads_name adsName, ObjectId objectId); + + /// + /// GetAdsName + /// + public static int GetAdsName(ref ads_name adsName, ObjectId id) + { + var major = Acaop.Version.Major; + var res = major switch + { + 25 => AcdbGetAdsName25(ref adsName, id), + 24 => AcdbGetAdsName24(ref adsName, id), + 23 => AcdbGetAdsName23(ref adsName, id), + 22 => AcdbGetAdsName22(ref adsName, id), + 21 => AcdbGetAdsName21(ref adsName, id), + 20 => AcdbGetAdsName20(ref adsName, id), + 19 => AcdbGetAdsName19(ref adsName, id), + _ => 1, + }; + return res; + } +} + +/// +/// 用于使用Entget等函数的结构体 +/// +// ReSharper disable once InconsistentNaming +public struct ads_name +{ + /// + /// 构造函数 + /// + public ads_name() + { + a = b = IntPtr.Zero; + } + + // ReSharper disable once NotAccessedField.Local + private IntPtr a; + + // ReSharper disable once NotAccessedField.Local + private IntPtr b; +} \ No newline at end of file diff --git a/src/CADShared/Runtime/SystemVariableManager.cs b/src/CADShared/Runtime/SystemVariableManager.cs index c16dd8c..fd874b5 100644 --- a/src/CADShared/Runtime/SystemVariableManager.cs +++ b/src/CADShared/Runtime/SystemVariableManager.cs @@ -202,10 +202,10 @@ public static short CVPort /// /// 是否开启双击 /// - public static bool DblClick + public static bool DblClkEdit { - get => Convert.ToBoolean(Acaop.GetSystemVariable(nameof(DblClick))); - set => Acaop.SetSystemVariable(nameof(DblClick), Convert.ToInt32(value)); + get => Convert.ToBoolean(Acaop.GetSystemVariable(nameof(DblClkEdit))); + set => Acaop.SetSystemVariable(nameof(DblClkEdit), Convert.ToInt32(value)); } /// diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 9a365f1..7dbaee6 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,8 +1,8 @@ - 0.9.4 - 整理支持文件搜索路径和信任路径的扩展方法并添加Get方法 + 0.9.5 + 添加EntGet,组织部分系统变量,添加可见性信息获取功能 diff --git a/tests/TestShared/TestBlkVisibility.cs b/tests/TestShared/TestBlkVisibility.cs new file mode 100644 index 0000000..8417fa3 --- /dev/null +++ b/tests/TestShared/TestBlkVisibility.cs @@ -0,0 +1,20 @@ +using System.Windows; + +namespace TestAcad2025; + +public static class TestBlkVisibility +{ + [CommandMethod(nameof(TestBlkVisibility))] + public static void Main() + { + var r1 = Env.Editor.GetEntity("\n选择块参照"); + if (r1.Status != PromptStatus.OK) + return; + using var tr = new DBTrans(); + if (tr.GetObject(r1.ObjectId) is not BlockReference { IsDynamicBlock: true } brf) + return; + var info = brf.GetVisibilityInfo(); + MessageBox.Show( + $"块{brf.Name}的可见性名字:{info.PropertyName},参数:{string.Join(", ", info.AllowedValues)}。是否可见?{info.Has}"); + } +} \ No newline at end of file diff --git a/tests/TestShared/TestEnv.cs b/tests/TestShared/TestEnv.cs index d1df3b8..b785ded 100644 --- a/tests/TestShared/TestEnv.cs +++ b/tests/TestShared/TestEnv.cs @@ -5,12 +5,12 @@ public class Testenv [CommandMethod(nameof(Test_Enum))] public void Test_Enum() { - Env.CmdEcho = true; + SystemVariableManager.CmdEcho = true; } [CommandMethod(nameof(Test_Enum1))] public void Test_Enum1() { - Env.CmdEcho = false; + SystemVariableManager.CmdEcho = false; } [CommandMethod(nameof(Test_Dimblk))] @@ -46,7 +46,7 @@ public void Test_Osmode() // 追加模式 Env.OSMode |= Env.OSModeType.Center; // 检查是否有某个模式 - var os = Env.OSMode.Include(Env.OSModeType.Center); + var os = Env.OSMode.HasFlag(Env.OSModeType.Center); // 取消某个模式 Env.OSMode ^= Env.OSModeType.Center; Env.Editor.WriteMessage(Env.OSMode.ToString()); diff --git a/tests/TestShared/TestShared.projitems b/tests/TestShared/TestShared.projitems index 3c6557b..ec7e67e 100644 --- a/tests/TestShared/TestShared.projitems +++ b/tests/TestShared/TestShared.projitems @@ -12,6 +12,7 @@ + -- Gitee From 6d612fd31116e357a7eecb2ab59b5f6a8fa89f4a Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Tue, 20 May 2025 18:04:24 +0800 Subject: [PATCH 424/453] =?UTF-8?q?=E6=96=B0=E5=A2=9EEntMod=E6=96=B9?= =?UTF-8?q?=E6=B3=95=E5=B9=B6=E4=BF=AE=E6=AD=A3PInvokeCad=E4=B8=AD?= =?UTF-8?q?=E7=9A=84AcdbEntMod=E8=BF=94=E5=9B=9E=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CADShared/Runtime/Env.cs | 11 +++++++++++ src/CADShared/Runtime/PInvokeCad.cs | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/CADShared/Runtime/Env.cs b/src/CADShared/Runtime/Env.cs index d50ae0a..59666de 100644 --- a/src/CADShared/Runtime/Env.cs +++ b/src/CADShared/Runtime/Env.cs @@ -788,6 +788,17 @@ public static TypedValue[] EntGet(ObjectId objectId) return typedValues; } + /// + /// EntMod + /// + public static bool EntMod(IEnumerable typedValues) + { + var tva = typedValues.ToArray(); + var intPtr = Marshaler.TypedValuesToResbuf(tva); + var result = PInvokeCad.AcdbEntMod(intPtr); + return result == 5100; + } + /// /// GetAdsName /// diff --git a/src/CADShared/Runtime/PInvokeCad.cs b/src/CADShared/Runtime/PInvokeCad.cs index 9a4ae25..c18c086 100644 --- a/src/CADShared/Runtime/PInvokeCad.cs +++ b/src/CADShared/Runtime/PInvokeCad.cs @@ -19,7 +19,7 @@ public static class PInvokeCad /// [DllImport("accore.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "acdbEntMod")] - public static extern void AcdbEndMod(IntPtr intPtr); + public static extern int AcdbEntMod(IntPtr intPtr); [DllImport("acdb25.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "?acdbGetAdsName@@YA?AW4ErrorStatus@Acad@@AEAY01_JVAcDbObjectId@@@Z")] -- Gitee From 3040c16672c54a289502b093e8942bb476e27398 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sat, 24 May 2025 14:50:34 +0800 Subject: [PATCH 425/453] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0EntMod,EntUpd?= =?UTF-8?q?=EF=BC=8C=E5=8F=91=E5=B8=830.9.6=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CADShared/Runtime/Env.cs | 10 ++++++++++ src/CADShared/Runtime/PInvokeCad.cs | 7 +++++++ src/Directory.Build.props | 4 ++-- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/CADShared/Runtime/Env.cs b/src/CADShared/Runtime/Env.cs index 59666de..f91ec4e 100644 --- a/src/CADShared/Runtime/Env.cs +++ b/src/CADShared/Runtime/Env.cs @@ -788,6 +788,16 @@ public static TypedValue[] EntGet(ObjectId objectId) return typedValues; } + /// + /// EntUpd + /// + public static bool EntUpd(ObjectId objectId) + { + var adsName = GetAdsName(objectId); + var res = PInvokeCad.AcdbEntUpd(ref adsName); + return res == 5100; + } + /// /// EntMod /// diff --git a/src/CADShared/Runtime/PInvokeCad.cs b/src/CADShared/Runtime/PInvokeCad.cs index c18c086..6064301 100644 --- a/src/CADShared/Runtime/PInvokeCad.cs +++ b/src/CADShared/Runtime/PInvokeCad.cs @@ -14,6 +14,13 @@ public static class PInvokeCad EntryPoint = "acdbEntGet")] public static extern IntPtr AcdbEntGet(ref ads_name adsName); + /// + /// EntUpd + /// + [DllImport("accore.dll", CallingConvention = CallingConvention.Cdecl, + EntryPoint = "acdbEntUpd")] + public static extern int AcdbEntUpd(ref ads_name adsName); + /// /// EntMod /// diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 7dbaee6..52edde3 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,8 +1,8 @@ - 0.9.5 - 添加EntGet,组织部分系统变量,添加可见性信息获取功能 + 0.9.6 + 添加EntMod,EntUpd -- Gitee From 26a05570b99d7711bc742dc2fbb03de3db3f80c2 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 29 May 2025 11:17:12 +0800 Subject: [PATCH 426/453] =?UTF-8?q?zwcad=E6=B7=BB=E5=8A=A0=E4=BA=86EntGet?= =?UTF-8?q?=E7=AD=89=E5=87=BD=E6=95=B0=E5=B9=B6=E5=8F=91=E5=B8=830.9.6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IFoxCAD.sln.DotSettings | 5 ++++- src/CADShared/Runtime/Env.cs | 32 +++++++++++++++++++++++++---- src/CADShared/Runtime/PInvokeCad.cs | 27 +++++++++++++++++++++++- 3 files changed, 58 insertions(+), 6 deletions(-) diff --git a/IFoxCAD.sln.DotSettings b/IFoxCAD.sln.DotSettings index cda8b1a..6b05d84 100644 --- a/IFoxCAD.sln.DotSettings +++ b/IFoxCAD.sln.DotSettings @@ -6,6 +6,7 @@ WMF True True + True True True True @@ -26,4 +27,6 @@ True True True - True \ No newline at end of file + True + True + True \ No newline at end of file diff --git a/src/CADShared/Runtime/Env.cs b/src/CADShared/Runtime/Env.cs index f91ec4e..a0f9430 100644 --- a/src/CADShared/Runtime/Env.cs +++ b/src/CADShared/Runtime/Env.cs @@ -475,14 +475,14 @@ public static void SetVar(string varName, object value, bool echo = true) // TODO: 中望没有测试,此处仅为不报错;本工程所有含有"中望"均存在问题 #if zcad [System.Security.SuppressUnmanagedCodeSecurity] - [DllImport("zced.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, + [DllImport("zwcad.exe", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, EntryPoint = "zcedGetEnv")] - static extern int AcedGetEnv(string? envName, StringBuilder ReturnValue); + private static extern int AcedGetEnv(string? envName, StringBuilder returnValue); [System.Security.SuppressUnmanagedCodeSecurity] - [DllImport("zced.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, + [DllImport("zwcad.exe", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, EntryPoint = "zcedSetEnv")] - static extern int AcedSetEnv(string? envName, StringBuilder NewValue); + private static extern int AcedSetEnv(string? envName, StringBuilder newValue); #endif /// @@ -782,12 +782,19 @@ public static Dictionary SaveCadVar(Dictionary a /// public static TypedValue[] EntGet(ObjectId objectId) { +#if zcad + var adsName = GetAdsName(objectId); + var intPtr = PInvokeCad.ZcdbEntGet(adsName); +#else var adsName = GetAdsName(objectId); var intPtr = PInvokeCad.AcdbEntGet(ref adsName); + +#endif var typedValues = Marshaler.ResbufToTypedValues(intPtr); return typedValues; } + #if acad /// /// EntUpd /// @@ -797,6 +804,7 @@ public static bool EntUpd(ObjectId objectId) var res = PInvokeCad.AcdbEntUpd(ref adsName); return res == 5100; } + #endif /// /// EntMod @@ -805,10 +813,25 @@ public static bool EntMod(IEnumerable typedValues) { var tva = typedValues.ToArray(); var intPtr = Marshaler.TypedValuesToResbuf(tva); +#if zcad + var result = PInvokeCad.ZcdbEntMod(intPtr); + #else var result = PInvokeCad.AcdbEntMod(intPtr); +#endif return result == 5100; } +#if zcad + /// + /// GetAdsName + /// + /// ObjectId + public static AdsName GetAdsName(ObjectId objectId) + { + _ = PInvokeCad.GetAdsName(out var adsName,objectId); + return adsName; + } + #else /// /// GetAdsName /// @@ -820,6 +843,7 @@ public static ads_name GetAdsName(ObjectId objectId) _ = PInvokeCad.GetAdsName(ref adsName, objectId); return adsName; } +#endif #endregion } \ No newline at end of file diff --git a/src/CADShared/Runtime/PInvokeCad.cs b/src/CADShared/Runtime/PInvokeCad.cs index 6064301..47e4ff1 100644 --- a/src/CADShared/Runtime/PInvokeCad.cs +++ b/src/CADShared/Runtime/PInvokeCad.cs @@ -7,6 +7,31 @@ namespace IFoxCAD.Cad; /// public static class PInvokeCad { +#if zcad + /// + /// EntGet + /// + [DllImport("zwcad.exe", CallingConvention = CallingConvention.Cdecl, EntryPoint = "zcdbEntGet")] + public static extern IntPtr ZcdbEntGet(AdsName adsName); + /// + /// EntGet + /// + [DllImport("zwcad.exe", CallingConvention = CallingConvention.Cdecl, EntryPoint = "zcdbEntMod")] + public static extern int ZcdbEntMod(IntPtr intPtr); + /// + /// GetZdsName + /// + [DllImport("ZwDatabase.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "?zcdbGetZdsName@@YA?AW4ErrorStatus@Zcad@@AEAY01_JVZcDbObjectId@@@Z")] + public static extern int ZcdbGetZdsName(out AdsName adsName, ObjectId id); + + /// + /// GetAdsName + /// + public static int GetAdsName(out AdsName adsName, ObjectId id) + { + return ZcdbGetZdsName(out adsName, id); + } +#else /// /// Entget /// @@ -55,7 +80,6 @@ public static class PInvokeCad [DllImport("acdb19.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "?acdbGetAdsName@@YA?AW4ErrorStatus@Acad@@AEAY01_JVAcDbObjectId@@@Z")] private static extern int AcdbGetAdsName19(ref ads_name adsName, ObjectId objectId); - /// /// GetAdsName /// @@ -75,6 +99,7 @@ public static int GetAdsName(ref ads_name adsName, ObjectId id) }; return res; } +#endif } /// -- Gitee From dd4b36c0ba6a60db0af147d006ca057c08e231ca Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 12 Jun 2025 10:33:53 +0800 Subject: [PATCH 427/453] =?UTF-8?q?fix:=20=E4=B8=AD=E6=9C=9B=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0net472=E4=BB=A5=E6=94=AF=E6=8C=81=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E4=B8=8D=E5=90=8C=E7=89=88=E6=9C=AC=E7=9A=84.NET=20Framework?= =?UTF-8?q?=E8=BF=9B=E8=A1=8C=E5=A4=9A=E7=89=88=E6=9C=AC=E5=BC=80=E5=8F=91?= =?UTF-8?q?=E7=9A=84=E6=96=B9=E6=A1=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Directory.Build.props | 4 ++-- src/IFoxCAD.ZwCad/IFoxCAD.ZwCad.csproj | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 52edde3..5476d3c 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,8 +1,8 @@ - 0.9.6 - 添加EntMod,EntUpd + 0.9.7 + ZCAD支持net472 diff --git a/src/IFoxCAD.ZwCad/IFoxCAD.ZwCad.csproj b/src/IFoxCAD.ZwCad/IFoxCAD.ZwCad.csproj index 4b659be..a55b007 100644 --- a/src/IFoxCAD.ZwCad/IFoxCAD.ZwCad.csproj +++ b/src/IFoxCAD.ZwCad/IFoxCAD.ZwCad.csproj @@ -1,6 +1,6 @@  - net48 + net48;net472 @@ -20,7 +20,7 @@ bin\Release\IFoxCAD.ZwCad.xml - + $(Configuration);zcad;z2025 @@ -35,13 +35,14 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive + -- Gitee From 13157c9096141589f9a34a356e947b5f4b954af6 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 12 Jun 2025 11:26:23 +0800 Subject: [PATCH 428/453] =?UTF-8?q?fix:=20=E4=B8=AD=E6=9C=9B=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0net472=E4=BB=A5=E6=94=AF=E6=8C=81=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E4=B8=8D=E5=90=8C=E7=89=88=E6=9C=AC=E7=9A=84.NET=20Framework?= =?UTF-8?q?=E8=BF=9B=E8=A1=8C=E5=A4=9A=E7=89=88=E6=9C=AC=E5=BC=80=E5=8F=91?= =?UTF-8?q?=E7=9A=84=E6=96=B9=E6=A1=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Directory.Build.props | 2 +- src/IFoxCAD.ZwCad/IFoxCAD.ZwCad.csproj | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 5476d3c..f49d549 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,7 +1,7 @@ - 0.9.7 + 0.9.8 ZCAD支持net472 diff --git a/src/IFoxCAD.ZwCad/IFoxCAD.ZwCad.csproj b/src/IFoxCAD.ZwCad/IFoxCAD.ZwCad.csproj index a55b007..118159e 100644 --- a/src/IFoxCAD.ZwCad/IFoxCAD.ZwCad.csproj +++ b/src/IFoxCAD.ZwCad/IFoxCAD.ZwCad.csproj @@ -36,13 +36,13 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + -- Gitee From 05045464eb457d23b72efcddd48eee8f11f22bbe Mon Sep 17 00:00:00 2001 From: vicwjb Date: Mon, 3 Feb 2025 23:09:57 +0800 Subject: [PATCH 429/453] =?UTF-8?q?=E6=9B=BF=E6=8D=A2IndexRange=E5=92=8CNu?= =?UTF-8?q?llable=E4=B8=BAPolySharp;=E6=9B=BF=E6=8D=A2ZWCad.Net.2025?= =?UTF-8?q?=E4=B8=BAZWCAD.NetApi;=E6=B8=85=E9=99=A4=E5=A4=9A=E4=BD=99?= =?UTF-8?q?=E7=9A=84nuget=E5=8C=85=E5=BC=95=E7=94=A8=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj | 3 +-- src/IFoxCAD.ZwCad/IFoxCAD.ZwCad.csproj | 3 +++ tests/TestAcad2025/TestAcad2025.csproj | 7 ++----- tests/TestZcad2025/TestZcad2025.csproj | 2 +- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj b/src/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj index d6c0b91..eb42055 100644 --- a/src/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj +++ b/src/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj @@ -45,8 +45,7 @@ - - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/IFoxCAD.ZwCad/IFoxCAD.ZwCad.csproj b/src/IFoxCAD.ZwCad/IFoxCAD.ZwCad.csproj index 118159e..44e4e95 100644 --- a/src/IFoxCAD.ZwCad/IFoxCAD.ZwCad.csproj +++ b/src/IFoxCAD.ZwCad/IFoxCAD.ZwCad.csproj @@ -39,6 +39,9 @@ + + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/tests/TestAcad2025/TestAcad2025.csproj b/tests/TestAcad2025/TestAcad2025.csproj index 1109e94..8ff61fe 100644 --- a/tests/TestAcad2025/TestAcad2025.csproj +++ b/tests/TestAcad2025/TestAcad2025.csproj @@ -34,12 +34,9 @@ - + - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/tests/TestZcad2025/TestZcad2025.csproj b/tests/TestZcad2025/TestZcad2025.csproj index 280480b..a0587c5 100644 --- a/tests/TestZcad2025/TestZcad2025.csproj +++ b/tests/TestZcad2025/TestZcad2025.csproj @@ -15,7 +15,7 @@ - + -- Gitee From 467fd072c8922fc40eb7d84625cd6be23afbda52 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Wed, 25 Jun 2025 20:43:39 +0800 Subject: [PATCH 430/453] =?UTF-8?q?=E6=9B=BF=E6=8D=A2=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/IFoxCAD.ZwCad/IFoxCAD.ZwCad.csproj | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/IFoxCAD.ZwCad/IFoxCAD.ZwCad.csproj b/src/IFoxCAD.ZwCad/IFoxCAD.ZwCad.csproj index 44e4e95..734e455 100644 --- a/src/IFoxCAD.ZwCad/IFoxCAD.ZwCad.csproj +++ b/src/IFoxCAD.ZwCad/IFoxCAD.ZwCad.csproj @@ -34,12 +34,7 @@ \ - - - - - all -- Gitee From 6d0ffb62cfb2bbda9de030472aa6fcc03aaa2cdd Mon Sep 17 00:00:00 2001 From: vicwjb Date: Sat, 28 Jun 2025 13:01:49 +0800 Subject: [PATCH 431/453] =?UTF-8?q?=E4=BC=98=E5=8C=96namespace=E5=BC=95?= =?UTF-8?q?=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CADShared/Runtime/Env.cs | 7 +------ src/IFoxCAD.AutoCad/GlobalUsings.cs | 2 ++ src/IFoxCAD.ZwCad/GlobalUsings.cs | 1 + 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/CADShared/Runtime/Env.cs b/src/CADShared/Runtime/Env.cs index a0f9430..d299067 100644 --- a/src/CADShared/Runtime/Env.cs +++ b/src/CADShared/Runtime/Env.cs @@ -1,9 +1,4 @@ -#if zcad -using Marshaler = ZwSoft.ZwCAD.Runtime.Marshaler; -#else -using System.Security; -using Marshaler = Autodesk.AutoCAD.Runtime.Marshaler; -#endif + #if a2024 || zcad using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif diff --git a/src/IFoxCAD.AutoCad/GlobalUsings.cs b/src/IFoxCAD.AutoCad/GlobalUsings.cs index 67dcfff..adf89e1 100644 --- a/src/IFoxCAD.AutoCad/GlobalUsings.cs +++ b/src/IFoxCAD.AutoCad/GlobalUsings.cs @@ -21,6 +21,7 @@ global using Utils = Autodesk.AutoCAD.Internal.Utils; global using SystemVariableChangedEventArgs = Autodesk.AutoCAD.ApplicationServices.SystemVariableChangedEventArgs; global using AcException = Autodesk.AutoCAD.Runtime.Exception; +global using Marshaler = Autodesk.AutoCAD.Runtime.Marshaler; global using System; global using System.Reflection; global using System.Collections; @@ -31,6 +32,7 @@ global using System.Text; global using System.Runtime.InteropServices; global using System.ComponentModel; +global using System.Security; global using Exception = System.Exception; global using DrawingColor = System.Drawing.Color; global using Registry = Microsoft.Win32.Registry; diff --git a/src/IFoxCAD.ZwCad/GlobalUsings.cs b/src/IFoxCAD.ZwCad/GlobalUsings.cs index a3365f5..7b2f55e 100644 --- a/src/IFoxCAD.ZwCad/GlobalUsings.cs +++ b/src/IFoxCAD.ZwCad/GlobalUsings.cs @@ -21,6 +21,7 @@ global using Utils = ZwSoft.ZwCAD.Internal.Utils; global using SystemVariableChangedEventArgs = ZwSoft.ZwCAD.ApplicationServices.SystemVariableChangedEventArgs; global using AcException = ZwSoft.ZwCAD.Runtime.Exception; +global using Marshaler = ZwSoft.ZwCAD.Runtime.Marshaler; global using System; global using System.Reflection; global using System.Collections; -- Gitee From 38a4f325dc773ab316afba0e1d3afac55f37af8a Mon Sep 17 00:00:00 2001 From: vicwjb Date: Mon, 3 Feb 2025 23:32:57 +0800 Subject: [PATCH 432/453] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E6=9D=A1=E4=BB=B6?= =?UTF-8?q?=E7=BC=96=E8=AF=91=E7=AC=A6=E5=8F=B7=EF=BC=8C=E8=A7=A3=E5=86=B3?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E7=9A=84=E7=BC=96=E8=AF=91=E7=AC=A6=E5=8F=B7?= =?UTF-8?q?=E4=B8=8Eifox=E7=9A=84=E6=BA=90=E7=A0=81=E4=B8=8D=E7=AC=A6?= =?UTF-8?q?=E6=97=B6=E7=BC=96=E8=AF=91=E6=8A=A5=E9=94=99=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CADShared/Algorithms/QuadTree/Rect.cs | 4 +--- src/CADShared/Basal/Nullable/ArgumentNullEx.cs | 2 +- .../Basal/Nullable/CallerArgumentExpressionAttribute.cs | 2 +- src/CADShared/Basal/Win/WindowsAPI.cs | 2 +- src/CADShared/ExtensionMethod/Entity/BlockReferenceEx.cs | 2 +- src/CADShared/ExtensionMethod/Entity/CurveEx.cs | 2 +- src/CADShared/ExtensionMethod/Geomerty/PointEx.cs | 2 +- src/CADShared/ExtensionMethod/Hatch/HatchConverter.cs | 2 +- src/CADShared/ExtensionMethod/Hatch/HatchInfo.cs | 2 +- src/CADShared/ExtensionMethod/Jig/JigEx.cs | 2 +- src/CADShared/ExtensionMethod/SelectionSetEx.cs | 3 +-- src/CADShared/ExtensionMethod/SymbolTableRecordEx.cs | 2 +- src/CADShared/ExtensionMethod/XrefEx.cs | 2 +- src/CADShared/Initialize/AutoRegAssem.cs | 2 +- src/CADShared/Initialize/MethodInfoHelper.cs | 2 +- src/CADShared/Runtime/DBTrans.cs | 2 +- src/CADShared/Runtime/Env.cs | 3 +-- src/CADShared/Runtime/SymbolTable.cs | 2 +- 18 files changed, 18 insertions(+), 22 deletions(-) diff --git a/src/CADShared/Algorithms/QuadTree/Rect.cs b/src/CADShared/Algorithms/QuadTree/Rect.cs index 1366442..d771c19 100644 --- a/src/CADShared/Algorithms/QuadTree/Rect.cs +++ b/src/CADShared/Algorithms/QuadTree/Rect.cs @@ -1,6 +1,4 @@ -using System.Diagnostics; -using System.Runtime.CompilerServices; -#if a2024 || zcad +#if !NET8_0_OR_GREATER using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif namespace IFoxCAD.Cad; diff --git a/src/CADShared/Basal/Nullable/ArgumentNullEx.cs b/src/CADShared/Basal/Nullable/ArgumentNullEx.cs index 7fb7763..517cd14 100644 --- a/src/CADShared/Basal/Nullable/ArgumentNullEx.cs +++ b/src/CADShared/Basal/Nullable/ArgumentNullEx.cs @@ -1,5 +1,5 @@  -#if a2024 || zcad +#if !NET8_0_OR_GREATER namespace IFoxCAD.Basal; /// diff --git a/src/CADShared/Basal/Nullable/CallerArgumentExpressionAttribute.cs b/src/CADShared/Basal/Nullable/CallerArgumentExpressionAttribute.cs index e6f5660..505d5ee 100644 --- a/src/CADShared/Basal/Nullable/CallerArgumentExpressionAttribute.cs +++ b/src/CADShared/Basal/Nullable/CallerArgumentExpressionAttribute.cs @@ -1,5 +1,5 @@  -#if a2024 || zcad +#if !NET8_0_OR_GREATER namespace System.Runtime.CompilerServices; /// /// 指示参数将为另一个参数传递的表达式捕获为字符串。 diff --git a/src/CADShared/Basal/Win/WindowsAPI.cs b/src/CADShared/Basal/Win/WindowsAPI.cs index 5125d47..5b12ae2 100644 --- a/src/CADShared/Basal/Win/WindowsAPI.cs +++ b/src/CADShared/Basal/Win/WindowsAPI.cs @@ -1,6 +1,6 @@ #pragma warning disable CS1591 // 缺少对公共可见类型或成员的 XML 注释 #define Marshal -#if a2024 || zcad +#if !NET8_0_OR_GREATER using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif namespace IFoxCAD.Basal; diff --git a/src/CADShared/ExtensionMethod/Entity/BlockReferenceEx.cs b/src/CADShared/ExtensionMethod/Entity/BlockReferenceEx.cs index fcd4041..cdeda32 100644 --- a/src/CADShared/ExtensionMethod/Entity/BlockReferenceEx.cs +++ b/src/CADShared/ExtensionMethod/Entity/BlockReferenceEx.cs @@ -1,4 +1,4 @@ -#if a2024 || zcad +#if !NET8_0_OR_GREATER using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif diff --git a/src/CADShared/ExtensionMethod/Entity/CurveEx.cs b/src/CADShared/ExtensionMethod/Entity/CurveEx.cs index 14a5113..0df06cd 100644 --- a/src/CADShared/ExtensionMethod/Entity/CurveEx.cs +++ b/src/CADShared/ExtensionMethod/Entity/CurveEx.cs @@ -1,6 +1,6 @@ // ReSharper disable ForCanBeConvertedToForeach -#if a2024 || zcad +#if !NET8_0_OR_GREATER using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif diff --git a/src/CADShared/ExtensionMethod/Geomerty/PointEx.cs b/src/CADShared/ExtensionMethod/Geomerty/PointEx.cs index f920a3c..2a89e17 100644 --- a/src/CADShared/ExtensionMethod/Geomerty/PointEx.cs +++ b/src/CADShared/ExtensionMethod/Geomerty/PointEx.cs @@ -1,4 +1,4 @@ -#if a2024 || zcad +#if !NET8_0_OR_GREATER using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif diff --git a/src/CADShared/ExtensionMethod/Hatch/HatchConverter.cs b/src/CADShared/ExtensionMethod/Hatch/HatchConverter.cs index fe79a62..eb17ddd 100644 --- a/src/CADShared/ExtensionMethod/Hatch/HatchConverter.cs +++ b/src/CADShared/ExtensionMethod/Hatch/HatchConverter.cs @@ -1,7 +1,7 @@ // ReSharper disable CompareOfFloatsByEqualityOperator // ReSharper disable ForCanBeConvertedToForeach -#if a2024 || zcad +#if !NET8_0_OR_GREATER using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif diff --git a/src/CADShared/ExtensionMethod/Hatch/HatchInfo.cs b/src/CADShared/ExtensionMethod/Hatch/HatchInfo.cs index f836615..b1d7576 100644 --- a/src/CADShared/ExtensionMethod/Hatch/HatchInfo.cs +++ b/src/CADShared/ExtensionMethod/Hatch/HatchInfo.cs @@ -1,6 +1,6 @@  -#if a2024 || zcad +#if !NET8_0_OR_GREATER using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif diff --git a/src/CADShared/ExtensionMethod/Jig/JigEx.cs b/src/CADShared/ExtensionMethod/Jig/JigEx.cs index 84fe249..eac7b62 100644 --- a/src/CADShared/ExtensionMethod/Jig/JigEx.cs +++ b/src/CADShared/ExtensionMethod/Jig/JigEx.cs @@ -1,4 +1,4 @@ -#if a2024 || zcad +#if !NET8_0_OR_GREATER using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; // ReSharper disable ClassWithVirtualMembersNeverInherited.Global diff --git a/src/CADShared/ExtensionMethod/SelectionSetEx.cs b/src/CADShared/ExtensionMethod/SelectionSetEx.cs index 58d513a..26d39bc 100644 --- a/src/CADShared/ExtensionMethod/SelectionSetEx.cs +++ b/src/CADShared/ExtensionMethod/SelectionSetEx.cs @@ -1,5 +1,4 @@ -using IFoxCAD.CAD; -#if a2024 || zcad +#if !NET8_0_OR_GREATER using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif diff --git a/src/CADShared/ExtensionMethod/SymbolTableRecordEx.cs b/src/CADShared/ExtensionMethod/SymbolTableRecordEx.cs index 4aa3a5a..1c2c1ab 100644 --- a/src/CADShared/ExtensionMethod/SymbolTableRecordEx.cs +++ b/src/CADShared/ExtensionMethod/SymbolTableRecordEx.cs @@ -1,5 +1,5 @@  -#if a2024 || zcad +#if !NET8_0_OR_GREATER using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif diff --git a/src/CADShared/ExtensionMethod/XrefEx.cs b/src/CADShared/ExtensionMethod/XrefEx.cs index b23d94c..5910cd3 100644 --- a/src/CADShared/ExtensionMethod/XrefEx.cs +++ b/src/CADShared/ExtensionMethod/XrefEx.cs @@ -1,6 +1,6 @@ // ReSharper disable ForCanBeConvertedToForeach -#if a2024 || zcad +#if !NET8_0_OR_GREATER using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif diff --git a/src/CADShared/Initialize/AutoRegAssem.cs b/src/CADShared/Initialize/AutoRegAssem.cs index eeecf3c..8bd70dc 100644 --- a/src/CADShared/Initialize/AutoRegAssem.cs +++ b/src/CADShared/Initialize/AutoRegAssem.cs @@ -1,4 +1,4 @@ -#if a2024 || zcad +#if !NET8_0_OR_GREATER using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif diff --git a/src/CADShared/Initialize/MethodInfoHelper.cs b/src/CADShared/Initialize/MethodInfoHelper.cs index 79bede7..b671885 100644 --- a/src/CADShared/Initialize/MethodInfoHelper.cs +++ b/src/CADShared/Initialize/MethodInfoHelper.cs @@ -1,4 +1,4 @@ -#if a2024 || zcad +#if !NET8_0_OR_GREATER using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif diff --git a/src/CADShared/Runtime/DBTrans.cs b/src/CADShared/Runtime/DBTrans.cs index a1a4cb4..dd8766b 100644 --- a/src/CADShared/Runtime/DBTrans.cs +++ b/src/CADShared/Runtime/DBTrans.cs @@ -1,5 +1,5 @@ namespace IFoxCAD.Cad; -#if a2024 || zcad +#if !NET8_0_OR_GREATER using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif using System.Diagnostics; diff --git a/src/CADShared/Runtime/Env.cs b/src/CADShared/Runtime/Env.cs index d299067..fd18bc8 100644 --- a/src/CADShared/Runtime/Env.cs +++ b/src/CADShared/Runtime/Env.cs @@ -1,5 +1,4 @@ - -#if a2024 || zcad +#if !NET8_0_OR_GREATER using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif diff --git a/src/CADShared/Runtime/SymbolTable.cs b/src/CADShared/Runtime/SymbolTable.cs index ad73274..c6c9422 100644 --- a/src/CADShared/Runtime/SymbolTable.cs +++ b/src/CADShared/Runtime/SymbolTable.cs @@ -1,6 +1,6 @@ // ReSharper disable RedundantNameQualifier -#if a2024 || zcad +#if !NET8_0_OR_GREATER using ArgumentNullException = IFoxCAD.Basal.ArgumentNullEx; #endif -- Gitee From 8ea7149f4cf19d36523e2e14d31b6efbf601c076 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Sat, 28 Jun 2025 13:51:55 +0800 Subject: [PATCH 433/453] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=90=8D=E7=A7=B0?= =?UTF-8?q?=E7=A9=BA=E9=97=B4=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CADShared/ExtensionMethod/RXClassEx.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CADShared/ExtensionMethod/RXClassEx.cs b/src/CADShared/ExtensionMethod/RXClassEx.cs index a6e299a..d077e53 100644 --- a/src/CADShared/ExtensionMethod/RXClassEx.cs +++ b/src/CADShared/ExtensionMethod/RXClassEx.cs @@ -1,4 +1,4 @@ -namespace IFoxCAD.CAD; +namespace IFoxCAD.Cad; /// /// RXClass扩展 -- Gitee From 1db46a7bc0f9fa9376535df1d393ddae53190d73 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Tue, 4 Feb 2025 00:09:45 +0800 Subject: [PATCH 434/453] =?UTF-8?q?=E5=A2=9E=E5=8A=A0Melkman=E7=AE=97?= =?UTF-8?q?=E6=B3=95=E6=B1=82=E7=AE=80=E5=8D=95=E5=A4=9A=E8=BE=B9=E5=BD=A2?= =?UTF-8?q?=E5=87=B8=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/Geomerty/GeometryEx.cs | 73 +++++++++++++++++++ tests/TestShared/TestConvexHull.cs | 16 ++++ 2 files changed, 89 insertions(+) diff --git a/src/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs b/src/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs index d21d818..3fed76d 100644 --- a/src/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs +++ b/src/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs @@ -495,7 +495,80 @@ private static double Cross(Point2d o, Point2d a, Point2d b) return hullPts.Count >= 3 ? hullPts : null; } + + /// + /// 判断三个点是否左转 + /// + /// 第一点 + /// 第二点 + /// 第三点 + /// 左转返回 true,否则返回 false + public static double IsClockWise(Point3d p1, Point3d p2, Point3d p3) + { + return (p2.X - p1.X) * (p3.Y - p2.Y) - (p2.Y - p1.Y) * (p3.X - p2.X); + + } + /// + /// Melkman算法求简单多边形凸包 + /// + /// 多边形端点列表 + /// 凸包端点列表 + public static List ConvexHull_Melkman(this List points) + { + if (points.Count <= 3) + { + return points; + } + + var deque = new LinkedList(); + if (IsClockWise(points[0], points[1], points[2]) > 0) + { + deque.AddFirst(points[2]); + deque.AddLast(points[0]); + deque.AddLast(points[1]); + deque.AddLast(points[2]); + } + else if (IsClockWise(points[0], points[1], points[2]) < 0) + { + deque.AddFirst(points[2]); + deque.AddLast(points[1]); + deque.AddLast(points[0]); + deque.AddLast(points[2]); + } + else + { + deque.AddFirst(points[2]); + deque.AddLast(points[0]); + deque.AddLast(points[2]); + } + + foreach (var p in points.Skip(3)) + { + if (IsClockWise(deque.Last!.Previous!.Value, deque.Last.Value, p) > 0 + && IsClockWise(p, deque.First!.Value, deque.First.Next!.Value) > 0) + { + continue; + } + while (deque.Count > 1 && IsClockWise(deque.Last!.Previous!.Value, deque.Last.Value, p) <= 0) + { + deque.RemoveLast(); + } + deque.AddLast(p); + while (deque.Count > 1 && IsClockWise(p, deque.First!.Value, deque.First.Next!.Value) <= 0) + { + deque.RemoveFirst(); + } + deque.AddFirst(p); + + } + + if (deque.First!.Value == deque.Last!.Value) + { + deque.RemoveFirst(); + } + return [.. deque]; + } #endregion PointList #endregion Point&Circle diff --git a/tests/TestShared/TestConvexHull.cs b/tests/TestShared/TestConvexHull.cs index 03692ae..c7bbafb 100644 --- a/tests/TestShared/TestConvexHull.cs +++ b/tests/TestShared/TestConvexHull.cs @@ -73,4 +73,20 @@ public void Test_ConvexHull() Env.Editor.WriteMessage($"点集的有向面积:{area5} \n"); Env.Editor.WriteMessage($"点集的有向面积:{area6} \n"); } + + [CommandMethod(nameof(Test_ConvexHull_Melkman))] + public static void Test_ConvexHull_Melkman() + { + using var tr = new DBTrans(); + var ent = Env.Editor.GetEntity("选取多段线"); + if (ent.Status != PromptStatus.OK) return; + var pts = ent.ObjectId.GetObject()!.GetPoints(); + var ptss = pts.ConvexHull_Melkman(); + var pl = ptss.CreatePolyline(p => + { + p.Closed = true; + p.ColorIndex = 3; + }); + tr.CurrentSpace.AddEntity(pl); + } } \ No newline at end of file -- Gitee From d20890f6607a1646dd69301a9c08a4b1cf52cc08 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Fri, 21 Mar 2025 16:22:46 +0800 Subject: [PATCH 435/453] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E5=B7=A6=E8=BD=AC?= =?UTF-8?q?=E5=87=BD=E6=95=B0=E7=9A=84=E8=BF=94=E5=9B=9E=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/Geomerty/GeometryEx.cs | 23 +++++++++++-------- tests/TestShared/TestConvexHull.cs | 13 +++++++++++ 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/src/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs b/src/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs index 3fed76d..3b19c07 100644 --- a/src/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs +++ b/src/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs @@ -502,10 +502,15 @@ private static double Cross(Point2d o, Point2d a, Point2d b) /// 第一点 /// 第二点 /// 第三点 - /// 左转返回 true,否则返回 false - public static double IsClockWise(Point3d p1, Point3d p2, Point3d p3) + /// OrientationType 类型值 + public static OrientationType IsClockWise(Point3d p1, Point3d p2, Point3d p3) { - return (p2.X - p1.X) * (p3.Y - p2.Y) - (p2.Y - p1.Y) * (p3.X - p2.X); + return ((p2.X - p1.X) * (p3.Y - p2.Y) - (p2.Y - p1.Y) * (p3.X - p2.X)) switch + { + > 0 => OrientationType.CounterClockWise, + < 0 => OrientationType.ClockWise, + _ => OrientationType.Parallel + }; } /// @@ -521,14 +526,14 @@ public static List ConvexHull_Melkman(this List points) } var deque = new LinkedList(); - if (IsClockWise(points[0], points[1], points[2]) > 0) + if (IsClockWise(points[0], points[1], points[2]) is OrientationType.CounterClockWise) { deque.AddFirst(points[2]); deque.AddLast(points[0]); deque.AddLast(points[1]); deque.AddLast(points[2]); } - else if (IsClockWise(points[0], points[1], points[2]) < 0) + else if (IsClockWise(points[0], points[1], points[2]) is OrientationType.ClockWise) { deque.AddFirst(points[2]); deque.AddLast(points[1]); @@ -544,18 +549,18 @@ public static List ConvexHull_Melkman(this List points) foreach (var p in points.Skip(3)) { - if (IsClockWise(deque.Last!.Previous!.Value, deque.Last.Value, p) > 0 - && IsClockWise(p, deque.First!.Value, deque.First.Next!.Value) > 0) + if (IsClockWise(deque.Last!.Previous!.Value, deque.Last.Value, p) is OrientationType.CounterClockWise + && IsClockWise(p, deque.First!.Value, deque.First.Next!.Value) is OrientationType.CounterClockWise) { continue; } - while (deque.Count > 1 && IsClockWise(deque.Last!.Previous!.Value, deque.Last.Value, p) <= 0) + while (deque.Count > 1 && IsClockWise(deque.Last!.Previous!.Value, deque.Last.Value, p) is not OrientationType.CounterClockWise) { deque.RemoveLast(); } deque.AddLast(p); - while (deque.Count > 1 && IsClockWise(p, deque.First!.Value, deque.First.Next!.Value) <= 0) + while (deque.Count > 1 && IsClockWise(p, deque.First!.Value, deque.First.Next!.Value) is not OrientationType.CounterClockWise) { deque.RemoveFirst(); } diff --git a/tests/TestShared/TestConvexHull.cs b/tests/TestShared/TestConvexHull.cs index c7bbafb..9060edf 100644 --- a/tests/TestShared/TestConvexHull.cs +++ b/tests/TestShared/TestConvexHull.cs @@ -89,4 +89,17 @@ public static void Test_ConvexHull_Melkman() }); tr.CurrentSpace.AddEntity(pl); } + + + [CommandMethod(nameof(Test_IsClockWise))] + public static void Test_IsClockWise() + { + using var tr = new DBTrans(); + var p1 = Env.Editor.GetPoint("第一点:").Value; + var p2 = Env.Editor.GetPoint("第二点:").Value; + var p3 = Env.Editor.GetPoint("第三点:").Value; + var res1 = GeometryEx.IsClockWise(p1, p2, p3); + Env.Printl($"IsClockWise(p1, p2, p3) 的结果为:{res1}"); + + } } \ No newline at end of file -- Gitee From 5f4125ff85ff476ace5a6b051034d43f740ae164 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Mon, 3 Feb 2025 23:48:21 +0800 Subject: [PATCH 436/453] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20GetBlockFrom=20?= =?UTF-8?q?=E5=87=BD=E6=95=B0=E6=97=A0=E6=B3=95=E8=8E=B7=E5=8F=96dxf?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E5=9D=97=E7=9A=84=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CADShared/ExtensionMethod/SymbolTableEx.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/CADShared/ExtensionMethod/SymbolTableEx.cs b/src/CADShared/ExtensionMethod/SymbolTableEx.cs index f780fd6..83e0b1f 100644 --- a/src/CADShared/ExtensionMethod/SymbolTableEx.cs +++ b/src/CADShared/ExtensionMethod/SymbolTableEx.cs @@ -189,7 +189,7 @@ public static void AddAttsToBlocks(this SymbolTable table, string fileName, bool over) { - var blkDefName = SymbolUtilityServices.GetSymbolNameFromPathName(fileName, "dwg"); + var blkDefName = SymbolUtilityServices.GetSymbolNameFromPathName(fileName, "dwg;dxf"); #if acad blkDefName = SymbolUtilityServices.RepairSymbolName(blkDefName, false); #endif @@ -216,7 +216,14 @@ public static ObjectId GetBlockFrom(this SymbolTable Date: Tue, 4 Feb 2025 23:33:35 +0800 Subject: [PATCH 437/453] =?UTF-8?q?params=E5=8F=82=E6=95=B0=E5=8D=87?= =?UTF-8?q?=E7=BA=A7=E4=B8=BAc#13=E7=9A=84=E5=86=99=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CADShared/ExtensionMethod/EditorEx.cs | 20 ++++++------------- .../ExtensionMethod/Geomerty/GeometryEx.cs | 12 +---------- .../ExtensionMethod/PromptOptionsEx.cs | 9 +++++---- .../ExtensionMethod/SingleKeyWordHook.cs | 4 ++-- .../ExtensionMethod/SymbolTableEx.cs | 2 +- .../ExtensionMethod/SymbolTableRecordEx.cs | 13 +----------- src/CADShared/SelectionFilter/OpFilter.cs | 4 ++-- 7 files changed, 18 insertions(+), 46 deletions(-) diff --git a/src/CADShared/ExtensionMethod/EditorEx.cs b/src/CADShared/ExtensionMethod/EditorEx.cs index bd18a46..ca53678 100644 --- a/src/CADShared/ExtensionMethod/EditorEx.cs +++ b/src/CADShared/ExtensionMethod/EditorEx.cs @@ -325,7 +325,7 @@ public static void SsgetAddKeys(this PromptSelectionOptions pso, /// /// 带格式项的字符串 /// 指定格式化的对象数组 - public static void StreamMessage(string format, params object[] args) + public static void StreamMessage(string format, params IEnumerable args) { StreamMessage(string.Format(format, args)); } @@ -392,7 +392,7 @@ public static void InfoMessageBox(string caption, string message) /// 对话框的标题 /// 带格式化项的对话框文本 /// 指定格式化的对象数组 - public static void InfoMessageBox(string caption, string format, params object[] args) + public static void InfoMessageBox(string caption, string format, params IEnumerable args) { InfoMessageBox(caption, string.Format(format, args)); } @@ -411,7 +411,7 @@ public static void InfoMessageBox(string message) /// /// 带格式化项的对话框文本 /// 指定格式化的对象数组 - public static void InfoMessageBox(string format, params object[] args) + public static void InfoMessageBox(string format, params IEnumerable args) { InfoMessageBox(string.Format(format, args)); } @@ -438,7 +438,7 @@ public static void WriteMessage(string message) /// /// 带格式化项的文本 /// 指定格式化的对象数组 - public static void WriteMessage(string format, params object[] args) + public static void WriteMessage(string format, params IEnumerable args) { WriteMessage(string.Format(format, args)); } @@ -1134,22 +1134,14 @@ public static void ComExportWMF(this Editor editor, string saveFile, ObjectId[]? #region JigEx - /// - /// jig前的准备工作,使图元暗显 - /// - /// 命令栏 - /// 实体(已存在数据库中) - public static void PrepareForJig(this Editor ed, params Entity[] ents) - { - ed.PrepareForJig(ents.ToList()); - } + /// /// jig前的准备工作,使图元暗显 /// /// 命令栏 /// 实体(已存在数据库中) - public static void PrepareForJig(this Editor ed, IEnumerable ents) + public static void PrepareForJig(this Editor ed, params IEnumerable ents) { var dic = new Dictionary(); foreach (var ent in ents) diff --git a/src/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs b/src/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs index 3b19c07..6fbbcd6 100644 --- a/src/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs +++ b/src/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs @@ -710,17 +710,7 @@ public static Size GetSize(this Extents3d ext) /// /// 图形界面几何 /// 可绘制的对象列表 - public static void Draw(this Geometry geometry, IEnumerable drawables) - { - drawables.ForEach(d => geometry.Draw(d)); - } - - /// - /// 重绘 - /// - /// 图形界面几何 - /// 可绘制的对象列表 - public static void Draw(this Geometry geometry, params Drawable[] drawables) + public static void Draw(this Geometry geometry, params IEnumerable drawables) { drawables.ForEach(d => geometry.Draw(d)); } diff --git a/src/CADShared/ExtensionMethod/PromptOptionsEx.cs b/src/CADShared/ExtensionMethod/PromptOptionsEx.cs index 637cc7c..17f33da 100644 --- a/src/CADShared/ExtensionMethod/PromptOptionsEx.cs +++ b/src/CADShared/ExtensionMethod/PromptOptionsEx.cs @@ -23,17 +23,18 @@ public static class PromptOptionsEx /// /// 选择集选项 /// 关键字 - public static void AddKeywords(this PromptSelectionOptions pso, params string[] keywords) + public static void AddKeywords(this PromptSelectionOptions pso, params IEnumerable keywords) { - for (var i = 0; i < keywords.Length / 2; i++) + var keyWords = keywords.ToList(); + for (var i = 0; i < keyWords.Count / 2; i++) { - var key = keywords[i * 2].ToUpper(); + var key = keyWords[i * 2].ToUpper(); if (SsGetSaveKeywords.FirstOrDefault(e => e.StartsWith(key)) is { } saveKey) { throw new ArgumentException($"关键字{key}与选择集保留关键字{saveKey}冲突"); } - var message = keywords[i * 2 + 1]; + var message = keyWords[i * 2 + 1]; var end = $"({key})"; if (!message.EndsWith(end)) { diff --git a/src/CADShared/ExtensionMethod/SingleKeyWordHook.cs b/src/CADShared/ExtensionMethod/SingleKeyWordHook.cs index 0f1f84c..f543953 100644 --- a/src/CADShared/ExtensionMethod/SingleKeyWordHook.cs +++ b/src/CADShared/ExtensionMethod/SingleKeyWordHook.cs @@ -74,7 +74,7 @@ public SingleKeyWordHook(SingleKeyWordWorkType workType = SingleKeyWordWorkType. /// 添加Keys /// /// Keys集合 - public void AddKeys(params Keys[] values) => values.ForEach(value => _keyWords.Add(value)); + public void AddKeys(params IEnumerable values) => values.ForEach(value => _keyWords.Add(value)); /// /// 添加Keys @@ -94,7 +94,7 @@ public void AddKeys(KeywordCollection keywordCollection) /// 移除Keys /// /// Keys集合 - public void Remove(params Keys[] values) => values.ForEach(value => _keyWords.Remove(value)); + public void Remove(params IEnumerable values) => values.ForEach(value => _keyWords.Remove(value)); /// /// 清空Keys diff --git a/src/CADShared/ExtensionMethod/SymbolTableEx.cs b/src/CADShared/ExtensionMethod/SymbolTableEx.cs index 83e0b1f..702961b 100644 --- a/src/CADShared/ExtensionMethod/SymbolTableEx.cs +++ b/src/CADShared/ExtensionMethod/SymbolTableEx.cs @@ -136,7 +136,7 @@ public static ObjectId Add(this SymbolTable table, /// 图元(包括属性) /// public static ObjectId Add(this SymbolTable table, string name, - params Entity[] ents) + params IEnumerable ents) { return table.Add(name, null, () => ents); } diff --git a/src/CADShared/ExtensionMethod/SymbolTableRecordEx.cs b/src/CADShared/ExtensionMethod/SymbolTableRecordEx.cs index 1c2c1ab..0f3d84f 100644 --- a/src/CADShared/ExtensionMethod/SymbolTableRecordEx.cs +++ b/src/CADShared/ExtensionMethod/SymbolTableRecordEx.cs @@ -115,7 +115,7 @@ public static ObjectId AddEntity(this BlockTableRecord btr, Entity entity) /// 块表记录 /// 实体集合 /// 对象 id 列表 - public static IEnumerable AddEntity(this BlockTableRecord btr, IEnumerable ents) + public static IEnumerable AddEntity(this BlockTableRecord btr, params IEnumerable ents) { var tr = DBTrans.GetTopTransaction(btr.Database); using (btr.ForWrite()) @@ -129,17 +129,6 @@ public static IEnumerable AddEntity(this BlockTableRecord btr, IEnumer } } - /// - /// 添加多个实体 - /// - /// 块表记录 - /// 实体集合 - /// 对象 id 列表 - public static IEnumerable AddEntity(this BlockTableRecord btr, params Entity[] ents) - { - return btr.AddEntity(ents.ToList()); - } - #endregion #region 获取实体/实体id diff --git a/src/CADShared/SelectionFilter/OpFilter.cs b/src/CADShared/SelectionFilter/OpFilter.cs index 7eb495d..b1e2b43 100644 --- a/src/CADShared/SelectionFilter/OpFilter.cs +++ b/src/CADShared/SelectionFilter/OpFilter.cs @@ -117,7 +117,7 @@ private Op(OpFilter filter) /// 操作符类型的可变参数 /// Op对象 #pragma warning disable CA1822 // 将成员标记为 static - public Op And(params Op[] args) + public Op And(params IEnumerable args) #pragma warning restore CA1822 // 将成员标记为 static { var filter = new OpAnd(); @@ -132,7 +132,7 @@ public Op And(params Op[] args) /// 操作符类型的可变参数 /// Op对象 #pragma warning disable CA1822 // 将成员标记为 static - public Op Or(params Op[] args) + public Op Or(params IEnumerable args) #pragma warning restore CA1822 // 将成员标记为 static { var filter = new OpOr(); -- Gitee From 8b34124544851c624a4ec68f3a4f1d847185ce72 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Wed, 9 Jul 2025 14:59:12 +0800 Subject: [PATCH 438/453] =?UTF-8?q?fixup!=20params=E5=8F=82=E6=95=B0?= =?UTF-8?q?=E5=8D=87=E7=BA=A7=E4=B8=BAc#13=E7=9A=84=E5=86=99=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CADShared/ExtensionMethod/TrustedPathEx.cs | 8 ++------ src/CADShared/Runtime/Env.cs | 4 ++-- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/CADShared/ExtensionMethod/TrustedPathEx.cs b/src/CADShared/ExtensionMethod/TrustedPathEx.cs index a5c37da..7e62b91 100644 --- a/src/CADShared/ExtensionMethod/TrustedPathEx.cs +++ b/src/CADShared/ExtensionMethod/TrustedPathEx.cs @@ -15,7 +15,7 @@ public static List Get() .Split([";"], StringSplitOptions.RemoveEmptyEntries) .Select(s => s.TrimEnd('\\')) .ToHashSet(); - return set.ToList(); + return [.. set]; } /// @@ -28,12 +28,8 @@ public static void Add(params IEnumerable dirs) if (dirSet.Count == 0) return; var paths = Get(); - foreach (var dir in dirSet) + foreach (var dir in dirSet.Where(Directory.Exists).Where(dir => !paths.Contains(dir))) { - if (!Directory.Exists(dir)) - continue; - if (paths.Contains(dir)) - continue; paths.Insert(0, dir); } diff --git a/src/CADShared/Runtime/Env.cs b/src/CADShared/Runtime/Env.cs index fd18bc8..e36d60e 100644 --- a/src/CADShared/Runtime/Env.cs +++ b/src/CADShared/Runtime/Env.cs @@ -548,7 +548,7 @@ public static List GetSupportPath() /// 添加目录至CAD受信任的位置 /// /// 目录 - public static void AppendTrustedPath(params string[] folders) + public static void AppendTrustedPath(params IEnumerable folders) { TrustedPathEx.Add(folders); } @@ -557,7 +557,7 @@ public static void AppendTrustedPath(params string[] folders) /// 移除信任目录 /// /// 目录 - public static void RemoveTrustedPath(params string[] folders) + public static void RemoveTrustedPath(params IEnumerable folders) { TrustedPathEx.Remove(folders); } -- Gitee From 3a39dcc2fbc6e5c6629494f8cd3c2d47d1a21a62 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Wed, 9 Jul 2025 07:02:58 +0000 Subject: [PATCH 439/453] =?UTF-8?q?Revert=20"fixup!=20params=E5=8F=82?= =?UTF-8?q?=E6=95=B0=E5=8D=87=E7=BA=A7=E4=B8=BAc#13=E7=9A=84=E5=86=99?= =?UTF-8?q?=E6=B3=95"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 8b34124544851c624a4ec68f3a4f1d847185ce72. --- src/CADShared/ExtensionMethod/TrustedPathEx.cs | 8 ++++++-- src/CADShared/Runtime/Env.cs | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/CADShared/ExtensionMethod/TrustedPathEx.cs b/src/CADShared/ExtensionMethod/TrustedPathEx.cs index 7e62b91..a5c37da 100644 --- a/src/CADShared/ExtensionMethod/TrustedPathEx.cs +++ b/src/CADShared/ExtensionMethod/TrustedPathEx.cs @@ -15,7 +15,7 @@ public static List Get() .Split([";"], StringSplitOptions.RemoveEmptyEntries) .Select(s => s.TrimEnd('\\')) .ToHashSet(); - return [.. set]; + return set.ToList(); } /// @@ -28,8 +28,12 @@ public static void Add(params IEnumerable dirs) if (dirSet.Count == 0) return; var paths = Get(); - foreach (var dir in dirSet.Where(Directory.Exists).Where(dir => !paths.Contains(dir))) + foreach (var dir in dirSet) { + if (!Directory.Exists(dir)) + continue; + if (paths.Contains(dir)) + continue; paths.Insert(0, dir); } diff --git a/src/CADShared/Runtime/Env.cs b/src/CADShared/Runtime/Env.cs index e36d60e..fd18bc8 100644 --- a/src/CADShared/Runtime/Env.cs +++ b/src/CADShared/Runtime/Env.cs @@ -548,7 +548,7 @@ public static List GetSupportPath() /// 添加目录至CAD受信任的位置 /// /// 目录 - public static void AppendTrustedPath(params IEnumerable folders) + public static void AppendTrustedPath(params string[] folders) { TrustedPathEx.Add(folders); } @@ -557,7 +557,7 @@ public static void AppendTrustedPath(params IEnumerable folders) /// 移除信任目录 /// /// 目录 - public static void RemoveTrustedPath(params IEnumerable folders) + public static void RemoveTrustedPath(params string[] folders) { TrustedPathEx.Remove(folders); } -- Gitee From c82ca4adc26e559fd309c8d6705445ec479132fd Mon Sep 17 00:00:00 2001 From: vicwjb Date: Wed, 9 Jul 2025 07:24:50 +0000 Subject: [PATCH 440/453] =?UTF-8?q?Revert=20"params=E5=8F=82=E6=95=B0?= =?UTF-8?q?=E5=8D=87=E7=BA=A7=E4=B8=BAc#13=E7=9A=84=E5=86=99=E6=B3=95"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit d2e88f1169c6d648af8fe6b2c5564af4d66ea42f. --- src/CADShared/ExtensionMethod/EditorEx.cs | 20 +++++++++++++------ .../ExtensionMethod/Geomerty/GeometryEx.cs | 12 ++++++++++- .../ExtensionMethod/PromptOptionsEx.cs | 9 ++++----- .../ExtensionMethod/SingleKeyWordHook.cs | 4 ++-- .../ExtensionMethod/SymbolTableEx.cs | 2 +- .../ExtensionMethod/SymbolTableRecordEx.cs | 13 +++++++++++- src/CADShared/SelectionFilter/OpFilter.cs | 4 ++-- 7 files changed, 46 insertions(+), 18 deletions(-) diff --git a/src/CADShared/ExtensionMethod/EditorEx.cs b/src/CADShared/ExtensionMethod/EditorEx.cs index ca53678..bd18a46 100644 --- a/src/CADShared/ExtensionMethod/EditorEx.cs +++ b/src/CADShared/ExtensionMethod/EditorEx.cs @@ -325,7 +325,7 @@ public static void SsgetAddKeys(this PromptSelectionOptions pso, /// /// 带格式项的字符串 /// 指定格式化的对象数组 - public static void StreamMessage(string format, params IEnumerable args) + public static void StreamMessage(string format, params object[] args) { StreamMessage(string.Format(format, args)); } @@ -392,7 +392,7 @@ public static void InfoMessageBox(string caption, string message) /// 对话框的标题 /// 带格式化项的对话框文本 /// 指定格式化的对象数组 - public static void InfoMessageBox(string caption, string format, params IEnumerable args) + public static void InfoMessageBox(string caption, string format, params object[] args) { InfoMessageBox(caption, string.Format(format, args)); } @@ -411,7 +411,7 @@ public static void InfoMessageBox(string message) /// /// 带格式化项的对话框文本 /// 指定格式化的对象数组 - public static void InfoMessageBox(string format, params IEnumerable args) + public static void InfoMessageBox(string format, params object[] args) { InfoMessageBox(string.Format(format, args)); } @@ -438,7 +438,7 @@ public static void WriteMessage(string message) /// /// 带格式化项的文本 /// 指定格式化的对象数组 - public static void WriteMessage(string format, params IEnumerable args) + public static void WriteMessage(string format, params object[] args) { WriteMessage(string.Format(format, args)); } @@ -1134,14 +1134,22 @@ public static void ComExportWMF(this Editor editor, string saveFile, ObjectId[]? #region JigEx - + /// + /// jig前的准备工作,使图元暗显 + /// + /// 命令栏 + /// 实体(已存在数据库中) + public static void PrepareForJig(this Editor ed, params Entity[] ents) + { + ed.PrepareForJig(ents.ToList()); + } /// /// jig前的准备工作,使图元暗显 /// /// 命令栏 /// 实体(已存在数据库中) - public static void PrepareForJig(this Editor ed, params IEnumerable ents) + public static void PrepareForJig(this Editor ed, IEnumerable ents) { var dic = new Dictionary(); foreach (var ent in ents) diff --git a/src/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs b/src/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs index 6fbbcd6..3b19c07 100644 --- a/src/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs +++ b/src/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs @@ -710,7 +710,17 @@ public static Size GetSize(this Extents3d ext) /// /// 图形界面几何 /// 可绘制的对象列表 - public static void Draw(this Geometry geometry, params IEnumerable drawables) + public static void Draw(this Geometry geometry, IEnumerable drawables) + { + drawables.ForEach(d => geometry.Draw(d)); + } + + /// + /// 重绘 + /// + /// 图形界面几何 + /// 可绘制的对象列表 + public static void Draw(this Geometry geometry, params Drawable[] drawables) { drawables.ForEach(d => geometry.Draw(d)); } diff --git a/src/CADShared/ExtensionMethod/PromptOptionsEx.cs b/src/CADShared/ExtensionMethod/PromptOptionsEx.cs index 17f33da..637cc7c 100644 --- a/src/CADShared/ExtensionMethod/PromptOptionsEx.cs +++ b/src/CADShared/ExtensionMethod/PromptOptionsEx.cs @@ -23,18 +23,17 @@ public static class PromptOptionsEx /// /// 选择集选项 /// 关键字 - public static void AddKeywords(this PromptSelectionOptions pso, params IEnumerable keywords) + public static void AddKeywords(this PromptSelectionOptions pso, params string[] keywords) { - var keyWords = keywords.ToList(); - for (var i = 0; i < keyWords.Count / 2; i++) + for (var i = 0; i < keywords.Length / 2; i++) { - var key = keyWords[i * 2].ToUpper(); + var key = keywords[i * 2].ToUpper(); if (SsGetSaveKeywords.FirstOrDefault(e => e.StartsWith(key)) is { } saveKey) { throw new ArgumentException($"关键字{key}与选择集保留关键字{saveKey}冲突"); } - var message = keyWords[i * 2 + 1]; + var message = keywords[i * 2 + 1]; var end = $"({key})"; if (!message.EndsWith(end)) { diff --git a/src/CADShared/ExtensionMethod/SingleKeyWordHook.cs b/src/CADShared/ExtensionMethod/SingleKeyWordHook.cs index f543953..0f1f84c 100644 --- a/src/CADShared/ExtensionMethod/SingleKeyWordHook.cs +++ b/src/CADShared/ExtensionMethod/SingleKeyWordHook.cs @@ -74,7 +74,7 @@ public SingleKeyWordHook(SingleKeyWordWorkType workType = SingleKeyWordWorkType. /// 添加Keys /// /// Keys集合 - public void AddKeys(params IEnumerable values) => values.ForEach(value => _keyWords.Add(value)); + public void AddKeys(params Keys[] values) => values.ForEach(value => _keyWords.Add(value)); /// /// 添加Keys @@ -94,7 +94,7 @@ public void AddKeys(KeywordCollection keywordCollection) /// 移除Keys /// /// Keys集合 - public void Remove(params IEnumerable values) => values.ForEach(value => _keyWords.Remove(value)); + public void Remove(params Keys[] values) => values.ForEach(value => _keyWords.Remove(value)); /// /// 清空Keys diff --git a/src/CADShared/ExtensionMethod/SymbolTableEx.cs b/src/CADShared/ExtensionMethod/SymbolTableEx.cs index 702961b..83e0b1f 100644 --- a/src/CADShared/ExtensionMethod/SymbolTableEx.cs +++ b/src/CADShared/ExtensionMethod/SymbolTableEx.cs @@ -136,7 +136,7 @@ public static ObjectId Add(this SymbolTable table, /// 图元(包括属性) /// public static ObjectId Add(this SymbolTable table, string name, - params IEnumerable ents) + params Entity[] ents) { return table.Add(name, null, () => ents); } diff --git a/src/CADShared/ExtensionMethod/SymbolTableRecordEx.cs b/src/CADShared/ExtensionMethod/SymbolTableRecordEx.cs index 0f3d84f..1c2c1ab 100644 --- a/src/CADShared/ExtensionMethod/SymbolTableRecordEx.cs +++ b/src/CADShared/ExtensionMethod/SymbolTableRecordEx.cs @@ -115,7 +115,7 @@ public static ObjectId AddEntity(this BlockTableRecord btr, Entity entity) /// 块表记录 /// 实体集合 /// 对象 id 列表 - public static IEnumerable AddEntity(this BlockTableRecord btr, params IEnumerable ents) + public static IEnumerable AddEntity(this BlockTableRecord btr, IEnumerable ents) { var tr = DBTrans.GetTopTransaction(btr.Database); using (btr.ForWrite()) @@ -129,6 +129,17 @@ public static IEnumerable AddEntity(this BlockTableRecord btr, params } } + /// + /// 添加多个实体 + /// + /// 块表记录 + /// 实体集合 + /// 对象 id 列表 + public static IEnumerable AddEntity(this BlockTableRecord btr, params Entity[] ents) + { + return btr.AddEntity(ents.ToList()); + } + #endregion #region 获取实体/实体id diff --git a/src/CADShared/SelectionFilter/OpFilter.cs b/src/CADShared/SelectionFilter/OpFilter.cs index b1e2b43..7eb495d 100644 --- a/src/CADShared/SelectionFilter/OpFilter.cs +++ b/src/CADShared/SelectionFilter/OpFilter.cs @@ -117,7 +117,7 @@ private Op(OpFilter filter) /// 操作符类型的可变参数 /// Op对象 #pragma warning disable CA1822 // 将成员标记为 static - public Op And(params IEnumerable args) + public Op And(params Op[] args) #pragma warning restore CA1822 // 将成员标记为 static { var filter = new OpAnd(); @@ -132,7 +132,7 @@ public Op And(params IEnumerable args) /// 操作符类型的可变参数 /// Op对象 #pragma warning disable CA1822 // 将成员标记为 static - public Op Or(params IEnumerable args) + public Op Or(params Op[] args) #pragma warning restore CA1822 // 将成员标记为 static { var filter = new OpOr(); -- Gitee From fc908eef738de04c0b0178fdd5b7079a04f8d6f3 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Wed, 9 Jul 2025 07:25:09 +0000 Subject: [PATCH 441/453] =?UTF-8?q?Revert=20"=E4=BF=AE=E5=A4=8D=20GetBlock?= =?UTF-8?q?From=20=E5=87=BD=E6=95=B0=E6=97=A0=E6=B3=95=E8=8E=B7=E5=8F=96dx?= =?UTF-8?q?f=E6=96=87=E4=BB=B6=E5=9D=97=E7=9A=84=E9=94=99=E8=AF=AF"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 5f4125ff85ff476ace5a6b051034d43f740ae164. --- src/CADShared/ExtensionMethod/SymbolTableEx.cs | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/CADShared/ExtensionMethod/SymbolTableEx.cs b/src/CADShared/ExtensionMethod/SymbolTableEx.cs index 83e0b1f..f780fd6 100644 --- a/src/CADShared/ExtensionMethod/SymbolTableEx.cs +++ b/src/CADShared/ExtensionMethod/SymbolTableEx.cs @@ -189,7 +189,7 @@ public static void AddAttsToBlocks(this SymbolTable table, string fileName, bool over) { - var blkDefName = SymbolUtilityServices.GetSymbolNameFromPathName(fileName, "dwg;dxf"); + var blkDefName = SymbolUtilityServices.GetSymbolNameFromPathName(fileName, "dwg"); #if acad blkDefName = SymbolUtilityServices.RepairSymbolName(blkDefName, false); #endif @@ -216,14 +216,7 @@ public static ObjectId GetBlockFrom(this SymbolTable Date: Wed, 9 Jul 2025 07:25:27 +0000 Subject: [PATCH 442/453] =?UTF-8?q?Revert=20"=E4=BF=AE=E6=AD=A3=E5=B7=A6?= =?UTF-8?q?=E8=BD=AC=E5=87=BD=E6=95=B0=E7=9A=84=E8=BF=94=E5=9B=9E=E5=80=BC?= =?UTF-8?q?"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit d20890f6607a1646dd69301a9c08a4b1cf52cc08. --- .../ExtensionMethod/Geomerty/GeometryEx.cs | 23 ++++++++----------- tests/TestShared/TestConvexHull.cs | 13 ----------- 2 files changed, 9 insertions(+), 27 deletions(-) diff --git a/src/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs b/src/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs index 3b19c07..3fed76d 100644 --- a/src/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs +++ b/src/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs @@ -502,15 +502,10 @@ private static double Cross(Point2d o, Point2d a, Point2d b) /// 第一点 /// 第二点 /// 第三点 - /// OrientationType 类型值 - public static OrientationType IsClockWise(Point3d p1, Point3d p2, Point3d p3) + /// 左转返回 true,否则返回 false + public static double IsClockWise(Point3d p1, Point3d p2, Point3d p3) { - return ((p2.X - p1.X) * (p3.Y - p2.Y) - (p2.Y - p1.Y) * (p3.X - p2.X)) switch - { - > 0 => OrientationType.CounterClockWise, - < 0 => OrientationType.ClockWise, - _ => OrientationType.Parallel - }; + return (p2.X - p1.X) * (p3.Y - p2.Y) - (p2.Y - p1.Y) * (p3.X - p2.X); } /// @@ -526,14 +521,14 @@ public static List ConvexHull_Melkman(this List points) } var deque = new LinkedList(); - if (IsClockWise(points[0], points[1], points[2]) is OrientationType.CounterClockWise) + if (IsClockWise(points[0], points[1], points[2]) > 0) { deque.AddFirst(points[2]); deque.AddLast(points[0]); deque.AddLast(points[1]); deque.AddLast(points[2]); } - else if (IsClockWise(points[0], points[1], points[2]) is OrientationType.ClockWise) + else if (IsClockWise(points[0], points[1], points[2]) < 0) { deque.AddFirst(points[2]); deque.AddLast(points[1]); @@ -549,18 +544,18 @@ public static List ConvexHull_Melkman(this List points) foreach (var p in points.Skip(3)) { - if (IsClockWise(deque.Last!.Previous!.Value, deque.Last.Value, p) is OrientationType.CounterClockWise - && IsClockWise(p, deque.First!.Value, deque.First.Next!.Value) is OrientationType.CounterClockWise) + if (IsClockWise(deque.Last!.Previous!.Value, deque.Last.Value, p) > 0 + && IsClockWise(p, deque.First!.Value, deque.First.Next!.Value) > 0) { continue; } - while (deque.Count > 1 && IsClockWise(deque.Last!.Previous!.Value, deque.Last.Value, p) is not OrientationType.CounterClockWise) + while (deque.Count > 1 && IsClockWise(deque.Last!.Previous!.Value, deque.Last.Value, p) <= 0) { deque.RemoveLast(); } deque.AddLast(p); - while (deque.Count > 1 && IsClockWise(p, deque.First!.Value, deque.First.Next!.Value) is not OrientationType.CounterClockWise) + while (deque.Count > 1 && IsClockWise(p, deque.First!.Value, deque.First.Next!.Value) <= 0) { deque.RemoveFirst(); } diff --git a/tests/TestShared/TestConvexHull.cs b/tests/TestShared/TestConvexHull.cs index 9060edf..c7bbafb 100644 --- a/tests/TestShared/TestConvexHull.cs +++ b/tests/TestShared/TestConvexHull.cs @@ -89,17 +89,4 @@ public static void Test_ConvexHull_Melkman() }); tr.CurrentSpace.AddEntity(pl); } - - - [CommandMethod(nameof(Test_IsClockWise))] - public static void Test_IsClockWise() - { - using var tr = new DBTrans(); - var p1 = Env.Editor.GetPoint("第一点:").Value; - var p2 = Env.Editor.GetPoint("第二点:").Value; - var p3 = Env.Editor.GetPoint("第三点:").Value; - var res1 = GeometryEx.IsClockWise(p1, p2, p3); - Env.Printl($"IsClockWise(p1, p2, p3) 的结果为:{res1}"); - - } } \ No newline at end of file -- Gitee From 533aee05742a6b646ac1b9fbdee32da83daecc8d Mon Sep 17 00:00:00 2001 From: vicwjb Date: Wed, 9 Jul 2025 07:25:41 +0000 Subject: [PATCH 443/453] =?UTF-8?q?Revert=20"=E5=A2=9E=E5=8A=A0Melkman?= =?UTF-8?q?=E7=AE=97=E6=B3=95=E6=B1=82=E7=AE=80=E5=8D=95=E5=A4=9A=E8=BE=B9?= =?UTF-8?q?=E5=BD=A2=E5=87=B8=E5=8C=85"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 1db46a7bc0f9fa9376535df1d393ddae53190d73. --- .../ExtensionMethod/Geomerty/GeometryEx.cs | 73 ------------------- tests/TestShared/TestConvexHull.cs | 16 ---- 2 files changed, 89 deletions(-) diff --git a/src/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs b/src/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs index 3fed76d..d21d818 100644 --- a/src/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs +++ b/src/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs @@ -495,80 +495,7 @@ private static double Cross(Point2d o, Point2d a, Point2d b) return hullPts.Count >= 3 ? hullPts : null; } - - /// - /// 判断三个点是否左转 - /// - /// 第一点 - /// 第二点 - /// 第三点 - /// 左转返回 true,否则返回 false - public static double IsClockWise(Point3d p1, Point3d p2, Point3d p3) - { - return (p2.X - p1.X) * (p3.Y - p2.Y) - (p2.Y - p1.Y) * (p3.X - p2.X); - - } - /// - /// Melkman算法求简单多边形凸包 - /// - /// 多边形端点列表 - /// 凸包端点列表 - public static List ConvexHull_Melkman(this List points) - { - if (points.Count <= 3) - { - return points; - } - - var deque = new LinkedList(); - if (IsClockWise(points[0], points[1], points[2]) > 0) - { - deque.AddFirst(points[2]); - deque.AddLast(points[0]); - deque.AddLast(points[1]); - deque.AddLast(points[2]); - } - else if (IsClockWise(points[0], points[1], points[2]) < 0) - { - deque.AddFirst(points[2]); - deque.AddLast(points[1]); - deque.AddLast(points[0]); - deque.AddLast(points[2]); - } - else - { - deque.AddFirst(points[2]); - deque.AddLast(points[0]); - deque.AddLast(points[2]); - } - - foreach (var p in points.Skip(3)) - { - if (IsClockWise(deque.Last!.Previous!.Value, deque.Last.Value, p) > 0 - && IsClockWise(p, deque.First!.Value, deque.First.Next!.Value) > 0) - { - continue; - } - while (deque.Count > 1 && IsClockWise(deque.Last!.Previous!.Value, deque.Last.Value, p) <= 0) - { - deque.RemoveLast(); - } - deque.AddLast(p); - while (deque.Count > 1 && IsClockWise(p, deque.First!.Value, deque.First.Next!.Value) <= 0) - { - deque.RemoveFirst(); - } - deque.AddFirst(p); - - } - - if (deque.First!.Value == deque.Last!.Value) - { - deque.RemoveFirst(); - } - return [.. deque]; - } #endregion PointList #endregion Point&Circle diff --git a/tests/TestShared/TestConvexHull.cs b/tests/TestShared/TestConvexHull.cs index c7bbafb..03692ae 100644 --- a/tests/TestShared/TestConvexHull.cs +++ b/tests/TestShared/TestConvexHull.cs @@ -73,20 +73,4 @@ public void Test_ConvexHull() Env.Editor.WriteMessage($"点集的有向面积:{area5} \n"); Env.Editor.WriteMessage($"点集的有向面积:{area6} \n"); } - - [CommandMethod(nameof(Test_ConvexHull_Melkman))] - public static void Test_ConvexHull_Melkman() - { - using var tr = new DBTrans(); - var ent = Env.Editor.GetEntity("选取多段线"); - if (ent.Status != PromptStatus.OK) return; - var pts = ent.ObjectId.GetObject()!.GetPoints(); - var ptss = pts.ConvexHull_Melkman(); - var pl = ptss.CreatePolyline(p => - { - p.Closed = true; - p.ColorIndex = 3; - }); - tr.CurrentSpace.AddEntity(pl); - } } \ No newline at end of file -- Gitee From dba7f2572c577bd068dcd5cd146490c87935f21f Mon Sep 17 00:00:00 2001 From: Medithaibet <12247633+medithaibet@user.noreply.gitee.com> Date: Thu, 10 Jul 2025 01:41:41 +0800 Subject: [PATCH 444/453] =?UTF-8?q?=E5=8D=95=E8=AF=8D=E6=8B=BC=E5=86=99?= =?UTF-8?q?=E9=94=99=E8=AF=AF=EF=BC=9Abluges=20=E6=9B=B4=E6=AD=A3=E4=B8=BA?= =?UTF-8?q?=20bulges=EF=BC=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExtensionMethod/Hatch/HatchInfo.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/CADShared/ExtensionMethod/Hatch/HatchInfo.cs b/src/CADShared/ExtensionMethod/Hatch/HatchInfo.cs index b1d7576..14b14c8 100644 --- a/src/CADShared/ExtensionMethod/Hatch/HatchInfo.cs +++ b/src/CADShared/ExtensionMethod/Hatch/HatchInfo.cs @@ -56,7 +56,7 @@ public class HatchInfo double Angle => _hatch.PatternAngle; // 延后处理角度 - private double _angle; + private readonly double _angle; #endregion #region 构造 @@ -163,7 +163,7 @@ public HatchInfo Mode4Gradient(GradientName name, Color colorStart, Color colorE float shadeTintValue = 0, bool gradientOneColorMode = false) { - // entget渐变的名字必然是"SOLID",但是这里作为"渐变"名,而不是"填充"名 + // entGet渐变的名字必然是"SOLID",但是这里作为"渐变"名,而不是"填充"名 _hatchName = name.ToString(); _hatch.HatchObjectType = HatchObjectType.GradientObject; // 对象类型(填充/渐变) _patternTypeGradient = GradientPatternType.PreDefinedGradient;// 模式4:渐变 @@ -207,7 +207,7 @@ public ObjectId Build(BlockTableRecord btrOfAddEntitySpace) // 利用 AppendLoop 重载加入,这里就不处理 if (_boundaryIds.Count > 0) - AppendLoop(_boundaryIds, HatchLoopTypes.Default); + AppendLoop(_boundaryIds); // 计算填充并显示(若边界出错,这句会异常) _hatch.EvaluateHatch(true); @@ -249,10 +249,10 @@ public HatchInfo EraseBoundary() /// /// 边界id /// 加入方式 - void AppendLoop(IEnumerable boundaryIds, - HatchLoopTypes hatchLoopTypes = HatchLoopTypes.Default) + private void AppendLoop(IEnumerable boundaryIds, + HatchLoopTypes hatchLoopTypes = HatchLoopTypes.Default) { - ObjectIdCollection obIds = new(); + ObjectIdCollection obIds = []; // 边界是闭合的,而且已经加入数据库 // 填充闭合环类型.最外面 @@ -289,12 +289,12 @@ void AppendLoop(IEnumerable boundaryIds, /// 加入边界(仿高版本的填充函数) /// /// 点集 - /// 凸度集 + /// 凸度集 /// 加入此空间 /// 加入方式 /// public HatchInfo AppendLoop(Point2dCollection pts, - DoubleCollection bluges, + DoubleCollection bulges, BlockTableRecord btrOfAddEntitySpace, HatchLoopTypes hatchLoopTypes = HatchLoopTypes.Default) { @@ -304,7 +304,7 @@ public HatchInfo AppendLoop(Point2dCollection pts, pts.End2End(); // 2011新增API,可以不生成图元的情况下加入边界, // 通过这里进入的话,边界 _boundaryIds 是空的,那么 Build() 时候就需要过滤空的 - _hatch.AppendLoop(hatchLoopTypes, pts, bluges); + _hatch.AppendLoop(hatchLoopTypes, pts, bulges); return this; } -- Gitee From 159c0761cf6289c0195e8c5b7fe7ca99210b9fa1 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Sun, 17 Aug 2025 11:43:48 +0800 Subject: [PATCH 445/453] =?UTF-8?q?=E4=BF=AE=E5=A4=8DzcedGetEnv=E5=87=BD?= =?UTF-8?q?=E6=95=B0=E5=85=A5=E5=8F=A3=E7=82=B9=E9=94=99=E8=AF=AF=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CADShared/Runtime/Env.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CADShared/Runtime/Env.cs b/src/CADShared/Runtime/Env.cs index fd18bc8..024eb5d 100644 --- a/src/CADShared/Runtime/Env.cs +++ b/src/CADShared/Runtime/Env.cs @@ -469,8 +469,8 @@ public static void SetVar(string varName, object value, bool echo = true) // TODO: 中望没有测试,此处仅为不报错;本工程所有含有"中望"均存在问题 #if zcad [System.Security.SuppressUnmanagedCodeSecurity] - [DllImport("zwcad.exe", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, - EntryPoint = "zcedGetEnv")] + [DllImport("zwcad.exe", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, + EntryPoint = "?zcedGetEnv@@YAHPEB_WPEA_W_K@Z")]//名称大小写不能换 private static extern int AcedGetEnv(string? envName, StringBuilder returnValue); [System.Security.SuppressUnmanagedCodeSecurity] -- Gitee From fe4a8388af389d166a58ac4f3a0b9f2caa7d6326 Mon Sep 17 00:00:00 2001 From: vicwjb Date: Sun, 17 Aug 2025 12:08:23 +0800 Subject: [PATCH 446/453] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=AE=BE=E7=BD=AE?= =?UTF-8?q?=E5=B1=9E=E6=80=A7=E4=B8=BA=E5=A4=9A=E8=A1=8C=E6=96=87=E5=AD=97?= =?UTF-8?q?=E5=B1=9E=E6=80=A7=E7=9A=84=E6=89=A9=E5=B1=95=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CADShared/CADShared.projitems | 1 + .../Entity/AttributeDefinitionEx.cs | 22 +++++++++++ tests/TestShared/TestBlock.cs | 38 +++++++++++++++++++ 3 files changed, 61 insertions(+) create mode 100644 src/CADShared/ExtensionMethod/Entity/AttributeDefinitionEx.cs diff --git a/src/CADShared/CADShared.projitems b/src/CADShared/CADShared.projitems index ecde82d..d221b2c 100644 --- a/src/CADShared/CADShared.projitems +++ b/src/CADShared/CADShared.projitems @@ -40,6 +40,7 @@ + diff --git a/src/CADShared/ExtensionMethod/Entity/AttributeDefinitionEx.cs b/src/CADShared/ExtensionMethod/Entity/AttributeDefinitionEx.cs new file mode 100644 index 0000000..e60e181 --- /dev/null +++ b/src/CADShared/ExtensionMethod/Entity/AttributeDefinitionEx.cs @@ -0,0 +1,22 @@ +namespace IFoxCAD.Cad; + +/// +/// 属性文字扩展 +/// +public static class AttributeDefinitionEx +{ + /// + /// 设置属性为多行文字,并通过委托设置多行文字的属性 + /// + /// 属性对象 + /// 设置多行文字的委托 + public static void SetMTextAttribute(this AttributeDefinition attr, Action action) + { + attr.IsMTextAttributeDefinition = true; + var mt = attr.MTextAttributeDefinition; + action(mt); + attr.MTextAttributeDefinition = mt; + attr.UpdateMTextAttributeDefinition(); + } + +} \ No newline at end of file diff --git a/tests/TestShared/TestBlock.cs b/tests/TestShared/TestBlock.cs index 20baa82..918dca2 100644 --- a/tests/TestShared/TestBlock.cs +++ b/tests/TestShared/TestBlock.cs @@ -287,6 +287,44 @@ public void Test_BlockFiledxf() } + + [CommandMethod("Test_CreateMTextAttributeBlock")] + public void Test_CreateMTextAttributeBlock() + { + + using var tr = new DBTrans(); + + tr.BlockTable.Add("MTextAttributeBlock",btr => + { + btr.Origin = Point3d.Origin; + // 创建一个多行文字作为块的一部分 + var mtext = new MText(); + mtext.Contents = "默认多行文字内容\n第二行内容\n第三行内容"; + mtext.Location = new Point3d(0, 0, 0); + mtext.Width = 200; // 多行文字宽度 + mtext.Height = 2.5; // 文字高度 + btr.AddEntity(mtext); + + + // 创建属性定义 + var attrDef = new AttributeDefinition(); + attrDef.Position = new Point3d(0, -50, 0); // 位置在多行文字下方 + attrDef.Prompt = "请输入属性值"; + attrDef.Tag = "ATTR_TAG"; + attrDef.TextString = "默认属性值"; + attrDef.Height = 2.5; + attrDef.Justify = AttachmentPoint.MiddleCenter; // 居中对齐 + + // 设置为多行属性 + attrDef.SetMTextAttribute(att => att.Width = 100); + btr.AddEntity(attrDef); + }); + + tr.CurrentSpace.InsertBlock(Point3d.Origin, "MTextAttributeBlock"); + + + } + [CommandMethod(nameof(Test_ClipBlock))] public void Test_ClipBlock() -- Gitee From e5ae5fa5fec8eb41074cff11e0051d667b529bd3 Mon Sep 17 00:00:00 2001 From: wxynotes <397858859@qq.com> Date: Sun, 28 Sep 2025 17:04:01 +0800 Subject: [PATCH 447/453] =?UTF-8?q?fix:Env.GetDimblkId()=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E5=9C=A8=E8=AE=BE=E7=BD=AE"dimblk"=E7=B3=BB=E7=BB=9F=E5=8F=98?= =?UTF-8?q?=E9=87=8F=E6=97=B6,oldDimblk=E5=8F=AF=E8=83=BD=E4=B8=BA?= =?UTF-8?q?=E7=A9=BA=E3=80=82=E5=BD=93=E5=85=B6=E4=B8=BA=E7=A9=BA=E6=97=B6?= =?UTF-8?q?=EF=BC=8C=E6=81=A2=E5=A4=8D=E7=B3=BB=E7=BB=9F=E5=8F=98=E9=87=8F?= =?UTF-8?q?=E6=97=B6=E8=A6=81=E8=AE=BE=E7=BD=AE=E4=B8=BA"."=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CADShared/Runtime/Env.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CADShared/Runtime/Env.cs b/src/CADShared/Runtime/Env.cs index 024eb5d..fd7b353 100644 --- a/src/CADShared/Runtime/Env.cs +++ b/src/CADShared/Runtime/Env.cs @@ -289,7 +289,7 @@ public static ObjectId GetDimblkId(DimblkType dimblk) var oldDimblk = Acaop.GetSystemVariable("dimblk"); Dimblk = dimblk; var id = HostApplicationServices.WorkingDatabase.Dimblk; - Acaop.SetSystemVariable("dimblk", oldDimblk); + Acaop.SetSystemVariable("dimblk", string.IsNullOrWhiteSpace(oldDimblk.ToString())? "." : oldDimblk); return id; } -- Gitee From 5340b971fd4fe3c298a15a1646382a0a9b47329e Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 9 Oct 2025 13:53:05 +0800 Subject: [PATCH 448/453] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=BF=9B=E5=BA=A6?= =?UTF-8?q?=E6=9D=A1=E5=B7=A5=E5=85=B7=E4=BB=A5=E9=80=82=E9=85=8D=E4=B8=AD?= =?UTF-8?q?=E6=9C=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CADShared/CADShared.projitems | 1 + src/CADShared/Runtime/ProgressMeterUtils.cs | 60 +++++++++++++++++++++ src/Directory.Build.props | 4 +- 3 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 src/CADShared/Runtime/ProgressMeterUtils.cs diff --git a/src/CADShared/CADShared.projitems b/src/CADShared/CADShared.projitems index d221b2c..5a1d56d 100644 --- a/src/CADShared/CADShared.projitems +++ b/src/CADShared/CADShared.projitems @@ -102,6 +102,7 @@ + diff --git a/src/CADShared/Runtime/ProgressMeterUtils.cs b/src/CADShared/Runtime/ProgressMeterUtils.cs new file mode 100644 index 0000000..aeb8862 --- /dev/null +++ b/src/CADShared/Runtime/ProgressMeterUtils.cs @@ -0,0 +1,60 @@ +namespace IFoxCAD.Cad; + +/// +/// 进度条 +/// +public static class ProgressMeterUtils +{ + /// + /// 设置状态栏进度条 + /// + public static void SetApplicationStatusBarProgressMeter(string str, int mixPos, int maxPos) + { +#if acad + Utils.SetApplicationStatusBarProgressMeter(str, mixPos, maxPos); +#elif zcad + ZcedSetStatusBarProgressMeter(str, mixPos, maxPos); +#endif + } + + /// + /// 设置状态栏进度条 + /// + public static void SetApplicationStatusBarProgressMeter(int nPos) + { +#if acad + Utils.SetApplicationStatusBarProgressMeter(nPos); +#elif zcad + ZcedSetStatusBarProgressMeterPos(nPos); +#endif + } + + /// + /// 关闭进度条 + /// + public static void RestoreApplicationStatusBar() + { +#if acad + Utils.RestoreApplicationStatusBar(); +#elif zcad + ZcedSetStatusBarProgressMeterStop(); +#endif + } + +#if zcad + private const string kDllName = "zwcad.exe"; + + [DllImport(kDllName, EntryPoint = "?zcedSetStatusBarProgressMeter@@YAHPEB_WHH@Z", + CallingConvention = CallingConvention.Cdecl)] + private static extern void ZcedSetStatusBarProgressMeter( + [MarshalAs(UnmanagedType.LPWStr)] string label, int minPos, int maxPos); + + [DllImport(kDllName, EntryPoint = "?zcedSetStatusBarProgressMeterPos@@YAHH@Z", + CallingConvention = CallingConvention.Cdecl)] + private static extern void ZcedSetStatusBarProgressMeterPos(int position); + + [DllImport(kDllName, EntryPoint = "?zcedSetStatusBarProgressMeterStop@@YAHXZ", + CallingConvention = CallingConvention.Cdecl)] + private static extern void ZcedSetStatusBarProgressMeterStop(); +#endif +} \ No newline at end of file diff --git a/src/Directory.Build.props b/src/Directory.Build.props index f49d549..ecea578 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,8 +1,8 @@ - 0.9.8 - ZCAD支持net472 + 0.9.8.1 + 支持中望cad的进度条 -- Gitee From ce9ff77ceaa65909f0812c2362d7864218d281e7 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 9 Oct 2025 19:04:39 +0800 Subject: [PATCH 449/453] =?UTF-8?q?=E8=A1=A5=E5=85=85=E4=B8=AD=E6=9C=9Bcad?= =?UTF-8?q?=E7=9A=84EntNext=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CADShared/ExtensionMethod/ObjectIdEx.cs | 18 ++++++++++++++++++ src/CADShared/Runtime/PInvokeCad.cs | 3 +++ 2 files changed, 21 insertions(+) diff --git a/src/CADShared/ExtensionMethod/ObjectIdEx.cs b/src/CADShared/ExtensionMethod/ObjectIdEx.cs index ba790c2..0fcf06e 100644 --- a/src/CADShared/ExtensionMethod/ObjectIdEx.cs +++ b/src/CADShared/ExtensionMethod/ObjectIdEx.cs @@ -133,6 +133,24 @@ public static ObjectId GetObjectId(this Database db, Handle? handle) : null; } + /// + /// 获取下一个实体的id + /// + /// id + /// 下一个实体的id + public static ObjectId EntNext(this ObjectId id) + { +#if acad + return Utils.EntNext(id); +#elif zcad + if (!id.ObjectClass.IsDerivedFrom(RXClassEx.Get())) + throw new ArgumentException("id必须是Entity类型"); + PInvokeCad.GetAdsName(out var adsName, id); + PInvokeCad.ZcdbEntNext(adsName, out var nextId); + return nextId; +#endif + } + /// /// id是否有效,未被删除 /// diff --git a/src/CADShared/Runtime/PInvokeCad.cs b/src/CADShared/Runtime/PInvokeCad.cs index 47e4ff1..3113168 100644 --- a/src/CADShared/Runtime/PInvokeCad.cs +++ b/src/CADShared/Runtime/PInvokeCad.cs @@ -23,6 +23,9 @@ public static class PInvokeCad /// [DllImport("ZwDatabase.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "?zcdbGetZdsName@@YA?AW4ErrorStatus@Zcad@@AEAY01_JVZcDbObjectId@@@Z")] public static extern int ZcdbGetZdsName(out AdsName adsName, ObjectId id); + + [DllImport("zwcad.exe", EntryPoint ="zcdbEntNext", CallingConvention = CallingConvention.Cdecl)] + public static extern int ZcdbEntNext(AdsName adsName,out ObjectId id); /// /// GetAdsName -- Gitee From 98030b2c17de7238539694d87b392402871eb9f9 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Tue, 14 Oct 2025 09:52:07 +0800 Subject: [PATCH 450/453] =?UTF-8?q?feat(CADShared):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=20DLL=20=E6=96=87=E4=BB=B6=E5=90=8D=E5=B8=B8=E9=87=8F=E5=B9=B6?= =?UTF-8?q?=E4=BC=98=E5=8C=96=20ZWCAD=20=E8=B0=83=E7=94=A8=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 Constant/DllFileNames.cs 文件定义常用 DLL 名称常量 - 在 DatabaseEx 类中增加 ZWCAD 的 Audit 方法支持- 将 ProgressMeterUtils 中的 ZWCAD 相关 P/Invoke 调用统一使用 DllFileNames.ZwCadExe - 更新 TangentEx 中的 DocGetPScale 方法调用使用 DllFileNames.TchKernalArx - 调整 CADShared.projitems 和 DotSettings 以包含新文件和命名空间配置 - 优化代码格式和注释内容提升可读性 --- src/CADShared/CADShared.projitems | 1 + src/CADShared/CADShared.shproj.DotSettings | 1 + src/CADShared/Constant/DllFileNames.cs | 12 ++++++++ src/CADShared/ExtensionMethod/DatabaseEx.cs | 33 ++++++++++++++++----- src/CADShared/ExtensionMethod/TangentEx.cs | 4 +-- src/CADShared/Runtime/ProgressMeterUtils.cs | 7 ++--- 6 files changed, 44 insertions(+), 14 deletions(-) create mode 100644 src/CADShared/Constant/DllFileNames.cs diff --git a/src/CADShared/CADShared.projitems b/src/CADShared/CADShared.projitems index 5a1d56d..870db27 100644 --- a/src/CADShared/CADShared.projitems +++ b/src/CADShared/CADShared.projitems @@ -29,6 +29,7 @@ + diff --git a/src/CADShared/CADShared.shproj.DotSettings b/src/CADShared/CADShared.shproj.DotSettings index ab0a621..959e918 100644 --- a/src/CADShared/CADShared.shproj.DotSettings +++ b/src/CADShared/CADShared.shproj.DotSettings @@ -1,2 +1,3 @@  + True True \ No newline at end of file diff --git a/src/CADShared/Constant/DllFileNames.cs b/src/CADShared/Constant/DllFileNames.cs new file mode 100644 index 0000000..92bc94a --- /dev/null +++ b/src/CADShared/Constant/DllFileNames.cs @@ -0,0 +1,12 @@ +namespace IFoxCAD.Cad; + +internal static class DllFileNames +{ + public const string TchKernalArx = +#if acad + "tch_kernal.arx"; +#elif zcad + "tch_kernal.zrx"; +#endif + public const string ZwCadExe = "zwcad.exe"; +} \ No newline at end of file diff --git a/src/CADShared/ExtensionMethod/DatabaseEx.cs b/src/CADShared/ExtensionMethod/DatabaseEx.cs index d4b5350..a2cd711 100644 --- a/src/CADShared/ExtensionMethod/DatabaseEx.cs +++ b/src/CADShared/ExtensionMethod/DatabaseEx.cs @@ -5,6 +5,27 @@ /// public static class DatabaseEx { +#if zcad + + /// + /// 审查 + /// + /// 数据库 + /// 修复错误 + /// 输出 + public static void Audit(this Database db, bool fixError, bool cmdEcho) + { + ZcedAudit(db.UnmanagedObject, fixError, cmdEcho); + } + + [DllImport(DllFileNames.ZwCadExe, + EntryPoint = "?zcedAudit@@YA?AW4ErrorStatus@Zcad@@PEAVZcDbDatabase@@_N1@Z", + CallingConvention = CallingConvention.Cdecl)] + private static extern int ZcedAudit(IntPtr pDatabase, + [MarshalAs(UnmanagedType.I1)] bool fixErrors, [MarshalAs(UnmanagedType.I1)] bool cmdEcho); + +#endif + /// /// 打开切换活动数据库 /// @@ -12,7 +33,6 @@ public static class DatabaseEx /// 切换数据库对象 public static SwitchDatabase SwitchDatabase(this Database db) => new(db); - /// /// 保存文件 /// @@ -49,7 +69,8 @@ public static void SaveFile(this Database db, DwgVersion version = DwgVersion.AC if (doc != null) { // 无法把 给这个面板 - doc.SendStringToExecute(saveAsFile == null ? "_qSave\n" : $"_SaveAs\n", false, true, true); + doc.SendStringToExecute(saveAsFile == null ? "_qSave\n" : $"_SaveAs\n", false, true, + true); return; } @@ -118,7 +139,6 @@ public static void SaveFile(this Database db, DwgVersion version = DwgVersion.AC #if acad || gcad db.DxfOut(saveAsFile, 7, true); #endif - #if zcad // 中望这里没有测试 db.DxfOut(saveAsFile, 7, version); #endif @@ -132,7 +152,6 @@ public static void SaveFile(this Database db, DwgVersion version = DwgVersion.AC // 若扩展名和版本号冲突,按照扩展名为准 if (version.IsDxfVersion()) version = DwgVersion.Current; - db.SaveAs(saveAsFile, version); } @@ -152,7 +171,6 @@ private static (bool error, string path) GetOrCreateSaveAsFile(this Database db) // 防止前台关闭了所有文档导致没有Editor,所以使用 MessageBox 发送警告 var fileName = Path.GetFileNameWithoutExtension(file); var fileExt = Path.GetExtension(file); - if (string.IsNullOrWhiteSpace(fileName)) // ReSharper disable once StringLiteralTypo fileName = DateTime.Now.ToString("--yyMMdd--hhmmssffff"); @@ -161,11 +179,10 @@ private static (bool error, string path) GetOrCreateSaveAsFile(this Database db) // 构造函数(fileName)用了不存在的路径进行后台打开,就会出现此问题 // 测试命令 FileNotExist - var dir = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + "\\后台保存出错的文件\\"; - + var dir = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + + "\\后台保存出错的文件\\"; if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); - file = dir + fileName + fileExt; while (File.Exists(file)) { diff --git a/src/CADShared/ExtensionMethod/TangentEx.cs b/src/CADShared/ExtensionMethod/TangentEx.cs index cc986b9..2cef599 100644 --- a/src/CADShared/ExtensionMethod/TangentEx.cs +++ b/src/CADShared/ExtensionMethod/TangentEx.cs @@ -10,13 +10,13 @@ public static class TangentEx /// /// 获取天正绘图比例 /// - /// + /// 比例 public static double TgetPscale() { return DocGetPScale(); } - [DllImport("tch_kernal.arx", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, + [DllImport(DllFileNames.TchKernalArx, CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, EntryPoint = "?DocGetPScale@@YANXZ")] private static extern double DocGetPScale(); diff --git a/src/CADShared/Runtime/ProgressMeterUtils.cs b/src/CADShared/Runtime/ProgressMeterUtils.cs index aeb8862..4234312 100644 --- a/src/CADShared/Runtime/ProgressMeterUtils.cs +++ b/src/CADShared/Runtime/ProgressMeterUtils.cs @@ -42,18 +42,17 @@ public static void RestoreApplicationStatusBar() } #if zcad - private const string kDllName = "zwcad.exe"; - [DllImport(kDllName, EntryPoint = "?zcedSetStatusBarProgressMeter@@YAHPEB_WHH@Z", + [DllImport(DllFileNames.ZwCadExe, EntryPoint = "?zcedSetStatusBarProgressMeter@@YAHPEB_WHH@Z", CallingConvention = CallingConvention.Cdecl)] private static extern void ZcedSetStatusBarProgressMeter( [MarshalAs(UnmanagedType.LPWStr)] string label, int minPos, int maxPos); - [DllImport(kDllName, EntryPoint = "?zcedSetStatusBarProgressMeterPos@@YAHH@Z", + [DllImport(DllFileNames.ZwCadExe, EntryPoint = "?zcedSetStatusBarProgressMeterPos@@YAHH@Z", CallingConvention = CallingConvention.Cdecl)] private static extern void ZcedSetStatusBarProgressMeterPos(int position); - [DllImport(kDllName, EntryPoint = "?zcedSetStatusBarProgressMeterStop@@YAHXZ", + [DllImport(DllFileNames.ZwCadExe, EntryPoint = "?zcedSetStatusBarProgressMeterStop@@YAHXZ", CallingConvention = CallingConvention.Cdecl)] private static extern void ZcedSetStatusBarProgressMeterStop(); #endif -- Gitee From b044c4eea4bb98f48d71381151415108f89714b4 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Tue, 14 Oct 2025 10:53:13 +0800 Subject: [PATCH 451/453] =?UTF-8?q?=E5=88=A0=E9=99=A4=E4=B8=8D=E5=BA=94?= =?UTF-8?q?=E8=AF=A5=E5=87=BA=E7=8E=B0=E7=9A=84=E4=B8=AD=E6=9C=9B=E5=86=85?= =?UTF-8?q?=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CADShared/CADShared.projitems | 1 - src/CADShared/Constant/DllFileNames.cs | 8 ++------ src/CADShared/ExtensionMethod/TangentEx.cs | 24 ---------------------- src/CADShared/Runtime/PInvokeCad.cs | 17 ++++++++++----- 4 files changed, 14 insertions(+), 36 deletions(-) delete mode 100644 src/CADShared/ExtensionMethod/TangentEx.cs diff --git a/src/CADShared/CADShared.projitems b/src/CADShared/CADShared.projitems index 870db27..bd2680b 100644 --- a/src/CADShared/CADShared.projitems +++ b/src/CADShared/CADShared.projitems @@ -73,7 +73,6 @@ - diff --git a/src/CADShared/Constant/DllFileNames.cs b/src/CADShared/Constant/DllFileNames.cs index 92bc94a..81384e0 100644 --- a/src/CADShared/Constant/DllFileNames.cs +++ b/src/CADShared/Constant/DllFileNames.cs @@ -2,11 +2,7 @@ namespace IFoxCAD.Cad; internal static class DllFileNames { - public const string TchKernalArx = -#if acad - "tch_kernal.arx"; -#elif zcad - "tch_kernal.zrx"; -#endif +#if zcad public const string ZwCadExe = "zwcad.exe"; +#endif } \ No newline at end of file diff --git a/src/CADShared/ExtensionMethod/TangentEx.cs b/src/CADShared/ExtensionMethod/TangentEx.cs deleted file mode 100644 index 2cef599..0000000 --- a/src/CADShared/ExtensionMethod/TangentEx.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace IFoxCAD.Cad; - -/// -/// 天正接口 -/// -public static class TangentEx -{ - #region 获取天正比例 - - /// - /// 获取天正绘图比例 - /// - /// 比例 - public static double TgetPscale() - { - return DocGetPScale(); - } - - [DllImport(DllFileNames.TchKernalArx, CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, - EntryPoint = "?DocGetPScale@@YANXZ")] - private static extern double DocGetPScale(); - - #endregion -} \ No newline at end of file diff --git a/src/CADShared/Runtime/PInvokeCad.cs b/src/CADShared/Runtime/PInvokeCad.cs index 3113168..f0b3af7 100644 --- a/src/CADShared/Runtime/PInvokeCad.cs +++ b/src/CADShared/Runtime/PInvokeCad.cs @@ -13,19 +13,26 @@ public static class PInvokeCad /// [DllImport("zwcad.exe", CallingConvention = CallingConvention.Cdecl, EntryPoint = "zcdbEntGet")] public static extern IntPtr ZcdbEntGet(AdsName adsName); + /// /// EntGet /// [DllImport("zwcad.exe", CallingConvention = CallingConvention.Cdecl, EntryPoint = "zcdbEntMod")] public static extern int ZcdbEntMod(IntPtr intPtr); + /// /// GetZdsName /// - [DllImport("ZwDatabase.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "?zcdbGetZdsName@@YA?AW4ErrorStatus@Zcad@@AEAY01_JVZcDbObjectId@@@Z")] + [DllImport("ZwDatabase.dll", CallingConvention = CallingConvention.Cdecl, + EntryPoint = "?zcdbGetZdsName@@YA?AW4ErrorStatus@Zcad@@AEAY01_JVZcDbObjectId@@@Z")] public static extern int ZcdbGetZdsName(out AdsName adsName, ObjectId id); - - [DllImport("zwcad.exe", EntryPoint ="zcdbEntNext", CallingConvention = CallingConvention.Cdecl)] - public static extern int ZcdbEntNext(AdsName adsName,out ObjectId id); + + /// + /// EntNext + /// + [DllImport("zwcad.exe", EntryPoint = "zcdbEntNext", + CallingConvention = CallingConvention.Cdecl)] + public static extern int ZcdbEntNext(AdsName adsName, out ObjectId id); /// /// GetAdsName @@ -33,7 +40,7 @@ public static class PInvokeCad public static int GetAdsName(out AdsName adsName, ObjectId id) { return ZcdbGetZdsName(out adsName, id); - } + } #else /// /// Entget -- Gitee From 5f9a8c6b1aa1ea45518137bbd2a43cafb0dce91f Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 16 Oct 2025 10:16:10 +0800 Subject: [PATCH 452/453] =?UTF-8?q?=E4=BC=98=E5=8C=96EntNext=E7=9A=84?= =?UTF-8?q?=E5=8F=82=E6=95=B0=EF=BC=8C=E5=A2=9E=E5=8A=A0=E8=B7=B3=E8=BF=87?= =?UTF-8?q?=E5=AD=90=E5=AF=B9=E8=B1=A1=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CADShared/ExtensionMethod/ObjectIdEx.cs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/CADShared/ExtensionMethod/ObjectIdEx.cs b/src/CADShared/ExtensionMethod/ObjectIdEx.cs index 0fcf06e..31b23e3 100644 --- a/src/CADShared/ExtensionMethod/ObjectIdEx.cs +++ b/src/CADShared/ExtensionMethod/ObjectIdEx.cs @@ -137,16 +137,31 @@ public static ObjectId GetObjectId(this Database db, Handle? handle) /// 获取下一个实体的id /// /// id + /// 跳过子对象 /// 下一个实体的id - public static ObjectId EntNext(this ObjectId id) + public static ObjectId EntNext(this ObjectId id, bool skipSub = false) { #if acad - return Utils.EntNext(id); + return Utils.EntNext(id, skipSub); #elif zcad if (!id.ObjectClass.IsDerivedFrom(RXClassEx.Get())) throw new ArgumentException("id必须是Entity类型"); PInvokeCad.GetAdsName(out var adsName, id); PInvokeCad.ZcdbEntNext(adsName, out var nextId); + if (skipSub && id.IsOk()) + { + var owner1 = (ObjectId)Env.EntGet(id).FirstOrDefault(e => e.TypeCode == 330).Value; + while (nextId.IsOk()) + { + var owner2 = + (ObjectId)Env.EntGet(nextId).FirstOrDefault(e => e.TypeCode == 330).Value; + if (owner1 == owner2) + break; + PInvokeCad.GetAdsName(out var nextAdsName, nextId); + PInvokeCad.ZcdbEntNext(nextAdsName, out nextId); + } + } + return nextId; #endif } -- Gitee From 12215dadc4bf7df8d19bb000471887830f9e7b66 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 30 Oct 2025 18:13:33 +0800 Subject: [PATCH 453/453] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=B8=8D=E9=A1=BA?= =?UTF-8?q?=E7=95=85=E7=9A=84=E5=86=99=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/TestShared/TestDwgFilerEx.cs | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/tests/TestShared/TestDwgFilerEx.cs b/tests/TestShared/TestDwgFilerEx.cs index 851677b..32a5f78 100644 --- a/tests/TestShared/TestDwgFilerEx.cs +++ b/tests/TestShared/TestDwgFilerEx.cs @@ -7,21 +7,14 @@ public class CmdTestDwgFilerEx public static void CmdTest_DwgFilerEx() { var ed = Env.Editor; - // ed.WriteMessage("\n****测试,序列化图元"); - - var ssPsr = ed.GetSelection(); - if (ssPsr.Status != PromptStatus.OK) + var r1 = ed.GetSelection(); + if (r1.Status != PromptStatus.OK) return; - using DBTrans tr = new(); - var ids = ssPsr.Value.GetObjectIds(); - foreach (var id in ids) + using var tr = new DBTrans(); + var ents = r1.Value.GetEntities(); + foreach (var ent in ents) { - if (!id.IsOk()) - continue; - var ent = tr.GetObject(id); - if (ent is null) - continue; var dwgFiler = new IFoxDwgFiler(); ent.DwgOut(dwgFiler); foreach (var objectId in dwgFiler.SoftPointerIdList) @@ -29,7 +22,7 @@ public static void CmdTest_DwgFilerEx() objectId.ObjectClass.DxfName.Print(); } - ed.WriteMessage(Environment.NewLine + dwgFiler.ToString()); + // ed.WriteMessage(Environment.NewLine + dwgFiler.ToString()); } } -- Gitee
    /// 遍历符号表,执行委托 @@ -318,13 +356,14 @@ internal ObjectId GetRecordFrom(Func> tabl /// 是否打开已删除对象,默认为不打开 /// 是否打开锁定图层对象,默认为不打开 public void ForEach(Action task, - OpenMode openMode = OpenMode.ForRead, - bool checkIdOk = true, - bool openErased = false, - bool openLockedLayer = false) + OpenMode openMode = OpenMode.ForRead, + bool checkIdOk = true, + bool openErased = false, + bool openLockedLayer = false) { - ForEach((a, _, _) => { - task.Invoke(a);//由于此处是委托,所以 DebuggerStepThrough 特性会进入,改用预处理方式避免 + ForEach((a, _, _) => + { + task.Invoke(a); //由于此处是委托,所以 DebuggerStepThrough 特性会进入,改用预处理方式避免 }, openMode, checkIdOk, openErased, openLockedLayer); } @@ -337,14 +376,12 @@ public void ForEach(Action task, /// 是否打开已删除对象,默认为不打开 /// 是否打开锁定图层对象,默认为不打开 public void ForEach(Action task, - OpenMode openMode = OpenMode.ForRead, - bool checkIdOk = true, - bool openErased = false, - bool openLockedLayer = false) + OpenMode openMode = OpenMode.ForRead, + bool checkIdOk = true, + bool openErased = false, + bool openLockedLayer = false) { - ForEach((a, b, _) => { - task.Invoke(a, b); - }, openMode, checkIdOk, openErased, openLockedLayer); + ForEach((a, b, _) => { task.Invoke(a, b); }, openMode, checkIdOk, openErased, openLockedLayer); } /// @@ -357,15 +394,15 @@ public void ForEach(Action task, /// 是否打开锁定图层对象,默认为不打开 [System.Diagnostics.DebuggerStepThrough] public void ForEach(Action task, - OpenMode openMode = OpenMode.ForRead, - bool checkIdOk = true, - bool openErased = false, - bool openLockedLayer = false) + OpenMode openMode = OpenMode.ForRead, + bool checkIdOk = true, + bool openErased = false, + bool openLockedLayer = false) { //if (task == null) // throw new ArgumentNullException(nameof(task)); ArgumentNullEx.ThrowIfNull(task); - LoopState state = new();/*这种方式比Action改Func更友好*/ + LoopState state = new(); /*这种方式比Action改Func更友好*/ int i = 0; foreach (var id in this) { @@ -379,12 +416,14 @@ public void ForEach(Action task, i++; } } -/// + + /// #line default #endregion #region IEnumerable 成员 + [System.Diagnostics.DebuggerStepThrough] public IEnumerator GetEnumerator() { @@ -397,5 +436,6 @@ IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } + #endregion } \ No newline at end of file -- Gitee From 09d1b6cd17d519d3529a08c5d9f794e237ed07a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=97=AA=E4=BA=BA?= <14422236+flash-manmmm@user.noreply.gitee.com> Date: Tue, 14 May 2024 14:50:53 +0000 Subject: [PATCH 291/453] =?UTF-8?q?update=20Test/TestAddEntity.cs.=20?= =?UTF-8?q?=E5=8A=A0=E4=B8=AA=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 闪人 <14422236+flash-manmmm@user.noreply.gitee.com> --- Test/TestAddEntity.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Test/TestAddEntity.cs b/Test/TestAddEntity.cs index d70932c..70cb05f 100644 --- a/Test/TestAddEntity.cs +++ b/Test/TestAddEntity.cs @@ -1,4 +1,4 @@ -namespace Test; +namespace Test; public partial class Test { @@ -80,7 +80,7 @@ public void Test_TypeSpeed() var tt = line1.GetRXClass().DxfName == nameof(Line); }); } - + // 测试延迟刷新 [CommandMethod(nameof(Test_sleeptrans))] public static void Test_sleeptrans() { -- Gitee From b4f2cfa7b7a25c68b966387c8a8298b949ccda51 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Mon, 20 May 2024 16:17:25 +0800 Subject: [PATCH 292/453] =?UTF-8?q?=E5=A2=9E=E5=8A=A0Print=E7=9A=84?= =?UTF-8?q?=E6=98=93=E7=94=A8=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/Runtime/Env.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CADShared/Runtime/Env.cs b/CADShared/Runtime/Env.cs index 967c0b0..eeb53c1 100644 --- a/CADShared/Runtime/Env.cs +++ b/CADShared/Runtime/Env.cs @@ -673,11 +673,12 @@ public static void RemoveTrustedPath(params string[] folders) /// /// 命令行打印,会自动调用对象的toString函数 /// - /// 要打印的对象 - public static void Print(object message) + /// 要打印的对象 + public static T Print(T obj) { // ReSharper disable once ConditionalAccessQualifierIsNonNullableAccordingToAPIContract - Document?.Editor.WriteMessage($"{message}\n"); + Document?.Editor.WriteMessage($"{obj}\n"); + return obj; } /// -- Gitee From 5899440a83345a5f7a87bfd88c6f22e866a133b5 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Mon, 20 May 2024 16:20:02 +0800 Subject: [PATCH 293/453] =?UTF-8?q?=E5=A2=9E=E5=8A=A0print=E7=9A=84?= =?UTF-8?q?=E6=98=93=E7=94=A8=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/Runtime/Env.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CADShared/Runtime/Env.cs b/CADShared/Runtime/Env.cs index eeb53c1..4b89412 100644 --- a/CADShared/Runtime/Env.cs +++ b/CADShared/Runtime/Env.cs @@ -674,7 +674,7 @@ public static void RemoveTrustedPath(params string[] folders) /// 命令行打印,会自动调用对象的toString函数 /// /// 要打印的对象 - public static T Print(T obj) + public static T Print(this T obj) { // ReSharper disable once ConditionalAccessQualifierIsNonNullableAccordingToAPIContract Document?.Editor.WriteMessage($"{obj}\n"); -- Gitee From 69af3d4a22820b83a98201e448492fdce5cd6336 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Wed, 5 Jun 2024 11:13:54 +0800 Subject: [PATCH 294/453] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=94=B1=E4=BA=8ERes?= =?UTF-8?q?ultBuffer=E4=B8=BA=E7=A9=BA=E5=AF=BC=E8=87=B4=E9=9A=90=E5=BC=8F?= =?UTF-8?q?=E8=BD=AC=E6=8D=A2=E5=A4=B1=E8=B4=A5=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/ResultData/XDataList.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CADShared/ResultData/XDataList.cs b/CADShared/ResultData/XDataList.cs index b238950..11f9754 100644 --- a/CADShared/ResultData/XDataList.cs +++ b/CADShared/ResultData/XDataList.cs @@ -138,7 +138,7 @@ private void RangeTask(string appName, Action action /// ResultBuffer 隐式转换到 XDataList /// /// ResultBuffer 实例 - public static implicit operator XDataList(ResultBuffer buffer) => new(buffer.AsArray()); + public static implicit operator XDataList(ResultBuffer? buffer) => new(buffer?.AsArray() ?? []); /// /// XDataList 隐式转换到 TypedValue 数组 -- Gitee From e2bdf7cc653f381b63ebc422fcea2a7520a406b1 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Wed, 5 Jun 2024 15:39:43 +0800 Subject: [PATCH 295/453] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=B1=9E=E6=80=A7?= =?UTF-8?q?=E5=9D=97=E6=96=87=E5=AD=97=E5=AF=B9=E9=BD=90=E6=96=B9=E5=BC=8F?= =?UTF-8?q?=E4=B8=8D=E4=B8=BA=E9=BB=98=E8=AE=A4=E6=97=B6=E5=81=8F=E7=A7=BB?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/ExtensionMethod/Entity/BlockReferenceEx.cs | 1 + CADShared/ExtensionMethod/SymbolTableRecordEx.cs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CADShared/ExtensionMethod/Entity/BlockReferenceEx.cs b/CADShared/ExtensionMethod/Entity/BlockReferenceEx.cs index a7f0974..a8d3402 100644 --- a/CADShared/ExtensionMethod/Entity/BlockReferenceEx.cs +++ b/CADShared/ExtensionMethod/Entity/BlockReferenceEx.cs @@ -149,6 +149,7 @@ public static void ChangeBlockAttribute(this BlockReference blockReference, Dict if (propertyNameValues.TryGetValue(att.Tag, out var value)) { att.TextString = value; + att.AdjustAlignment(blockReference.Database); } } } diff --git a/CADShared/ExtensionMethod/SymbolTableRecordEx.cs b/CADShared/ExtensionMethod/SymbolTableRecordEx.cs index f330df3..43b8043 100644 --- a/CADShared/ExtensionMethod/SymbolTableRecordEx.cs +++ b/CADShared/ExtensionMethod/SymbolTableRecordEx.cs @@ -284,7 +284,6 @@ public static ObjectId InsertBlock(this BlockTableRecord blockTableRecord, attref.SetDatabaseDefaults(); attref.SetAttributeFromBlock(attdef, blockRef.BlockTransform); attref.Position = attdef.Position.TransformBy(blockRef.BlockTransform); - attref.AdjustAlignment(tr.Database); if (atts is not null && atts.TryGetValue(attdef.Tag, out string str)) { attref.TextString = str; @@ -295,6 +294,7 @@ public static ObjectId InsertBlock(this BlockTableRecord blockTableRecord, blockRef.AttributeCollection.AppendAttribute(attref); tr.Transaction.AddNewlyCreatedDBObject(attref, true); + attref.AdjustAlignment(tr.Database); } return objectId; -- Gitee From 028aabf58232b3999e8d33000084a11e5f1bfb6a Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Wed, 12 Jun 2024 09:27:38 +0800 Subject: [PATCH 296/453] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=B8=80=E4=BA=9B?= =?UTF-8?q?=E5=9F=BA=E7=A1=80=E7=B1=BB=E5=9E=8B=E7=9A=84=E6=89=A9=E5=B1=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/CADShared.projitems | 1 + CADShared/ExtensionMethod/BaseEx.cs | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 CADShared/ExtensionMethod/BaseEx.cs diff --git a/CADShared/CADShared.projitems b/CADShared/CADShared.projitems index ff89251..c954833 100644 --- a/CADShared/CADShared.projitems +++ b/CADShared/CADShared.projitems @@ -19,6 +19,7 @@ + diff --git a/CADShared/ExtensionMethod/BaseEx.cs b/CADShared/ExtensionMethod/BaseEx.cs new file mode 100644 index 0000000..51766f3 --- /dev/null +++ b/CADShared/ExtensionMethod/BaseEx.cs @@ -0,0 +1,17 @@ +namespace IFoxCAD.Cad; + +/// +/// 基础扩展 +/// +public static class BaseEx +{ + /// + /// 判断图层名是否合法 + /// + /// 图层名 + /// 是则返回true + public static bool IsLegalLayerName(this string layerName) + { + return !string.IsNullOrWhiteSpace(layerName) && SymbolUtilityServices.RepairSymbolName(layerName, true) == layerName; + } +} \ No newline at end of file -- Gitee From c42f60c2a99186087ad62f209474cc2cbdb5501f Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Wed, 12 Jun 2024 16:52:39 +0800 Subject: [PATCH 297/453] =?UTF-8?q?jig=E9=BB=98=E8=AE=A4=E7=BB=99=E4=B8=80?= =?UTF-8?q?=E4=B8=AAoptions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/ExtensionMethod/Jig/JigEx.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/CADShared/ExtensionMethod/Jig/JigEx.cs b/CADShared/ExtensionMethod/Jig/JigEx.cs index 0d451d3..ac3ebdc 100644 --- a/CADShared/ExtensionMethod/Jig/JigEx.cs +++ b/CADShared/ExtensionMethod/Jig/JigEx.cs @@ -68,6 +68,7 @@ bool SystemVariablesOrthomode // 正交修改还原 { _drawEntitys = new(); DimensionEntitys = new(); + _options = JigPointOptions(); } /// -- Gitee From c1a20a4abb0c90cccbfef0962dfcaa6963f3e367 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 13 Jun 2024 14:37:00 +0800 Subject: [PATCH 298/453] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dzoom=E5=9C=A8plan?= =?UTF-8?q?=E8=B0=83=E6=95=B4=E7=9A=84=E6=83=85=E5=86=B5=E4=B8=8B=E4=BD=8D?= =?UTF-8?q?=E7=BD=AE=E4=B8=8D=E6=AD=A3=E7=A1=AE=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/ExtensionMethod/EditorEx.cs | 111 +++++++++++++++----------- 1 file changed, 66 insertions(+), 45 deletions(-) diff --git a/CADShared/ExtensionMethod/EditorEx.cs b/CADShared/ExtensionMethod/EditorEx.cs index 9219c6b..0b874c5 100644 --- a/CADShared/ExtensionMethod/EditorEx.cs +++ b/CADShared/ExtensionMethod/EditorEx.cs @@ -6,6 +6,7 @@ namespace IFoxCAD.Cad; public static class EditorEx { #region 选择集 + /// /// 选择穿过一个点的对象 /// @@ -14,7 +15,7 @@ public static class EditorEx /// 过滤器 /// 选择集结果类 public static PromptSelectionResult SelectAtPoint(this Editor editor, Point3d point, - SelectionFilter? filter = default) + SelectionFilter? filter = default) { return editor.SelectCrossingWindow(point, point, filter); } @@ -31,22 +32,22 @@ public static SelectionSet SelectByLineWeight(this Editor editor, LineWeight lin var lays = DBTrans.Top.LayerTable - .GetRecords() - .Where(ltr => ltr.LineWeight == lineWeight) - .Select(ltr => ltr.Name) - .ToArray(); + .GetRecords() + .Where(ltr => ltr.LineWeight == lineWeight) + .Select(ltr => ltr.Name) + .ToArray(); if (lays.Length > 0) { filter = new OpOr { - filter, - new OpAnd - { - { 8, string.Join(",", lays) }, - { 370, LineWeight.ByLayer } - } + filter, + new OpAnd + { + { 8, string.Join(",", lays) }, + { 370, LineWeight.ByLayer } + } }; } @@ -67,10 +68,10 @@ public static SelectionSet SelectByLineWeight(this Editor editor, LineWeight lin /// /// public static PromptSelectionResult SSGet(this Editor editor, - string? mode = null, - SelectionFilter? filter = null, - (string add, string remove)? messages = null, - Dictionary? keywords = null) + string? mode = null, + SelectionFilter? filter = null, + (string add, string remove)? messages = null, + Dictionary? keywords = null) { PromptSelectionOptions pso = new(); if (mode is not null) @@ -87,6 +88,7 @@ public static PromptSelectionResult SSGet(this Editor editor, pso.AllowSubSelections = mode.Contains("-A"); pso.ForceSubSelections = mode.Contains("-F"); } + if (messages is not null) { pso.MessageForAdding = messages.Value.add; @@ -100,14 +102,16 @@ public static PromptSelectionResult SSGet(this Editor editor, if (pso.MessageForRemoval is null) pso.MessageForAdding = "选择对象"; - var str = keywords.Keys.Select(key => { + var str = keywords.Keys.Select(key => + { keywords.TryGetValue(key, out (string, Action) value); return $"{value.Item1}({key})"; }); pso.MessageForAdding += $" [{string.Join("/", str)}]"; - pso.KeywordInput += (_, e) => { + pso.KeywordInput += (_, e) => + { if (keywords.TryGetValue(e.Input, out var value)) value.Item2.Invoke(); }; @@ -182,6 +186,7 @@ public static void SsgetAddKeys(this PromptSelectionOptions pso, else tmp.Add(item, value); } + dicActions.Remove(key); } @@ -213,7 +218,7 @@ public static void SsgetAddKeys(this PromptSelectionOptions pso, var keySplitS = item.Key.Split(new string[] { ",", "|" }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < keySplitS.Length; i += 2) pso.Keywords.Add(keySplitS[i], keySplitS[i], - keySplitS[i + 1] + "(" + keySplitS[i] + ")"); + keySplitS[i + 1] + "(" + keySplitS[i] + ")"); } // 回调的时候我想用Dict的O(1)索引, @@ -228,16 +233,10 @@ public static void SsgetAddKeys(this PromptSelectionOptions pso, // 从选择集命令中显示关键字 pso.MessageForAdding = keyWords.GetDisplayString(true); // 关键字回调事件 ssget关键字 - pso.KeywordInput += (_, e) => { - dicActions[e.Input].Invoke(); - }; + pso.KeywordInput += (_, e) => { dicActions[e.Input].Invoke(); }; } - - - - // #region 即时选择样板 // /// // /// 即时选择,框选更新关键字 @@ -332,6 +331,7 @@ public static void SsgetAddKeys(this PromptSelectionOptions pso, // throw new ArgumentException("XuError"); // } // #endregion + #endregion #region Info @@ -470,8 +470,8 @@ public static void WriteMessage(string format, params object[] args) public static bool HasEditor() { return Acap.DocumentManager.MdiActiveDocument is not null - && Acap.DocumentManager.Count != 0 - && Acap.DocumentManager.MdiActiveDocument.Editor is not null; + && Acap.DocumentManager.Count != 0 + && Acap.DocumentManager.MdiActiveDocument.Editor is not null; } /// @@ -481,7 +481,7 @@ public static bool HasEditor() public static bool Acceptable() { return HasEditor() - && !Acap.DocumentManager.MdiActiveDocument.Editor.IsDragging; + && !Acap.DocumentManager.MdiActiveDocument.Editor.IsDragging; } #endregion Info @@ -575,6 +575,7 @@ public static void DrawCircles(this Editor editor, IEnumerable pnts, sh rlst.AddRange(GetLines(tpnts, true)); } + editor.DrawVectors(new(rlst.ToArray()), editor.CurrentUserCoordinateSystem); } @@ -597,6 +598,7 @@ public static void DrawCircle(this Editor editor, Point2d pnt, short colorIndex, editor.DrawVectors(pnts, colorIndex, true); } + /// /// 根据点表绘制矢量线段(每两点为一条线段的起始点和终止点) /// @@ -605,7 +607,7 @@ public static void DrawCircle(this Editor editor, Point2d pnt, short colorIndex, /// CAD颜色索引;默认:1为红色 /// 是否高亮显示;为高亮显示,默认:为不高亮显示 public static void DrawLineVectors(this Editor editor, IEnumerable points, int colorIndex = 1, - bool drawHighlighted = false) + bool drawHighlighted = false) { Point3d endPoint1, endPoint2; using var itor = points.GetEnumerator(); @@ -617,6 +619,7 @@ public static void DrawLineVectors(this Editor editor, IEnumerable poin editor.DrawVector(endPoint1, endPoint2, colorIndex, drawHighlighted); } } + /// /// 根据点表绘制首尾相连的矢量 /// @@ -626,7 +629,7 @@ public static void DrawLineVectors(this Editor editor, IEnumerable poin /// 是否闭合; 为闭合,默认: 为不闭合 /// 是否高亮显示;为高亮显示,默认:为不高亮显示 public static void DrawEndToEndVectors(this Editor editor, IEnumerable points, int colorIndex = 1, - bool isclose = false, bool drawHighlighted = false) + bool isclose = false, bool drawHighlighted = false) { using var itor = points.GetEnumerator(); if (!points.Any() || !itor.MoveNext()) return; @@ -637,9 +640,11 @@ public static void DrawEndToEndVectors(this Editor editor, IEnumerable editor.DrawVector(endPoint1, endPoint2, colorIndex, drawHighlighted); endPoint1 = endPoint2; } + if (isclose) editor.DrawVector(endPoint2, firstEndPoint, colorIndex, drawHighlighted); } + #endregion #region 矩阵 @@ -717,6 +722,7 @@ public static Matrix3d GetMatrixFromMDcsToPDcs(this Editor editor) throw new Exception("Aucun fenêtre active...ErrorStatus.InvalidInput"); } } + if (vp == null) return mat; @@ -757,7 +763,7 @@ public static Matrix3d GetMatrix(this Editor editor, CoordinateSystemCode from, (CoordinateSystemCode.MDcs, CoordinateSystemCode.PDcs) => editor.GetMatrixFromMDcsToPDcs(), (CoordinateSystemCode.PDcs, CoordinateSystemCode.MDcs) => editor.GetMatrixFromPDcsToMDcs(), (CoordinateSystemCode.PDcs, CoordinateSystemCode.Wcs or CoordinateSystemCode.Ucs) - or (CoordinateSystemCode.Wcs or CoordinateSystemCode.Ucs, CoordinateSystemCode.PDcs) => throw new Exception("To be used only with DCS...ErrorStatus.InvalidInput"), + or (CoordinateSystemCode.Wcs or CoordinateSystemCode.Ucs, CoordinateSystemCode.PDcs) => throw new Exception("To be used only with DCS...ErrorStatus.InvalidInput"), (_, _) => Matrix3d.Identity }; } @@ -767,7 +773,7 @@ public static Matrix3d GetMatrix(this Editor editor, CoordinateSystemCode from, #region 缩放 // todo 暂时先屏蔽这个又臭又长的代码,待搞明白为什么都这么写之后再说 -#if false +#if false /// /// 缩放窗口范围 /// @@ -828,16 +834,16 @@ public static void ZoomWindow(this Editor ed, Extents3d ext) /// 按范围缩放 /// /// 命令行对象 - /// 中心点 + /// 中心点 /// 窗口宽 /// 窗口高 - public static void Zoom(this Editor ed, Point3d CenPt, double width, double height) + public static void Zoom(this Editor ed, Point3d cenPt, double width, double height) { - using ViewTableRecord view = ed.GetCurrentView(); - view.Width = width; - view.Height = height; - view.CenterPoint = new Point2d(CenPt.X, CenPt.Y); - ed.SetCurrentView(view);// 更新当前视图 + using var vtr = ed.GetCurrentView(); + vtr.Width = width; + vtr.Height = height; + vtr.CenterPoint = (cenPt.Point2d() - vtr.Target.GetAsVector().Convert2d()).RotateBy(vtr.ViewTwist, Point2d.Origin); + ed.SetCurrentView(vtr); // 更新当前视图 } /// @@ -867,7 +873,7 @@ public static void ZoomWindow(this Editor ed, Point3d lpt, Point3d rpt, double o /// public static Extents3d? GetValidExtents3d(this Database db, double extention = 1e-6) { - db.UpdateExt(true);// 更新当前模型空间的范围 + db.UpdateExt(true); // 更新当前模型空间的范围 var ve = new Vector3d(extention, extention, extention); // 数据库没有图元的时候,min是大,max是小,导致新建出错 // 数据如下: @@ -909,7 +915,7 @@ public static void ZoomObject(this Editor ed, Entity ent, double offsetDist = 0. ed.ZoomWindow(ext.MinPoint, ext.MaxPoint, offsetDist); } -#endregion + #endregion #region Get交互类 @@ -981,6 +987,7 @@ public static PromptResult GetString(this Editor ed, string Message, string Defa #endregion #region 执行lisp + [DllImport("accore.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "acedInvoke")] static extern int AcedInvoke(IntPtr args, out IntPtr result); @@ -988,12 +995,13 @@ public static PromptResult GetString(this Editor ed, string Message, string Defa // 高版本此接口不能使用lisp(command "xx"),但是可以直接在自动运行接口上 [DllImport("accore.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, EntryPoint = "?acedEvaluateLisp@@YAHPEB_WAEAPEAUresbuf@@@Z")] - [System.Security.SuppressUnmanagedCodeSecurity]// 初始化默认值 + [System.Security.SuppressUnmanagedCodeSecurity] // 初始化默认值 static extern int AcedEvaluateLisp(string lispLine, out IntPtr result); [DllImport("accore.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ads_queueexpr")] static extern int Ads_queueexpr(string strExpr); + /// /// 执行lisp的方式枚举 /// @@ -1004,10 +1012,12 @@ public enum RunLispFlag : byte /// AdsQueueexpr /// AdsQueueexpr = 1, + /// /// AcedEvaluateLisp /// AcedEvaluateLisp = 2, + /// /// SendStringToExecute /// @@ -1048,23 +1058,28 @@ public enum RunLispFlag : byte // 0x02 自执行发送lisp都是异步,用来发送 含有(command)的lisp的 _ = Ads_queueexpr(lispCode + "\n"); } + if ((flag & RunLispFlag.AcedEvaluateLisp) == RunLispFlag.AcedEvaluateLisp) { _ = AcedEvaluateLisp(lispCode, out IntPtr rb); if (rb != IntPtr.Zero) return (ResultBuffer)DisposableWrapper.Create(typeof(ResultBuffer), rb, true); } + if ((flag & RunLispFlag.SendStringToExecute) == RunLispFlag.SendStringToExecute) { var dm = Acap.DocumentManager; var doc = dm.MdiActiveDocument; doc?.SendStringToExecute(lispCode + "\n", false, false, false); } + return null; } + #endregion #region Export + /// /// 输出WMF
    /// 此函数不适用于后台 @@ -1075,7 +1090,7 @@ public enum RunLispFlag : byte /// 是否清空选择集 /// public static void ComExportWMF(this Editor editor, string saveFile, - ObjectId[]? ids = null, bool wmfSetDel = false) + ObjectId[]? ids = null, bool wmfSetDel = false) { if (string.IsNullOrWhiteSpace(saveFile)) throw new ArgumentNullException(nameof(saveFile)); @@ -1093,13 +1108,14 @@ public static void ComExportWMF(this Editor editor, string saveFile, // 因此此处netAPI进行选择,它就能读取当前选择集缓冲区的对象 if (ids == null || ids.Length == 0) { - var psr = editor.SelectImplied();// 预选 + var psr = editor.SelectImplied(); // 预选 if (psr.Status != PromptStatus.OK) - psr = editor.GetSelection();// 手选 + psr = editor.GetSelection(); // 手选 if (psr.Status != PromptStatus.OK) return; ids = psr.Value.GetObjectIds(); } + editor.SetImpliedSelection(ids); #if zcad @@ -1116,9 +1132,11 @@ public static void ComExportWMF(this Editor editor, string saveFile, if (wmfSetDel) wmfSet.Delete(); } + #endregion #region JigEx + /// /// jig前的准备工作,使图元暗显 /// @@ -1128,6 +1146,7 @@ public static void PrepareForJig(this Editor ed, params Entity[] ents) { ed.PrepareForJig(ents.ToList()); } + /// /// jig前的准备工作,使图元暗显 /// @@ -1147,6 +1166,7 @@ public static void PrepareForJig(this Editor ed, IEnumerable ents) ent.Draw(); } } + ed.Redraw(); foreach (var kvp in dic) { @@ -1157,6 +1177,7 @@ public static void PrepareForJig(this Editor ed, IEnumerable ents) } } } + #endregion #region Extension -- Gitee From 9f6e507fa582d9991aa10ac4bc68f2db91141ec3 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Fri, 14 Jun 2024 18:20:10 +0800 Subject: [PATCH 299/453] =?UTF-8?q?=E6=97=A5=E5=B8=B8=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/CADShared.projitems | 1 + CADShared/ExtensionMethod/IFoxUtils.cs | 99 ++++++++++++++++++++++++++ 2 files changed, 100 insertions(+) create mode 100644 CADShared/ExtensionMethod/IFoxUtils.cs diff --git a/CADShared/CADShared.projitems b/CADShared/CADShared.projitems index c954833..9ecbbab 100644 --- a/CADShared/CADShared.projitems +++ b/CADShared/CADShared.projitems @@ -45,6 +45,7 @@ + diff --git a/CADShared/ExtensionMethod/IFoxUtils.cs b/CADShared/ExtensionMethod/IFoxUtils.cs new file mode 100644 index 0000000..7a90b57 --- /dev/null +++ b/CADShared/ExtensionMethod/IFoxUtils.cs @@ -0,0 +1,99 @@ +namespace IFoxCAD.Cad; + +/// +/// 工具类 +/// +// ReSharper disable once InconsistentNaming +public static class IFoxUtils +{ +#if acad + /// + /// 刷新图层状态,在修改图层的锁定或冻结状态后使用 + /// + /// 图层id集合 + public static void RegenLayers(IEnumerable objectIds) + { + var type = Acaop.Version.Major >= 21 + ? Assembly.Load("accoremgd")?.GetType("Autodesk.AutoCAD.Internal.CoreLayerUtilities") + : Assembly.Load("acmgd")?.GetType("Autodesk.AutoCAD.Internal.LayerUtilities"); + var mi = type?.GetMethods().FirstOrDefault(e => e.Name == "RegenLayers"); + var pi = type?.GetProperties().FirstOrDefault(e => e.Name == "RegenPending"); + var regenPending = (int)(pi?.GetValue(null) ?? 0); + mi?.Invoke(null, new object[] { objectIds.ToArray(), regenPending }); + } + + /// + /// 发送气泡通知 + /// + /// 显示的秒数,范围1-10为相应秒数,0为常显 + /// 标题 + /// 内容1 + /// 图标样式 + /// 链接 + /// 链接地址 + /// 内容2 + public static void ShowBubbleWindow(int second, string title, string text, IconType iconType = IconType.None, string? hyperText = null, string? hyperLink = null, string? text2 = null) + { + TrayItem? trayItem = null; + const string name = "IFox"; + var num = Acap.StatusBar.TrayItems.Count; + for (var i = 0; i < num; i++) + { + var ti = Acap.StatusBar.TrayItems[i]; + if (ti.ToolTipText != name) continue; + trayItem = ti; + break; + } + + if (trayItem == null) + { + trayItem = new() + { + ToolTipText = name, + Visible = true, + }; + Acap.StatusBar.TrayItems.Add(trayItem); + Acap.StatusBar.Update(); + } + + if (second <= 0) second = 0; + else if (second % 10 == 0) second = 10; + else second %= 10; + Acaop.SetSystemVariable("TrayTimeOut", second); + var tibw = new TrayItemBubbleWindow + { + IconType = iconType, + Title = title, + Text = text, + HyperText = hyperText, + HyperLink = hyperLink, + Text2 = text2 + }; + Acaop.SetSystemVariable("TRAYICONS", 1); + Acaop.SetSystemVariable("TRAYNOTIFY", 1); + trayItem.Visible = true; + trayItem.ShowBubbleWindow(tibw); + } + + /// + /// 否决双击事件本身的后续操作,在双击事件中使用 + /// + public static void VetoMouseDoubleClickEvent() + { + const string key = "DBLCLKEDIT"; + var value = Acaop.GetSystemVariable(key); + Acaop.SetSystemVariable(key, 0); + IdleAction.Add(() => Acaop.SetSystemVariable(key, value)); + } + + /// + /// 获取透明度 + /// + /// cad特性栏透明度值,范围0-100 + /// cad透明度值 + public static Transparency CreateTransparency(int value) + { + return new Transparency(Convert.ToByte(Math.Floor((100 - value) * 2.55))); + } +#endif +} \ No newline at end of file -- Gitee From 002241942ba69a98847181352c6da8f429be7e96 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Tue, 16 Jul 2024 23:46:22 +0800 Subject: [PATCH 300/453] refactor(block-controller): optimize block operations and remove deprecated code - Implement improvements in the BlockController for better functionality.- Remove unused code and dependencies to clean up the project. - Update related view and view model components for block operations.- Refactor command methods and palette set management. --- CADShared/ExtensionMethod/SingleKeyWordHook.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CADShared/ExtensionMethod/SingleKeyWordHook.cs b/CADShared/ExtensionMethod/SingleKeyWordHook.cs index c18a916..d231e51 100644 --- a/CADShared/ExtensionMethod/SingleKeyWordHook.cs +++ b/CADShared/ExtensionMethod/SingleKeyWordHook.cs @@ -136,7 +136,7 @@ private void Acap_PreTranslateMessage(object sender, PreTranslateMessageEventArg if (!_working || e.Message.message != 256) return; var tempKey = IntPtr.Size == 4 ? (Keys)e.Message.wParam.ToInt32() : (Keys)e.Message.wParam.ToInt64(); bool contains = _keyWords.Contains(tempKey); - if (contains || tempKey == Keys.ProcessKey) + if (contains) { // 标记为true,表示此按键已经被处理,Windows不会再进行处理 if (_workType != SingleKeyWordWorkType.ENTER) -- Gitee From 26c16f3ed704afebc2efea20a96a76dbac0b97a7 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Wed, 31 Jul 2024 14:27:56 +0800 Subject: [PATCH 301/453] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=95=BF=E5=BA=A6?= =?UTF-8?q?=E4=B8=BA0=E7=9A=84id=E5=88=97=E8=A1=A8ToCollection=E6=97=B6?= =?UTF-8?q?=E4=BC=9A=E6=8A=A5=E9=94=99=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/ExtensionMethod/CollectionEx.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CADShared/ExtensionMethod/CollectionEx.cs b/CADShared/ExtensionMethod/CollectionEx.cs index f0b8cda..01e2801 100644 --- a/CADShared/ExtensionMethod/CollectionEx.cs +++ b/CADShared/ExtensionMethod/CollectionEx.cs @@ -13,7 +13,9 @@ public static class CollectionEx [DebuggerStepThrough] public static ObjectIdCollection ToCollection(this IEnumerable ids) { - return new ObjectIdCollection(ids.ToArray()); + var objectIds = ids as ObjectId[] ?? ids.ToArray(); + // new ObjectIdCollection时填长度为0的数组会报错 + return objectIds.Length == 0 ? new ObjectIdCollection() : new ObjectIdCollection(objectIds); } -- Gitee From 9f9e0e9191001590db9aaa2f81be84c8b30bddaf Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 15 Aug 2024 21:16:21 +0800 Subject: [PATCH 302/453] =?UTF-8?q?=E6=97=A5=E5=B8=B8=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/CADShared.projitems | 1 + 1 file changed, 1 insertion(+) diff --git a/CADShared/CADShared.projitems b/CADShared/CADShared.projitems index 9ecbbab..3ee17f8 100644 --- a/CADShared/CADShared.projitems +++ b/CADShared/CADShared.projitems @@ -64,6 +64,7 @@ + -- Gitee From 59ce2c3858df68feb47718e9b27b5aecf7200470 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 15 Aug 2024 21:16:37 +0800 Subject: [PATCH 303/453] =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E5=8F=98=E9=87=8F?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/Runtime/SystemVariableManager.cs | 90 ++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 CADShared/Runtime/SystemVariableManager.cs diff --git a/CADShared/Runtime/SystemVariableManager.cs b/CADShared/Runtime/SystemVariableManager.cs new file mode 100644 index 0000000..69e6c4b --- /dev/null +++ b/CADShared/Runtime/SystemVariableManager.cs @@ -0,0 +1,90 @@ +namespace IFoxCAD.Cad; + +/// +/// 系统变量管理器 +/// +public class SystemVariableManager +{ + #region C + + /// + /// 存在活动命令 + /// + public static bool CmdActive => Convert.ToBoolean(Acap.GetSystemVariable(nameof(CmdActive))); + + /// + /// 当前的命令 + /// + public static string CmdNames => Acap.GetSystemVariable(nameof(CmdNames)).ToString(); + + + public static short CVPort + { + get => Convert.ToInt16(Acap.GetSystemVariable(nameof(CVPort))); + set => Acap.SetSystemVariable(nameof(CVPort), value); + } + + #endregion + + #region D + + /// + /// 是否开启双击 + /// + public static bool DblClick + { + get => Convert.ToBoolean(Acap.GetSystemVariable(nameof(DblClick))); + set => Acap.SetSystemVariable(nameof(DblClick), Convert.ToInt32(value)); + } + + public static int DynMode + { + get => Convert.ToInt32(Acap.GetSystemVariable(nameof(DynMode))); + set => Acap.SetSystemVariable(nameof(DynMode), value); + } + + public static bool DynPrompt + { + get => Convert.ToBoolean(Acap.GetSystemVariable(nameof(DynPrompt))); + set => Acap.SetSystemVariable(nameof(DynPrompt), Convert.ToInt32(value)); + } + + #endregion + + #region H + + /// + /// 填充比例 + /// + public static double HPScale + { + get => Convert.ToDouble(Acap.GetSystemVariable(nameof(HPScale))); + set + { + if (value <= 0) + throw new ArgumentOutOfRangeException(nameof(HPScale), "HPScale必须大于0"); + Acap.SetSystemVariable(nameof(HPScale), value); + } + } + + #endregion + + #region P + + /// + /// 允许先选择后执行 + /// + public static bool PickFirst + { + get => Convert.ToBoolean(Acap.GetSystemVariable(nameof(PickFirst))); + set => Acap.SetSystemVariable(nameof(PickFirst), Convert.ToInt32(value)); + } + + #endregion + + #region T + + public static Point3d Target => (Point3d)Acap.GetSystemVariable(nameof(Target)); + + #endregion +} \ No newline at end of file -- Gitee From 1870bcca991f358a30335037d8c77d660515a765 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 15 Aug 2024 21:17:47 +0800 Subject: [PATCH 304/453] =?UTF-8?q?=E5=88=A0=E9=99=A4JigEx=E4=B8=8D?= =?UTF-8?q?=E5=BF=85=E8=A6=81=E7=9A=84=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/ExtensionMethod/Jig/JigEx.cs | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/CADShared/ExtensionMethod/Jig/JigEx.cs b/CADShared/ExtensionMethod/Jig/JigEx.cs index ac3ebdc..fc600d4 100644 --- a/CADShared/ExtensionMethod/Jig/JigEx.cs +++ b/CADShared/ExtensionMethod/Jig/JigEx.cs @@ -47,6 +47,7 @@ public class JigEx : DrawJig, IDisposable private bool _worldDrawFlag; // 20220503 private bool _systemVariablesOrthomode; + bool SystemVariablesOrthomode // 正交修改还原 { get => _systemVariablesOrthomode; @@ -291,26 +292,6 @@ public PromptResult Drag() return dr; } - /// - /// 最后一次的图元加入数据库 - /// - /// 加入此空间 - /// 不生成的图元用于排除,例如刷新时候的提示文字 - /// 加入数据库的id集合 - public IEnumerable? AddEntityToMsPs(BlockTableRecord btrOfAddEntitySpace, - IEnumerable? removeEntity = null) - { - // 内部用 _drawEntitys 外部用 Entitys,减少一层转换 - if (_drawEntitys.Count == 0) - return null; - - IEnumerable es = _drawEntitys; - if (removeEntity != null) - es = es.Except(removeEntity); // 差集 - - return btrOfAddEntitySpace.AddEntity(es); - } - #region 配置 -- Gitee From f0528c44cd1d6a359cfbc95a37ef1476fb7a4631 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sat, 17 Aug 2024 13:07:55 +0800 Subject: [PATCH 305/453] =?UTF-8?q?=E8=A1=A5=E5=85=85PE=E5=86=85=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/Basal/Win/Enums.cs | 1073 ++++++++++++++++ CADShared/Basal/Win/WindowsAPI.cs | 660 ++++++++++ CADShared/CADShared.projitems | 6 + CADShared/PE/AcadPeInfo.cs | 389 ++++++ CADShared/PE/DBmod.cs | 120 ++ CADShared/PE/PostCmd.cs | 237 ++++ CADShared/PE/ProgramPE.cs | 1576 ++++++++++++++++++++++++ IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj | 1 + 8 files changed, 4062 insertions(+) create mode 100644 CADShared/Basal/Win/Enums.cs create mode 100644 CADShared/Basal/Win/WindowsAPI.cs create mode 100644 CADShared/PE/AcadPeInfo.cs create mode 100644 CADShared/PE/DBmod.cs create mode 100644 CADShared/PE/PostCmd.cs create mode 100644 CADShared/PE/ProgramPE.cs diff --git a/CADShared/Basal/Win/Enums.cs b/CADShared/Basal/Win/Enums.cs new file mode 100644 index 0000000..059f92c --- /dev/null +++ b/CADShared/Basal/Win/Enums.cs @@ -0,0 +1,1073 @@ +#pragma warning disable CS1591 // 缺少对公共可见类型或成员的 XML 注释 +#if true +namespace IFoxCAD.Basal; + +// https://blog.csdn.net/qq_43812868/article/details/108587936 +[Flags] +public enum TH32CS : uint +{ + /// + /// 原因在于如果不采用改参数的话,有可能快照会占用整个堆的空间 + /// + TH32CS_SNAPNOHEAPS = 0x40000000, + /// + /// 声明快照句柄是可继承的 + /// + TH32CS_INHERIT = 0x80000000, + /// + /// 在快照中包含在th32ProcessID中指定的进程的所有的堆 + /// + TH32CS_SNAPHEAPLIST = 0x00000001, + /// + /// 在快照中包含系统中所有的进程 + /// + TH32CS_SNAPPROCESS = 0x00000002, + /// + /// 在快照中包含系统中所有的线程 + /// + TH32CS_SNAPTHREAD = 0x00000004, + /// + /// 在快照中包含在th32ProcessID中指定的进程的所有的模块 + /// + TH32CS_SNAPMODULE = 0x00000008, + /// + /// 在快照中包含系统中所有的进程和线程 + /// + TH32CS_SNAPALL = TH32CS_SNAPHEAPLIST | TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD | TH32CS_SNAPMODULE, +} + +/// +/// 设置的钩子类型 +/// +[Flags] +public enum HookType : int +{ + /// + /// WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks使我们可以监视菜单,滚动 + /// 条,消息框,对话框消息并且发现用户使用ALT+TAB or ALT+ESC 组合键切换窗口。 + /// WH_MSGFILTER Hook只能监视传递到菜单,滚动条,消息框的消息,以及传递到通 + /// 过安装了Hook子过程的应用程序建立的对话框的消息。WH_SYSMSGFILTER Hook + /// 监视所有应用程序消息。 + /// + /// WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks使我们可以在模式循环期间 + /// 过滤消息,这等价于在主消息循环中过滤消息。 + /// + /// 通过调用CallMsgFilter function可以直接的调用WH_MSGFILTER Hook。通过使用这 + /// 个函数,应用程序能够在模式循环期间使用相同的代码去过滤消息,如同在主消息循 + /// 环里一样 + /// + WH_MSGFILTER = -1, + /// + /// WH_JOURNALRECORD Hook用来监视和记录输入事件。典型的,可以使用这 + /// 个Hook记录连续的鼠标和键盘事件,然后通过使用WH_JOURNALPLAYBACK Hook + /// 来回放。WH_JOURNALRECORD Hook是全局Hook,它不能象线程特定Hook一样 + /// 使用。WH_JOURNALRECORD是system-wide local hooks,它们不会被注射到任何行 + /// 程地址空间 + /// + WH_JOURNALRECORD = 0, + /// + /// WH_JOURNALPLAYBACK Hook使应用程序可以插入消息到系统消息队列。可 + /// 以使用这个Hook回放通过使用WH_JOURNALRECORD Hook记录下来的连续的鼠 + /// 标和键盘事件。只要WH_JOURNALPLAYBACK Hook已经安装,正常的鼠标和键盘 + /// 事件就是无效的。WH_JOURNALPLAYBACK Hook是全局Hook,它不能象线程特定 + /// Hook一样使用。WH_JOURNALPLAYBACK Hook返回超时值,这个值告诉系统在处 + /// 理来自回放Hook当前消息之前需要等待多长时间(毫秒)。这就使Hook可以控制实 + /// 时事件的回放。WH_JOURNALPLAYBACK是system-wide local hooks,它们不会被 + /// 注射到任何行程地址空间 + /// + WH_JOURNALPLAYBACK = 1, + /// + /// 在应用程序中,WH_KEYBOARD Hook用来监视WM_KEYDOWN and + /// WM_KEYUP消息,这些消息通过GetMessage or PeekMessage function返回。可以使 + /// 用这个Hook来监视输入到消息队列中的键盘消息 + /// + WH_KEYBOARD = 2, + /// + /// 应用程序使用WH_GETMESSAGE Hook来监视从GetMessage or PeekMessage函 + /// 数返回的消息。你可以使用WH_GETMESSAGE Hook去监视鼠标和键盘输入,以及 + /// 其它发送到消息队列中的消息 + /// + WH_GETMESSAGE = 3, + /// + /// 监视发送到窗口过程的消息,系统在消息发送到接收窗口过程之前调用 + /// + WH_CALLWNDPROC = 4, + /// + /// 在以下事件之前,系统都会调用WH_CBT Hook子过程,这些事件包括: + /// 1. 激活,建立,销毁,最小化,最大化,移动,改变尺寸等窗口事件; + /// 2. 完成系统指令; + /// 3. 来自系统消息队列中的移动鼠标,键盘事件; + /// 4. 设置输入焦点事件; + /// 5. 同步系统消息队列事件。 + /// Hook子过程的返回值确定系统是否允许或者防止这些操作中的一个 + /// + WH_CBT = 5, + /// + /// WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks使我们可以监视菜单,滚动 + /// 条,消息框,对话框消息并且发现用户使用ALT+TAB or ALT+ESC 组合键切换窗口。 + /// WH_MSGFILTER Hook只能监视传递到菜单,滚动条,消息框的消息,以及传递到通 + /// 过安装了Hook子过程的应用程序建立的对话框的消息。WH_SYSMSGFILTER Hook + /// 监视所有应用程序消息。 + /// + /// WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks使我们可以在模式循环期间 + /// 过滤消息,这等价于在主消息循环中过滤消息。 + /// + /// 通过调用CallMsgFilter function可以直接的调用WH_MSGFILTER Hook。通过使用这 + /// 个函数,应用程序能够在模式循环期间使用相同的代码去过滤消息,如同在主消息循 + /// 环里一样 + /// + WH_SYSMSGFILTER = 6, + /// + /// WH_MOUSE Hook监视从GetMessage 或者 PeekMessage 函数返回的鼠标消息。 + /// 使用这个Hook监视输入到消息队列中的鼠标消息 + /// + WH_MOUSE = 7, + /// + /// 当调用GetMessage 或 PeekMessage 来从消息队列种查询非鼠标、键盘消息时 + /// + WH_HARDWARE = 8, + /// + /// 在系统调用系统中与其它Hook关联的Hook子过程之前,系统会调用 + /// WH_DEBUG Hook子过程。你可以使用这个Hook来决定是否允许系统调用与其它 + /// Hook关联的Hook子过程 + /// + WH_DEBUG = 9, + /// + /// 外壳应用程序可以使用WH_SHELL Hook去接收重要的通知。当外壳应用程序是 + /// 激活的并且当顶层窗口建立或者销毁时,系统调用WH_SHELL Hook子过程。 + /// WH_SHELL 共有5钟情况: + /// 1. 只要有个top-level、unowned 窗口被产生、起作用、或是被摧毁; + /// 2. 当Taskbar需要重画某个按钮; + /// 3. 当系统需要显示关于Taskbar的一个程序的最小化形式; + /// 4. 当目前的键盘布局状态改变; + /// 5. 当使用者按Ctrl+Esc去执行Task Manager(或相同级别的程序)。 + /// + /// 按照惯例,外壳应用程序都不接收WH_SHELL消息。所以,在应用程序能够接 + /// 收WH_SHELL消息之前,应用程序必须调用SystemParametersInfo function注册它自 + /// 己 + /// + WH_SHELL = 10, + /// + /// 当应用程序的前台线程处于空闲状态时,可以使用WH_FOREGROUNDIDLE + /// Hook执行低优先级的任务。当应用程序的前台线程大概要变成空闲状态时,系统就 + /// 会调用WH_FOREGROUNDIDLE Hook子过程 + /// + WH_FOREGROUNDIDLE = 11, + /// + /// 监视发送到窗口过程的消息,系统在消息发送到接收窗口过程之后调用 + /// + WH_CALLWNDPROCRET = 12, + /// + /// 监视键盘消息 + /// + WH_KEYBOARD_LL = 13, + /// + /// 监视鼠标消息 + /// + WH_MOUSE_LL = 14 +} + +/// +/// 消息类型 +/// 作为SendMessage和PostMessage的参数 +/// +[Flags] +public enum WM : uint +{ + /// + /// 创建一个窗口 + /// + WM_CREATE = 0x01, + /// + /// 当一个窗口被破坏时发送 + /// + WM_DESTROY = 0x02, + /// + /// 移动一个窗口 + /// + WM_MOVE = 0x03, + /// + /// 改变一个窗口的大小 + /// + WM_SIZE = 0x05, + /// + /// 一个窗口被激活或失去激活状态 + /// + WM_ACTIVATE = 0x06, + /// + /// 一个窗口获得焦点 + /// + WM_SETFOCUS = 0x07, + /// + /// 一个窗口失去焦点 + /// + WM_KILLFOCUS = 0x08, + /// + /// 一个窗口改变成Enable状态 + /// + WM_ENABLE = 0x0A, + /// + /// 设置窗口是否能重画 + /// + WM_SETREDRAW = 0x0B, + /// + /// 应用程序发送此消息来设置一个窗口的文本 + /// + WM_SETTEXT = 0x0C, + /// + /// 应用程序发送此消息来复制对应窗口的文本到缓冲区 + /// + WM_GETTEXT = 0x0D, + /// + /// 得到与一个窗口有关的文本的长度(不包含空字符) + /// + WM_GETTEXTLENGTH = 0x0E, + /// + /// 要求一个窗口重画自己 + /// + WM_PAINT = 0x0F, + /// + /// 当一个窗口或应用程序要关闭时发送一个信号 + /// + WM_CLOSE = 0x10, + /// + /// 当用户选择结束对话框或程序自己调用ExitWindows函数 + /// + WM_QUERYENDSESSION = 0x11, + /// + /// 用来结束程序运行 + /// + WM_QUIT = 0x12, + /// + /// 当用户窗口恢复以前的大小位置时,把此消息发送给某个图标 + /// + WM_QUERYOPEN = 0x13, + /// + /// 当窗口背景必须被擦除时(例在窗口改变大小时) + /// + WM_ERASEBKGND = 0x14, + /// + /// 当系统颜色改变时,发送此消息给所有顶级窗口 + /// + WM_SYSCOLORCHANGE = 0x15, + /// + /// 当系统进程发出WM_QUERYENDSESSION消息后,此消息发送给应用程序,通知它对话是否结束 + /// + WM_ENDSESSION = 0x16, + /// + /// 当隐藏或显示窗口是发送此消息给这个窗口 + /// + WM_SHOWWINDOW = 0x18, + /// + /// 发此消息给应用程序哪个窗口是激活的,哪个是非激活的 + /// + WM_ACTIVATEAPP = 0x1C, + /// + /// 当系统的字体资源库变化时发送此消息给所有顶级窗口 + /// + WM_FONTCHANGE = 0x1D, + /// + /// 当系统的时间变化时发送此消息给所有顶级窗口 + /// + WM_TIMECHANGE = 0x1E, + /// + /// 发送此消息来取消某种正在进行的摸态(操作) + /// + WM_CANCELMODE = 0x1F, + /// + /// 如果鼠标引起光标在某个窗口中移动且鼠标输入没有被捕获时,就发消息给某个窗口 + /// + WM_SETCURSOR = 0x20, + /// + /// 当光标在某个非激活的窗口中而用户正按着鼠标的某个键发送此消息给当前窗口 + /// + WM_MOUSEACTIVATE = 0x21, + /// + /// 发送此消息给MDI子窗口当用户点击此窗口的标题栏或当窗口被激活,移动,改变大小 + /// + WM_CHILDACTIVATE = 0x22, + /// + /// 此消息由基于计算机的训练程序发送,通过WH_JOURNALPALYBACK的hook程序分离出用户输入消息 + /// + WM_QUEUESYNC = 0x23, + /// + /// 此消息发送给窗口当它将要改变大小或位置 + /// + WM_GETMINMAXINFO = 0x24, + /// + /// 发送给最小化窗口当它图标将要被重画 + /// + WM_PAINTICON = 0x26, + /// + /// 此消息发送给某个最小化窗口,仅当它在画图标前它的背景必须被重画 + /// + WM_ICONERASEBKGND = 0x27, + /// + /// 发送此消息给一个对话框程序去更改焦点位置 + /// + WM_NEXTDLGCTL = 0x28, + /// + /// 每当打印管理列队增加或减少一条作业时发出此消息 + /// + WM_SPOOLERSTATUS = 0x2A, + /// + /// 当button,combobox,listbox,menu的可视外观改变时发送 + /// + WM_DRAWITEM = 0x2B, + /// + /// 当button, combo box, list box, list view control, or menu item 被创建时 + /// + WM_MEASUREITEM = 0x2C, + /// + /// 此消息有一个LBS_WANTKEYBOARDINPUT风格的发出给它的所有者来响应WM_KEYDOWN消息 + /// + WM_VKEYTOITEM = 0x2E, + /// + /// 此消息由一个LBS_WANTKEYBOARDINPUT风格的列表框发送给他的所有者来响应WM_CHAR消息 + /// + WM_CHARTOITEM = 0x2F, + /// + /// 当绘制文本时程序发送此消息得到控件要用的颜色 + /// + WM_SETFONT = 0x30, + /// + /// 应用程序发送此消息得到当前控件绘制文本的字体 + /// + WM_GETFONT = 0x31, + /// + /// 应用程序发送此消息让一个窗口与一个热键相关连 + /// + WM_SETHOTKEY = 0x32, + /// + /// 应用程序发送此消息来判断热键与某个窗口是否有关联 + /// + WM_GETHOTKEY = 0x33, + /// + /// 此消息发送给最小化窗口,当此窗口将要被拖放而它的类中没有定义图标,应用程序能返回一个图标或光标的句柄,当用户拖放图标时系统显示这个图标或光标 + /// + WM_QUERYDRAGICON = 0x37, + /// + /// 发送此消息来判定combobox或listbox新增加的项的相对位置 + /// + WM_COMPAREITEM = 0x39, + /// + /// 显示内存已经很少了 + /// + WM_COMPACTING = 0x41, + /// + /// 窗口大小和位置将要被改变时,来调用Setwindowpos函数或其它窗口管理函数 + /// + WM_WINDOWPOSCHANGING = 0x46, + /// + /// 窗口大小和位置已经被改变后,来调用Setwindowpos函数或其它窗口管理函数 + /// + WM_WINDOWPOSCHANGED = 0x47, + /// + /// 当系统将要进入暂停状态时发送此消息 + /// + WM_POWER = 0x48, + /// + /// 当一个应用程序传递数据给另一个应用程序时发送此消息 + /// + WM_COPYDATA = 0x4A, + /// + /// 当某个用户取消程序日志激活状态,提交此消息给程序 + /// + WM_CANCELJOURNA = 0x4B, + /// + /// 当某个控件的某个事件已经发生或这个控件需要得到一些信息时,发送此消息给它的父窗口 + /// + WM_NOTIFY = 0x4E, + /// + /// 当用户选择某种输入语言,或输入语言的热键改变 + /// + WM_INPUTLANGCHANGEREQUEST = 0x50, + /// + /// 当平台现场已经被改变后发送此消息给受影响的最顶级窗口 + /// + WM_INPUTLANGCHANGE = 0x51, + /// + /// 当程序已经初始化windows帮助例程时发送此消息给应用程序 + /// + WM_TCARD = 0x52, + /// + /// 此消息显示用户按下了F1,如果某个菜单是激活的,就发送此消息个此窗口关联的菜单,否则就发送给有焦点的窗口,如果当前都没有焦点,就把此消息发送给当前激活的窗口 + /// + WM_HELP = 0x53, + /// + /// 当用户已经登入或退出后发送此消息给所有的窗口,当用户登入或退出时系统更新用户的具体设置信息,在用户更新设置时系统马上发送此消息 + /// + WM_USERCHANGED = 0x54, + /// + /// 公用控件,自定义控件和他们的父窗口通过此消息来判断控件是使用ANSI还是UNICODE结构 + /// + WM_NOTIFYFORMAT = 0x55, + /// + /// 当用户某个窗口中点击了一下右键就发送此消息给这个窗口 + /// + WM_CONTEXTMENU = 0x7B, + /// + /// 当调用SETWINDOWLONG函数将要改变一个或多个窗口的风格时发送此消息给那个窗口 + /// + WM_STYLECHANGING = 0x7C, + /// + /// 当调用SETWINDOWLONG函数一个或多个窗口的风格后发送此消息给那个窗口 + /// + WM_STYLECHANGED = 0x7D, + /// + /// 当显示器的分辨率改变后发送此消息给所有的窗口 + /// + WM_DISPLAYCHANGE = 0x7E, + /// + /// 此消息发送给某个窗口来返回与某个窗口有关连的大图标或小图标的句柄 + /// + WM_GETICON = 0x7F, + /// + /// 程序发送此消息让一个新的大图标或小图标与某个窗口关联 + /// + WM_SETICON = 0x80, + /// + /// 当某个窗口第一次被创建时,此消息在WM_CREATE消息发送前发送 + /// + WM_NCCREATE = 0x81, + /// + /// 此消息通知某个窗口,非客户区正在销毁 + /// + WM_NCDESTROY = 0x82, + /// + /// 当某个窗口的客户区域必须被核算时发送此消息 + /// + WM_NCCALCSIZE = 0x83, + /// + /// 移动鼠标/按住/释放鼠标时 + /// + WM_NCHITTEST = 0x84, + /// + /// 程序发送此消息给某个窗口当它(窗口)的框架必须被绘制时 + /// + WM_NCPAINT = 0x85, + /// + /// 此消息发送给某个窗口仅当它的非客户区需要被改变来显示是激活还是非激活状态 + /// + WM_NCACTIVATE = 0x86, + /// + /// 发送此消息给某个与对话框程序关联的控件,widdows控制方位键和TAB键使输入进入此控件通过应 + /// + WM_GETDLGCODE = 0x87, + /// + /// 当光标在一个窗口的非客户区内移动时发送此消息给这个窗口 非客户区为:窗体的标题栏及窗的边框体 + /// + WM_NCMOUSEMOVE = 0xA0, + /// + /// 当光标在一个窗口的非客户区同时按下鼠标左键时提交此消息 + /// + WM_NCLBUTTONDOWN = 0xA1, + /// + /// 当用户释放鼠标左键同时光标某个窗口在非客户区时发送此消息 + /// + WM_NCLBUTTONUP = 0xA2, + /// + /// 当用户双击鼠标左键同时光标某个窗口在非客户区时发送此消息 + /// + WM_NCLBUTTONDBLCLK = 0xA3, + /// + /// 当用户按下鼠标右键同时光标又在窗口的非客户区时发送此消息 + /// + WM_NCRBUTTONDOWN = 0xA4, + /// + /// 当用户释放鼠标右键同时光标又在窗口的非客户区时发送此消息 + /// + WM_NCRBUTTONUP = 0xA5, + /// + /// 当用户双击鼠标右键同时光标某个窗口在非客户区时发送此消息 + /// + WM_NCRBUTTONDBLCLK = 0xA6, + /// + /// 当用户按下鼠标中键同时光标又在窗口的非客户区时发送此消息 + /// + WM_NCMBUTTONDOWN = 0xA7, + /// + /// 当用户释放鼠标中键同时光标又在窗口的非客户区时发送此消息 + /// + WM_NCMBUTTONUP = 0xA8, + /// + /// 当用户双击鼠标中键同时光标又在窗口的非客户区时发送此消息 + /// + WM_NCMBUTTONDBLCLK = 0xA9, + + // 所有的键盘消息只有中间的八种,也就是 WM_KEYDOWN 到 WM_SYSDEADCHAR + /// + /// 按下一个键 == WM_KEYDOWN + /// + WM_KEYFIRST = 0x0100, + /// + /// 按下一个键 + /// + WM_KEYDOWN = 0x0100, + /// + /// 释放一个键 + /// + WM_KEYUP = 0x0101, + /// + /// 按下某键,并已发出WM_KEYDOWN, WM_KEYUP消息 + /// + WM_CHAR = 0x102, + /// + /// 当用translatemessage函数翻译WM_KEYUP消息时发送此消息给拥有焦点的窗口 + /// + WM_DEADCHAR = 0x103, + /// + /// 当用户按住ALT键同时按下其它键时提交此消息给拥有焦点的窗口 + /// + WM_SYSKEYDOWN = 0x104, + /// + /// 当用户释放一个键同时ALT 键还按着时提交此消息给拥有焦点的窗口 + /// + WM_SYSKEYUP = 0x105, + /// + /// 当WM_SYSKEYDOWN消息被TRANSLATEMESSAGE函数翻译后提交此消息给拥有焦点的窗口 + /// + WM_SYSCHAR = 0x106, + /// + /// 当WM_SYSKEYDOWN消息被TRANSLATEMESSAGE函数翻译后发送此消息给拥有焦点的窗口 + /// + WM_SYSDEADCHAR = 0x107, + /// + /// 在一个对话框程序被显示前发送此消息给它,通常用此消息初始化控件和执行其它任务 + /// + WM_INITDIALOG = 0x110, + /// + /// 当用户选择一条菜单命令项或当某个控件发送一条消息给它的父窗口 + /// + WM_COMMAND = 0x111, + + /// + /// 当用户选择窗口菜单的一条命令或最大化最小化时窗口前会收到此消息 + /// + WM_SYSCOMMAND = 0x112, + /// + /// 发生了定时器事件 + /// + WM_TIMER = 0x113, + /// + /// 当一个窗口标准水平滚动条产生一个滚动事件时发送此消息给那个窗口,也发送给拥有它的控件 + /// + WM_HSCROLL = 0x114, + /// + /// 当一个窗口标准垂直滚动条产生一个滚动事件时发送此消息给那个窗口也,发送给拥有它的控件 + /// + WM_VSCROLL = 0x115, + /// + /// 当一个菜单将要被激活时发送此消息,它发生在用户菜单条中的某项或按下某个菜单键,它允许程序在显示前更改菜单 + /// + WM_INITMENU = 0x116, + /// + /// 当一个下拉菜单或子菜单将要被激活时发送此消息,它允许程序在它显示前更改菜单,而不要改变全部 + /// + WM_INITMENUPOPUP = 0x117, + /// + /// 当用户选择一条菜单项时发送此消息给菜单的所有者(一般是窗口) + /// + WM_MENUSELECT = 0x11F, + /// + /// 当菜单已被激活用户按下了某个键(不同于加速键),发送此消息给菜单的所有者 + /// + WM_MENUCHAR = 0x120, + /// + /// 当一个模态对话框或菜单进入空载状态时发送此消息给它的所有者,一个模态对话框或菜单进入空载状态就是在处理完一条或几条先前的消息后没有消息它的列队中等待 + /// + WM_ENTERIDLE = 0x121, + /// + /// 在windows绘制消息框前发送此消息给消息框的所有者窗口,通过响应这条消息,所有者窗口可以通过使用给定的相关显示设备的句柄来设置消息框的文本和背景颜色 + /// + WM_CTLCOLORMSGBOX = 0x132, + /// + /// 当一个编辑型控件将要被绘制时发送此消息给它的父窗口通过响应这条消息,所有者窗口可以通过使用给定的相关显示设备的句柄来设置编辑框的文本和背景颜色 + /// + WM_CTLCOLOREDIT = 0x133, + + /// + /// 当一个列表框控件将要被绘制前发送此消息给它的父窗口通过响应这条消息,所有者窗口可以通过使用给定的相关显示设备的句柄来设置列表框的文本和背景颜色 + /// + WM_CTLCOLORLISTBOX = 0x134, + /// + /// 当一个按钮控件将要被绘制时发送此消息给它的父窗口通过响应这条消息,所有者窗口可以通过使用给定的相关显示设备的句柄来设置按纽的文本和背景颜色 + /// + WM_CTLCOLORBTN = 0x135, + /// + /// 当一个对话框控件将要被绘制前发送此消息给它的父窗口通过响应这条消息,所有者窗口可以通过使用给定的相关显示设备的句柄来设置对话框的文本背景颜色 + /// + WM_CTLCOLORDLG = 0x136, + /// + /// 当一个滚动条控件将要被绘制时发送此消息给它的父窗口通过响应这条消息,所有者窗口可以通过使用给定的相关显示设备的句柄来设置滚动条的背景颜色 + /// + WM_CTLCOLORSCROLLBAR = 0x137, + /// + /// 当一个静态控件将要被绘制时发送此消息给它的父窗口通过响应这条消息,所有者窗口可以通过使用给定的相关显示设备的句柄来设置静态控件的文本和背景颜色 + /// + WM_CTLCOLORSTATIC = 0x138, + + /// + /// 当鼠标轮子转动时发送此消息个当前有焦点的控件 + /// + WM_MOUSEWHEEL = 0x20A, + /// + /// 双击鼠标中键 + /// + WM_MBUTTONDBLCLK = 0x209, + /// + /// 释放鼠标中键 + /// + WM_MBUTTONUP = 0x208, + /// + /// 移动鼠标时发生,同WM_MOUSEFIRST + /// + WM_MOUSEMOVE = 0x200, + /// + /// 按下鼠标左键 + /// + WM_LBUTTONDOWN = 0x201, + /// + /// 释放鼠标左键 + /// + WM_LBUTTONUP = 0x202, + /// + /// 双击鼠标左键 + /// + WM_LBUTTONDBLCLK = 0x203, + /// + /// 按下鼠标右键 + /// + WM_RBUTTONDOWN = 0x204, + /// + /// 释放鼠标右键 + /// + WM_RBUTTONUP = 0x205, + /// + /// 双击鼠标右键 + /// + WM_RBUTTONDBLCLK = 0x206, + /// + /// 按下鼠标中键 + /// + WM_MBUTTONDOWN = 0x207, + + WM_USER = 0x0400, + + /// + /// 执行复制成功 + /// + WM_CLIPBOARDUPDATE = 0x031D, +} + +// https://blog.csdn.net/biyusr/article/details/108376195 +public enum MOUSEEVENTF : int +{ + /// + /// 移动鼠标 + /// + MOVE = 0x0001, + /// + /// 模拟鼠标左键按下 + /// + LEFTDOWN = 0x0002, + /// + /// 模拟鼠标左键抬起 + /// + LEFTUP = 0x0004, + /// + /// 模拟鼠标右键按下 + /// + RIGHTDOWN = 0x0008, + /// + /// 模拟鼠标右键抬起 + /// + RIGHTUP = 0x0010, + /// + /// 模拟鼠标中键按下 + /// + MIDDLEDOWN = 0x0020, + /// + /// 模拟鼠标中键抬起 + /// + MIDDLEUP = 0x0040, + /// + /// 标示是否采用绝对坐标 + /// + ABSOLUTE = 0x8000, + /// + /// 模拟鼠标滚轮滚动操作,必须配合dwData参数 + /// + WHEEL = 0x0800, +} + +// C#使用SendMessage发送组合键 +// https://www.cnblogs.com/johnsonton/articles/2331430.html +// Windows 使用的256个虚拟键码 +[Flags]// 打印的时候可以有名称输出,而不是值输出 +public enum VK : int +{ + VK_LBUTTON = 0x1, + VK_RBUTTON = 0x2, + VK_CANCEL = 0x3, + VK_MBUTTON = 0x4, + VK_BACK = 0x8, + VK_TAB = 0x9, + VK_CLEAR = 0xC, + VK_RETURN = 0xD, + VK_SHIFT = 0x10, + VK_CONTROL = 0x11, + VK_MENU = 0x12,// VK_ALT + VK_ALT = 0x12, + VK_PAUSE = 0x13, + VK_CAPITAL = 0x14, + VK_ESCAPE = 0x1B, + VK_SPACE = 0x20, + VK_PRIOR = 0x21, + VK_NEXT = 0x22, + VK_END = 0x23, + VK_HOME = 0x24, + VK_LEFT = 0x25, + VK_UP = 0x26, + VK_RIGHT = 0x27, + VK_DOWN = 0x28, + VK_Select = 0x29, + VK_PRINT = 0x2A, + VK_EXECUTE = 0x2B, + VK_SNAPSHOT = 0x2C, + VK_Insert = 0x2D, + VK_Delete = 0x2E, + VK_HELP = 0x2F, + VK_0 = 0x30, + VK_1 = 0x31, + VK_2 = 0x32, + VK_3 = 0x33, + VK_4 = 0x34, + VK_5 = 0x35, + VK_6 = 0x36, + VK_7 = 0x37, + VK_8 = 0x38, + VK_9 = 0x39, + VK_A = 0x41, + VK_B = 0x42, + VK_C = 0x43, + VK_D = 0x44, + VK_E = 0x45, + VK_F = 0x46, + VK_G = 0x47, + VK_H = 0x48, + VK_I = 0x49, + VK_J = 0x4A, + VK_K = 0x4B, + VK_L = 0x4C, + VK_M = 0x4D, + VK_N = 0x4E, + VK_O = 0x4F, + VK_P = 0x50, + VK_Q = 0x51, + VK_R = 0x52, + VK_S = 0x53, + VK_T = 0x54, + VK_U = 0x55, + VK_V = 0x56, + VK_W = 0x57, + VK_X = 0x58, + VK_Y = 0x59, + VK_Z = 0x5A, + VK_STARTKEY = 0x5B, + VK_CONTEXTKEY = 0x5D, + VK_NUMPAD0 = 0x60, + VK_NUMPAD1 = 0x61, + VK_NUMPAD2 = 0x62, + VK_NUMPAD3 = 0x63, + VK_NUMPAD4 = 0x64, + VK_NUMPAD5 = 0x65, + VK_NUMPAD6 = 0x66, + VK_NUMPAD7 = 0x67, + VK_NUMPAD8 = 0x68, + VK_NUMPAD9 = 0x69, + VK_MULTIPLY = 0x6A, + VK_ADD = 0x6B, + VK_SEPARATOR = 0x6C, + VK_SUBTRACT = 0x6D, + VK_DECIMAL = 0x6E, + VK_DIVIDE = 0x6F, + VK_F1 = 0x70, + VK_F2 = 0x71, + VK_F3 = 0x72, + VK_F4 = 0x73, + VK_F5 = 0x74, + VK_F6 = 0x75, + VK_F7 = 0x76, + VK_F8 = 0x77, + VK_F9 = 0x78, + VK_F10 = 0x79, + VK_F11 = 0x7A, + VK_F12 = 0x7B, + VK_F13 = 0x7C, + VK_F14 = 0x7D, + VK_F15 = 0x7E, + VK_F16 = 0x7F, + VK_F17 = 0x80, + VK_F18 = 0x81, + VK_F19 = 0x82, + VK_F20 = 0x83, + VK_F21 = 0x84, + VK_F22 = 0x85, + VK_F23 = 0x86, + VK_F24 = 0x87, + VK_NUMLOCK = 0x90, + VK_OEM_SCROLL = 0x91, + VK_OEM_1 = 0xBA, + VK_OEM_PLUS = 0xBB, + VK_OEM_COMMA = 0xBC, + VK_OEM_MINUS = 0xBD, + VK_OEM_PERIOD = 0xBE, + VK_OEM_2 = 0xBF, + VK_OEM_3 = 0xC0, + VK_OEM_4 = 0xDB, + VK_OEM_5 = 0xDC, + VK_OEM_6 = 0xDD, + VK_OEM_7 = 0xDE, + VK_OEM_8 = 0xDF, + VK_ICO_F17 = 0xE0, + VK_ICO_F18 = 0xE1, + VK_OEM102 = 0xE2, + VK_ICO_HELP = 0xE3, + VK_ICO_00 = 0xE4, + VK_ICO_CLEAR = 0xE6, + VK_OEM_RESET = 0xE9, + VK_OEM_JUMP = 0xEA, + VK_OEM_PA1 = 0xEB, + VK_OEM_PA2 = 0xEC, + VK_OEM_PA3 = 0xED, + VK_OEM_WSCTRL = 0xEE, + VK_OEM_CUSEL = 0xEF, + VK_OEM_ATTN = 0xF0, + VK_OEM_FINNISH = 0xF1, + VK_OEM_COPY = 0xF2, + VK_OEM_AUTO = 0xF3, + VK_OEM_ENLW = 0xF4, + VK_OEM_BACKTAB = 0xF5, + VK_ATTN = 0xF6, + VK_CRSEL = 0xF7, + VK_EXSEL = 0xF8, + VK_EREOF = 0xF9, + VK_PLAY = 0xFA, + VK_ZOOM = 0xFB, + VK_NONAME = 0xFC, + VK_PA1 = 0xFD, + VK_OEM_CLEAR = 0xFE, +} + +[Flags] +public enum SC : uint +{ + // 窗体关闭消息 + SC_CLOSE = 0xf060, + // 窗体最小化消息 + SC_MINIMIZE = 0xf020, + // 窗体最大化消息 + SC_MAXIMIZE = 0xf030, + // 窗体正常态消息 SC_RESTORE = 0xf120, + SC_NOMAL = 0xf120, +} + +[Flags] +public enum NCmdShow : uint +{ + /// + /// 隐藏窗口并激活其他窗口。nCmdShow + /// + SW_HIDE = 0, + /// + /// 正常态的窗口(非最大化和非最小化) + /// 激活并显示一个窗口。如果窗口被最小化或最大化,系统将其恢复到原来的尺寸和大小。应用程序在第一次显示窗口的时候应该指定此标志 + /// + SW_SHOWNORMAL = 1, + /// + /// 激活窗口并将其最小化 + /// + SW_SHOWMINIMIZED = 2, + /// + /// 激活窗口并将其最大化 + /// + SW_SHOWMAXIMIZED = 3, + /// + /// 最大化指定的窗口 + /// + SW_MAXIMIZE = 3, + /// + /// 以窗口最近一次的大小和状态显示窗口。激活窗口仍然维持激活状态 + /// + SW_SHOWNOACTIVATE = 4, + /// + /// 在窗口原来的位置以原来的尺寸激活和显示窗口 + /// + SW_SHOW = 5, + /// + /// 最小化指定的窗口并且激活在Z序中的下一个顶层窗口 + /// + SW_MINIMIZE = 6, + /// + /// 窗口最小化,激活窗口仍然维持激活状态 + /// + SW_SHOWMINNOACTIVE = 7, + /// + /// 以窗口原来的状态显示窗口。激活窗口仍然维持激活状态 + /// + SW_SHOWNA = 8, + /// + /// 激活并显示窗口。如果窗口最小化或最大化,则系统将窗口恢复到原来的尺寸和位置。在恢复最小化窗口时,应用程序应该指定这个标志 + /// + SW_RESTORE = 9, + /// + /// 依据在STARTUPINFO结构中指定的SW_FLAG标志设定显示状态,STARTUPINFO 结构是由启动应用程序的程序传递给CreateProcess函数的 + /// + SW_SHOWDEFAULT = 10, + /// + /// 在WindowNT5.0中最小化窗口,即使拥有窗口的线程被挂起也会最小化。在从其他线程最小化窗口时才使用这个参数 + /// + SW_FORCEMINIMIZE = 11, +} + +public enum WS : uint +{ + // 窗口风格 + WS_CAPTION = 0xC00000, // 带标题栏的窗口 + WS_MAXIMIZEBOX = 0x10000, // 带最大化按钮的窗口 + WS_MINIMIZEBOX = 0x20000, // 带最小化按钮的窗口 + WS_SYSMENU = 0x80000, // 带系统菜单的窗口 + WS_CLIPSIBLINGS = 0x4000000, // 不重绘层叠子窗口 + WS_CLIPCHILDREN = 0x2000000, // 绘图时排子窗口区域 + WS_OVERLAPPED = 0x0, // 具有标题栏和边框的层叠窗口 + WS_THICKFRAME = 0x40000, // 具有可调边框 + + // 具有标题栏、窗口菜单、可调边框和最大化、最小化按钮的窗口 + WS_OVERLAPPEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX, + + WS_GROUP = 0x20000, // 指定一组控制的第一个控制 + WS_POPUP = 0x80000000, // 弹出式窗口 + WS_BORDER = 0x800000, // 单边框窗口 + WS_POPUPWINDOW = WS_POPUP | WS_BORDER | WS_SYSMENU, // 具有单边框、标题栏菜单的弹出式窗口 + WS_MINIMIZE = 0x20000000, // 窗口最小化 + WS_VISIBLE = 0x10000000, // 窗口可见 + WS_DISABLED = 0x8000000, // 窗口被禁用 + WS_MAXIMIZE = 0x1000000, // 窗口最大化 + WS_DLGFRAME = 0x400000, // 对话框边框风格 + WS_VSCROLL = 0x200000, // 具有垂直滚动条 + WS_HSCROLL = 0x100000, // 具有水平滚动条 + WS_TABSTOP = 0x10000, // 具有TAB键控制 + WS_CHILD = 0x40000000, // 设置窗口属性为child 多文档界面的子窗体 + WS_CHILDWINDOW = WS_CHILD, // 具有子窗口 + + // 扩展风格 + WS_EX_WINDOWEDGE = 0x100, // 窗口具有凸起的3D边框 + WS_EX_CLIENTEDGE = 0x200, // 窗口具有阴影边界 + WS_EX_TOOLWINDOW = 0x80, // 小标题工具窗口 + WS_EX_TOPMOST = 0x8, // 窗口总在顶层 const int WS_EX_TOPMOST = 0x00000008; + WS_EX_OVERLAPPEDWINDOW = WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE, // WS_EX-CLIENTEDGE和WS_EX_WINDOWEDGE的组合 + WS_EX_PALETTEWINDOW = WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST, // WS_EX_WINDOWEDGE和WS_EX_TOOLWINDOW和WS_EX_TOPMOST的组合 + WS_EX_DLGMODALFRAME = 0x1, // 带双边的窗口 + WS_EX_NOPARENTNOTIFY = 0x4, // 窗口在创建和销毁时不向父窗口发送WM_PARENTNOTIFY消息 + WS_EX_TRANSPARENT = 0x20, // 窗口透眀 + WS_EX_MDICHILD = 0x40, // MDI子窗口 + WS_EX_CONTEXTHELP = 0x400, // 标题栏包含问号联机帮助按钮 + WS_EX_RIGHT = 0x1000, // 窗口具有右对齐属性 + WS_EX_RTLREADING = 0x2000, // 窗口文本自右向左显示 + WS_EX_LEFTSCROLLBAR = 0x4000, // 标题栏在客户区的左边 + WS_EX_CONTROLPARENT = 0x10000, // 允许用户使用Tab键在窗口的子窗口间搜索 + WS_EX_STATICEDGE = 0x20000, // 为不接受用户输入的项创建一个三维边界风格 + WS_EX_APPWINDOW = 0x40000, // 在任务栏上显示顶层窗口的标题按钮 + WS_EX_LAYERED = 0x80000, // 窗口具有透眀属性(Win2000)以上 + WS_EX_NOINHERITLAYOUT = 0x100000, // 窗口布局不传递给子窗口(Win2000)以上 + WS_EX_LAYOUTRTL = 0x400000, // 水平起点在右边的窗口 + WS_EX_NOACTIVATE = 0x8000000, // 窗口不会变成前台窗口(Win2000)以上 + WS_EX_LEFT = 0x0, // 窗口具有左对齐属性 + WS_EX_LTRREADING = 0x0, // 窗口文本自左向右显示 + WS_EX_RIGHTSCROLLBAR = 0x0, // 垂直滚动条在窗口的右边界 + WS_EX_ACCEPTFILES = 0x10, // 接受文件拖曳 + WS_EX_COMPOSITED = 0x2000000, // 窗体所有子窗口使用双缓冲从低到高绘制(XP) +} + +public enum GWL : int +{ + /// + /// 获取、设置窗口过程的地址 + /// + GWL_WNDPROC = -4, + /// + /// 获取应用程序的实例句柄 + /// + GWL_HINSTANCE = -6, + /// + /// 获取父窗口句柄 + /// + GWL_HWNDPARENT = -8, + /// + /// 获取窗口标识 + /// + GWL_ID = -12, + /// + /// 获取、设置窗口样式 + /// + GWL_STYLE = -16, + /// + /// 获取、设置窗口扩展样式 + /// + GWL_EXSTYLE = -20, + /// + /// 获取、设置与窗口关联的自定义数据 + /// + GWL_USERDATA = -21, +} + +public enum GetWindowCmd : uint +{ + /// + /// 返回的句柄标识了在Z序最高端的相同类型的窗口。 + /// 如果指定窗口是最高端窗口,则该句柄标识了在Z序最高端的最高端窗口; + /// 如果指定窗口是顶层窗口,则该句柄标识了在z序最高端的顶层窗口: + /// 如果指定窗口是子窗口,则句柄标识了在Z序最高端的同属窗口。 + /// + GW_HWNDFIRST = 0, + /// + /// 返回的句柄标识了在z序最低端的相同类型的窗口。 + /// 如果指定窗口是最高端窗口,则该柄标识了在z序最低端的最高端窗口: + /// 如果指定窗口是顶层窗口,则该句柄标识了在z序最低端的顶层窗口; + /// 如果指定窗口是子窗口,则句柄标识了在Z序最低端的同属窗口。 + /// + GW_HWNDLAST = 1, + /// + /// 返回的句柄标识了在Z序中指定窗口下的相同类型的窗口。 + /// 如果指定窗口是最高端窗口,则该句柄标识了在指定窗口下的最高端窗口: + /// 如果指定窗口是顶层窗口,则该句柄标识了在指定窗口下的顶层窗口; + /// 如果指定窗口是子窗口,则句柄标识了在指定窗口下的同属窗口。 + /// + GW_HWNDNEXT = 2, + /// + /// 返回的句柄标识了在Z序中指定窗口上的相同类型的窗口。 + /// 如果指定窗口是最高端窗口,则该句柄标识了在指定窗口上的最高端窗口; + /// 如果指定窗口是顶层窗口,则该句柄标识了在指定窗口上的顶层窗口; + /// 如果指定窗口是子窗口,则句柄标识了在指定窗口上的同属窗口。 + /// + GW_HWNDPREV = 3, + /// + /// 返回的句柄标识了指定窗口的所有者窗口(如果存在)。 + /// GW_OWNER与GW_CHILD不是相对的参数,没有父窗口的含义,如果想得到父窗口请使用GetParent()。 + /// 例如:例如有时对话框的控件的GW_OWNER,是不存在的。 + /// + GW_OWNER = 4, + /// + /// 如果指定窗口是父窗口,则获得的是在Tab序顶端的子窗口的句柄,否则为NULL。 + /// 函数仅检查指定父窗口的子窗口,不检查继承窗口。 + /// + GW_CHILD = 5, + /// + /// (WindowsNT 5.0)返回的句柄标识了属于指定窗口的处于使能状态弹出式窗口(检索使用第一个由GW_HWNDNEXT 查找到的满足前述条件的窗口); + /// 如果无使能窗口,则获得的句柄与指定窗口相同。 + /// + GW_ENABLEDPOPUP = 6 +} +#endif +#pragma warning restore CS1591 // 缺少对公共可见类型或成员的 XML 注释 diff --git a/CADShared/Basal/Win/WindowsAPI.cs b/CADShared/Basal/Win/WindowsAPI.cs new file mode 100644 index 0000000..986a7f9 --- /dev/null +++ b/CADShared/Basal/Win/WindowsAPI.cs @@ -0,0 +1,660 @@ +#pragma warning disable CS1591 // 缺少对公共可见类型或成员的 XML 注释 +#define Marshal + +namespace IFoxCAD.Basal; +public partial class WindowsAPI +{ + #region kernel32 + // https://blog.csdn.net/haelang/article/details/45147121 + [DllImport("kernel32.dll")] + public extern static uint GetLastError(); + + [DllImport("kernel32.dll")] + public static extern long GetHandleInformation(long hObject, ref long lpdwFlags); + + [DllImport("kernel32.dll")] + public static extern IntPtr GetModuleHandle(string ModuleName); + + [DllImport("kernel32.dll")] + public static extern int GetCurrentThreadId(); + + /// + /// 获取要引入的函数,将符号名或标识号转换为DLL内部地址 + /// + /// exe/dll句柄 + /// 接口名 + /// + [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true)] + public static extern IntPtr GetProcAddress(IntPtr hModule, string procName); + + /// + /// 锁定内存 + /// + /// + /// + [DllImport("kernel32.dll", SetLastError = true)] + static extern IntPtr GlobalLock(IntPtr hMem); + /// + /// 解锁内存 + /// + /// + /// + [DllImport("kernel32.dll", SetLastError = true)] + static extern bool GlobalUnlock(IntPtr hMem); +#if !Marshal + /* + const int GMEM_MOVEABLE = 0x0002; + IntPtr newPtr = WindowsAPI.GlobalAlloc(GMEM_MOVEABLE, Marshal.SizeOf(structObj)); + */ + /// + /// 从堆中分配内存 + /// 被代替: Marshal.AllocHGlobal + /// + /// 分配方式 + /// 分配的字节数 + /// + [DllImport("kernel32.dll", SetLastError = true)] + public static extern IntPtr GlobalAlloc(uint uFlags, int dwBytes); + /// + /// 释放堆内存 + /// 被代替: Marshal.FreeHGlobal + /// + /// 产生的句柄 + /// + [DllImport("kernel32.dll", SetLastError = true)] + public static extern IntPtr GlobalFree(IntPtr hMem); +#endif + /// + /// 获取内存块大小 + /// + /// + /// + [DllImport("kernel32.dll", SetLastError = true)] + public static extern uint GlobalSize(IntPtr hMem); + + /// + /// 锁定和释放内存 + /// + /// 锁定数据对象指针 + /// 返回锁定的内存片段指针,锁定期间执行任务 + /// 是否锁定成功 + /// + public static bool GlobalLockTask(IntPtr data, Action task) + { + //if (task == null) + // throw new ArgumentNullException(nameof(task)); + ArgumentNullEx.ThrowIfNull(task); + if (data == IntPtr.Zero) + return false; + + try + { + var ptr = GlobalLock(data); + // 有几率导致无效锁定: + // 重复复制同一个图元时,第二次是 IntPtr.Zero, + // 第三次就又可以复制了 + if (ptr == IntPtr.Zero) + return false; + task.Invoke(ptr); + } + finally { GlobalUnlock(data); } + return true; + } + + /// + /// byte数组转结构体 + /// + /// byte数组 + /// 返回的结构大小 + /// 返回的结构体 + [Obsolete("效率太低", true)] + public static T? BytesToStruct(byte[] bytes, out int typeSize) + { + var structType = typeof(T); + typeSize = Marshal.SizeOf(structType); + if (typeSize > bytes.Length) + return default; + + // 安全写法效率太低了 + // 分配结构体大小的内存空间 + IntPtr structPtr = Marshal.AllocHGlobal(typeSize); + + // 将byte数组拷到分配好的内存空间 + Marshal.Copy(bytes, 0, structPtr, typeSize); + // 将内存空间转换为目标结构体; + // 转类型的时候会拷贝一次,看它们地址验证 &result != &structPtr + var result = (T)Marshal.PtrToStructure(structPtr, structType); + + // 释放内存空间 + Marshal.FreeHGlobal(structPtr); + return result; + } + + /// + /// byte数组转结构体 + /// + /// byte数组 + /// 返回的结构体 + [MethodImpl] + public static T? BytesToStruct(byte[] bytes) + { + T? result = default; + unsafe + { + // 安全指针方法 + // var pB = Marshal.UnsafeAddrOfPinnedArrayElement(bytes, 0); + // 不安全指针方法 + fixed (byte* pB = &bytes[0]) + { + result = (T?)Marshal.PtrToStructure(new IntPtr(pB), typeof(T)); + } + } + return result; + } + + ///
    + /// 结构体转byte数组 + /// unmanaged + /// + /// 要转换的结构体 + [MethodImpl] + public static byte[] StructToBytes(T structObj) where T : unmanaged/*非托管的T从来不为空*/ + { + // 得到结构体的大小 + var typeSize = Marshal.SizeOf(structObj); + // 从内存空间拷到byte数组 + var bytes = new byte[typeSize]; + unsafe + { + Marshal.Copy(new IntPtr(&structObj), bytes, 0, typeSize); + } +#if true20221030 + // 安全写法效率太低了 + StructToPtr(structObj, structPtr => { + Marshal.Copy(structPtr, bytes, 0, typeSize); + }); +#endif + return bytes; + } + +#if true20221030 + /// + /// 结构体转指针 + /// + /// 要转换的结构体 + /// 输出指针 + /// 释放申请的内存 + /// 是否锁定内存 + /// + public static void StructToPtr(T structObj, + Action? task = null, + bool freeHGlobal = true, + bool lockPrt = true) + { + IntPtr newPtr = Marshal.AllocHGlobal(Marshal.SizeOf(structObj)); + if (newPtr == IntPtr.Zero) + throw new ArgumentException(nameof(newPtr)); + + try + { + // 剪贴板写入的时候不允许锁定内存,否则在频繁触发剪贴板将导致卡死程序 + if (lockPrt) + { + GlobalLockTask(newPtr, ptr => { + // 将结构体拷到分配好的内存空间 + Marshal.StructureToPtr(structObj, newPtr, true); + task?.Invoke(newPtr); + }); + } + else + { + // 将结构体拷到分配好的内存空间 + Marshal.StructureToPtr(structObj, newPtr, true); + task?.Invoke(newPtr); + } + } + catch (Exception e) + { + Debugger.Break(); + Debugx.Printl(e.Message); + } + finally + { + if (freeHGlobal && newPtr != IntPtr.Zero) + Marshal.FreeHGlobal(newPtr); + } + } +#endif + #endregion +} + +public partial class WindowsAPI +{ + #region imm32 + /// + /// 获取输入法的虚拟键码 + /// + /// + /// + [DllImport("imm32.dll")] + public static extern IntPtr ImmGetVirtualKey(IntPtr hWnd); + /// + /// 获取输入法状态 + /// + /// 输入法标识符 + /// 输入模式 + /// 指向函数在其中检索句子模式值的变量的指针 + /// + [DllImport("imm32.dll")] + public static extern bool ImmGetConversionStatus(IntPtr himc, out int lpdw, out int lpdw2); + + /// + /// 获取指定窗口的输入法状态 + /// + /// 窗口句柄 + /// + [DllImport("imm32.dll")] + public static extern IntPtr ImmGetContext(IntPtr hwnd); + /// + /// 设置输入法的当前状态 + /// + /// 窗口句柄 + /// + /// + [DllImport("imm32.dll")] + public static extern bool ImmSetOpenStatus(IntPtr hwnd, bool fOpen); + /// + /// 输入法打开状态 + /// + /// + /// 非0打开,0关闭;(true中文,false英文) + [DllImport("imm32.dll")] + public static extern bool ImmGetOpenStatus(IntPtr hwnd); + #endregion +} + +public partial class WindowsAPI +{ + #region user32 + + /// + /// 获取窗口客户区的大小,客户区为窗口中除标题栏,菜单栏之外的地方 + /// + /// + /// + /// + [DllImport("user32.dll", CharSet = CharSet.Auto, EntryPoint = "GetClientRect")] + public static extern bool GetClientRect(IntPtr hwnd, out IntRect lpRect); + + /// + /// 查找主线程
    + /// 代替
    + /// 托管线程和他们不一样: + ///
    + /// 主窗口 + /// 进程ID + /// 线程ID + [DllImport("user32.dll", SetLastError = true)] + public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId); + + /// + /// 设置焦点 + /// + /// + /// + [DllImport("user32.dll")] + public static extern IntPtr SetFocus(IntPtr hWnd); + + /// + /// 获取当前窗口 + /// + /// 当前窗口标识符 + [DllImport("user32.dll")] + public static extern IntPtr GetForegroundWindow(); + /// + /// 将一个消息的组成部分合成一个消息并放入对应线程消息队列的方法 + /// + /// 控件句柄 + /// 消息是什么。键盘按键、鼠标点击还是其他 + /// + /// + /// + [DllImport("user32.dll")] + public static extern bool PostMessage(IntPtr hhwnd, int msg, IntPtr wparam, IntPtr lparam); + /// + /// 发送击键 + /// + /// + /// + /// + /// + [DllImport("user32.dll", EntryPoint = "keybd_event")] + public static extern void KeybdEvent(byte bVk, byte bScan, int dwFlags, int dwExtraInfo); + /// + /// 获取窗口文字的长度 + /// + /// 窗口标识符 + /// 文字长度 + [DllImport("user32.dll")] + public static extern int GetWindowTextLength(IntPtr hWnd); + /// + /// 获取窗口的标题 + /// + /// 窗口标识符 + /// 窗口文字 + /// 文字长度 + /// + [DllImport("User32.dll", CharSet = CharSet.Auto)] + public static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int nMaxCount); + + // [DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)] + // internal static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount); + + + /// + /// 获取某个线程的输入法布局 + /// + /// 线程ID + /// 布局码 + [DllImport("user32.dll")] + public static extern int GetKeyboardLayout(int threadid); + + + /// + /// 获取按键的当前状态 + /// + /// 按键虚拟代码 + /// 表示没按下>0;按下<0 + [DllImport("user32.dll")] + public static extern short GetKeyState(int nVirtKey); + /// + /// 检索指定窗口所属的类的名称。 + /// + /// 窗口标识符 + /// + /// + /// + [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] + public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount); + + [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] + public static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd); + + [DllImport("user32.DLL", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall, SetLastError = true)] + public static extern IntPtr GetTopWindow(IntPtr hWnd); + + + /// + /// 获取线程对应的窗体信息 + /// + /// 线程 + /// + /// + [DllImport("user32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + static extern bool GetGUIThreadInfo(uint idThread, ref GuiThreadInfo lpgui); + + /// + /// 获取线程对应的窗体信息 + /// + [StructLayout(LayoutKind.Sequential)] + public struct GuiThreadInfo + { + public int cbSize; + public int flags; + public IntPtr hwndActive; + public IntPtr hwndFocus; + public IntPtr hwndCapture; + public IntPtr hwndMenuOwner; + public IntPtr hwndMoveSize; + public IntPtr hwndCaret; + public System.Drawing.Rectangle rcCaret; + + public static GuiThreadInfo Create(uint windowThreadProcessId) + { + if (windowThreadProcessId == 0) + throw new ArgumentNullException(nameof(windowThreadProcessId)); + + GuiThreadInfo gti = new(); + gti.cbSize = Marshal.SizeOf(gti); + GetGUIThreadInfo(windowThreadProcessId, ref gti); + return gti; + } + } + + [DllImport("user32.dll", SetLastError = true)] + public static extern IntPtr GetFocus(); + + [DllImport("user32.dll")] + public static extern IntPtr SendMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam); + + [DllImport("user32.dll", SetLastError = true)] + public static extern IntPtr GetParent(IntPtr hWnd); + + [DllImport("user32.dll")] + public static extern int ToAscii(int uVirtKey, int uScancode, byte[] lpdKeyState, byte[] lpwTransKey, int fuState); + + [DllImport("user32.dll", SetLastError = true)] + public static extern IntPtr GetActiveWindow(); + + [DllImport("user32.dll", SetLastError = true)] + public static extern long GetWindowThreadProcessId(IntPtr hwnd, ref int lpdwProcessId); + + [DllImport("user32.dll", SetLastError = true)] + public static extern bool IsIconic(int hWnd); + + [DllImport("user32.dll")] + public static extern bool IsWindowEnabled(IntPtr hWnd); + #endregion + + #region 键盘钩子 + public delegate IntPtr CallBack(int nCode, int wParam, IntPtr lParam); + [DllImport("user32.dll")] + public static extern IntPtr SetWindowsHookEx(HookType idHook, CallBack lpfn, IntPtr hmod, int dwThreadId); + [DllImport("user32.dll")] + public static extern IntPtr UnhookWindowsHookEx(IntPtr hHook); + [DllImport("user32.dll")] + public static extern IntPtr CallNextHookEx(IntPtr hHook, int ncode, int wParam, IntPtr lParam); + /// + /// Hook键盘数据结构 + /// + [ComVisible(true)] + [Serializable] + //[DebuggerDisplay("{DebuggerDisplay,nq}")] + //[DebuggerTypeProxy(typeof(KeyboardHookStruct))] + [StructLayout(LayoutKind.Sequential)] + public struct KeyboardHookStruct + { + public int VkCode; // 键码,该代码必须有一个价值的范围1至254 + public int ScanCode; // 指定的硬件扫描码的关键 + public int Flags; // 键标志 + public int Time; // 指定的时间戳记的这个讯息 + public int DwExtraInfo; // 指定额外信息相关的信息 + + public static KeyboardHookStruct Create(IntPtr lParam) + { + return (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct)); + } + public void ToPtr(IntPtr lParam) + { + Marshal.StructureToPtr(this, lParam, true); + } + } + /// + /// 注册表增加低级钩子超时处理,防止系统不允许, + /// 否则:偶发性出现 键盘钩子不能用了,而且退出时产生 1404 错误 + /// https://www.cnblogs.com/songr/p/5131655.html + /// + public static void CheckLowLevelHooksTimeout(int setLowLevel = 25000) + { + const string llh = "LowLevelHooksTimeout"; + using var registryKey = Registry.CurrentUser.OpenSubKey("Control Panel\\Desktop", true); + if ((int)registryKey.GetValue(llh, 0) < setLowLevel) + registryKey.SetValue(llh, setLowLevel, RegistryValueKind.DWord); + } + #endregion +} + +public partial class WindowsAPI +{ + [DllImport("user32.dll")] + public static extern bool GetWindowRect(IntPtr hwnd, ref IntRect lpRect); + + [ComVisible(true)] + [Serializable] + [StructLayout(LayoutKind.Sequential)] + [DebuggerDisplay("{DebuggerDisplay,nq}")] + [DebuggerTypeProxy(typeof(IntRect))] + public struct IntRect + { + [DebuggerBrowsable(DebuggerBrowsableState.Never)] + private string DebuggerDisplay => $"(Left:{_Left},Top:{_Top},Right:{_Right},Bottom:{_Bottom})"; + + int _Left; + int _Top; + int _Right; + int _Bottom; + public int Left => _Left; + public int Top => _Top; + public int Right => _Right; + public int Bottom => _Bottom; + public int Width => checked(Right - Left); + public int Height => checked(Bottom - Top); + + public IntRect(int left, int top, int right, int bottom) + { + _Left = left; + _Top = top; + _Right = right; + _Bottom = bottom; + } + + static readonly IntRect _Zero = new(0, 0, 0, 0); + public static IntRect Zero => _Zero; + + public override string ToString() => $"({_Left},{_Top},{_Right},{_Bottom})"; + + #region 重载运算符_比较 + public bool Equals(IntRect other) + { + return + _Left == other._Left && + _Top == other._Top && + _Right == other._Right && + _Bottom == other._Bottom; + } + public static bool operator !=(IntRect a, IntRect b) + { + return !(a == b); + } + public static bool operator ==(IntRect a, IntRect b) + { + return a.Equals(b); + } + public override bool Equals(object obj) + { + return obj is IntRect d && Equals(d); + } + public override int GetHashCode() + { + return ((_Left, _Top).GetHashCode(), _Right).GetHashCode() ^ _Bottom.GetHashCode(); + } + + public IntRect Clone() + { + return (IntRect)MemberwiseClone(); + } + #endregion + } + + [ComVisible(true)] + [Serializable] + [DebuggerDisplay("{DebuggerDisplay,nq}")] + [DebuggerTypeProxy(typeof(IntSize))] + [StructLayout(LayoutKind.Sequential)] + public struct IntSize + { + [DebuggerBrowsable(DebuggerBrowsableState.Never)] + private string DebuggerDisplay => $"(Hight:{Hight},Width:{Width})"; + public int Hight; + public int Width; + + public IntSize(int cx, int cy) + { + Hight = cx; + Width = cy; + } + public override string ToString() => $"({Hight},{Width})"; + } + + [ComVisible(true)] + [Serializable] + [DebuggerDisplay("{DebuggerDisplay,nq}")] + [DebuggerTypeProxy(typeof(Point3D))] + [StructLayout(LayoutKind.Sequential)] + public struct Point3D : IEquatable + { + [DebuggerBrowsable(DebuggerBrowsableState.Never)] + private string DebuggerDisplay => $"(X:{X},Y:{Y},Z:{Z})"; + + /* 由于此类是用来优化,从而实现字段修改,因此直接暴露字段减少栈帧 */ + public double X; + public double Y; + public double Z; + + public Point3D(double x, double y, double z) + { + X = x; + Y = y; + Z = z; + } + //public static implicit operator Point3D(Point3d pt) + //{ + // return new Point3D(pt.X, pt.Y, pt.Z); + //} + //public static implicit operator Point3d(Point3D pt) + //{ + // return new Point3d(pt.X, pt.Y, pt.Z); + //} + public override string ToString() => $"({X},{Y},{Z})"; + + public static Point3D Create(IntPtr lParam) + { + return (Point3D)Marshal.PtrToStructure(lParam, typeof(Point3D)); + } + + public void ToPtr(IntPtr lParam) + { + Marshal.StructureToPtr(this, lParam, true); + } + + + #region 重载运算符_比较 + public bool Equals(Point3D other) + { + return + X == other.X && + Y == other.Y && + Z == other.Z; + } + public static bool operator !=(Point3D a, Point3D b) + { + return !(a == b); + } + public static bool operator ==(Point3D a, Point3D b) + { + return a.Equals(b); + } + public override bool Equals(object obj) + { + return obj is Point3D d && Equals(d); + } + public override int GetHashCode() + { + return (X, Y).GetHashCode() ^ Z.GetHashCode(); + } + #endregion + } +} + +#pragma warning restore CS1591 // 缺少对公共可见类型或成员的 XML 注释 \ No newline at end of file diff --git a/CADShared/CADShared.projitems b/CADShared/CADShared.projitems index 9ecbbab..a807023 100644 --- a/CADShared/CADShared.projitems +++ b/CADShared/CADShared.projitems @@ -17,8 +17,10 @@ + + @@ -55,6 +57,10 @@ + + + + diff --git a/CADShared/PE/AcadPeInfo.cs b/CADShared/PE/AcadPeInfo.cs new file mode 100644 index 0000000..df72756 --- /dev/null +++ b/CADShared/PE/AcadPeInfo.cs @@ -0,0 +1,389 @@ +using System.Diagnostics; + +namespace IFoxCAD.Cad; + +/// +/// 选择模式 +/// +[Flags] +public enum AcadPeEnum : byte +{ + /// + /// AcadExe + /// + AcadExe = 1, + /// + /// AccoreDll + /// + AccoreDll = 2, + /// + /// Acdb + /// + Acdb = 4, + /// + /// ExeAndCore + /// + ExeAndCore = AcadExe | AccoreDll, +} + +/// +/// 这里的枚举对应 GetMethodException 错误值 +/// +[Flags] +public enum GetMethodErrorNum : byte +{ + /// + /// + /// + Ok = 0, + /// + /// + /// + NoModule = 1, + /// + /// + /// + NoFuncName = 2, +} + +/// +/// 自动获取本工程上面的发送命令的接口 +/// +public class AcadPeInfo +{ + #region 静态单例获取exe/dll信息 + static PeInfo? _PeForAcadExe; + /// + /// + /// + public static PeInfo? PeForAcadExe + { + get + { + if (_PeForAcadExe is null) + { + // 获取此acad.exe获取所有的函数名 + var file = Process.GetCurrentProcess().MainModule.FileName; + _PeForAcadExe = new PeInfo(file); + } + return _PeForAcadExe; + } + } + + static PeInfo? _PeForAccoreDll; + /// + /// + /// + public static PeInfo? PeForAccoreDll + { + get + { + if (_PeForAccoreDll is null) + { + // 获取此dll所有的函数名 + var file = Process.GetCurrentProcess().MainModule.FileName; + var dll = Path.GetDirectoryName(file) + "\\accore.dll"; + if (File.Exists(dll))// 08没有,高版本分离的 + _PeForAccoreDll = new PeInfo(dll); + } + return _PeForAccoreDll; + } + } + + static PeInfo? _PeForAcdbDll; + /// + /// + /// + public static PeInfo? PeForAcdbDll + { + get + { + if (_PeForAcdbDll is null) + { + // 获取此dll所有的函数名 + var file = Process.GetCurrentProcess().MainModule.FileName; + var dll = Path.GetDirectoryName(file) + $"\\acdb{Acap.Version.Major}.dll"; + if (File.Exists(dll)) + _PeForAcdbDll = new PeInfo(dll); + } + return _PeForAcdbDll; + } + } + + List? _Methods; // 这个不是静态的 + /// + /// 同名函数指针们 + /// + public List? Methods + { + get + { + if (_Methods is null) + { + _Methods = new(); + + if ((_acadPeEnum & AcadPeEnum.AcadExe) == AcadPeEnum.AcadExe) + GetPeMethod(PeForAcadExe); + if ((_acadPeEnum & AcadPeEnum.AccoreDll) == AcadPeEnum.AccoreDll) + GetPeMethod(PeForAccoreDll); + if ((_acadPeEnum & AcadPeEnum.Acdb) == AcadPeEnum.Acdb) + GetPeMethod(PeForAcdbDll); + } + return _Methods; + } + } + #endregion + + #region 字段/构造 + /// + /// 用于查找PE不带修饰的函数名 + /// + string _findFuncName; + /// + /// 枚举查找对象 + /// + AcadPeEnum _acadPeEnum; + + /// + /// 通过函数名获取指针,指定类型 + /// + /// 不带修饰的函数名 + /// 读取哪个cad内部文件的枚举(目前只支持两个) + public AcadPeInfo(string methodName, AcadPeEnum acadPeEnum) + { + _findFuncName = methodName; + _acadPeEnum = acadPeEnum; + } + + /// + /// 获取CAD的函数指针 + /// + /// 委托 + /// 不带修饰的函数名 + /// 读取哪个cad内部文件的枚举(目前只支持两个) + /// 委托 + public static TDelegate? GetDelegate(string methodName, AcadPeEnum acadPeEnum) + where TDelegate : class + { + return new AcadPeInfo(methodName, acadPeEnum) + .GetDelegate(); + } + #endregion + + #region 方法 + /// + /// 储存旧值,去除修饰函数名(查找的),带修饰函数名们 + /// + static Dictionary> _Dict = new(); + + /// + /// 返回函数指针 + /// + /// Pe信息:可能来自exe/dll + /// 错误信息 + GetMethodErrorNum GetPeMethod(PeInfo? peInfo) + { + if (peInfo == null) + return GetMethodErrorNum.NoFuncName;// cad08需要检查 AccoreDll 的时候跳过 + + var identifyStr = _findFuncName + ";" + peInfo.FullName; + if (_Dict.ContainsKey(identifyStr))// 如果已经找过,直接返回 + { + _Methods = _Dict[identifyStr]; + } + else + { + _Methods ??= new(); + try + { + PeFunction.Finds(peInfo, _findFuncName, _Methods); + if (_Methods.Count != 0)// 此时从不含有 + _Dict.Add(identifyStr, _Methods); + } + catch (GetPeMethodException ex) + { return (GetMethodErrorNum)ex.ErrorNum; } + } + return GetMethodErrorNum.Ok; + } + + /// + /// 转为委托 + /// + /// 委托对象 + /// + public TDelegate? GetDelegate() where TDelegate : class + { + if (Methods is null || Methods.Count == 0) + return null; + + TDelegate? func = null; + + /* + * 0x01 + * 这里永远不报错,但是不代表不会出错. + * 调用C盘exe/dll时需要权限, + * 所以会出现:[DLLImport]可以,直接运行cad也可以,但是调试不行. + * 此时可以提权vs再调试,有时候会出现:调试不显示东西,但是运行是对的. + * + * 0x02 + * 出错时候用完整的修饰名 + * + * 0x03 + * 这里可能同时存在acad.exe和accore.dll相同指针? + * 所以我是用排序方法找最短的指针,所以它是第First个. + */ + + // 排序,最少长度原则本身就是让完全相同字符串在最前面 + // 这里替换为有序哈希,因为我总是需要不带修饰的返回函数,所以是排序长度的第一个 + _Methods = _Methods.OrderBy(str => str.CName?.Length) + .ThenBy(str => str.MethodName.Length) + .ToList(); + + func = Marshal.GetDelegateForFunctionPointer(Methods.First().GetProcAddress(), typeof(TDelegate)) as TDelegate; + return func; + } + #endregion +} + +/// +/// 通过名字查找exe/dll内所有名字 +/// +public class PeFunction +{ + #region 字段/构造 + string? _CName; + /// + /// 纯c语言名 + /// + public string? CName + { + get + { + if (_CName is null && MethodName is not null) + { + _CName = MethodName.Replace("?", string.Empty); // 剔除cpp前缀 + int num = _CName.IndexOf("@"); + if (num > -1) + _CName = _CName.Substring(0, num); // 剔除参数部分 + } + return _CName; + } + } + + /// + /// 模块文件路径 + /// + public string? ModuleFullName; + /// + /// 模块指针 + /// + public IntPtr ModuleIntPtr; + /// + /// 函数名 + /// + public string MethodName; + /// + /// 通过名字查找exe/dll内所有名字 + /// + /// 没修饰的方法名 + public PeFunction(string methodName) + { + MethodName = methodName; + } + #endregion + + /// + /// 获取函数指针 + /// + public IntPtr GetProcAddress() + { + return WindowsAPI.GetProcAddress(ModuleIntPtr, MethodName); + } + + /// + /// 通过名字查找exe/dll内所有名字 + /// + /// pe结构 + /// 用于查找的方法名 + /// 返回函数集合 + public static void Finds(PeInfo peInfo, + string findFuncName, + List funcAdress_Out) + { + if (findFuncName == null) + throw new GetPeMethodException(2, "没有找到对应的函数:" + findFuncName); + + var peModuleFullName = peInfo.FullName; + if (peModuleFullName == null) + throw new GetPeMethodException(1, "找不到模块:" + peModuleFullName + "当前程序没有加载这个东西?"); + var hModule = WindowsAPI.GetModuleHandle(peModuleFullName); // 执行前必须加载了先,acad.exe/accore.dll + if (hModule == IntPtr.Zero) + throw new GetPeMethodException(1, "找不到模块:" + peModuleFullName + "当前程序没有加载这个东西?"); + + // 遍历函数接口名单 + var names = peInfo.ExportDirectory?.FunctionNames(); + if (names == null) + throw new ArgumentException(nameof(names)); + + foreach (var name in names) + { + if (name.Contains(findFuncName))// 这里是名称含有,不是容器含有 + { + var fn = new PeFunction(name) + { + ModuleFullName = peModuleFullName, + ModuleIntPtr = hModule + }; + funcAdress_Out.Add(fn); + } + } + } +} + + + +/// +/// 错误信息 +/// +public class GetPeMethodException : ApplicationException +{ + /// + /// + /// + public int ErrorNum; + /// + /// + /// + public string? ErrorMsg; + /// + /// + /// + public Exception? InnerException1; + /// + /// + /// + /// + public GetPeMethodException(string msg) : base(msg) + { + ErrorMsg = msg; + } + /// + /// + /// + /// + /// + public GetPeMethodException(int errorNum, string msg) : base(msg) + { + ErrorNum = errorNum; + } + /// + /// + /// + /// + /// + public GetPeMethodException(string msg, Exception innerException) : base(msg, innerException) + { + InnerException1 = innerException; + ErrorMsg = msg; + } +} \ No newline at end of file diff --git a/CADShared/PE/DBmod.cs b/CADShared/PE/DBmod.cs new file mode 100644 index 0000000..b45a033 --- /dev/null +++ b/CADShared/PE/DBmod.cs @@ -0,0 +1,120 @@ +namespace IFoxCAD.Cad; + +/// +/// 获取数据库修改状态 +/// +/// 相关链接 +/// +[Flags] +public enum DBmod : short +{ + /// + /// 数据库未修改 + /// + [Description("数据库未修改")] + DatabaseNoModifies = 0, + /// + /// 数据库有修改 + /// + [Description("数据库有修改")] + Database = 1, + /// + /// 变量有修改 + /// + [Description("变量有修改")] + Value = 4, + /// + /// 窗口有修改 + /// + [Description("窗口有修改")] + Window = 8, + /// + /// 视图有修改 + /// + [Description("视图有修改")] + View = 16, + /// + /// 字段有修改 + /// + [Description("字段有修改")] + Field = 32 +} +/// +/// 图形修改状态 +/// +public class DBmodEx +{ + /// + /// 图形修改状态 + /// + public static DBmod DBmod => (DBmod)Env.GetVar("dbmod"); + + delegate long DelegateAcdbSetDbmod(IntPtr db, DBmod newValue); + static DelegateAcdbSetDbmod? acdbSetDbmod;//别改名称 + /// + /// 设置图形修改状态 + /// + /// 数据库的指针 + /// 修改状态 + /// + public static long AcdbSetDbmod(IntPtr db, DBmod newValue) + { + acdbSetDbmod ??= AcadPeInfo.GetDelegate( + nameof(acdbSetDbmod), AcadPeEnum.Acdb); + if (acdbSetDbmod is null) + return -1; + return acdbSetDbmod.Invoke(db, newValue);// 调用方法 + } + + /// + /// Dbmod 不被修改的任务 + /// + /// + public static void DBmodTask(Action action) + { + var dm = Acap.DocumentManager; + if (dm.Count == 0) + return; + var doc = dm.MdiActiveDocument; + if (doc is null) + return; + + var bak = DBmod; + action.Invoke(); + if (bak == DBmod.DatabaseNoModifies && DBmod != DBmod.DatabaseNoModifies) + AcdbSetDbmod(doc.Database.UnmanagedObject, DBmod.DatabaseNoModifies); + } + + static bool _flag = true; + /// + /// 请在无法处理的初始化才使用它 + /// (源泉在初始化的时候进行了修改数据库,所以必须要用一个新线程等待lisp执行完成才可以) + /// + public static void DatabaseNoModifies() + { + if (_flag)// 仅执行一次,在初始化时候 + { + var dm = Acap.DocumentManager; + if (dm.Count == 0) + return; + var doc = dm.MdiActiveDocument; + if (doc is null) + return; + + if (DBmod != DBmod.DatabaseNoModifies) + AcdbSetDbmod(doc.Database.UnmanagedObject, DBmod.DatabaseNoModifies); + _flag = false; + } + } + + + //[CommandMethod(nameof(TestCmd_AcdbSetDbmodChange))] + //public void TestCmd_AcdbSetDbmodChange() + //{ + // DBmodTask(() => { + // using DBTrans tr = new(); + // Line line = new(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); + // tr.CurrentSpace.AddEntity(line); + // }); + //} +} \ No newline at end of file diff --git a/CADShared/PE/PostCmd.cs b/CADShared/PE/PostCmd.cs new file mode 100644 index 0000000..7e70074 --- /dev/null +++ b/CADShared/PE/PostCmd.cs @@ -0,0 +1,237 @@ +namespace IFoxCAD.Cad; +/// +/// 发送命令 +/// +public class PostCmd +{ + /* + * #if NET35 || NET40 + * [DllImport("acad.exe", EntryPoint = "acedCmd", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)] + * #else + * // cad2015的AcedCmd改为AcedCmdS.参数也改了,不过不影响pe读取,accore.dll是2013版本后才开始改 + * [DllImport("accore.dll", EntryPoint = "acedCmdS", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)] + * static extern int AcedCmd(IntPtr rbp, bool forFutureUse = false, IntPtr pForFutureUse = IntPtr.Zero); + * #endif + * static extern int AcedCmd(IntPtr rbp); + * public static int AcedCmd(ResultBuffer args) + * { + * if (Acap.DocumentManager.IsApplicationContext) + * return 0; + * else + * return AcedCmd(args.UnmanagedObject); + * } + */ + delegate int DelegateAcedCmd(IntPtr parameter); + static DelegateAcedCmd? acedCmd;//nameof 别改名称 + /// + /// 发送命令(同步)如果2015.+这里报错,那么表示vs需要提权测试 + /// + static PromptStatus AcedCmd(ResultBuffer args) + { + if (Acap.DocumentManager.IsApplicationContext) + return 0; + if (acedCmd is null) + { + string str = nameof(acedCmd); + if (Acap.Version.Major >= 20)// 2015.+ + str += "S"; + + acedCmd = AcadPeInfo.GetDelegate( + str, AcadPeEnum.ExeAndCore); + } + if (acedCmd is null) + return 0; + + var result = (PromptStatus)acedCmd.Invoke(args.UnmanagedObject); + if (result != PromptStatus.OK) + throw new ArgumentException("发送命令出错,是否vs权限不足?"); + return result; + } + + /* + * [DllImport("accore.dll", EntryPoint = "acedCommand")] + * static extern int AcedCommand(IntPtr vlist); + */ + delegate int DelegateAcedCommand(IntPtr parameter); + static DelegateAcedCommand? acedCommand;//nameof 别改名称 + /// + /// 发送命令(同步) + /// + static PromptStatus AcedCommand(IntPtr args) + { + acedCommand ??= AcadPeInfo.GetDelegate( + nameof(acedCommand), AcadPeEnum.ExeAndCore); + if (acedCommand is null) + return PromptStatus.Error; + return (PromptStatus)acedCommand.Invoke(args);// 调用方法 + } + + /* + * [DllImport("acad.exe", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, + * EntryPoint = "?acedPostCommand@@YAHPB_W@Z")] + * public static extern int AcedPostCommand(string strExpr); + */ + delegate int DelegateAcedPostCommand(byte[] parameter); + static DelegateAcedPostCommand? acedPostCommand;//nameof 别改名称 + /// + /// 发送命令(同步) + /// 这个可以在多线程发送 + /// + static PromptStatus AcedPostCommand(string args) + { + acedPostCommand ??= AcadPeInfo.GetDelegate( + nameof(acedPostCommand), AcadPeEnum.ExeAndCore); + + // 不然到CAD之后会乱码 + byte[] bytes = Encoding.Unicode.GetBytes(args); + if (acedPostCommand is null) + return PromptStatus.Error; + return (PromptStatus)acedPostCommand.Invoke(bytes);// 调用方法 + } + + delegate int DelegateAcedInvoke(byte[] parameter); + static DelegateAcedInvoke? acedInvoke;//nameof 别改名称 + /// + /// 发送命令(同步) + /// + static PromptStatus AcedInvoke(string args) + { + acedInvoke ??= AcadPeInfo.GetDelegate( + nameof(acedInvoke), AcadPeEnum.ExeAndCore); + + // 不然到CAD之后会乱码 + byte[] bytes = Encoding.Unicode.GetBytes(args); + + if (acedInvoke is null) + return PromptStatus.Error; + return (PromptStatus)acedInvoke.Invoke(bytes);// 调用方法 + } + + /// + /// 发送命令(异步)+CommandFlags.Session可以同步发送 + /// + static void AsyncCommand(string args) + { + object[] commandArray = { args + "\n" }; +#if zcad + var com = Acap.ZcadApplication; +#else + var com = Acap.AcadApplication; +#endif + // activeDocument 加载lisp第二个文档有问题,似乎要切换了才能 + var doc = com.GetType() + .InvokeMember("ActiveDocument", BindingFlags.GetProperty, null, com, null); + doc?.GetType() + .InvokeMember("SendCommand", BindingFlags.InvokeMethod, null, doc, commandArray);// 返回值是null + } + /// + /// 命令模式 + /// + public enum RunCmdFlag : byte + { + /// + /// 发送命令(同步)如果2015.+这里报错,那么表示vs需要提权测试 + /// + AcedCmd = 1, + /// + /// 发送命令(同步) + /// + AcedCommand = 2, + /// + /// 发送命令(同步),可以多线程 + /// + AcedPostCommand = 4, + /// + /// 发送命令(同步) + /// + AcedInvoke = 8, + /// + /// 默认的发送命令 + /// + SendStringToExecute = 16, + /// + /// 异步命令 + /// + AsyncCommand = 32, + } + + /* + * 发送命令会记录在命令历史 + * 发送lisp的(command "xx")就不会 + */ + /// + /// 发送命令 + /// + /// + /// + public static PromptStatus SendCommand(ResultBuffer args) + { + return AcedCmd(args); + } + /// + /// 发送命令 + /// + /// + /// + public static PromptStatus SendCommand(IntPtr args) + { + return AcedCommand(args); + } + /// + /// 发送命令 + /// + /// + /// + /// + public static PromptStatus SendCommand(string args, RunCmdFlag flag) + { + PromptStatus ret = PromptStatus.OK; + if (!Acap.DocumentManager.IsApplicationContext) + { + if ((flag & RunCmdFlag.AcedCmd) == RunCmdFlag.AcedCmd) + { + using ResultBuffer rb = new() + { + new((int)LispDataType.Text, args), + }; + ret = SendCommand(rb); + } + if ((flag & RunCmdFlag.AcedCommand) == RunCmdFlag.AcedCommand) + { + // 此处是这样转换吗? + using ResultBuffer rb = new() + { + new((int)LispDataType.Text, args), + }; + ret = SendCommand(rb.UnmanagedObject); + } + if ((flag & RunCmdFlag.AcedPostCommand) == RunCmdFlag.AcedPostCommand) + { + ret = AcedPostCommand(args); + } + if ((flag & RunCmdFlag.AcedInvoke) == RunCmdFlag.AcedInvoke) + { + ret = AcedInvoke(args); + } + } + else + { + var dm = Acap.DocumentManager; + var doc = dm.MdiActiveDocument; + if (doc == null) + return PromptStatus.Error; + + if ((flag & RunCmdFlag.SendStringToExecute) == RunCmdFlag.SendStringToExecute) + { + doc.SendStringToExecute(args, true, false, false); + } + if ((flag & RunCmdFlag.AsyncCommand) == RunCmdFlag.AsyncCommand) + { + // 此处+CommandFlags.Session可以同步发送,bo命令可以,其他是否可以? + // 仿人工输入,像lisp一样可以直接发送关键字 + AsyncCommand(args); + } + } + return ret; + } +} \ No newline at end of file diff --git a/CADShared/PE/ProgramPE.cs b/CADShared/PE/ProgramPE.cs new file mode 100644 index 0000000..32208fc --- /dev/null +++ b/CADShared/PE/ProgramPE.cs @@ -0,0 +1,1576 @@ +#pragma warning disable CS1591 // 缺少对公共可见类型或成员的 XML 注释 +namespace IFoxCAD.Cad; + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.IO; +using System.Text; + + +/* 来源 https://blog.csdn.net/zgke/article/details/2955560 我在他基础上面增加了X64的处理 + * 调用例子 + static void Main(string[] args) + { + var path = @"C:\Program Files\Autodesk\AutoCAD 2021\acad.exe"; + // path = @"G:\AutoCAD 2008\acad.exe"; + + var pe = new JoinBox.BasalCurrency.PeInfo(path); + + // 输出所有的函数名 + var sb = new StringBuilder(); + foreach (var item in pe.ExportDirectory.NameList) + { + sb.Append(Environment.NewLine); + var str = System.Text.Encoding.Default.GetString(item as byte[]); + sb.Append(str); + } + Debugx.Printl(sb.ToString()); + + // 原作者的封装 + var ss = pe.GetPETable(); + foreach (var item in ss.Tables) + { + } + } +*/ + +/// +/// 微软软件结构PE信息 +/// +public class PeInfo +{ + #region 成员 + /// + /// 获取是否正常打开文件 + /// + public bool OpenFile { get; private set; } = false; + + public DosHeader? DosHeader { get; private set; } + + public DosStub? DosStub { get; private set; } + public PEHeader? PEHeader { get; private set; } + public OptionalHeader? OptionalHeader { get; private set; } + public OptionalDirAttrib? OptionalDirAttrib { get; private set; } + public SectionTable? SectionTable { get; private set; } + /// + /// 函数接口名单 + /// + public ExportDirectory? ExportDirectory { get; private set; } + public ImportDirectory? ImportDirectory { get; private set; } + public ResourceDirectory? ResourceDirectory { get; private set; } + /// + /// PE文件完整路径 + /// + public string? FullName; + + bool _IsX86 = true; + + /// + /// 全部文件数据 + /// + readonly byte[]? _PEFileByte; + /// + /// 文件读取的位置 + /// + long _PEFileIndex = 0; + #endregion + + #region 构造 + /// + /// 构造函数 + /// + /// + /// + public PeInfo(string fullName) + { + if (fullName is null) + throw new ArgumentException(nameof(fullName)); ; + + FullName = fullName; + FileStream? file = null; + OpenFile = false; + try + { + // 文件流 + file = new FileStream(fullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);// FileShare才能进c盘 + _PEFileByte = new byte[file.Length]; + file.Read(_PEFileByte, 0, _PEFileByte.Length); + LoadFile(); + OpenFile = true; + } + catch (Exception) { throw; } + finally + { + file?.Close(); + } + } + #endregion + + #region 读表方法 + /// + /// 开始读取 + /// + private void LoadFile() + { + LoadDosHeader(); // 获取DOS头,为了兼容DOS所以首先处理这个,然后才到PE头 + LoadDosStub(); // 获取DOS的身体 + LoadPEHeader(); // PE头 + LoadOptionalHeader(); // PE头扩展 + LoadOptionalDirAttrib(); // 获取选项目录属性 + LoadSectionTable(); // 获取节表 + LoadExportDirectory(); // 获取输出表 + LoadImportDirectory(); // 获取输入表 + LoadResourceDirectory(); // 获取资源目录 + } + + /// + /// 获得DOS头 + /// + private void LoadDosHeader() + { + DosHeader = new DosHeader + { + FileStarIndex = _PEFileIndex + }; + Loadbyte(ref DosHeader.e_magic); + Loadbyte(ref DosHeader.e_cblp); + Loadbyte(ref DosHeader.e_cp); + Loadbyte(ref DosHeader.e_crlc); + Loadbyte(ref DosHeader.e_cparhdr); + Loadbyte(ref DosHeader.e_minalloc); + Loadbyte(ref DosHeader.e_maxalloc); + Loadbyte(ref DosHeader.e_ss); + Loadbyte(ref DosHeader.e_sp); + Loadbyte(ref DosHeader.e_csum); + Loadbyte(ref DosHeader.e_ip); + Loadbyte(ref DosHeader.e_cs); + Loadbyte(ref DosHeader.e_rva); + Loadbyte(ref DosHeader.e_fg); + Loadbyte(ref DosHeader.e_bl1); + Loadbyte(ref DosHeader.e_oemid); + Loadbyte(ref DosHeader.e_oeminfo); + Loadbyte(ref DosHeader.e_bl2); + Loadbyte(ref DosHeader.e_PESTAR); + + DosHeader.FileEndIndex = _PEFileIndex; + } + + /// + /// 获得DOS SUB字段 + /// + private void LoadDosStub() + { + if (DosHeader is null) + return; + + long Size = GetLong(DosHeader.e_PESTAR) - _PEFileIndex; // 获得SUB的大小 + DosStub = new DosStub(Size) + { + FileStarIndex = _PEFileIndex + }; + Loadbyte(ref DosStub.DosStubData); + DosStub.FileEndIndex = _PEFileIndex; + } + + /// + /// 获得PE的文件头 + /// + /// + private void LoadPEHeader() + { + PEHeader = new PEHeader + { + FileStarIndex = _PEFileIndex + }; + Loadbyte(ref PEHeader.Header); + Loadbyte(ref PEHeader.Machine);// [76 1]==[0x4C 1]是x32, + _IsX86 = PEHeader.Machine[0] == 0x4c && PEHeader.Machine[1] == 0x1; + // (PEHeader.Machine[0] == 0x64 && PEHeader.Machine[1] == 0x86)// x64 + Loadbyte(ref PEHeader.NumberOfSections); + Loadbyte(ref PEHeader.TimeDateStamp); + Loadbyte(ref PEHeader.PointerToSymbolTable); + Loadbyte(ref PEHeader.NumberOfSymbols); + Loadbyte(ref PEHeader.SizeOfOptionalHeader); + Loadbyte(ref PEHeader.Characteristics); + PEHeader.FileEndIndex = _PEFileIndex; + } + + /// + /// 获得OPTIONAL PE扩展属性 + /// + /// + private void LoadOptionalHeader() + { + // 这里必须通过PE文件来判断它是一个什么架构,从而使用x86-x64 + OptionalHeader = new OptionalHeader(_IsX86) + { + FileStarIndex = _PEFileIndex + }; + Loadbyte(ref OptionalHeader.Magic); + Loadbyte(ref OptionalHeader.MajorLinkerVersion); + Loadbyte(ref OptionalHeader.MinorLinkerVersion); + Loadbyte(ref OptionalHeader.SizeOfCode); + Loadbyte(ref OptionalHeader.SizeOfInitializedData); + Loadbyte(ref OptionalHeader.SizeOfUninitializedData); + Loadbyte(ref OptionalHeader.AddressOfEntryPoint); + Loadbyte(ref OptionalHeader.BaseOfCode); + Loadbyte(ref OptionalHeader.ImageBase); + Loadbyte(ref OptionalHeader.BaseOfData); + Loadbyte(ref OptionalHeader.SectionAlignment); + Loadbyte(ref OptionalHeader.FileAlignment); + + Loadbyte(ref OptionalHeader.MajorOperatingSystemVersion); + Loadbyte(ref OptionalHeader.MinorOperatingSystemVersion); + Loadbyte(ref OptionalHeader.MajorImageVersion); + Loadbyte(ref OptionalHeader.MinorImageVersion); + Loadbyte(ref OptionalHeader.MajorSubsystemVersion); + Loadbyte(ref OptionalHeader.MinorSubsystemVersion); + Loadbyte(ref OptionalHeader.Win32VersionValue); + Loadbyte(ref OptionalHeader.SizeOfImage); + Loadbyte(ref OptionalHeader.SizeOfHeards); + Loadbyte(ref OptionalHeader.CheckSum); + Loadbyte(ref OptionalHeader.Subsystem); + Loadbyte(ref OptionalHeader.DLLCharacteristics); + Loadbyte(ref OptionalHeader.SizeOfStackReserve); + Loadbyte(ref OptionalHeader.SizeOfStackCommit); + Loadbyte(ref OptionalHeader.SizeOfHeapReserve); + Loadbyte(ref OptionalHeader.SizeOfHeapCommit); + Loadbyte(ref OptionalHeader.LoaderFlags); + Loadbyte(ref OptionalHeader.NumberOfRvaAndSizes); + + OptionalHeader.FileEndIndex = _PEFileIndex; + } + + /// + /// 获取目录表 + /// + /// + private void LoadOptionalDirAttrib() + { + if (OptionalHeader is null) + return; + + OptionalDirAttrib = new OptionalDirAttrib + { + FileStarIndex = _PEFileIndex + }; + + long DirCount = GetLong(OptionalHeader.NumberOfRvaAndSizes);// 这里导致无法使用64位 + for (int i = 0; i != DirCount; i++) + { + OptionalDirAttrib.DirAttrib? directAttrib = new(); + Loadbyte(ref directAttrib.DirRva); + Loadbyte(ref directAttrib.DirSize); + OptionalDirAttrib.DirByte.Add(directAttrib); + } + OptionalDirAttrib.FileEndIndex = _PEFileIndex; + } + + /// + /// 获取节表 + /// + private void LoadSectionTable() + { + if (PEHeader is null) + return; + + SectionTable = new SectionTable(); + long Count = GetLong(PEHeader.NumberOfSections); + SectionTable.FileStarIndex = _PEFileIndex; + for (long i = 0; i != Count; i++) + { + var Section = new SectionTable.SectionData(); + + Loadbyte(ref Section.SectName); + Loadbyte(ref Section.VirtualAddress); + Loadbyte(ref Section.SizeOfRawDataRVA); + Loadbyte(ref Section.SizeOfRawDataSize); + Loadbyte(ref Section.PointerToRawData); + Loadbyte(ref Section.PointerToRelocations); + Loadbyte(ref Section.PointerToLinenumbers); + Loadbyte(ref Section.NumberOfRelocations); + Loadbyte(ref Section.NumberOfLinenumbers); + Loadbyte(ref Section.Characteristics); + SectionTable.Section.Add(Section); + } + SectionTable.FileEndIndex = _PEFileIndex; + } + + /// + /// 读取输出表 + /// + private void LoadExportDirectory() + { + if (OptionalDirAttrib is null) + return; + if (OptionalDirAttrib.DirByte.Count == 0) + return; + + if (OptionalDirAttrib.DirByte[0] is not OptionalDirAttrib.DirAttrib exporRVA || + GetLong(exporRVA.DirRva) == 0) + return; + + long exporAddress = GetLong(exporRVA.DirRva); // 获取的位置 + ExportDirectory = new ExportDirectory(); + + if (SectionTable is null) + return; + + for (int i = 0; i != SectionTable.Section.Count; i++) // 循环节表 + { + if (SectionTable.Section[i] is not SectionTable.SectionData sect) + continue; + + long starRva = GetLong(sect.SizeOfRawDataRVA); + long endRva = GetLong(sect.SizeOfRawDataSize); + + if (exporAddress >= starRva && exporAddress < starRva + endRva) + { + _PEFileIndex = exporAddress - GetLong(sect.SizeOfRawDataRVA) + GetLong(sect.PointerToRawData); + + ExportDirectory.FileStarIndex = _PEFileIndex; + ExportDirectory.FileEndIndex = _PEFileIndex + GetLong(exporRVA.DirSize); + + Loadbyte(ref ExportDirectory.Characteristics); + Loadbyte(ref ExportDirectory.TimeDateStamp); + Loadbyte(ref ExportDirectory.MajorVersion); + Loadbyte(ref ExportDirectory.MinorVersion); + Loadbyte(ref ExportDirectory.Name); + Loadbyte(ref ExportDirectory.Base); + Loadbyte(ref ExportDirectory.NumberOfFunctions); + Loadbyte(ref ExportDirectory.NumberOfNames); + Loadbyte(ref ExportDirectory.AddressOfFunctions); + Loadbyte(ref ExportDirectory.AddressOfNames); + Loadbyte(ref ExportDirectory.AddressOfNameOrdinals); + + _PEFileIndex = GetLong(ExportDirectory.AddressOfFunctions) - GetLong(sect.SizeOfRawDataRVA) + GetLong(sect.PointerToRawData); + long endIndex = GetLong(ExportDirectory.AddressOfNames) - GetLong(sect.SizeOfRawDataRVA) + GetLong(sect.PointerToRawData); + long numb = (endIndex - _PEFileIndex) / 4; + for (long z = 0; z != numb; z++) + { + byte[] Data = new byte[4]; + Loadbyte(ref Data); + ExportDirectory.AddressOfFunctionsList.Add(Data); + } + + _PEFileIndex = endIndex; + endIndex = GetLong(ExportDirectory.AddressOfNameOrdinals) - GetLong(sect.SizeOfRawDataRVA) + GetLong(sect.PointerToRawData); + numb = (endIndex - _PEFileIndex) / 4; + for (long z = 0; z != numb; z++) + { + byte[] Data = new byte[4]; + Loadbyte(ref Data); + ExportDirectory.AddressOfNamesList.Add(Data); + } + + _PEFileIndex = endIndex; + endIndex = GetLong(ExportDirectory.Name) - GetLong(sect.SizeOfRawDataRVA) + GetLong(sect.PointerToRawData); + numb = (endIndex - _PEFileIndex) / 2; + for (long z = 0; z != numb; z++) + { + byte[] Data = new byte[2]; + Loadbyte(ref Data); + ExportDirectory.AddressOfNameOrdinalsList.Add(Data); + } + + _PEFileIndex = endIndex; + + if (_PEFileByte is not null) + { + long ReadIndex = 0; + while (true) + { + if (_PEFileByte[_PEFileIndex + ReadIndex] == 0) + { + if (_PEFileByte[_PEFileIndex + ReadIndex + 1] == 0) + break; + + var Date = new byte[ReadIndex]; + Loadbyte(ref Date); + ExportDirectory.FunctionNamesByte.Add(Date); + + _PEFileIndex++; + ReadIndex = 0; + } + ReadIndex++; + } + } + break; + } + } + } + + /// + /// 读取输入表 + /// + private void LoadImportDirectory() + { + if (OptionalDirAttrib is null) + return; + if (OptionalDirAttrib.DirByte.Count < 1) + return; + if (OptionalDirAttrib.DirByte[1] is not OptionalDirAttrib.DirAttrib ImporRVA) + return; + + long ImporAddress = GetLong(ImporRVA.DirRva); // 获取的位置 + if (ImporAddress == 0) + return; + long ImporSize = GetLong(ImporRVA.DirSize); // 获取大小 + + ImportDirectory = new ImportDirectory(); + + long SizeRva = 0; + long PointerRva = 0; + + long StarRva = 0; + long EndRva = 0; + + #region 获取位置 + if (SectionTable is null) + return; + for (int i = 0; i != SectionTable.Section.Count; i++) // 循环节表 + { + if (SectionTable.Section[i] is not SectionTable.SectionData Sect) + continue; + + StarRva = GetLong(Sect.SizeOfRawDataRVA); + EndRva = GetLong(Sect.SizeOfRawDataSize); + + if (ImporAddress >= StarRva && ImporAddress < StarRva + EndRva) + { + SizeRva = GetLong(Sect.SizeOfRawDataRVA); + PointerRva = GetLong(Sect.PointerToRawData); + _PEFileIndex = ImporAddress - SizeRva + PointerRva; + + ImportDirectory.FileStarIndex = _PEFileIndex; + ImportDirectory.FileEndIndex = _PEFileIndex + ImporSize; + break; + } + } + + if (SizeRva == 0 && PointerRva == 0) + return; + #endregion + + #region 输入表结构 + while (true) + { + var import = new ImportDirectory.ImportDate(); + Loadbyte(ref import.OriginalFirstThunk); + Loadbyte(ref import.TimeDateStamp); + Loadbyte(ref import.ForwarderChain); + Loadbyte(ref import.Name); + Loadbyte(ref import.FirstThunk); + + if (GetLong(import.Name) == 0) + break; + ImportDirectory.ImportList.Add(import); // 添加 + } + #endregion + + + #region 获取输入DLL名称 + for (int z = 0; z != ImportDirectory.ImportList.Count; z++) // 获取引入DLL名字 + { + if (ImportDirectory.ImportList[z] is not ImportDirectory.ImportDate Import) + continue; + + long ImportDLLName = GetLong(Import.Name) - SizeRva + PointerRva; + _PEFileIndex = ImportDLLName; + long ReadCount = 0; + while (_PEFileByte is not null) // 获取引入名 + { + if (_PEFileByte[_PEFileIndex + ReadCount] == 0) + { + Import.DLLName = new byte[ReadCount]; + Loadbyte(ref Import.DLLName); + break; + } + ReadCount++; + } + } + #endregion + + #region 获取引入方法 先获取地址 然后获取名字和头 + for (int z = 0; z != ImportDirectory.ImportList.Count; z++) // 获取引入方法 + { + if (ImportDirectory.ImportList[z] is not ImportDirectory.ImportDate import) + continue; + + long importDLLName = GetLong(import.OriginalFirstThunk) - SizeRva + PointerRva; + _PEFileIndex = importDLLName; + while (true) + { + var function = new ImportDirectory.ImportDate.FunctionList(); + Loadbyte(ref function.OriginalFirst); + + long loadIndex = GetLong(function.OriginalFirst); + if (loadIndex == 0) + break; + long oldIndex = _PEFileIndex; + + _PEFileIndex = loadIndex - SizeRva + PointerRva; + + if (loadIndex >= StarRva && loadIndex < StarRva + EndRva) // 发现有些数字超级大 + { + int ReadCount = 0; + + while (_PEFileByte is not null) + { + if (ReadCount == 0) + Loadbyte(ref function.FunctionHead); + if (_PEFileByte[_PEFileIndex + ReadCount] == 0) + { + byte[] FunctionName = new byte[ReadCount]; + Loadbyte(ref FunctionName); + function.FunctionName = FunctionName; + + break; + } + ReadCount++; + } + } + else + { + function.FunctionName = new byte[1]; + } + + _PEFileIndex = oldIndex; + import.DLLFunctionList.Add(function); + } + } + #endregion + } + + /// + /// 读取资源表 + /// + private void LoadResourceDirectory() + { + #region 初始化 + if (OptionalDirAttrib is null || OptionalDirAttrib.DirByte.Count < 3) + return; + if (OptionalDirAttrib.DirByte[2] is not OptionalDirAttrib.DirAttrib ImporRVA) + return; + + long ImporAddress = GetLong(ImporRVA.DirRva); // 获取的位置 + if (ImporAddress == 0) + return; + long ImporSize = GetLong(ImporRVA.DirSize); // 获取大小 + + ResourceDirectory = new ResourceDirectory(); + + long SizeRva = 0; + long PointerRva = 0; + long StarRva = 0; + long PEIndex = 0; + #endregion + + #region 获取位置 + if (SectionTable is null) + return; + + for (int i = 0; i != SectionTable.Section.Count; i++) // 循环节表 + { + if (SectionTable.Section[i] is not SectionTable.SectionData sect) + continue; + + StarRva = GetLong(sect.SizeOfRawDataRVA); + var EndRva = GetLong(sect.SizeOfRawDataSize); + if (ImporAddress >= StarRva && ImporAddress < StarRva + EndRva) + { + SizeRva = GetLong(sect.SizeOfRawDataRVA); + PointerRva = GetLong(sect.PointerToRawData); + _PEFileIndex = ImporAddress - SizeRva + PointerRva; + PEIndex = _PEFileIndex; + ResourceDirectory.FileStarIndex = _PEFileIndex; + ResourceDirectory.FileEndIndex = _PEFileIndex + ImporSize; + break; + } + } + + if (SizeRva == 0 && PointerRva == 0) + return; + #endregion + + AddResourceNode(ResourceDirectory, PEIndex, 0, StarRva); + } + + /// + /// 添加资源节点 + /// + /// + /// + /// + /// + private void AddResourceNode(ResourceDirectory node, long PEIndex, long RVA, long resourSectRva) + { + _PEFileIndex = PEIndex + RVA; // 设置位置 + Loadbyte(ref node.Characteristics); + Loadbyte(ref node.TimeDateStamp); + Loadbyte(ref node.MajorVersion); + Loadbyte(ref node.MinorVersion); + Loadbyte(ref node.NumberOfNamedEntries); + Loadbyte(ref node.NumberOfIdEntries); + + long NameRVA = GetLong(node.NumberOfNamedEntries); + for (int i = 0; i != NameRVA; i++) + { + var Entry = new ResourceDirectory.DirectoryEntry(); + Loadbyte(ref Entry.Name); + Loadbyte(ref Entry.Id); + byte[] temp = new byte[2]; + temp[0] = Entry.Name[0]; + temp[1] = Entry.Name[1]; + + if (_PEFileByte is null) + return; + + long NameIndex = GetLong(temp) + PEIndex; + temp[0] = _PEFileByte[NameIndex + 0]; + temp[1] = _PEFileByte[NameIndex + 1]; + + long NameCount = GetLong(temp); + node.Name = new byte[NameCount * 2]; + + for (int z = 0; z != node.Name.Length; z++) + node.Name[z] = _PEFileByte[NameIndex + 2 + z]; + // System.Windows.Forms.MessageBox.Show(GetString(Entry.ID)); + + temp[0] = Entry.Id[2]; + temp[1] = Entry.Id[3]; + + long oldIndex = _PEFileIndex; + + if (GetLong(temp) == 0) + { + temp[0] = Entry.Id[0]; + temp[1] = Entry.Id[1]; + + _PEFileIndex = GetLong(temp) + PEIndex; + + var dataRVA = new ResourceDirectory.DirectoryEntry.DataEntry(); + + Loadbyte(ref dataRVA.ResourRVA); + Loadbyte(ref dataRVA.ResourSize); + Loadbyte(ref dataRVA.ResourTest); + Loadbyte(ref dataRVA.ResourWen); + + _PEFileIndex = oldIndex; + Entry.DataEntryList.Add(dataRVA); + // System.Windows.Forms.MessageBox.Show(GetString(DataRVA.ResourRVA)+"*"+GetString(DataRVA.ResourSize)); + } + else + { + temp[0] = Entry.Id[0]; + temp[1] = Entry.Id[1]; + + var Resource = new ResourceDirectory(); + Entry.NodeDirectoryList.Add(Resource); + AddResourceNode(Resource, PEIndex, GetLong(temp), resourSectRva); + } + _PEFileIndex = oldIndex; + node.EntryList.Add(Entry); + } + + long Count = GetLong(node.NumberOfIdEntries); + for (int i = 0; i != Count; i++) + { + var entry = new ResourceDirectory.DirectoryEntry(); + Loadbyte(ref entry.Name); + Loadbyte(ref entry.Id); + // System.Windows.Forms.MessageBox.Show(GetString(Entry.Name)+"_"+GetString(Entry.Id)); + + byte[] temp = new byte[2]; + temp[0] = entry.Id[2]; + temp[1] = entry.Id[3]; + + long OldIndex = _PEFileIndex; + + if (GetLong(temp) == 0) + { + temp[0] = entry.Id[0]; + temp[1] = entry.Id[1]; + + _PEFileIndex = GetLong(temp) + PEIndex; + + var dataRVA = new ResourceDirectory.DirectoryEntry.DataEntry(); + Loadbyte(ref dataRVA.ResourRVA); + Loadbyte(ref dataRVA.ResourSize); + Loadbyte(ref dataRVA.ResourTest); + Loadbyte(ref dataRVA.ResourWen); + + long FileRva = GetLong(dataRVA.ResourRVA) - resourSectRva + PEIndex; + + dataRVA.FileStarIndex = FileRva; + dataRVA.FileEndIndex = FileRva + GetLong(dataRVA.ResourSize); + + _PEFileIndex = OldIndex; + entry.DataEntryList.Add(dataRVA); + // System.Windows.Forms.MessageBox.Show(GetString(DataRVA.ResourRVA)+"*"+GetString(DataRVA.ResourSize)); + } + else + { + temp[0] = entry.Id[0]; + temp[1] = entry.Id[1]; + var Resource = new ResourceDirectory(); + entry.NodeDirectoryList.Add(Resource); + AddResourceNode(Resource, PEIndex, GetLong(temp), resourSectRva); + } + _PEFileIndex = OldIndex; + node.EntryList.Add(entry); + } + } + + #endregion + + #region 工具方法 + /// + /// 读数据 读byte[]的数量 会改边PEFileIndex的值 + /// + /// + private void Loadbyte(ref byte[] data) + { + if (_PEFileByte is null) + return; + + for (int i = 0; i != data.Length; i++) + { + data[i] = _PEFileByte[_PEFileIndex]; + _PEFileIndex++; + } + } + /// + /// 转换byte为字符串 + /// + /// byte[] + /// AA BB CC DD + private string GetString(byte[] data) + { + string Temp = ""; + for (int i = 0; i != data.Length - 1; i++) + Temp += data[i].ToString("X02") + " "; + + Temp += data[data.Length - 1].ToString("X02"); + // Temp += data[^1].ToString("X02"); + return Temp; + } + /// + /// 转换字符为显示数据 + /// + /// byte[] + /// ASCII DEFAULT UNICODE BYTE + /// + private string GetString(byte[] data, string type) + { + if (type.Trim().ToUpper() == "ASCII") + return System.Text.Encoding.ASCII.GetString(data); + if (type.Trim().ToUpper() == "DEFAULT") + return System.Text.Encoding.Default.GetString(data); + if (type.Trim().ToUpper() == "UNICODE") + return System.Text.Encoding.Unicode.GetString(data); + if (type.Trim().ToUpper() == "BYTE") + { + string Temp = ""; + for (int i = data.Length - 1; i != 0; i--) + Temp += data[i].ToString("X02") + " "; + Temp += data[0].ToString("X02"); + return Temp; + } + return GetInt(data); + } + /// + /// 转换BYTE为INT + /// + /// + /// + static string GetInt(byte[] data) + { + string Temp = ""; + for (int i = 0; i != data.Length - 1; i++) + { + int ByteInt = (int)data[i]; + Temp += ByteInt.ToString() + " "; + } + int EndByteInt = (int)data[data.Length - 1]; + // int EndByteInt = (int)data[^1]; + Temp += EndByteInt.ToString(); + return Temp; + } + /// + /// 转换数据为LONG + /// + /// + /// + private long GetLong(byte[] data) + { + if (data.Length > 4) + return 0; + + string MC = ""; + // if (data.Length <= 4) + for (int i = data.Length - 1; i != -1; i--) + MC += data[i].ToString("X02"); + return Convert.ToInt64(MC, 16); + } + /// + /// 添加一行信息 + /// + /// 表 + /// 数据 + /// 名称 + /// 说明 + private void AddTableRow(DataTable refTable, byte[]? data, string name, string describe) + { + if (data == null) + throw new ArgumentException(nameof(data)); + + refTable.Rows.Add( + new string[] + { + name, + data.Length.ToString(), + GetString(data), + GetLong(data).ToString(), + GetString(data,"ASCII"), + describe + }); + } + #endregion + + #region Table绘制 + /// + /// 获取PE信息 DataSet方式 + /// + /// 多个表 最后资源表 绘制成树结构TABLE + public DataSet? GetPETable() + { + if (OpenFile == false) + return null; + + var ds = new DataSet("PEFile"); + var a1 = TableDosHeader(); + if (a1 is not null) + ds.Tables.Add(a1); + var a2 = TablePEHeader(); + if (a2 is not null) + ds.Tables.Add(a2); + var a3 = TableOptionalHeader(); + if (a3 is not null) + ds.Tables.Add(a3); + var a4 = TableOptionalDirAttrib(); + if (a4 is not null) + ds.Tables.Add(a4); + var a5 = TableSectionData(); + if (a5 is not null) + ds.Tables.Add(a5); + + + var a6 = TableExportDirectory(); + var a7 = TableExportFunction(); + if (a6 is not null) + ds.Tables.Add(a6); + if (a7 is not null) + ds.Tables.Add(a7); + + var a8 = TableImportDirectory(); + var a9 = TableImportFunction(); + if (a8 is not null) + ds.Tables.Add(a8); + if (a9 is not null) + ds.Tables.Add(a9); + + var a10 = TableResourceDirectory(); + if (a10 is not null) + ds.Tables.Add(a10); + + return ds; + } + + private DataTable? TableDosHeader() + { + if (DosHeader is null) + return null; + + var returnTable = new DataTable("DosHeader FileStar{" + DosHeader.FileStarIndex.ToString() + "}FileEnd{" + DosHeader.FileEndIndex.ToString() + "}"); + returnTable.Columns.Add("Name"); + returnTable.Columns.Add("Size"); + returnTable.Columns.Add("Value16"); + returnTable.Columns.Add("Value10"); + returnTable.Columns.Add("ASCII"); + returnTable.Columns.Add("Describe"); + + AddTableRow(returnTable, DosHeader.e_magic, "e_magic", "魔术数字"); + AddTableRow(returnTable, DosHeader.e_cblp, "e_cblp", "文件最后页的字节数"); + AddTableRow(returnTable, DosHeader.e_cp, "e_cp", "文件页数"); + AddTableRow(returnTable, DosHeader.e_crlc, "e_crlc", "重定义元素个数"); + AddTableRow(returnTable, DosHeader.e_cparhdr, "e_cparhdr", "头部尺寸,以段落为单位"); + AddTableRow(returnTable, DosHeader.e_minalloc, "e_minalloc", "所需的最小附加段"); + AddTableRow(returnTable, DosHeader.e_maxalloc, "e_maxalloc", "所需的最大附加段"); + AddTableRow(returnTable, DosHeader.e_ss, "e_ss", "初始的SS值(相对偏移量)"); + AddTableRow(returnTable, DosHeader.e_sp, "e_sp", "初始的SP值"); + AddTableRow(returnTable, DosHeader.e_csum, "e_csum", "校验和"); + AddTableRow(returnTable, DosHeader.e_ip, "e_ip", "初始的IP值"); + AddTableRow(returnTable, DosHeader.e_cs, "e_cs", "初始的CS值(相对偏移量)"); + AddTableRow(returnTable, DosHeader.e_rva, "e_rva", ""); + AddTableRow(returnTable, DosHeader.e_fg, "e_fg", ""); + AddTableRow(returnTable, DosHeader.e_bl1, "e_bl1", ""); + AddTableRow(returnTable, DosHeader.e_oemid, "e_oemid", ""); + AddTableRow(returnTable, DosHeader.e_oeminfo, "e_oeminfo", ""); + AddTableRow(returnTable, DosHeader.e_bl2, "e_bl2", ""); + AddTableRow(returnTable, DosHeader.e_PESTAR, "e_PESTAR", "PE开始 +本结构的位置"); + + return returnTable; + } + + private DataTable? TablePEHeader() + { + if (PEHeader is null) + return null; + + var returnTable = new DataTable("PeHeader FileStar{" + PEHeader.FileStarIndex.ToString() + "}FileEnd{" + PEHeader.FileEndIndex.ToString() + "}"); + returnTable.Columns.Add("Name"); + returnTable.Columns.Add("Size"); + returnTable.Columns.Add("Value16"); + returnTable.Columns.Add("Value10"); + returnTable.Columns.Add("ASCII"); + returnTable.Columns.Add("Describe"); + + + AddTableRow(returnTable, PEHeader.Header, "Header", "PE文件标记"); + AddTableRow(returnTable, PEHeader.Machine, "Machine", "该文件运行所要求的CPU.对于Intel平台,该值是IMAGE_FILE_MACHINE_I386 (14Ch).我们尝试了LUEVELSMEYER的pe.txt声明的14Dh和14Eh,但Windows不能正确执行. "); + AddTableRow(returnTable, PEHeader.NumberOfSections, "NumberOfSections", "文件的节数目.如果我们要在文件中增加或删除一个节,就需要修改这个值."); + AddTableRow(returnTable, PEHeader.TimeDateStamp, "TimeDateStamp", "文件创建日期和时间. "); + AddTableRow(returnTable, PEHeader.PointerToSymbolTable, "PointerToSymbolTable", "用于调试. "); + AddTableRow(returnTable, PEHeader.NumberOfSymbols, "NumberOfSymbols", "用于调试. "); + AddTableRow(returnTable, PEHeader.SizeOfOptionalHeader, "SizeOfOptionalHeader", "指示紧随本结构之后的 OptionalHeader 结构大小,必须为有效值."); + AddTableRow(returnTable, PEHeader.Characteristics, "Characteristics", "关于文件信息的标记,比如文件是exe还是dll."); + + return returnTable; + } + + private DataTable? TableOptionalHeader() + { + if (OptionalHeader is null) + return null; + + var returnTable = new DataTable("OptionalHeader FileStar{" + OptionalHeader.FileStarIndex.ToString() + "}FileEnd{" + OptionalHeader.FileEndIndex.ToString() + "}"); + returnTable.Columns.Add("Name"); + returnTable.Columns.Add("Size"); + returnTable.Columns.Add("Value16"); + returnTable.Columns.Add("Value10"); + returnTable.Columns.Add("ASCII"); + returnTable.Columns.Add("Describe"); + + AddTableRow(returnTable, OptionalHeader.Magic, "Magic", "Magic 010B=普通可以执行,0107=ROM映像"); + AddTableRow(returnTable, OptionalHeader.MajorLinkerVersion, "MajorLinkerVersion", "主版本号"); + AddTableRow(returnTable, OptionalHeader.MinorLinkerVersion, "MinorLinkerVersion", "副版本号"); + AddTableRow(returnTable, OptionalHeader.SizeOfCode, "SizeOfCode", "代码段大小"); + AddTableRow(returnTable, OptionalHeader.SizeOfInitializedData, "SizeOfInitializedData", "已初始化数据大小"); + AddTableRow(returnTable, OptionalHeader.SizeOfUninitializedData, "SizeOfUninitializedData", "未初始化数据大小"); + AddTableRow(returnTable, OptionalHeader.AddressOfEntryPoint, "AddressOfEntryPoint", "执行将从这里开始(RVA)"); + AddTableRow(returnTable, OptionalHeader.BaseOfCode, "BaseOfCode", "代码基址(RVA)"); + AddTableRow(returnTable, OptionalHeader.ImageBase, "ImageBase", "数据基址(RVA)"); + if (_IsX86) + { + AddTableRow(returnTable, OptionalHeader.BaseOfData, "ImageFileCode", "映象文件基址"); + } + AddTableRow(returnTable, OptionalHeader.SectionAlignment, "SectionAlign", "区段列队"); + AddTableRow(returnTable, OptionalHeader.MajorOperatingSystemVersion, "MajorOSV", "文件列队"); + AddTableRow(returnTable, OptionalHeader.MinorOperatingSystemVersion, "MinorOSV", "操作系统主版本号"); + AddTableRow(returnTable, OptionalHeader.MajorImageVersion, "MajorImageVer", "映象文件主版本号"); + AddTableRow(returnTable, OptionalHeader.MinorImageVersion, "MinorImageVer", "映象文件副版本号"); + AddTableRow(returnTable, OptionalHeader.MajorSubsystemVersion, "MajorSV", "子操作系统主版本号"); + AddTableRow(returnTable, OptionalHeader.MinorSubsystemVersion, "MinorSV", "子操作系统副版本号"); + AddTableRow(returnTable, OptionalHeader.Win32VersionValue, "UNKNOW", "Win32版本值"); + AddTableRow(returnTable, OptionalHeader.SizeOfImage, "SizeOfImage", "映象文件大小"); + AddTableRow(returnTable, OptionalHeader.SizeOfHeards, "SizeOfHeards", "标志头大小"); + AddTableRow(returnTable, OptionalHeader.CheckSum, "CheckSum", "文件效验"); + AddTableRow(returnTable, OptionalHeader.Subsystem, "Subsystem", "子系统(映象文件)1本地 2WINDOWS-GUI 3WINDOWS-CUI 4 POSIX-CUI"); + AddTableRow(returnTable, OptionalHeader.DLLCharacteristics, "DLL_Characteristics", "DLL标记"); + AddTableRow(returnTable, OptionalHeader.SizeOfStackReserve, "Bsize", "保留栈的大小"); + AddTableRow(returnTable, OptionalHeader.SizeOfStackCommit, "TimeBsize", "初始时指定栈大小"); + AddTableRow(returnTable, OptionalHeader.SizeOfHeapReserve, "AucBsize", "保留堆的大小"); + AddTableRow(returnTable, OptionalHeader.SizeOfHeapCommit, "SizeOfBsize", "初始时指定堆大小"); + AddTableRow(returnTable, OptionalHeader.LoaderFlags, "FuckBsize", "加载器标志"); + AddTableRow(returnTable, OptionalHeader.NumberOfRvaAndSizes, "DirectCount", "数据目录数"); + + return returnTable; + } + + private DataTable? TableOptionalDirAttrib() + { + if (OptionalDirAttrib is null) + return null; + + var returnTable = new DataTable( + "OptionalDirAttrib FileStar{" + + OptionalDirAttrib.FileStarIndex.ToString() + + "}FileEnd{" + + OptionalDirAttrib.FileEndIndex.ToString() + + "}"); + returnTable.Columns.Add("Name"); + returnTable.Columns.Add("Size"); + returnTable.Columns.Add("Value16"); + returnTable.Columns.Add("Value10"); + returnTable.Columns.Add("ASCII"); + returnTable.Columns.Add("Describe"); + + var tableName = new Hashtable + { + { 0, "输出表" }, + { 1, "输入表" }, + { 2, "资源表" }, + { 3, "异常表" }, + { 4, "安全表" }, + { 5, "基部重定位表" }, + { 6, "调试数据" }, + { 7, "版权数据" }, + { 8, "全局PTR" }, + { 9, "TLS表" }, + { 10, "装入配置表" }, + { 11, "其他表1" }, + { 12, "其他表2" }, + { 13, "其他表3" }, + { 14, "其他表4" }, + { 15, "其他表5" } + }; + + for (int i = 0; i != OptionalDirAttrib.DirByte.Count; i++) + { + if (OptionalDirAttrib.DirByte[i] is not OptionalDirAttrib.DirAttrib MyDirByte) + continue; + + string? Name; + var tn = tableName[i]; + if (tn is not null) + Name = tn.ToString(); + else + Name = $"未知表{i}"; + AddTableRow(returnTable, MyDirByte.DirRva, Name!, "地址"); + AddTableRow(returnTable, MyDirByte.DirSize, "", "大小"); + } + return returnTable; + } + + private DataTable? TableSectionData() + { + if (SectionTable is null) + return null; + + var returnTable = new DataTable( + "SectionData FileStar{" + + SectionTable.FileStarIndex.ToString() + + "}FileEnd{" + + SectionTable.FileEndIndex.ToString() + + "}"); + returnTable.Columns.Add("Name"); + returnTable.Columns.Add("Size"); + returnTable.Columns.Add("Value16"); + returnTable.Columns.Add("Value10"); + returnTable.Columns.Add("ASCII"); + returnTable.Columns.Add("Describe"); + + for (int i = 0; i != SectionTable.Section.Count; i++) + { + if (SectionTable.Section[i] is not SectionTable.SectionData SectionDate) + continue; + + AddTableRow(returnTable, SectionDate.SectName, "SectName", "名字"); + AddTableRow(returnTable, SectionDate.VirtualAddress, "VirtualAddress", "虚拟内存地址"); + AddTableRow(returnTable, SectionDate.SizeOfRawDataRVA, "SizeOfRawDataRVA", "RVA偏移"); + AddTableRow(returnTable, SectionDate.SizeOfRawDataSize, "SizeOfRawDataSize", "RVA大小"); + AddTableRow(returnTable, SectionDate.PointerToRawData, "PointerToRawData", "指向RAW数据"); + AddTableRow(returnTable, SectionDate.PointerToRelocations, "PointerToRelocations", "指向定位号"); + AddTableRow(returnTable, SectionDate.PointerToLinenumbers, "PointerToLinenumbers", "指向行数"); + AddTableRow(returnTable, SectionDate.NumberOfRelocations, "NumberOfRelocations", "定位号"); + AddTableRow(returnTable, SectionDate.NumberOfLinenumbers, "NumberOfLinenumbers", "行数号"); + AddTableRow(returnTable, SectionDate.Characteristics, "Characteristics", "区段标记"); + } + return returnTable; + } + + private DataTable? TableExportDirectory() + { + if (ExportDirectory is null) + return null; + + var returnTable = new DataTable( + "ExportDirectory FileStar{" + + ExportDirectory.FileStarIndex.ToString() + + "}FileEnd{" + + ExportDirectory.FileEndIndex.ToString() + + "}"); + returnTable.Columns.Add("Name"); + returnTable.Columns.Add("Size"); + returnTable.Columns.Add("Value16"); + returnTable.Columns.Add("Value10"); + returnTable.Columns.Add("ASCII"); + returnTable.Columns.Add("Describe"); + + AddTableRow(returnTable, ExportDirectory.Characteristics, "Characteristics", "一个保留字段,目前为止值为0."); + AddTableRow(returnTable, ExportDirectory.TimeDateStamp, "TimeDateStamp", "产生的时间."); + AddTableRow(returnTable, ExportDirectory.MajorVersion, "MajorVersion", "主版本号"); + AddTableRow(returnTable, ExportDirectory.MinorVersion, "MinorVersion", "副版本号"); + AddTableRow(returnTable, ExportDirectory.Name, "Name", "一个RVA,指向一个dll的名称的ascii字符串."); + AddTableRow(returnTable, ExportDirectory.Base, "Base", "输出函数的起始序号.一般为1."); + AddTableRow(returnTable, ExportDirectory.NumberOfFunctions, "NumberOfFunctions", "输出函数入口地址的数组 中的元素个数."); + AddTableRow(returnTable, ExportDirectory.NumberOfNames, "NumberOfNames", "输出函数名的指针的数组 中的元素个数,也是输出函数名对应的序号的数组 中的元素个数."); + AddTableRow(returnTable, ExportDirectory.AddressOfFunctions, "AddressOfFunctions", "一个RVA,指向输出函数入口地址的数组."); + AddTableRow(returnTable, ExportDirectory.AddressOfNames, "AddressOfNames", "一个RVA,指向输出函数名的指针的数组."); + AddTableRow(returnTable, ExportDirectory.AddressOfNameOrdinals, "AddressOfNameOrdinals", "一个RVA,指向输出函数名对应的序号的数组."); + + return returnTable; + } + private DataTable? TableExportFunction() + { + if (ExportDirectory is null) + return null; + + var returnTable = new DataTable("ExportFunctionList"); + returnTable.Columns.Add("Name"); + returnTable.Columns.Add("Size"); + returnTable.Columns.Add("Value16"); + returnTable.Columns.Add("Value10"); + returnTable.Columns.Add("ASCII"); + returnTable.Columns.Add("Describe"); + + for (int i = 0; i != ExportDirectory.FunctionNamesByte.Count; i++) + { + AddTableRow(returnTable, + ExportDirectory.FunctionNamesByte[i], + "Name", + "_ExportDirectory.Name-Sect.SizeOfRawDataRVA+Sect.PointerToRawData"); + } + + for (int i = 0; i != ExportDirectory.AddressOfNamesList.Count; i++) + { + if (ExportDirectory.AddressOfNamesList[i] is not byte[] a) + continue; + AddTableRow(returnTable, a, "NamesList", ""); + } + + for (int i = 0; i != ExportDirectory.AddressOfFunctionsList.Count; i++) + { + if (ExportDirectory.AddressOfFunctionsList[i] is not byte[] a) + continue; + AddTableRow(returnTable, a, "Functions", ""); + } + + for (int i = 0; i != ExportDirectory.AddressOfNameOrdinalsList.Count; i++) + { + if (ExportDirectory.AddressOfNameOrdinalsList[i] is not byte[] a) + continue; + AddTableRow(returnTable, a, "NameOrdinals", ""); + } + return returnTable; + } + private DataTable? TableImportDirectory() + { + if (ImportDirectory is null) + return null; + + var returnTable = new DataTable("ImportDirectory FileStar{" + ImportDirectory.FileStarIndex.ToString() + "}FileEnd{" + ImportDirectory.FileEndIndex.ToString() + "}"); + returnTable.Columns.Add("Name"); + returnTable.Columns.Add("Size"); + returnTable.Columns.Add("Value16"); + returnTable.Columns.Add("Value10"); + returnTable.Columns.Add("ASCII"); + returnTable.Columns.Add("Describe"); + + for (int i = 0; i != ImportDirectory.ImportList.Count; i++) + { + if (ImportDirectory.ImportList[i] is not ImportDirectory.ImportDate ImportByte) + continue; + + AddTableRow(returnTable, ImportByte.DLLName, "输入DLL名称", "**********"); + AddTableRow(returnTable, ImportByte.OriginalFirstThunk, "OriginalFirstThunk", "这里实际上保存着一个RVA,这个RVA指向一个DWORD数组,这个数组可以叫做输入查询表.每个数组元素,或者叫一个表项,保存着一个指向函数名的RVA或者保存着一个函数的序号."); + AddTableRow(returnTable, ImportByte.TimeDateStamp, "TimeDateStamp", "当这个值为0的时候,表明还没有bind.不为0的话,表示已经bind过了.有关bind的内容后面介绍."); + AddTableRow(returnTable, ImportByte.ForwarderChain, "ForwarderChain", ""); + AddTableRow(returnTable, ImportByte.Name, "Name", "一个RVA,这个RVA指向一个ascii以空字符结束的字符串,这个字符串就是本结构对应的dll文件的名字."); + AddTableRow(returnTable, ImportByte.FirstThunk, "FirstThunk", "一个RVA,这个RVA指向一个DWORD数组,这个数组可以叫输入地址表.如果bind了的话,这个数组的每个元素,就是一个输入函数的入口地址."); + } + + return returnTable; + } + private DataTable? TableImportFunction() + { + if (ImportDirectory is null) + return null; + + var returnTable = new DataTable("ImportFunctionList"); + returnTable.Columns.Add("Name"); + returnTable.Columns.Add("Size"); + returnTable.Columns.Add("Value16"); + returnTable.Columns.Add("Value10"); + returnTable.Columns.Add("ASCII"); + returnTable.Columns.Add("Describe"); + + for (int i = 0; i != ImportDirectory.ImportList.Count; i++) + { + if (ImportDirectory.ImportList[i] is not ImportDirectory.ImportDate ImportByte) + continue; + + AddTableRow(returnTable, ImportByte.DLLName, "DLL-Name", "**********"); + + for (int z = 0; z != ImportByte.DLLFunctionList.Count; z++) + { + if (ImportByte.DLLFunctionList[z] is not ImportDirectory.ImportDate.FunctionList Function) + continue; + + AddTableRow(returnTable, Function.FunctionName, "FunctionName", ""); + AddTableRow(returnTable, Function.FunctionHead, "FunctionHead", ""); + AddTableRow(returnTable, Function.OriginalFirst, "OriginalFirstThunk", ""); + } + } + return returnTable; + } + private DataTable? TableResourceDirectory() + { + if (ResourceDirectory is null) + return null; + var returnTable = new DataTable("ResourceDirectory FileStar{" + ResourceDirectory.FileStarIndex.ToString() + "}FileEnd{" + ResourceDirectory.FileEndIndex.ToString() + "}"); + returnTable.Columns.Add("GUID"); + returnTable.Columns.Add("Text"); + returnTable.Columns.Add("ParentID"); + AddResourceDirectoryRow(returnTable, ResourceDirectory, ""); + return returnTable; + } + private void AddResourceDirectoryRow(DataTable myTable, ResourceDirectory Node, string parentID) + { + string Name = ""; + if (Node.Name is not null) + Name = GetString(Node.Name, "UNICODE"); + + for (int i = 0; i != Node.EntryList.Count; i++) + { + if (Node.EntryList[i] is not ResourceDirectory.DirectoryEntry Entry) + continue; + + long ID = GetLong(Entry.Name); + + string GUID = Guid.NewGuid().ToString(); + + string IDNAME = "ID{" + ID + "}"; + if (Name.Length != 0) + IDNAME += "Name{" + Name + "}"; + + if (parentID.Length == 0) + { + IDNAME += ID switch + { + 1 => "Type{Cursor}", + 2 => "Type{Bitmap}", + 3 => "Type{Icon}", + 4 => "Type{Cursor}", + 5 => "Type{Menu}", + 6 => "Type{Dialog}", + 7 => "Type{String Table}", + 8 => "Type{Font Directory}", + 9 => "Type{Font}", + 10 => "Type{Accelerators}", + 11 => "Type{Unformatted}", + 12 => "Type{Message Table}", + 13 => "Type{Group Cursor}", + 14 => "Type{Group Icon}", + 15 => "Type{Information}", + 16 => "Type{Version}", + _ => "Type{未定义}", + }; + } + + myTable.Rows.Add(new string[] { GUID, IDNAME, parentID }); + + for (int z = 0; z != Entry.DataEntryList.Count; z++) + { + if (Entry.DataEntryList[z] is not ResourceDirectory.DirectoryEntry.DataEntry Data) + continue; + + string Text = "Address{" + GetString(Data.ResourRVA) + "} Size{" + GetString(Data.ResourSize) + "} FileBegin{" + Data.FileStarIndex.ToString() + "-" + Data.FileEndIndex.ToString() + "}"; + + myTable.Rows.Add(new string[] { Guid.NewGuid().ToString(), Text, GUID }); + } + + for (int z = 0; z != Entry.NodeDirectoryList.Count; z++) + { + if (Entry.NodeDirectoryList[z] is not ResourceDirectory a) + continue; + AddResourceDirectoryRow(myTable, a, GUID); + } + } + } + #endregion +} + +#region 类 +/// +/// DOS文件都MS开始 +/// +public class DosHeader // IMAGE_DOS_HEADER +{ + public byte[] e_magic = new byte[2]; // 魔术数字 + public byte[] e_cblp = new byte[2]; // 文件最后页的字节数 + public byte[] e_cp = new byte[2]; // 文件页数 + public byte[] e_crlc = new byte[2]; // 重定义元素个数 + public byte[] e_cparhdr = new byte[2]; // 头部尺寸,以段落为单位 + public byte[] e_minalloc = new byte[2]; // 所需的最小附加段 + public byte[] e_maxalloc = new byte[2]; // 所需的最大附加段 + public byte[] e_ss = new byte[2]; // 初始的SS值(相对偏移量) + public byte[] e_sp = new byte[2]; // 初始的SP值 + public byte[] e_csum = new byte[2]; // 校验和 + public byte[] e_ip = new byte[2]; // 初始的IP值 + public byte[] e_cs = new byte[2]; // 初始的CS值(相对偏移量) + public byte[] e_rva = new byte[2]; + public byte[] e_fg = new byte[2]; + public byte[] e_bl1 = new byte[8]; + public byte[] e_oemid = new byte[2]; + public byte[] e_oeminfo = new byte[2]; + public byte[] e_bl2 = new byte[20]; + public byte[] e_PESTAR = new byte[2]; // PE开始 +自己的位置........重点 + + public long FileStarIndex = 0; + public long FileEndIndex = 0; +} + +/// +/// DOS程序 提示 +/// +public class DosStub +{ + public byte[] DosStubData; + public DosStub(long Size) + { + DosStubData = new byte[Size]; + } + public long FileStarIndex = 0; + public long FileEndIndex = 0; +} + +/// +/// PE文件头 +/// +public class PEHeader // IMAGE_FILE_HEADER +{ + public byte[] Header = new byte[4];// PE文件标记 + public byte[] Machine = new byte[2];// 该文件运行所要求的CPU.对于Intel平台,该值是IMAGE_FILE_MACHINE_I386 (14Ch).我们尝试了LUEVELSMEYER的pe.txt声明的14Dh和14Eh,但Windows不能正确执行.看起来,除了禁止程序执行之外,本域对我们来说用处不大. + public byte[] NumberOfSections = new byte[2];// 文件的节数目.如果我们要在文件中增加或删除一个节,就需要修改这个值. + public byte[] TimeDateStamp = new byte[4];// 文件创建日期和时间.我们不感兴趣. + public byte[] PointerToSymbolTable = new byte[4];// 用于调试. + public byte[] NumberOfSymbols = new byte[4];// 用于调试. + public byte[] SizeOfOptionalHeader = new byte[2];// 指示紧随本结构之后的 OptionalHeader 结构大小,必须为有效值. IMAGE_OPTIONAL_HEADER32 结构大小 + public byte[] Characteristics = new byte[2];// 关于文件信息的标记,比如文件是exe还是dll. + + public long FileStarIndex = 0; + public long FileEndIndex = 0; +} + +/// +/// PE头扩展 +/// +// https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_optional_header32 // IMAGE_OPTIONAL_HEADER32 +// https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_optional_header64 // IMAGE_OPTIONAL_HEADER64 +public class OptionalHeader +{ + public byte[] Magic = new byte[2]; // Magic 010B=普通可以执行,0107=ROM映像 + public byte[] MajorLinkerVersion = new byte[1]; // 主版本号 + public byte[] MinorLinkerVersion = new byte[1]; // 副版本号 + public byte[] SizeOfCode = new byte[4]; // 代码段大小 + public byte[] SizeOfInitializedData = new byte[4]; // 已初始化数据大小 + public byte[] SizeOfUninitializedData = new byte[4]; // 未初始化数据大小 + public byte[] AddressOfEntryPoint = new byte[4]; // 执行将从这里开始(RVA).........入口点指向,dll填充0 + public byte[] BaseOfCode = new byte[4]; // 代码基址(RVA) + + public byte[] BaseOfData = new byte[4]; // 映象文件基址 + + public byte[] ImageBase = new byte[4]; // 数据基址(RVA) + + public byte[] SectionAlignment = new byte[4]; // 区段列队..... + public byte[] FileAlignment = new byte[4]; // 文件列队 + + public byte[] MajorOperatingSystemVersion = new byte[2]; // 操作系统主版本号 + public byte[] MinorOperatingSystemVersion = new byte[2]; // 操作系统副版本号 + public byte[] MajorImageVersion = new byte[2]; // 映象文件主版本号 + public byte[] MinorImageVersion = new byte[2]; // 映象文件副版本号 + public byte[] MajorSubsystemVersion = new byte[2]; // 子操作系统主版本号 + public byte[] MinorSubsystemVersion = new byte[2]; // 子操作系统副版本号 + public byte[] Win32VersionValue = new byte[4]; // Win32版本值 + public byte[] SizeOfImage = new byte[4]; // 映象文件大小 + public byte[] SizeOfHeards = new byte[4]; // 标志头大小 + public byte[] CheckSum = new byte[4]; // 文件效验 + public byte[] Subsystem = new byte[2]; // 子系统(映象文件)1本地 2WINDOWS-GUI 3WINDOWS-CUI 4 POSIX-CUI + public byte[] DLLCharacteristics = new byte[2]; // DLL标记 + + public byte[] SizeOfStackReserve = new byte[4]; // 保留栈的大小 + public byte[] SizeOfStackCommit = new byte[4]; // 初始时指定栈大小 + public byte[] SizeOfHeapReserve = new byte[4]; // 保留堆的大小 + public byte[] SizeOfHeapCommit = new byte[4]; // 初始时指定堆大小 + public byte[] LoaderFlags = new byte[4]; // 加载器标志 + public byte[] NumberOfRvaAndSizes = new byte[4]; // 数据目录数 + + public long FileStarIndex = 0; + public long FileEndIndex = 0; + + public OptionalHeader(bool is32) + { + if (!is32) + { + // X64没有了,但是为了代码保留修改幅度不大,所以置0 + BaseOfData = new byte[0];// x64必须置于0 + // x64长度增加的 + int ulonglong = 8; + ImageBase = new byte[ulonglong]; // 数据基址(RVA) + SizeOfStackReserve = new byte[ulonglong]; // 保留栈的大小 + SizeOfStackCommit = new byte[ulonglong]; // 初始时指定栈大小 + SizeOfHeapReserve = new byte[ulonglong]; // 保留堆的大小 + SizeOfHeapCommit = new byte[ulonglong]; // 初始时指定堆大小 + } + } +} + +/// +/// 目录结构 +/// +public class OptionalDirAttrib +{ + public ArrayList DirByte = new(); + public class DirAttrib + { + public byte[] DirRva = new byte[4]; // 地址 + public byte[] DirSize = new byte[4]; // 大小 + } + public long FileStarIndex = 0; + public long FileEndIndex = 0; +} + +/// +/// 节表 +/// +public class SectionTable +{ + public ArrayList Section = new(); + public class SectionData + { + public byte[] SectName = new byte[8]; // 名字 + public byte[] VirtualAddress = new byte[4]; // 虚拟内存地址 + public byte[] SizeOfRawDataRVA = new byte[4]; // RVA偏移 + public byte[] SizeOfRawDataSize = new byte[4]; // RVA大小 + public byte[] PointerToRawData = new byte[4]; // 指向RAW数据 + public byte[] PointerToRelocations = new byte[4]; // 指向定位号 + public byte[] PointerToLinenumbers = new byte[4]; // 指向行数 + public byte[] NumberOfRelocations = new byte[2]; // 定位号 + public byte[] NumberOfLinenumbers = new byte[2]; // 行数号 + public byte[] Characteristics = new byte[4]; // 区段标记 + } + + public long FileStarIndex = 0; + public long FileEndIndex = 0; +} + +/// +/// 输出表 +/// +public class ExportDirectory +{ + public byte[] Characteristics = new byte[4]; // 一个保留字段,目前为止值为0. + public byte[] TimeDateStamp = new byte[4]; // 产生的时间 + public byte[] MajorVersion = new byte[2]; // 主版本号 + public byte[] MinorVersion = new byte[2]; // 副版本号 + public byte[] Name = new byte[4]; // 一个RVA,指向一个dll的名称的ascii字符串 + public byte[] Base = new byte[4]; // 输出函数的起始序号.一般为1 + public byte[] NumberOfFunctions = new byte[4]; // 输出函数入口地址的数组中的元素个数 + public byte[] NumberOfNames = new byte[4]; // 输出函数名的指针的数组中的元素个数,也是输出函数名对应的序号的数组中的元素个数 + public byte[] AddressOfFunctions = new byte[4]; // 一个RVA,指向输出函数入口地址的数组 + public byte[] AddressOfNames = new byte[4]; // 一个RVA,指向输出函数名的指针的数组 + public byte[] AddressOfNameOrdinals = new byte[4]; // 一个RVA,指向输出函数名对应的序号的数组 + + public ArrayList AddressOfFunctionsList = new(); + public ArrayList AddressOfNamesList = new(); + public ArrayList AddressOfNameOrdinalsList = new(); + /// + /// 函数指针名称集合 + /// + public List FunctionNamesByte = new(); + public long FileStarIndex = 0; + public long FileEndIndex = 0; + + /// + /// 获取函数名 + /// + public HashSet FunctionNames() + { + HashSet names = new(); + for (int i = 0; i < FunctionNamesByte.Count; i++) + names.Add(Encoding.Default.GetString(FunctionNamesByte[i])); + return names; + } +} + + +/// +/// 输入表 +/// +public class ImportDirectory +{ + public ArrayList ImportList = new(); + + public class ImportDate + { + public byte[] OriginalFirstThunk = new byte[4]; // 这里实际上保存着一个RVA,这个RVA指向一个DWORD数组,这个数组可以叫做输入查询表.每个数组元素,或者叫一个表项,保存着一个指向函数名的RVA或者保存着一个函数的序号. + public byte[] TimeDateStamp = new byte[4]; // 当这个值为0的时候,表明还没有bind.不为0的话,表示已经bind过了.有关bind的内容后面介绍. + public byte[] ForwarderChain = new byte[4]; + public byte[] Name = new byte[4]; // 一个RVA,这个RVA指向一个ascii以空字符结束的字符串,这个字符串就是本结构对应的dll文件的名字. + public byte[] FirstThunk = new byte[4]; // 一个RVA,这个RVA指向一个DWORD数组,这个数组可以叫输入地址表.如果bind了的话,这个数组的每个元素,就是一个输入函数的入口地址. + + public byte[]? DLLName; // DLL名称 + public ArrayList DLLFunctionList = new(); + public class FunctionList + { + public byte[] OriginalFirst = new byte[4]; + public byte[]? FunctionName; + public byte[] FunctionHead = new byte[2]; + } + } + public long FileStarIndex = 0; + public long FileEndIndex = 0; +} + +/// +/// 资源表 +/// +public class ResourceDirectory +{ + public byte[] Characteristics = new byte[4]; + public byte[] TimeDateStamp = new byte[4]; + public byte[] MajorVersion = new byte[2]; + public byte[] MinorVersion = new byte[2]; + public byte[] NumberOfNamedEntries = new byte[2]; + public byte[] NumberOfIdEntries = new byte[2]; + public byte[]? Name; + public ArrayList EntryList = new(); + + public class DirectoryEntry + { + public byte[] Name = new byte[4]; + public byte[] Id = new byte[4]; + public ArrayList DataEntryList = new(); + public ArrayList NodeDirectoryList = new(); + + public class DataEntry + { + public byte[] ResourRVA = new byte[4]; + public byte[] ResourSize = new byte[4]; + public byte[] ResourTest = new byte[4]; + public byte[] ResourWen = new byte[4]; + + public long FileStarIndex = 0; + public long FileEndIndex = 0; + } + } + + public long FileStarIndex = 0; + public long FileEndIndex = 0; +} +#endregion +#pragma warning restore CS1591 // 缺少对公共可见类型或成员的 XML 注释 \ No newline at end of file diff --git a/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj b/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj index 09590ae..980e272 100644 --- a/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj +++ b/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj @@ -8,6 +8,7 @@ IFoxCAD.Cad true true + true -- Gitee From 7324e8003e06618e7ad959104e4c590d980366d4 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Mon, 2 Sep 2024 14:24:32 +0800 Subject: [PATCH 306/453] =?UTF-8?q?=E5=AE=89=E5=85=A8=E9=94=81=E5=AE=9A?= =?UTF-8?q?=EF=BC=8C=E9=81=BF=E5=85=8D=E4=B8=80=E4=B8=AAcad=E4=B8=AD?= =?UTF-8?q?=E5=8A=A0=E8=BD=BD=E5=A4=9A=E4=B8=AA=E6=8F=92=E4=BB=B6=E6=97=B6?= =?UTF-8?q?=E5=90=8C=E6=97=B6=E9=94=81=E5=AE=9A=E5=AF=BC=E8=87=B4=E5=87=BA?= =?UTF-8?q?=E7=8E=B0"=E5=91=BD=E4=BB=A4=E6=AD=A3=E5=9C=A8=E6=89=A7?= =?UTF-8?q?=E8=A1=8C"=E5=8D=A1=E6=AD=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/CADShared.projitems | 1 + .../ExtensionMethod/DocumentLockManager.cs | 59 +++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 CADShared/ExtensionMethod/DocumentLockManager.cs diff --git a/CADShared/CADShared.projitems b/CADShared/CADShared.projitems index c7b131d..7bbb36c 100644 --- a/CADShared/CADShared.projitems +++ b/CADShared/CADShared.projitems @@ -25,6 +25,7 @@ + diff --git a/CADShared/ExtensionMethod/DocumentLockManager.cs b/CADShared/ExtensionMethod/DocumentLockManager.cs new file mode 100644 index 0000000..17a2928 --- /dev/null +++ b/CADShared/ExtensionMethod/DocumentLockManager.cs @@ -0,0 +1,59 @@ +namespace IFoxCAD.Cad; + +/// +/// 文档锁管理器,用于管理文档的锁定和解锁。 +/// +public class DocumentLockManager : IDisposable +{ + /// + /// 用于存储文档锁的实例,如果文档未锁定则为null。 + /// + private readonly DocumentLock? _documentLock; + + /// + /// 初始化DocumentLockManager实例。 + /// + /// 需要进行锁定管理的文档。 + internal DocumentLockManager(Document doc) + { + // 如果文档未锁定,则尝试锁定文档,否则不创建锁实例。 + _documentLock = doc.LockMode(false) == DocumentLockMode.NotLocked ? doc.LockDocument() : null; + } + + /// + /// 表示当前实例是否已被释放。 + /// + public bool IsDisposed { get; private set; } + + /// + /// 释放当前实例持有的资源。 + /// + public void Dispose() + { + // 如果资源已经被释放,则不再次释放。 + if (IsDisposed) + return; + // 释放文档锁资源,如果存在的话。 + _documentLock?.Dispose(); + + // 标记当前实例为已释放状态。 + IsDisposed = true; + } +} + +/// +/// 提供Document类型的扩展方法来方便创建DocumentLockManager实例。 +/// +public static class DocumentLockManagerExtension +{ + /// + /// 安全锁定文档,返回一个新的DocumentLockManager实例。 + /// + /// 需要进行锁定的文档。 + /// DocumentLockManager实例,用于管理文档锁。 + public static DocumentLockManager SecurelyLock(this Document doc) + { + // 创建并返回DocumentLockManager实例。 + return new DocumentLockManager(doc); + } +} -- Gitee From a2b478fdc8c78cfb13b7774f8990e14a4f8d8cf7 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Fri, 6 Sep 2024 15:57:41 +0800 Subject: [PATCH 307/453] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=89=98=E7=9B=98?= =?UTF-8?q?=E5=A4=84=E7=90=86=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/ExtensionMethod/PaneEx.cs | 160 ++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 CADShared/ExtensionMethod/PaneEx.cs diff --git a/CADShared/ExtensionMethod/PaneEx.cs b/CADShared/ExtensionMethod/PaneEx.cs new file mode 100644 index 0000000..f06828c --- /dev/null +++ b/CADShared/ExtensionMethod/PaneEx.cs @@ -0,0 +1,160 @@ +namespace IFoxCAD.Cad; + +public static class PaneEx +{ + /// + /// 设置Pane的左右边距 + /// + /// Pane + /// 左边距类型 + /// 右边距类型 + public static void SetMargin(this Pane pane, PaneMarginType leftMarginType, PaneMarginType rightMarginType) + { + SetLeftMargin(pane, leftMarginType); + SetRightMargin(pane, rightMarginType); + } + + /// + /// 设置左侧的边距 + /// + /// pane + /// 边距类型 + public static void SetLeftMargin(this Pane pane, PaneMarginType marginType) + { + var hasMargin = marginType != PaneMarginType.NONE; + if (hasMargin) + { + var style = (PaneStyles)(marginType == PaneMarginType.LARGE ? 64 : 128); + while (true) + { + Acap.StatusBar.Update(); + var index = Acap.StatusBar.Panes.IndexOf(pane); + if (index == -1 || index == 0) + break; + var left1 = Acap.StatusBar.Panes[index - 1]; + var left1Style = Convert.ToInt32(left1.Style); + + if (index == 1 && (left1Style == 64 || left1Style == 128)) + { + Acap.StatusBar.Panes.Remove(left1); + continue; + } + + if (left1Style != 64 && left1Style != 128) + { + var leftAdd1 = new Pane() { ToolTipText = pane.ToolTipText, Style = style }; + Acap.StatusBar.Panes.Insert(index, leftAdd1); + continue; + } + + left1.Style = style; + if (index > 1) + { + var left2 = Acap.StatusBar.Panes[index - 2]; + var left2Style = Convert.ToInt32(left2.Style); + if (left2Style == 64 || left2Style == 128) + { + Acap.StatusBar.Panes.Remove(left2); + continue; + } + } + + break; + } + } + else + { + while (true) + { + Acap.StatusBar.Update(); + var index = Acap.StatusBar.Panes.IndexOf(pane); + if (index > 0) + { + var left1 = Acap.StatusBar.Panes[index - 1]; + var left1Style = Convert.ToInt32(left1.Style); + if (left1Style == 64 || left1Style == 128) + { + Acap.StatusBar.Panes.Remove(left1); + continue; + } + } + + break; + } + } + + Acap.StatusBar.Update(); + } + + /// + /// 设置右侧的边距 + /// + /// pane + /// 边距类型 + public static void SetRightMargin(this Pane pane, PaneMarginType marginType) + { + var hasMargin = marginType != PaneMarginType.NONE; + if (hasMargin) + { + var style = (PaneStyles)(marginType == PaneMarginType.LARGE ? 64 : 128); + while (true) + { + Acap.StatusBar.Update(); + var index = Acap.StatusBar.Panes.IndexOf(pane); + if (index == -1 || index == Acap.StatusBar.Panes.Count - 1) + break; + var right1 = Acap.StatusBar.Panes[index + 1]; + var right1Style = Convert.ToInt32(right1.Style); + if (right1Style != 64 && right1Style != 128) + { + var rightAdd1 = new Pane() { ToolTipText = pane.ToolTipText, Style = style }; + Acap.StatusBar.Panes.Insert(index + 1, rightAdd1); + continue; + } + + right1.Style = style; + if (index < Acap.StatusBar.Panes.Count - 2) + { + var right2 = Acap.StatusBar.Panes[index + 2]; + var right2Style = Convert.ToInt32(right2.Style); + if (right2Style == 64 || right2Style == 128) + { + Acap.StatusBar.Panes.Remove(right2); + continue; + } + } + + break; + } + } + else + { + while (true) + { + Acap.StatusBar.Update(); + var index = Acap.StatusBar.Panes.IndexOf(pane); + if (index < Acap.StatusBar.Panes.Count - 1) + { + var right1 = Acap.StatusBar.Panes[index + 1]; + var right1Style = Convert.ToInt32(right1.Style); + if (right1Style == 64 || right1Style == 128) + { + Acap.StatusBar.Panes.Remove(right1); + continue; + } + } + + break; + } + } + + Acap.StatusBar.Update(); + } +} + +public enum PaneMarginType : byte +{ + NONE, + SMALL, + LARGE +} \ No newline at end of file -- Gitee From dbb53f2df35e474904635d4e5db1f48b7ba91e64 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Fri, 6 Sep 2024 17:52:12 +0800 Subject: [PATCH 308/453] =?UTF-8?q?=E6=97=A5=E5=B8=B8=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/CADShared.projitems | 1 + 1 file changed, 1 insertion(+) diff --git a/CADShared/CADShared.projitems b/CADShared/CADShared.projitems index 7bbb36c..f0064dc 100644 --- a/CADShared/CADShared.projitems +++ b/CADShared/CADShared.projitems @@ -42,6 +42,7 @@ + -- Gitee From 93e4f74d76338fb7d402fc5911417d49ed542c46 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Wed, 11 Sep 2024 19:25:07 +0800 Subject: [PATCH 309/453] =?UTF-8?q?=E8=AE=BE=E7=BD=AE=E5=AD=97=E5=85=B8?= =?UTF-8?q?=E5=89=8D=E5=85=88=E5=88=A0=E9=99=A4=E6=97=A7=E7=9A=84=EF=BC=8C?= =?UTF-8?q?=E9=81=BF=E5=85=8D=E6=92=A4=E5=9B=9E=E5=90=8E=E5=8E=9F=E5=AD=97?= =?UTF-8?q?=E5=85=B8=E6=B6=88=E5=A4=B1=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/ExtensionMethod/DBDictionaryEx.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CADShared/ExtensionMethod/DBDictionaryEx.cs b/CADShared/ExtensionMethod/DBDictionaryEx.cs index f3912ac..ce1268f 100644 --- a/CADShared/ExtensionMethod/DBDictionaryEx.cs +++ b/CADShared/ExtensionMethod/DBDictionaryEx.cs @@ -119,6 +119,15 @@ public static ObjectId SetData(this DBDictionary dict, string key, T newValue using (dict.ForWrite()) { + if (dict.Contains(key)) + { + var oldValue = dict.GetData(key)!; + using (oldValue.ForWrite()) + { + oldValue.Erase(); + dict.Remove(key); + } + } var id = dict.SetAt(key, newValue); tr.AddNewlyCreatedDBObject(newValue, true); return id; -- Gitee From e898ea19339000bed1ce4d33c3ebf6c3a05d6ef5 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 12 Sep 2024 15:51:43 +0800 Subject: [PATCH 310/453] =?UTF-8?q?=E9=94=81=E6=96=87=E6=A1=A3=E6=94=B9?= =?UTF-8?q?=E4=B8=BA=E5=AE=89=E5=85=A8=E9=94=81=EF=BC=8C=E9=81=BF=E5=85=8D?= =?UTF-8?q?=E5=87=BA=E7=8E=B0"=E5=BD=93=E5=89=8D=E5=91=BD=E4=BB=A4?= =?UTF-8?q?=E6=AD=A3=E5=9C=A8=E6=89=A7=E8=A1=8C"=E5=8D=A1=E6=AD=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/Runtime/DBTrans.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/CADShared/Runtime/DBTrans.cs b/CADShared/Runtime/DBTrans.cs index 38af048..e882e6b 100644 --- a/CADShared/Runtime/DBTrans.cs +++ b/CADShared/Runtime/DBTrans.cs @@ -150,11 +150,10 @@ public DBTrans(Document? doc = null, bool commit = true, bool docLock = false) Document = doc ?? Acaop.DocumentManager.MdiActiveDocument; Database = Document.Database; Editor = Document.Editor; + if (docLock && Document.LockMode(false) == DocumentLockMode.NotLocked) + _documentLock = Document.LockDocument(); Transaction = Database.TransactionManager.StartTransaction(); _commit = commit; - if (docLock) - _documentLock = Document.LockDocument(); - _dBTrans.Push(this); } -- Gitee From b0ee703a1ce5b0568152afbd2c6d93ac583ad534 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Thu, 12 Sep 2024 20:53:33 +0800 Subject: [PATCH 311/453] =?UTF-8?q?=E8=A1=A5=E5=85=85=E6=9B=B4=E5=A4=9A?= =?UTF-8?q?=E7=9A=84=E7=B3=BB=E7=BB=9F=E5=8F=98=E9=87=8F=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/Runtime/SystemVariableManager.cs | 114 ++++++++++++++++++++- 1 file changed, 113 insertions(+), 1 deletion(-) diff --git a/CADShared/Runtime/SystemVariableManager.cs b/CADShared/Runtime/SystemVariableManager.cs index 69e6c4b..f5e9196 100644 --- a/CADShared/Runtime/SystemVariableManager.cs +++ b/CADShared/Runtime/SystemVariableManager.cs @@ -1,10 +1,52 @@ -namespace IFoxCAD.Cad; +using Autodesk.AutoCAD.Internal.DatabaseServices; + +namespace IFoxCAD.Cad; /// /// 系统变量管理器 /// public class SystemVariableManager { + #region A + + /// + /// 打开或关闭自动捕捉靶框的显示 + /// + public bool ApBox + { + get => Convert.ToBoolean(Acap.GetSystemVariable(nameof(ApBox))); + set => Acap.SetSystemVariable(nameof(ApBox), Convert.ToInt32(value)); + } + + /// + /// 对象捕捉靶框的大小,范围[1,50] + /// + public int Aperture + { + get => Convert.ToInt32(Acap.GetSystemVariable(nameof(Aperture))); + set => Acap.SetSystemVariable(nameof(Aperture), value); + } + + /// + /// 图形单位-角度-类型,范围[0-十进制度数,1-度/分/秒,2-百分度,3-弧度,4-勘测单位] + /// + public int Aunits + { + get => Convert.ToInt32(Acap.GetSystemVariable(nameof(Aunits))); + set => Acap.SetSystemVariable(nameof(Aunits), value); + } + + /// + /// 图形单位-角度-精度,范围[0,8] + /// + public int Auprec + { + get => Convert.ToInt32(Acap.GetSystemVariable(nameof(Auprec))); + set => Acap.SetSystemVariable(nameof(Auprec), value); + } + + #endregion + #region C /// @@ -51,6 +93,19 @@ public static bool DynPrompt #endregion + #region G + + /// + /// 显示图形栅格 + /// + public bool GridMode + { + get => Acap.GetSystemVariable(nameof(GridMode)) is 1; + set => Acap.SetSystemVariable(nameof(GridMode), Convert.ToInt32(value)); + } + + #endregion + #region H /// @@ -69,6 +124,63 @@ public static double HPScale #endregion + #region I + + /// + /// 图形单位-插入时的缩放单位 + /// + public UnitsValue Insunits + { + get => (UnitsValue)Acap.GetSystemVariable(nameof(Insunits)); + set => Acap.SetSystemVariable(nameof(Insunits), (int)value); + } + + #endregion + + #region L + + /// + /// 储存所输入相对于当前用户坐标系统(UCS)的最后点的值 + /// + public Point3d LastPoint + { + get => (Point3d)Acap.GetSystemVariable(nameof(LastPoint)); + set => Acap.SetSystemVariable(nameof(LastPoint), value); + } + + /// + /// 图形单位-长度-类型,范围[1-科学,2-小数,3-工程,4-建筑,5-分数] + /// + public int Lunits + { + get => Convert.ToInt32(Acap.GetSystemVariable(nameof(Lunits))); + set => Acap.SetSystemVariable(nameof(Lunits), value); + } + + /// + /// 图形单位-长度-精度,范围[0,8] + /// + public int Luprec + { + get => Convert.ToInt32(Acap.GetSystemVariable(nameof(Luprec))); + set => Acap.SetSystemVariable(nameof(Luprec), value); + } + + #endregion + + #region M + + /// + /// 图形单位 + /// + public MeasurementValue Measurement + { + get => (MeasurementValue)Acap.GetSystemVariable(nameof(Measurement)); + set => Acap.SetSystemVariable(nameof(Measurement), Convert.ToInt32(value)); + } + + #endregion + #region P /// -- Gitee From 6b2187c1ed1fdb20120b9ccdf8f12b2e20ce520b Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Fri, 13 Sep 2024 10:31:08 +0800 Subject: [PATCH 312/453] =?UTF-8?q?=E4=BF=AE=E6=AD=A3GlobalUsings=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E7=9A=84=E5=91=BD=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IFoxCAD.AutoCad/{GlobalUsing.cs => GlobalUsings.cs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename IFoxCAD.AutoCad/{GlobalUsing.cs => GlobalUsings.cs} (100%) diff --git a/IFoxCAD.AutoCad/GlobalUsing.cs b/IFoxCAD.AutoCad/GlobalUsings.cs similarity index 100% rename from IFoxCAD.AutoCad/GlobalUsing.cs rename to IFoxCAD.AutoCad/GlobalUsings.cs -- Gitee From 6e6d73851cb541b54531dcea5f199e83e38268e1 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Wed, 18 Sep 2024 11:35:33 +0800 Subject: [PATCH 313/453] =?UTF-8?q?=E8=A7=84=E8=8C=83=E5=87=BD=E6=95=B0?= =?UTF-8?q?=E5=91=BD=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/ExtensionMethod/Jig/JigExTransient.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CADShared/ExtensionMethod/Jig/JigExTransient.cs b/CADShared/ExtensionMethod/Jig/JigExTransient.cs index 2c00e1b..b7a0677 100644 --- a/CADShared/ExtensionMethod/Jig/JigExTransient.cs +++ b/CADShared/ExtensionMethod/Jig/JigExTransient.cs @@ -103,7 +103,7 @@ public void Clear() /// /// 清空瞬态容器并移除图元显示 /// - public void ClearAndDispose() + public void ClearAndDisposeDrawables() { foreach (var drawable in _drawableSet) { @@ -173,7 +173,7 @@ protected virtual void Dispose(bool disposing) if (disposing) { - ClearAndDispose(); // 清空瞬态容器并移除对象在图纸上的显示 + ClearAndDisposeDrawables(); // 清空瞬态容器并移除对象在图纸上的显示 } _drawableSet.Clear(); -- Gitee From 330586b1b582f83a9b03cb5c39050af3486d5d65 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Wed, 18 Sep 2024 12:22:19 +0800 Subject: [PATCH 314/453] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=AD=90=E5=AF=B9?= =?UTF-8?q?=E8=B1=A1=E5=85=B3=E7=B3=BB=E6=89=A9=E5=B1=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/CADShared.projitems | 1 + .../Assoc/AssocPersSubentityIdPEEx.cs | 59 +++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 CADShared/ExtensionMethod/Assoc/AssocPersSubentityIdPEEx.cs diff --git a/CADShared/CADShared.projitems b/CADShared/CADShared.projitems index f0064dc..f558176 100644 --- a/CADShared/CADShared.projitems +++ b/CADShared/CADShared.projitems @@ -21,6 +21,7 @@ + diff --git a/CADShared/ExtensionMethod/Assoc/AssocPersSubentityIdPEEx.cs b/CADShared/ExtensionMethod/Assoc/AssocPersSubentityIdPEEx.cs new file mode 100644 index 0000000..2efdbc5 --- /dev/null +++ b/CADShared/ExtensionMethod/Assoc/AssocPersSubentityIdPEEx.cs @@ -0,0 +1,59 @@ +namespace IFoxCAD.Cad.Assoc; + +/// +/// 子对象关系Id扩展 +/// +public static class AssocPersSubentityIdPEEx +{ + private static readonly RXClass _acdbAssocPersSubentityIdPEClass = RXObject.GetClass(typeof(AssocPersSubentityIdPE)); + + /// + /// 获取实体的个性化子对象关系Id + /// + /// 要查询的实体 + /// 返回个性化子对象关系Id实例,如果不存在则返回null + public static AssocPersSubentityIdPE? GetPersSubentityIdPE(this Entity entity) + { + var intPtr = entity.QueryX(_acdbAssocPersSubentityIdPEClass); + return AssocPersSubentityIdPE.Create(intPtr, false) as AssocPersSubentityIdPE; + } + + /// + /// 获取实体中所有指定类型的子对象Id + /// + /// 要查询的实体 + /// 子对象的类型 + /// 返回所有子对象Id的数组 + public static SubentityId[] GetAllSubentityIds(this Entity entity, SubentityType subentityType) + { + var assocPersSubentityIdPE = entity.GetPersSubentityIdPE(); + return assocPersSubentityIdPE is null + ? [] + : assocPersSubentityIdPE.GetAllSubentities(entity, subentityType); + } + + /// + /// 获取实体中所有指定类型的子对象 + /// + /// 要查询的实体 + /// 子对象的类型 + /// 返回所有子对象的列表 + public static List GetAllSubentities(this Entity entity, SubentityType subentityType) + { + var subentityIds = entity.GetAllSubentityIds(subentityType); + + List result = []; + foreach (var subentityId in subentityIds) + { + var fullSubentityPath = new FullSubentityPath([entity.ObjectId], subentityId); + // 这里会有get不到的情况 + // 比如一条line,获取edge能获取到有一个子边,但是实际是取不到的 + // 可能cad认为子边和自身一样没必要再返回 + if (entity.GetSubentity(fullSubentityPath) is not { } subentity) + continue; + result.Add(subentity); + } + + return result; + } +} \ No newline at end of file -- Gitee From 70ff2b9c04bc4b381b4f8ba329790283d560737c Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Wed, 18 Sep 2024 12:23:38 +0800 Subject: [PATCH 315/453] =?UTF-8?q?=E5=85=B3=E7=B3=BB=E5=86=85=E5=AE=B9?= =?UTF-8?q?=E8=BE=83=E5=A4=9A=E6=89=A9=E5=B1=95=E7=B1=BB=E5=8D=95=E7=8B=AC?= =?UTF-8?q?=E5=BB=BA=E6=96=87=E4=BB=B6=E5=A4=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{ExtensionMethod => }/Assoc/AssocPersSubentityIdPEEx.cs | 0 CADShared/CADShared.projitems | 1 - 2 files changed, 1 deletion(-) rename CADShared/{ExtensionMethod => }/Assoc/AssocPersSubentityIdPEEx.cs (100%) diff --git a/CADShared/ExtensionMethod/Assoc/AssocPersSubentityIdPEEx.cs b/CADShared/Assoc/AssocPersSubentityIdPEEx.cs similarity index 100% rename from CADShared/ExtensionMethod/Assoc/AssocPersSubentityIdPEEx.cs rename to CADShared/Assoc/AssocPersSubentityIdPEEx.cs diff --git a/CADShared/CADShared.projitems b/CADShared/CADShared.projitems index f558176..f0064dc 100644 --- a/CADShared/CADShared.projitems +++ b/CADShared/CADShared.projitems @@ -21,7 +21,6 @@ - -- Gitee From 2e47a9011e9624755814d90f46f626bd26a08784 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Wed, 18 Sep 2024 14:26:36 +0800 Subject: [PATCH 316/453] =?UTF-8?q?=E7=A7=BB=E5=8A=A8=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E5=A4=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/CADShared.projitems | 1 + 1 file changed, 1 insertion(+) diff --git a/CADShared/CADShared.projitems b/CADShared/CADShared.projitems index f0064dc..30b8efd 100644 --- a/CADShared/CADShared.projitems +++ b/CADShared/CADShared.projitems @@ -9,6 +9,7 @@ CADShared + -- Gitee From 93f00a3026e78ee52373eb5512e0648aaa73ae1b Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sun, 29 Sep 2024 11:13:34 +0800 Subject: [PATCH 317/453] =?UTF-8?q?=E6=B7=BB=E5=8A=A0CreateActionAndAction?= =?UTF-8?q?BodyAndPostToDatabase=E5=87=BD=E6=95=B0=E6=9D=A5=E6=9B=BF?= =?UTF-8?q?=E4=BB=A3cad=E8=87=AA=E5=B8=A6=E7=9A=84=E9=94=99=E8=AF=AF?= =?UTF-8?q?=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/Assoc/AssocUtils.cs | 45 +++++++++++++++++++++++++++++++++++ CADShared/CADShared.projitems | 1 + 2 files changed, 46 insertions(+) create mode 100644 CADShared/Assoc/AssocUtils.cs diff --git a/CADShared/Assoc/AssocUtils.cs b/CADShared/Assoc/AssocUtils.cs new file mode 100644 index 0000000..8c17ed3 --- /dev/null +++ b/CADShared/Assoc/AssocUtils.cs @@ -0,0 +1,45 @@ +using ErrorStatus = Autodesk.AutoCAD.Runtime.ErrorStatus; + +namespace IFoxCAD.Cad.Assoc; + +public static class AssocUtils +{ + /// + /// 创建关系动作并提交到数据库
    + /// 替代AssocActionBody.CreateActionAndActionBodyAndPostToDatabase();函数 + ///
    + /// actionBody的RXClass + /// 拥有者Id + /// 动作id + /// 动作bodyId + /// + public static ErrorStatus CreateActionAndActionBodyAndPostToDatabase(RXClass actionBodyClass, ObjectId ownerId, out ObjectId actionId, out ObjectId actionBodyId) + { + actionId = actionBodyId = ObjectId.Null; + try + { + if (!actionBodyClass.IsDerivedFrom(RXObject.GetClass(typeof(AssocActionBody))) || + Activator.CreateInstance(actionBodyClass.GetRuntimeType()) is not AssocActionBody actionBody) + return ErrorStatus.NotThatKindOfClass; + var db = ownerId.Database; + using var tr = new DBTrans(db); + var networkId = AssocNetwork.GetInstanceFromObject(ownerId, true, true, ""); + var network = (AssocNetwork)tr.GetObject(networkId, OpenMode.ForWrite); + actionBodyId = db.AddDBObject(actionBody); + tr.Transaction.AddNewlyCreatedDBObject(actionBody, true); + using var action = new AssocAction(); + action.ActionBody = actionBodyId; + actionId = db.AddDBObject(action); + network.AddAction(actionId, true); + return ErrorStatus.OK; + } + catch (AcException e) + { + return e.ErrorStatus; + } + catch (Exception) + { + return ErrorStatus.InternetUnknownError; + } + } +} \ No newline at end of file diff --git a/CADShared/CADShared.projitems b/CADShared/CADShared.projitems index 30b8efd..9d58b70 100644 --- a/CADShared/CADShared.projitems +++ b/CADShared/CADShared.projitems @@ -10,6 +10,7 @@ + -- Gitee From 681bce71b4933153864b8de1c742d7b966a557a6 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Fri, 11 Oct 2024 16:17:20 +0800 Subject: [PATCH 318/453] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=9E=AC=E6=80=81?= =?UTF-8?q?=E7=9A=84=E9=BB=98=E8=AE=A4=E7=BB=98=E5=9B=BE=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/ExtensionMethod/Jig/JigExTransient.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CADShared/ExtensionMethod/Jig/JigExTransient.cs b/CADShared/ExtensionMethod/Jig/JigExTransient.cs index b7a0677..3e388d5 100644 --- a/CADShared/ExtensionMethod/Jig/JigExTransient.cs +++ b/CADShared/ExtensionMethod/Jig/JigExTransient.cs @@ -66,7 +66,7 @@ public bool Contains(Drawable drawable) ///
    /// 图元 /// 绘图模式 - public void Add(Drawable drawable, TransientDrawingMode tdm = TransientDrawingMode.Main) + public void Add(Drawable drawable, TransientDrawingMode tdm = TransientDrawingMode.DirectShortTerm) { if (_drawableSet.Add(drawable)) { -- Gitee From 5413dffc1b20586f4d05626f508abdf2431ec37d Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sat, 12 Oct 2024 10:28:32 +0800 Subject: [PATCH 319/453] =?UTF-8?q?=E5=88=A0=E9=99=A4JigEx=E7=9A=84?= =?UTF-8?q?=E6=AD=A3=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/ExtensionMethod/Jig/JigEx.cs | 80 +++++++++----------------- 1 file changed, 27 insertions(+), 53 deletions(-) diff --git a/CADShared/ExtensionMethod/Jig/JigEx.cs b/CADShared/ExtensionMethod/Jig/JigEx.cs index fc600d4..8c8d185 100644 --- a/CADShared/ExtensionMethod/Jig/JigEx.cs +++ b/CADShared/ExtensionMethod/Jig/JigEx.cs @@ -19,6 +19,7 @@ /// /// jig扩展类 /// +// ReSharper disable once ClassWithVirtualMembersNeverInherited.Global public class JigEx : DrawJig, IDisposable { #region 成员 @@ -36,28 +37,18 @@ public class JigEx : DrawJig, IDisposable /// /// 最后的图元,用来生成 /// - public Entity[] Entitys => _drawEntitys.ToArray(); - + public Entity[] Entities => _drawEntities.ToArray(); + /// + /// 鼠标移动时的委托 + /// readonly Action>? _mouseAction; readonly Tolerance _tolerance; // 容差 - readonly Queue _drawEntitys; // 重复生成的图元,放在这里刷新 + readonly Queue _drawEntities; // 委托内重复生成的图元,放在这里刷新 JigPromptPointOptions? _options; // jig鼠标配置 private bool _worldDrawFlag; // 20220503 - private bool _systemVariablesOrthomode; - - bool SystemVariablesOrthomode // 正交修改还原 - { - get => _systemVariablesOrthomode; - set - { - if (Env.OrthoMode != value) - Env.OrthoMode = _systemVariablesOrthomode = value; - } - } - #endregion #region 构造 @@ -67,8 +58,8 @@ bool SystemVariablesOrthomode // 正交修改还原 ///
    JigEx() { - _drawEntitys = new(); - DimensionEntitys = new(); + _drawEntities = new(); + DimensionEntities = new(); _options = JigPointOptions(); } @@ -112,7 +103,7 @@ protected override SamplerStatus Sampler(JigPrompts prompts) if (pro.Status != PromptStatus.OK && pro.Status != PromptStatus.Keyword) return SamplerStatus.Cancel; // 记上次的状态,因为马上要还原 - bool isOk = !lastIsKw; + var isOk = !lastIsKw; lastIsKw = pro.Status == PromptStatus.Keyword; // 上次鼠标点不同(一定要这句,不然图元刷新太快会看到奇怪的边线) @@ -128,11 +119,11 @@ protected override SamplerStatus Sampler(JigPrompts prompts) } // 上次循环的缓冲区图元清理,否则将会在vs输出遗忘 Dispose - while (_drawEntitys.Count > 0) - _drawEntitys.Dequeue().Dispose(); + while (_drawEntities.Count > 0) + _drawEntities.Dequeue().Dispose(); // 委托把容器扔出去接收新创建的图元,然后给重绘更新 - _mouseAction?.Invoke(mousePointWcs, _drawEntitys); + _mouseAction?.Invoke(mousePointWcs, _drawEntities); MousePointWcsLast = mousePointWcs; return SamplerStatus.OK; @@ -165,10 +156,10 @@ public void DatabaseEntityDraw(WorldDrawEvent action) * 四个箭头最近鼠标的亮显,其余淡显, * 在jig使用淡显ent.Unhighlight和亮显ent.Highlight() * 需要绕过重绘,否则重绘将导致图元频闪,令这两个操作失效, - * 此时需要自定义一个集合 EntityList (不使用本函数的_drawEntitys) + * 此时需要自定义一个集合 EntityList (不使用本函数的_drawEntities) * 再将 EntityList 传给 WorldDrawEvent 事件,事件内实现亮显和淡显(事件已经利用 DatabaseEntityDraw函数进行提供). * 0x03 - * draw.Geometry.Draw(_drawEntitys[i]); + * draw.Geometry.Draw(_drawEntities[i]); * 此函数有问题,acad08克隆一份数组也可以用来刷新, * 而arx上面的jig只能一次改一个,所以可以用此函数. * 起因是此函数属于异步刷新, @@ -187,7 +178,7 @@ protected override bool WorldDraw(WorldDraw draw) { _worldDrawFlag = true; WorldDrawEvent?.Invoke(draw); - _drawEntitys.ForEach(ent => + _drawEntities.ForEach(ent => { #if zcad draw.Geometry.Draw(ent); @@ -209,17 +200,12 @@ protected override bool WorldDraw(WorldDraw draw) /// 基点 /// 光标绑定 /// 提示信息 - /// 正交开关 public JigPromptPointOptions SetOptions(Point3d basePoint, CursorType cursorType = CursorType.RubberBand, - string msg = "点选第二点", - bool orthomode = false) + string msg = "\n点选第二点") { - if (orthomode) - SystemVariablesOrthomode = true; - _options = JigPointOptions(); - _options.Message = Environment.NewLine + msg; + _options.Message = msg; _options.Cursor = cursorType; // 光标绑定 _options.UseBasePoint = true; // 基点打开 _options.BasePoint = basePoint; // 基点设定 @@ -231,19 +217,13 @@ public JigPromptPointOptions SetOptions(Point3d basePoint, ///
    /// 信息 /// 关键字 - /// 正交开关 - /// + /// jig配置 public JigPromptPointOptions SetOptions(string msg, - Dictionary? keywords = null, - bool orthomode = false) + Dictionary? keywords = null) { - if (orthomode) - SystemVariablesOrthomode = true; - _options = JigPointOptions(); _options.Message = Environment.NewLine + msg; - if (keywords != null) foreach (var item in keywords) _options.Keywords.Add(item.Key, item.Key, item.Value); @@ -265,12 +245,8 @@ public JigPromptPointOptions SetOptions(string msg, /// 鼠标配置:自定义 ///
    /// - /// 正交开关 - public void SetOptions(Action action, bool orthomode = false) + public void SetOptions(Action action) { - if (orthomode) - SystemVariablesOrthomode = true; - _options = new JigPromptPointOptions(); action.Invoke(_options); } @@ -278,7 +254,8 @@ public void SetOptions(Action action, bool orthomode = fa /// /// 执行 /// - /// + /// 交互结果 + [Obsolete("将在下个版本中删除,请使用Editor.Drag(JigEx)")] public PromptResult Drag() { // jig功能必然是当前前台文档,所以封装内部更好调用 @@ -286,9 +263,6 @@ public PromptResult Drag() var doc = dm.MdiActiveDocument; var ed = doc.Editor; var dr = ed.Drag(this); - - if (SystemVariablesOrthomode) - SystemVariablesOrthomode = !SystemVariablesOrthomode; return dr; } @@ -299,7 +273,7 @@ public PromptResult Drag() /// 用户输入控制默认配置 /// 令jig.Drag().Status == ///
    - /// + /// Jig配置 static JigPromptPointOptions JigPointOptions() { return new JigPromptPointOptions() @@ -333,7 +307,7 @@ public void SetSpaceIsKeyword() /// /// 注释数据,可以在缩放的时候不受影响 /// - public DynamicDimensionDataCollection DimensionEntitys { get; set; } + public DynamicDimensionDataCollection DimensionEntities { get; set; } /// /// 重写注释数据 @@ -343,7 +317,7 @@ public void SetSpaceIsKeyword() protected override DynamicDimensionDataCollection GetDynamicDimensionData(double dimScale) { base.GetDynamicDimensionData(dimScale); - return DimensionEntitys; + return DimensionEntities; } #endregion @@ -387,14 +361,14 @@ protected virtual void Dispose(bool disposing) if (disposing) { // 最后一次的图元如果没有加入数据库,就在此销毁,所以JigEx调用的时候加using - _drawEntitys.ForEach(ent => + _drawEntities.ForEach(ent => { if (ent.Database == null && !ent.IsDisposed) ent.Dispose(); }); } - _drawEntitys.Clear(); + _drawEntities.Clear(); } #endregion -- Gitee From ab63c9515b123414a64ccc34f991600c2dfebb57 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Mon, 14 Oct 2024 18:21:11 +0800 Subject: [PATCH 320/453] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/Runtime/Env.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CADShared/Runtime/Env.cs b/CADShared/Runtime/Env.cs index 4b89412..caa38dd 100644 --- a/CADShared/Runtime/Env.cs +++ b/CADShared/Runtime/Env.cs @@ -312,7 +312,7 @@ public static ObjectId GetDimblkId(DimblkType dimblk) var oldDimblk = Acaop.GetSystemVariable("dimblk"); Dimblk = dimblk; var id = HostApplicationServices.WorkingDatabase.Dimblk; - Acaop.SetSystemVariable("dimblk",oldDimblk); + Acaop.SetSystemVariable("dimblk", oldDimblk); return id; } @@ -677,7 +677,7 @@ public static void RemoveTrustedPath(params string[] folders) public static T Print(this T obj) { // ReSharper disable once ConditionalAccessQualifierIsNonNullableAccordingToAPIContract - Document?.Editor.WriteMessage($"{obj}\n"); + Document?.Editor.WriteMessage(obj is null ? "null\n" : $"{obj}\n"); return obj; } -- Gitee From 0423562fb5a7c22875c25d4958cff6a24a3aa015 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Wed, 16 Oct 2024 21:04:50 +0800 Subject: [PATCH 321/453] =?UTF-8?q?=E8=A1=A5=E5=85=85=E6=9B=B4=E5=A4=9A?= =?UTF-8?q?=E7=9A=84=E7=B3=BB=E7=BB=9F=E5=8F=98=E9=87=8F=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/Runtime/SystemVariableManager.cs | 149 ++++++++++++++++++++- 1 file changed, 148 insertions(+), 1 deletion(-) diff --git a/CADShared/Runtime/SystemVariableManager.cs b/CADShared/Runtime/SystemVariableManager.cs index f5e9196..967e509 100644 --- a/CADShared/Runtime/SystemVariableManager.cs +++ b/CADShared/Runtime/SystemVariableManager.cs @@ -1,4 +1,4 @@ -using Autodesk.AutoCAD.Internal.DatabaseServices; +// ReSharper disable InconsistentNaming namespace IFoxCAD.Cad; @@ -47,19 +47,142 @@ public int Auprec #endregion + #region B + + /// + /// 是否在块编辑器中 + /// + public bool BlockEditor => Acap.GetSystemVariable(nameof(BlockEditor)) is 1; + + #endregion + #region C + /// + /// 用于设置当前空间的当前注释比例的值 + /// + public static string CanNoScale => Acap.GetSystemVariable(nameof(CanNoScale)).ToString(); + + /// + /// 用于显示当前的注释性比例 + /// + public static double CanNoScaleValue => Convert.ToDouble(Acap.GetSystemVariable(nameof(CanNoScale))); + + /// + /// 储存以公元纪年为基准的日历数据和时间 + /// + public static double CDate => Convert.ToDouble(Acap.GetSystemVariable(nameof(CDate))); + + /// + /// 设置新对象的颜色 + /// + public static string CEColor + { + get => Acap.GetSystemVariable(nameof(CEColor)).ToString(); + set => Acap.SetSystemVariable(nameof(CEColor), value); + } + + /// + /// 设置新对象的线型比例因子 + /// + public static double CELtScale + { + get => Convert.ToDouble(Acap.GetSystemVariable(nameof(CELtScale))); + set => Acap.SetSystemVariable(nameof(CELtScale), value); + } + + /// + /// 设置新对象的线型 + /// + public static string CELType + { + get => Acap.GetSystemVariable(nameof(CELType)).ToString(); + set => Acap.SetSystemVariable(nameof(CELType), value); + } + + /// + /// 设置新对象的线宽 + /// + public static double CELWeight + { + get => Convert.ToDouble(Acap.GetSystemVariable(nameof(CELWeight))); + set => Acap.SetSystemVariable(nameof(CELWeight), value); + } + + /// + /// 设置圆的默认半径 + /// + public static double CircleRad + { + get => Convert.ToDouble(Acap.GetSystemVariable(nameof(CircleRad))); + set => Acap.SetSystemVariable(nameof(CircleRad), value); + } + + /// + /// 设置当前图层 + /// + public static string CLayer + { + get => Acap.GetSystemVariable(nameof(CLayer)).ToString(); + set => Acap.SetSystemVariable(nameof(CLayer), value); + } + + /// + /// 用于确定全屏显示是打开或关闭状态 + /// + public static bool CleanScreenState => Convert.ToBoolean(Acap.GetSystemVariable(nameof(CleanScreenState))); + + /// + /// 指示命令窗口是隐藏还是显示状态 + /// + public static bool CliState => Convert.ToBoolean(Acap.GetSystemVariable(nameof(CliState))); + /// /// 存在活动命令 /// public static bool CmdActive => Convert.ToBoolean(Acap.GetSystemVariable(nameof(CmdActive))); + /// + /// 控制是否要打开对话框来显示命令 + /// + public static bool CmdDia + { + get => Convert.ToBoolean(Acap.GetSystemVariable(nameof(CmdDia))); + set => Acap.SetSystemVariable(nameof(CmdDia), Convert.ToInt32(value)); + } + + /// + /// 在使用 LISP 的函数时,切换回应为打开或关闭 + /// + public static bool CmdEcho => Convert.ToBoolean(Acap.GetSystemVariable(nameof(CmdEcho))); + /// /// 当前的命令 /// public static string CmdNames => Acap.GetSystemVariable(nameof(CmdNames)).ToString(); + /// + /// 返回图形中的当前选项卡(模型或布局)的名称 + /// + public static string CTab + { + get => Acap.GetSystemVariable(nameof(CTab)).ToString(); + set => Acap.SetSystemVariable(nameof(CTab), value); + } + + /// + /// 指定十字光标的显示大小。输入的数字代表十字光标相对于屏幕的比例。
    + /// 范围[1, 100] + ///
    + public static int CursorSize + { + get => Convert.ToInt32(Acap.GetSystemVariable(nameof(CursorSize))); + set => Acap.SetSystemVariable(nameof(CursorSize), value); + } + /// + /// 当前viewport的编号 + /// public static short CVPort { get => Convert.ToInt16(Acap.GetSystemVariable(nameof(CVPort))); @@ -79,12 +202,23 @@ public static bool DblClick set => Acap.SetSystemVariable(nameof(DblClick), Convert.ToInt32(value)); } + /// + /// 指示图形的修改状态 + /// + public static DBmod DBMod => (DBmod)Acap.GetSystemVariable(nameof(DBMod)); + + /// + /// 动态输入 + /// public static int DynMode { get => Convert.ToInt32(Acap.GetSystemVariable(nameof(DynMode))); set => Acap.SetSystemVariable(nameof(DynMode), value); } + /// + /// 动态提示 + /// public static bool DynPrompt { get => Convert.ToBoolean(Acap.GetSystemVariable(nameof(DynPrompt))); @@ -181,6 +315,19 @@ public MeasurementValue Measurement #endregion + #region O + + /// + /// 正交 + /// + public static bool OrthoMode + { + get => Convert.ToBoolean(Acap.GetSystemVariable(nameof(OrthoMode))); + set => Acap.SetSystemVariable(nameof(OrthoMode), Convert.ToInt32(value)); + } + + #endregion + #region P /// -- Gitee From fb397cfff8613ec1a587ecdcc0c39381e7ffe78c Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Fri, 18 Oct 2024 20:18:35 +0800 Subject: [PATCH 322/453] =?UTF-8?q?=E6=8E=A8=E9=80=810.9=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Entity/BlockReferenceEx.cs | 23 ++--- IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj | 96 ++++++++++++------- IFoxCAD.sln | 4 + Test/{GlobalUsing.cs => GlobalUsings.cs} | 0 4 files changed, 77 insertions(+), 46 deletions(-) rename Test/{GlobalUsing.cs => GlobalUsings.cs} (100%) diff --git a/CADShared/ExtensionMethod/Entity/BlockReferenceEx.cs b/CADShared/ExtensionMethod/Entity/BlockReferenceEx.cs index a8d3402..7024393 100644 --- a/CADShared/ExtensionMethod/Entity/BlockReferenceEx.cs +++ b/CADShared/ExtensionMethod/Entity/BlockReferenceEx.cs @@ -18,12 +18,10 @@ public static class BlockReferenceEx public static void XClip(this BlockReference brf, IEnumerable pt3ds) { var mat = brf.BlockTransform.Inverse(); - var pts = - pt3ds - .Select(p => p.TransformBy(mat).Point2d()) - .ToCollection(); + var pts = pt3ds.Select(p => p.TransformBy(mat).Point2d()).ToCollection(); - SpatialFilterDefinition sfd = new(pts, Vector3d.ZAxis, 0.0, 0.0, 0.0, true); + SpatialFilterDefinition sfd = new(pts, Vector3d.ZAxis, 0.0, double.PositiveInfinity, + double.NegativeInfinity, true); using SpatialFilter sf = new(); sf.Definition = sfd; var dict = brf.GetXDictionary().GetSubDictionary(true, [filterDictName])!; @@ -49,9 +47,8 @@ public static void XClip(this BlockReference brf, Point3d pt1, Point3d pt2) ]; using SpatialFilter sf = new(); - sf.Definition = new(pts, Vector3d.ZAxis, 0.0, 0.0, 0.0, true); - var dict = brf.GetXDictionary() - .GetSubDictionary(true, [filterDictName])!; + sf.Definition = new(pts, Vector3d.ZAxis, 0.0, double.PositiveInfinity, double.NegativeInfinity, true); + var dict = brf.GetXDictionary().GetSubDictionary(true, [filterDictName])!; dict.SetData(spatialName, sf); #if !acad pts.Dispose(); @@ -96,8 +93,7 @@ public static bool ChangeBlockProperty(this BlockReference blockReference, /// /// 更新动态块参数值 /// - public static bool ChangeBlockProperty(this BlockReference blockReference, - string propName, object value) + public static bool ChangeBlockProperty(this BlockReference blockReference, string propName, object value) { if (!blockReference.IsDynamicBlock) return false; @@ -127,7 +123,8 @@ public static bool ChangeBlockProperty(this BlockReference blockReference, /// /// 更新属性块的属性值 /// - public static void ChangeBlockAttribute(this BlockReference blockReference, Dictionary propertyNameValues) + public static void ChangeBlockAttribute(this BlockReference blockReference, + Dictionary propertyNameValues) { var tr = DBTrans.GetTopTransaction(blockReference.Database); foreach (var item in blockReference.AttributeCollection) @@ -197,7 +194,6 @@ public static string GetBlockName(this BlockReference blk) return blk.Name; } - /// /// 获取嵌套块的位置(wcs) /// @@ -282,7 +278,8 @@ public static void ForEach(this BlockReference brf, Action块参照 /// 委托 /// 事务 - public static void NestedForEach(this Entity blockReference, Action action, DBTrans? tr = null) + public static void NestedForEach(this Entity blockReference, Action action, + DBTrans? tr = null) { tr ??= DBTrans.GetTop(blockReference.IsNewObject ? Env.Database : blockReference.Database); var queue = new Queue<(Entity, Matrix3d)>(); diff --git a/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj b/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj index 980e272..55a1de2 100644 --- a/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj +++ b/IFoxCAD.AutoCad/IFoxCAD.AutoCad.csproj @@ -1,39 +1,69 @@  - - net48 - Preview - enable - x64 - IFoxCAD.Cad - true - true - true - + + net48 + Preview + enable + x64 + IFoxCAD.CAD + true + true + true + + + + + true + IFox.CAD.ACAD + IFox.CAD.ACAD + IFox.CAD.ACAD + 0.9.0 + xsfhlzh, vicwjb, liuqihong, DYH + 基于.NET的二次开发基本类库. + https://www.nuget.org/packages/IFox.CAD.ACAD/ + https://gitee.com/inspirefunction/ifoxcad + git + IFox,Cad,AutoCad,C#,NET, + InspireFunction + readme.md + 普通包更新至0.9,修改部分api优化代码 + LICENSE + - - full - True - $(DefineConstants);acad - + + none + True + $(DefineConstants);acad + - - full - True - $(DefineConstants);acad - + + none + True + $(DefineConstants);acad + - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - + + + True + \ + + + True + \ + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + diff --git a/IFoxCAD.sln b/IFoxCAD.sln index 02a5e11..ed2cf93 100644 --- a/IFoxCAD.sln +++ b/IFoxCAD.sln @@ -30,4 +30,8 @@ Global GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {57CA0128-08DE-436F-B9F1-82C64F49BF67} EndGlobalSection + GlobalSection(SharedMSBuildProjectFiles) = preSolution + CADShared\CADShared.projitems*{5178502e-9a78-4588-b849-33ed439976b2}*SharedItemsImports = 13 + CADShared\CADShared.projitems*{6b29955a-5796-4035-9297-210fa15d3846}*SharedItemsImports = 5 + EndGlobalSection EndGlobal diff --git a/Test/GlobalUsing.cs b/Test/GlobalUsings.cs similarity index 100% rename from Test/GlobalUsing.cs rename to Test/GlobalUsings.cs -- Gitee From f7e7858474dc025e00b68200e3faafa2db382301 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sun, 20 Oct 2024 21:00:50 +0800 Subject: [PATCH 323/453] =?UTF-8?q?=E8=A1=A5=E5=85=85=E5=9B=9B=E5=8F=89?= =?UTF-8?q?=E6=A0=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/Algorithms/QuadTree/QuadEntity.cs | 25 + CADShared/Algorithms/QuadTree/QuadTree.cs | 260 ++++++ CADShared/Algorithms/QuadTree/QuadTreeEvn.cs | 28 + CADShared/Algorithms/QuadTree/QuadTreeNode.cs | 818 ++++++++++++++++++ .../Algorithms/QuadTree/QuadTreeSelectMode.cs | 39 + CADShared/Algorithms/QuadTree/Rect.cs | 742 ++++++++++++++++ CADShared/CADShared.projitems | 6 + 7 files changed, 1918 insertions(+) create mode 100644 CADShared/Algorithms/QuadTree/QuadEntity.cs create mode 100644 CADShared/Algorithms/QuadTree/QuadTree.cs create mode 100644 CADShared/Algorithms/QuadTree/QuadTreeEvn.cs create mode 100644 CADShared/Algorithms/QuadTree/QuadTreeNode.cs create mode 100644 CADShared/Algorithms/QuadTree/QuadTreeSelectMode.cs create mode 100644 CADShared/Algorithms/QuadTree/Rect.cs diff --git a/CADShared/Algorithms/QuadTree/QuadEntity.cs b/CADShared/Algorithms/QuadTree/QuadEntity.cs new file mode 100644 index 0000000..c5f7f11 --- /dev/null +++ b/CADShared/Algorithms/QuadTree/QuadEntity.cs @@ -0,0 +1,25 @@ +namespace IFoxCAD.Cad; + +/* + * 这个类存在的意义是为了不暴露Rect类字段 + * 同时利用了Rect类字段的快速 + * 提供到外面去再继承 + */ + +/// +/// 四叉树图元 +/// +public class QuadEntity : Rect +{ + /// + /// 四叉树图元 + /// + /// 包围盒 + public QuadEntity(Rect box) + { + _X = box._X; + _Y = box._Y; + _Top = box._Top; + _Right = box._Right; + } +} \ No newline at end of file diff --git a/CADShared/Algorithms/QuadTree/QuadTree.cs b/CADShared/Algorithms/QuadTree/QuadTree.cs new file mode 100644 index 0000000..2872540 --- /dev/null +++ b/CADShared/Algorithms/QuadTree/QuadTree.cs @@ -0,0 +1,260 @@ +/* + * 四叉树维基百科 http://en.wikipedia.org/wiki/Quadtree + * 四叉树是一种分区空间的算法,更快找出内部或外部给定区域. + * 通过一个正交矩形边界进行中心点分裂四个正交矩形, + * 插入时候会一直分裂四个正交矩形, + * 当分裂四个节点都无法单独拥有 图元包围盒 就停止分裂,并且你属于这四个节点的父亲. + * (不包含就是面积少了,就这么一句话看代码看半天), + * 还可以通过限制树的深度实现加速. + * + * 第一版: https://www.codeproject.com/script/Articles/ViewDownloads.aspx?aid=30535 + * + * 第二版: 找邻居 + * https://blog.csdn.net/dive_shallow/article/details/112438050 + * https://geidav.wordpress.com/2017/12/02/advanced-octrees-4-finding-neighbor-nodes/ + * + * 1.根节点:控制根节点从而控制所有节点 + * 2.子节点:包含自身根节点,插入矩形的时候进行递归分裂自身,和实现查找. + * 3.接口:约束都要有正交矩形,否则无法调用"包含"方法 + * 4.选择模式:模仿cad的窗选和框选 + */ +namespace IFoxCAD.Cad; + +/// +/// 根节点控制器 +/// +/// 类型接口约束必须有正交矩形 +public class QuadTree where TEntity : QuadEntity +{ + #region 成员 + /// + /// 根节点 + /// + QuadTreeNode _rootNode; + + /// + /// 四叉树节点的数目 + /// + public int Count { get => _rootNode.CountSubTree; } + + /// + /// 点容器(红黑树) + /// + SortedSet _points; + #endregion + + #region 构造 + /// + /// 四叉树根节点控制器 + /// + /// 四叉树矩形范围 + public QuadTree(Rect rect) + { + _rootNode = new QuadTreeNode(rect, null, 0);// 初始化根节点 + _points = new(); + } + #endregion + + #region 方法 + /// + /// 通过根节点插入数据项 + /// + /// + public void Insert(TEntity ent) + { + /* + * 图元点 是不分裂空间的,加入一个红黑树内部. + */ + if (ent.IsPoint) + { + _points.Add(ent); + return; + } + + while (!_rootNode.Contains(ent)) + { + /* + * 四叉树插入时候,如果超出根边界,就需要扩展 + * 扩展时候有一个要求,当前边界要作为扩展边界的一个象限,也就是反向分裂 + * + * 创建新根,计算原根在新根的位置, + * 替换指针:获取新分裂的节点的父节点,判断它哪个儿子是它, + * 替换之后可能仍然不包含图元边界,再循环计算. + */ + var sq_Left = _rootNode._X; + var sq_Botton = _rootNode._Y; + var sq_Right = _rootNode._Right; + var sq_Top = _rootNode._Top; + if (ent._Y >= _rootNode._Y)// 上↑增殖 + { + if (ent._X >= _rootNode._X) + { + // 右上↗增殖 + sq_Right += _rootNode.Width; + sq_Top += _rootNode.Height; + } + else + { + // 左上↖增殖 + sq_Left -= _rootNode.Width; + sq_Top += _rootNode.Height; + } + } + else// 在下↓ + { + if (ent._X >= _rootNode._X) + { + // 右下↘增殖 + sq_Right += _rootNode.Width; + sq_Botton -= _rootNode.Height; + } + else + { + // 左下↙增殖 + sq_Left -= _rootNode.Width; + sq_Botton -= _rootNode.Height; + } + } + // 扩大2次方 + var rectSquare = new Rect(sq_Left, sq_Botton, sq_Right, sq_Top); + + // 四叉树的旧根要作为四分之一插入 + // 新根中计算原根 + // 把 旧根节点 连接到 新根节点 上面,然后新根成为根 + var newRoot = new QuadTreeNode(rectSquare, null, 0); + var insert = newRoot.Insert(_rootNode); + if (insert is null) + throw new("四叉树:新根尺寸不对"); + if (!insert.Equals(_rootNode)) + throw new("四叉树:新旧节点大小不一致,无法连接"); + + var insPar = insert.Parent; + _rootNode.Parent = insPar; + if (insPar is null) + return; + + if (_rootNode.Equals(insPar.RightTopTree)) + insPar.RightTopTree = _rootNode; + else if (_rootNode.Equals(insPar.RightBottomTree)) + insPar.RightBottomTree = _rootNode; + else if (_rootNode.Equals(insPar.LeftBottomTree)) + insPar.LeftBottomTree = _rootNode; + else if (_rootNode.Equals(insPar.LeftTopTree)) + insPar.LeftTopTree = _rootNode; + else + throw new("四叉树:新节点不对,无法连接"); + + // 其后的子节点层数全部增加层数, + // 要加多少层取决于当前根边界属于新根边界的所在层 + var depth = insert.Depth; + if (depth == 0) + throw new("四叉树:插入节点是0,造成错误"); + _rootNode.ForEach(node => { + node.Depth += depth; + return false; + }); + + // 交换根控制 + _rootNode = newRoot; + } + + _rootNode.Insert(ent); + } + + + /// + /// 查询四叉树,返回给定区域的数据项 + /// + /// 矩形选区查询 + /// 查询模式 + /// 查询结果列表 + public List Query(Rect rect, QuadTreeSelectMode selectMode = QuadTreeSelectMode.IntersectsWith) + { + QuadTreeEvn.SelectMode = selectMode; + + List results = []; + // 选择图元 + _rootNode.Query(rect, results); + // 选择点 + using var ptge = _points.GetEnumerator(); + switch (selectMode) + { + case QuadTreeSelectMode.IntersectsWith: + case QuadTreeSelectMode.Contains: + /* 由于红黑树的方法 _points.GetViewBetween() + * 过滤只能过滤X区间,Y区间还是要过滤, + * 那么我就只能用这样的方法加速了 + * + * 而更好的方式是不用红黑树,去加入一个点云数据来进行,可谓是编程无极限.... + */ + while (ptge.MoveNext()) + { + var ptEnt = ptge.Current; + if (ptEnt != null && rect._X <= ptEnt._X && ptEnt._X <= rect._Right) + { + if (rect._Y <= ptEnt._Y && ptEnt._Y <= rect.Top) + results.Add(ptEnt); + } + else if (ptEnt != null && ptEnt._X > rect._Right) + break;// 超过后面范围就break,因为红黑树已经排序 + } + break; + default: + throw new("四叉树:" + nameof(selectMode)); + } + return results; + } + + /// + /// 删除子节点 + /// + /// 根据范围删除 + public void Remove(Rect rect) + { + _rootNode.Remove(rect); + } + + /// + /// 删除子节点 + /// + /// 根据图元删除 + public void Remove(TEntity ent) + { + _rootNode.Remove(ent); + } + + /// + /// 找到附近节点图元 + /// + [Obsolete("找附近节点的并不是最近的图元")] + public TEntity? FindNeibor(Rect rect, QuadTreeFindMode findMode) + { + return _rootNode.FindNeibor(rect, findMode); + } + + /// + /// 找到附近图元 + /// + /// + /// + public TEntity? FindNearEntity(Rect rect) + { + return _rootNode.FindNearEntity(rect); + } + + /// + /// 执行四叉树中特定的行为 + /// + /// + public void ForEach(QTAction action) + { + _rootNode.ForEach(action); + } + + /// + /// 委托:四叉树节点上执行一个操作 + /// + /// + public delegate bool QTAction(QuadTreeNode obj); + #endregion +} \ No newline at end of file diff --git a/CADShared/Algorithms/QuadTree/QuadTreeEvn.cs b/CADShared/Algorithms/QuadTree/QuadTreeEvn.cs new file mode 100644 index 0000000..f077a02 --- /dev/null +++ b/CADShared/Algorithms/QuadTree/QuadTreeEvn.cs @@ -0,0 +1,28 @@ +#pragma warning disable CA2211 // 非常量字段应当不可见 +namespace IFoxCAD.Cad; +/// +/// 四叉树环境变量 +/// +public class QuadTreeEvn +{ + /// + /// 最小的节点有一个面积(一定要大于0) + /// + public static double MinArea = 1e-6; + + /// + /// 选择模式 + /// + public static QuadTreeSelectMode SelectMode; + + /// + /// 最大深度 + /// + public static int QuadTreeMaximumDepth = 2046; + + /// + /// 节点内容超过就分裂 + /// + public static int QuadTreeContentsCountSplit = 20; +} +#pragma warning restore CA2211 // 非常量字段应当不可见 \ No newline at end of file diff --git a/CADShared/Algorithms/QuadTree/QuadTreeNode.cs b/CADShared/Algorithms/QuadTree/QuadTreeNode.cs new file mode 100644 index 0000000..315117f --- /dev/null +++ b/CADShared/Algorithms/QuadTree/QuadTreeNode.cs @@ -0,0 +1,818 @@ +namespace IFoxCAD.Cad; + +/// +/// 子节点 +/// +/// +public class QuadTreeNode + : Rect + where TEntity : QuadEntity +{ + #region 成员 + /// + /// 子节点:第一象限:右上↗ + /// + public QuadTreeNode? RightTopTree; + /// + /// 子节点:第二象限:左上↖ + /// + public QuadTreeNode? LeftTopTree; + /// + /// 子节点:第三象限:左下↙ + /// + public QuadTreeNode? LeftBottomTree; + /// + /// 子节点:第四象限:右下↘ + /// + public QuadTreeNode? RightBottomTree; + /// + /// 所有子节点 + /// + QuadTreeNode[] Nodes + { + get + { + return new QuadTreeNode[] + { + RightTopTree!, + LeftTopTree!, + LeftBottomTree!, + RightBottomTree!, + }; + } + } + /// + /// 所有子节点是空的 + /// + bool NodesIsEmpty => RightTopTree is null && LeftTopTree is null && LeftBottomTree is null && RightBottomTree is null; + + /// + /// 父节点 + /// + public QuadTreeNode? Parent; + /// + /// 节点的在四叉树的深度 + /// + public int Depth; + + // 注意,内容没有限制:这不是 impement 四叉树的标准方法 + /// (节点图元是交叉线压着的,并不是矩形范围内全部,因为这是四叉树的特性决定) + /// + /// 本节点:内容 + /// + public List Contents; + + /// + /// 本节点和旗下所有子节点:内容群 + /// + public void ContentsSubTree(List results) + { + if (Contents is null) + return; + results.AddRange(Contents); + var nodes = Nodes; + for (int i = 0; i < nodes.Length; i++) + nodes[i]?.ContentsSubTree(results); + } + + /// + /// 本节点和旗下所有子节点:内容群数量 + /// + public int CountSubTree + { + get + { + if (Contents is null) + return 0; + int count = Contents.Count; + + var nodes = Nodes; + for (int i = 0; i < nodes.Length; i++) + { + var node = nodes[i]; + if (node is null) + continue; + count += node.CountSubTree; + } + return count; + } + } + #endregion + + #region 构造 + /// + /// 四叉树节点 + /// + /// 当前节点边界 + /// 父节点 + /// 节点深度 + public QuadTreeNode(Rect box, QuadTreeNode? parent, int depth) + { + _X = box._X; + _Y = box._Y; + _Right = box._Right; + _Top = box._Top; + + Parent = parent; + Depth = depth; + Contents = new(); + } + #endregion + + #region 增 + /// + /// 将原有节点插入用 + /// + /// + internal QuadTreeNode? Insert(Rect rect) + { + if (!Contains(rect)) + return null; + + // 四叉树分裂,将当前节点分为四个子节点 + if (NodesIsEmpty) + CreateChildren(); + + // 当前节点边界 包含 图元包围盒 就插入 + // 退出递归:4个节点都不完全包含 + // 4个节点的上层 + var nodes = Nodes; + for (int i = 0; i < nodes.Length; i++) + { + var node = nodes[i]; + if (node is null) + continue; + + if (node.Equals(rect)) + { + rect = node; + return node.Insert(rect); + } + } + return this; + } + + /// + /// 将数据项递归插入四叉树 + /// + /// + public QuadTreeNode? Insert(TEntity ent) + { + if (!Contains(ent)) + { + // Debugx.Printl("不在四叉树边界范围"); + // Trace.WriteLine("不在四叉树边界范围"); + return null; + } + + // if (ent.IsPoint) + // { + // // 找到最后一层包含它的节点,然后加入它 + // // 因此是跳过分裂矩形的,以免造成无限递归 + // var minNode = GetMinNode(ent); + // minNode.Contents.Add(ent); + // return minNode; + // } + +#if true2 + // 方案二: + // 内容数超过才分裂,防止树深度过高,但是多选过滤时候慢一点 + if (Contents.Count > QuadTreeEvn.QuadTreeContentsCountSplit) + { + // 分裂出四个子节点 + if (_nodesIsEmpty) + { + CreateChildren(); + // 分裂之后将当前层的内容扔到四个子节点, + // 如果被压着,那么就不会扔到下面 + for (int i = Contents.Count - 1; i >= 0; i--) + { + var minNode = GetMinNode(Contents[i].Box); + minNode.Contents.Add(Contents[i]); + Contents.RemoveAt(i); + } + } + else + { + // 没有分裂的话,就递归 + // 退出递归:4个节点都不完全包含,内容就是他们的父亲 + var nodes = _Nodes; + for (int i = 0; i < nodes.Length; i++) + { + var node = nodes[i]; + if (node is null) + continue; + + // 这里需要中断.(匿名方法ForEach无法中断,会造成父节点加入内容) + if (node.Contains(ent)) + return node.Insert(ent); + } + } + } +#else + // 方案一:分裂到最细节点 + + // 分裂出四个子节点 + if (NodesIsEmpty) + CreateChildren(); + + // 4个子节点开始递归 + // 退出递归:4个节点都不完全包含,内容就是他们的父亲 + var nodes = Nodes; + for (int i = 0; i < nodes.Length; i++) + { + var node = nodes[i]; + if (node is null) + continue; + // 这里需要中断.(匿名方法ForEach无法中断,会造成父节点加入内容) + if (node.Contains(ent)) + return node.Insert(ent); + } +#endif + + // 为什么要用容器? + // 相同包围盒或者四叉树分割线压着多个. + this.Contents.Add(ent); + return this; + } + + /// + /// 创建子节点 + /// + void CreateChildren() + { + // 最小面积控制节点深度,但是这样可能导致树分成高,引起爆栈 + if (Depth > QuadTreeEvn.QuadTreeMaximumDepth) + return; + var recs = RectSplit(this); + var de = Depth + 1; + RightTopTree = new QuadTreeNode(recs[0], this, de); + LeftTopTree = new QuadTreeNode(recs[1], this, de); + LeftBottomTree = new QuadTreeNode(recs[2], this, de); + RightBottomTree = new QuadTreeNode(recs[3], this, de); + } + + /// + /// 矩形分裂为四个 + /// + /// + /// + static Rect[] RectSplit(Rect box) + { + var halfWidth = box.Width / 2.0; + var halfHeight = box.Height / 2.0; + + var upperRight = new Rect(box._X + halfWidth, box._Y + halfHeight, box._Right, box._Top); + var upperLeft = new Rect(box._X, box._Y + halfHeight, box._Right - halfWidth, box._Top); + var lowerleft = new Rect(box._X, box._Y, box._Right - halfWidth, box._Top - halfHeight);// 基础 + var lowerRight = new Rect(box._X + halfWidth, box._Y, box._Right, box._Top - halfHeight); + + // 依照象限顺序输出 + return new Rect[] { upperRight, upperLeft, lowerleft, lowerRight }; + } + #endregion + + #region 删 + /// + /// 删除图元 + /// + /// 根据图元删除 + public bool Remove(TEntity easeEnt) + { + // 通过图元id删除无疑是非常低效的, + // 1.相当于在所有的容器查找它,但是移除只会移除一次, + // 因此必须要求图元只会加入一次,才能中断检索剩余分支. + // 2.这个代价还是太高,因此我们还是要默认条件,图元载入一次之后,不再改动. + // 3.不再改动也不太合理,因为cad图元还是可以修改的 + + // 1.处理内容 + if (Contents.Remove(easeEnt)) + { + if (CountSubTree == 0) + this.Clear(this); + return true; + } + + // 2.递归子节点移除 + var nodes = Nodes; + for (int i = 0; i < nodes.Length; i++) + { + var node = nodes[i]; + if (node is null) + continue; + if (node.Remove(easeEnt)) // 递归进入子节点删除内容 + return true; // 删除成功就中断其他节点的搜索 + } + return false; + } + + /// + /// 递归进入最下层节点,然后开始清理 + /// + /// + void Clear(QuadTreeNode node) + { + var nodes = Nodes; + for (int i = 0; i < nodes.Length; i++) + nodes[i]?.Clear(nodes[i]); + + node.Contents.Clear(); + // node.Contents = null;// 重复加入时候会出错 + node.RightTopTree = null; + node.LeftTopTree = null; + node.LeftBottomTree = null; + node.RightBottomTree = null; + node.Parent = null; + // node.Box = zoreRect; + } + + /// + /// 删除子节点内容 + /// + /// 根据范围删除 + public void Remove(Rect queryArea) + { + // 本节点内容移除 + if (Contents is not null && Contents.Count > 0)// 从最上层的根节点开始进入 + { + for (int i = Contents.Count - 1; i >= 0; i--) + { + var ent = Contents[i]; + // 移除之后,如果容器是0,那么这里不能直接 Contents=null, + // 因为此节点下面可能还有节点, + // 需要判断了其后数量0才可以清理. + // 否则其后还有内容,那么此节点就是仍然可以用的. + if (queryArea.Contains(ent)) + Contents.Remove(ent); + } + } + + // 同插入一样 + // 跳到指定节点再搜索这个节点下面的图元 + var nodes = Nodes; + for (int i = 0; i < nodes.Length; i++) + { + var node = nodes[i]; + if (node is null) + continue; + if (node.NodesIsEmpty) + continue; + + // 此节点边界 完全包含 查询区域,则转到该节点,并跳过其余节点(打断此循环) + if (node.Contains(queryArea)) + { + node.Remove(queryArea); + break; + } + // 查询区域 完全包含 此节点边界,提取此节点全部内容 + // 跳过分析碰撞,并继续循环搜索其他节点 + if (queryArea.Contains(node)) + { + node.Clear(node); + continue; + } + // 查询区域 与 此节点四边形边线碰撞 查询该四边形中,并继续循环搜索其他节点 + // 1,角点碰撞 2,边界碰撞 + if (node.IntersectsWith(queryArea)) + node.Remove(queryArea); + } + + // 本节点内容移除之后,旗下还有内容的话, + // 会跳过此处,再进入子节点进行递归,直到最后一个节点 + if (CountSubTree == 0) + Clear(this); + } + #endregion + + #region 查 + /// + /// 查询范围内的实体 + /// + /// 查询矩形 + /// 查询结果 + public void Query(Rect queryArea, List results) + { + GetCurrentContents(queryArea, results); + + // 遍历子节点 + var nodes = Nodes; + for (int i = 0; i < nodes.Length; i++) + { + var node = nodes[i]; + if (node is null) + continue; + // 子节点的4个子节点都是空的, + // 那么表示元素会在子节点这一层啊... + if (node.NodesIsEmpty) + continue; + + // 此节点边界 完全包含 查询区域,则转到该节点,并跳过其余节点(打断此循环) + if (node.Contains(queryArea)) + { + node.Query(queryArea, results); + break; + } + // 查询区域 完全包含 此节点边界,提取此节点全部内容 + // 跳过分析碰撞,并继续循环搜索其他节点 + if (queryArea.Contains(node)) + { + node.ContentsSubTree(results); + continue; + } + // 查询区域 与 此节点四边形边线碰撞 查询该四边形中,并继续循环搜索其他节点 + // 1,角点碰撞 2,边界碰撞 + if (node.IntersectsWith(queryArea)) + node.Query(queryArea, results); + } + } + + /// + /// 获取本节点内容 + /// + /// + /// + void GetCurrentContents(Rect queryArea, List results) + { + // 遍历当前节点内容,加入方式取决于碰撞模式 + if (QuadTreeEvn.SelectMode == QuadTreeSelectMode.IntersectsWith) + { + for (int i = 0; i < Contents.Count; i++) + { + var ent = Contents[i]; + if (queryArea.IntersectsWith(ent)) + results.Add(ent); + } + } + else + { + for (int i = 0; i < Contents.Count; i++) + { + var ent = Contents[i]; + if (queryArea.Contains(ent)) + results.Add(ent); + } + } + } + + /// + /// 找临近图元 + /// + /// 查找矩形 + /// + public TEntity? FindNearEntity(Rect queryArea) + { + TEntity? resultEntity = default; + // 1.找到 查找矩形 所在的节点,利用此节点的矩形. + var queryNode = GetMinNode(queryArea); + var queryAreaCenter = queryArea.CenterPoint; + + // 2.从根开始搜索 + // 如果搜索父亲的父亲的...内容群,它不是距离最近的,只是节点(亲属关系)最近 + // 储存找过的<图元,距离> + var entDic = new Dictionary(); + + var old = QuadTreeEvn.SelectMode; + QuadTreeEvn.SelectMode = QuadTreeSelectMode.IntersectsWith; + while (true) + { + // 循环找父节点大小 + var hw = queryNode.Width / 2.0; + var hh = queryNode.Height / 2.0; + // 3.利用选区中心扩展一个节点边界大小的矩形.从而选择图元 + // 再判断图元的与目标的距离,找到最小距离,即为最近 + var minPt = new Point2d(queryAreaCenter.X - hw, queryAreaCenter.Y - hh); + var maxPt = new Point2d(queryAreaCenter.X + hw, queryAreaCenter.Y + hh); + List ents = []; + Query(new Rect(minPt, maxPt), ents); + for (int i = 0; i < ents.Count; i++) + { + var ent = ents[i]; + if (entDic.ContainsKey(ent)) + continue; + var dis = ent.CenterPoint.GetDistanceTo(queryAreaCenter); + if (dis > 1e-6)// 剔除本身 + entDic.Add(ent, dis); + } + if (entDic.Count > 0) + { + resultEntity = entDic.OrderBy(a => a.Value).First().Key; + break; + } + if (queryNode.Parent is null)// 最顶层就退出 + break; + queryNode = queryNode.Parent;// 利用父节点矩形进行变大选区 + } + QuadTreeEvn.SelectMode = old; + return resultEntity; + } + + /// + /// 找临近节点的图元 + /// + /// 查找矩形 + /// 查找什么方向 + /// + [Obsolete("找附近节点的并不是最近的图元")] + public TEntity? FindNeibor(Rect queryArea, QuadTreeFindMode findMode) + { + TEntity? resultEntity = default; + // 1.找到 查找矩形 所在的节点,利用此节点的矩形. + // 2.利用节点矩形是分裂的特点,边和边必然贴合. + // 3.找到方向 findMode 拥有的节点,然后查找节点的内容 + var queryNode = GetMinNode(queryArea); + + bool whileFlag = true; + // 同一个节点可能包含邻居,因为四叉树的加入是图元压线, + // 那么就在这里搜就得了,用中心点决定空间位置 + // 但是本空间的图元可能都比它矮,无法满足条件 + if (queryNode.CountSubTree > 1) + { + resultEntity = GetNearestNeighbor(queryNode, findMode, queryArea); + if (resultEntity is null || resultEntity.CenterPoint == queryArea.CenterPoint) + whileFlag = true; + else + whileFlag = false; + } + + while (whileFlag) + { + // 同一个父节点是临近的,优先获取 兄弟节点 的内容. + // 循环了第二次是北方兄弟的节点, + // 但是这不是一个找到临近图元的方法, + // 因为临近的可能是父亲的父亲的父亲...另一个函数 FindNearEntity 写 + // 本方案也仅仅作为找北方节点 + var parent = queryNode.Parent; + if (parent is not null) + { + switch (findMode) + { + case QuadTreeFindMode.Top: + { + // 下格才获取上格,否则导致做了无用功,上格就直接获取邻居了 + if (parent.LeftBottomTree == queryNode || parent.RightBottomTree == queryNode) + resultEntity = GetNearestNeighbor(parent, findMode, queryArea); + } + break; + case QuadTreeFindMode.Bottom: + { + if (parent.LeftTopTree == queryNode || parent.RightTopTree == queryNode) + resultEntity = GetNearestNeighbor(parent, findMode, queryArea); + } + break; + case QuadTreeFindMode.Left: + { + if (parent.RightTopTree == queryNode || parent.RightBottomTree == queryNode) + resultEntity = GetNearestNeighbor(parent, findMode, queryArea); + } + break; + case QuadTreeFindMode.Right: + { + if (parent.LeftTopTree == queryNode || parent.LeftBottomTree == queryNode) + resultEntity = GetNearestNeighbor(parent, findMode, queryArea); + } + break; + } + } + if (resultEntity is not null) + break; + + // 通过 所在节点 找 邻居节点, + // 拿到 邻居节点 下面的所有内容(图元) + // 内容可能是空的,再从邻居那往北找...如果找到了四叉树最外层,仍然没有内容,退出循环 + var neiborNode = FindNeiborNode(queryNode, findMode); + if (neiborNode is null) + continue; + if (neiborNode.CountSubTree > 0) + { + resultEntity = GetNearestNeighbor(neiborNode, findMode, queryArea); + break; + } + if (neiborNode.Parent is null)// 如果找到了四叉树最外层,仍然没有内容,退出循环 + break; + queryNode = neiborNode; + } + + return resultEntity; + } + + /// + /// 查找节点的(本内容和子内容)与(查找面积)矩形中点对比,找到最近一个内容 + /// + /// 查找面积 + /// 查找方向 + /// 查找节点 + /// + static TEntity? GetNearestNeighbor(QuadTreeNode queryNode, + QuadTreeFindMode findMode, + Rect queryArea) + { + TEntity? results = default; + + List lst = []; + var qcent = queryArea.CenterPoint; + + switch (findMode) + { + case QuadTreeFindMode.Top: + { + // 取出Y比queryArea的还大的一个,是最近的那个 + var qy = qcent.Y; + queryNode.ContentsSubTree(lst); + lst.ForEach(ent => { + if (ent.CenterPoint.Y > qy) + lst.Add(ent); + }); + lst = lst.OrderBy(ent => ent.CenterPoint.Y).ToList(); + } + break; + case QuadTreeFindMode.Bottom: + { + var qy = qcent.Y; + queryNode.ContentsSubTree(lst); + lst.ForEach(ent => { + if (ent.CenterPoint.Y < qy) + lst.Add(ent); + }); + lst = lst.OrderByDescending(ent => ent.CenterPoint.Y).ToList(); + } + break; + case QuadTreeFindMode.Left: + { + var qx = qcent.Y; + queryNode.ContentsSubTree(lst); + lst.ForEach(ent => { + if (ent.CenterPoint.X > qx) + lst.Add(ent); + }); + lst = lst.OrderBy(ent => ent.CenterPoint.X).ToList(); + } + break; + case QuadTreeFindMode.Right: + { + var qx = qcent.Y; + queryNode.ContentsSubTree(lst); + lst.ForEach(ent => { + if (ent.CenterPoint.X < qx) + lst.Add(ent); + }); + lst = lst.OrderByDescending(ent => ent.CenterPoint.X).ToList(); + } + break; + } + + if (lst.Count > 0) + return lst[0];// 可能就是本体重叠 + return results; + } + + /// + /// 找包含它的最小分支 + /// + /// 查询的矩形 + /// 节点 + QuadTreeNode GetMinNode(Rect queryArea) + { + var nodes = Nodes; + for (int i = 0; i < nodes.Length; i++) + { + var node = nodes[i]; + if (node is null) + continue; + + // 边界包含查询面积,那么再递归查询, + // 直到最后四个都不包含,那么上一个就是图元所在节点 + if (node.Contains(queryArea)) + return node.GetMinNode(queryArea);// 中断后面的范围,才可以返回正确的 + } + return this; + } + + /// + /// 四叉树找邻居节点(相同或更大) + /// + /// 源节点 + /// 方向 + /// + QuadTreeNode? FindNeiborNode(QuadTreeNode tar, QuadTreeFindMode findMode) + { + var parent = tar.Parent; + if (parent is null) + return null; + switch (findMode) + { + case QuadTreeFindMode.Top: + { + // 判断当前节点在父节点的位置,如果是在 下格 就取对应的 上格 + if (tar == parent.LeftBottomTree) + return parent.LeftTopTree; + if (tar == parent.RightBottomTree) + return parent.RightTopTree; + // 否则就是上格 + // 找父节点的北方邻居..也就是在爷节点上面找 + // 递归,此时必然是 下格,就必然返回 上格,然后退出递归 + var parentNeibor = FindNeiborNode(parent, QuadTreeFindMode.Top); + // 父节点的北方邻居 无 子节点 + if (parentNeibor is null || parentNeibor.RightTopTree is null) + return parentNeibor;// 返回父节点的北方邻居,比较大 + // 父节点的北方邻居 有 子节点,剩下条件就只有这两 + + // 如果直接返回,那么是(相同或更大), + // 而找邻近图元需要的是这个(相同或更大)下面的图元,在外面对这个格子内图元用坐标分析就好了 + if (tar == parent.LeftTopTree) + return parentNeibor.LeftBottomTree; + return parentNeibor.RightBottomTree; + } + case QuadTreeFindMode.Bottom: + { + if (tar == parent.LeftTopTree) + return parent.LeftBottomTree; + if (tar == parent.RightTopTree) + return parent.RightBottomTree; + var parentNeibor = FindNeiborNode(parent, QuadTreeFindMode.Bottom); + if (parentNeibor is null || parentNeibor.RightTopTree is null) + return parentNeibor; + if (tar == parent.LeftBottomTree) + return parentNeibor.LeftTopTree; + return parentNeibor.RightTopTree; + } + case QuadTreeFindMode.Right: + { + if (tar == parent.LeftTopTree) + return parent.RightTopTree; + if (tar == parent.LeftBottomTree) + return parent.RightBottomTree; + var parentNeibor = FindNeiborNode(parent, QuadTreeFindMode.Right); + if (tar == parent.RightTopTree) + return parentNeibor?.LeftTopTree; + return parentNeibor?.LeftBottomTree; + } + case QuadTreeFindMode.Left: + { + if (tar == parent.RightTopTree) + return parent.LeftTopTree; + if (tar == parent.RightBottomTree) + return parent.LeftBottomTree; + var parentNeibor = FindNeiborNode(parent, QuadTreeFindMode.Left); + if (tar == parent.LeftTopTree) + return parentNeibor?.RightTopTree; + return parentNeibor?.RightBottomTree; + } + } + return null; + } + #endregion + + #region 改 + /* + /// + /// 所有的点归类到最小包围它的空间 + /// + public void PointsToMinNode() + { + ForEach(node => + { + for (int i = 0; i < node.Contents.Count; i++) + { + var ent = node.Contents[i]; + if (ent.IsPoint) + { + // 如果最小包含!=当前,就是没有放在最适合的位置 + var queryNode = GetMinNode(ent); + if (queryNode != node) + { + node.Remove(ent); + queryNode.Contents.Add(ent); + } + } + } + return false; + }); + } + */ + #endregion + + #region 方法 + /// + /// 递归全部节点(提供给根用的,所以是全部) + /// + /// QTAction + public bool ForEach(QuadTree.QTAction action) + { + // 执行本节点 + if (action(this)) + return true; + + // 递归执行本节点的子节点 + var nodes = Nodes; + for (int i = 0; i < nodes.Length; i++) + { + var node = nodes[i]; + if (node is null) + continue; + if (node.ForEach(action)) + break; + } + return false; + } + #endregion +} \ No newline at end of file diff --git a/CADShared/Algorithms/QuadTree/QuadTreeSelectMode.cs b/CADShared/Algorithms/QuadTree/QuadTreeSelectMode.cs new file mode 100644 index 0000000..624d313 --- /dev/null +++ b/CADShared/Algorithms/QuadTree/QuadTreeSelectMode.cs @@ -0,0 +1,39 @@ +namespace IFoxCAD.Cad; + +/// +/// 四叉树选择模式 +/// +public enum QuadTreeSelectMode +{ + /// + /// 碰撞到就选中 + /// + IntersectsWith, + /// + /// 全包含才选中 + /// + Contains, +} + +/// +/// 四叉树查找方向 +/// +public enum QuadTreeFindMode +{ + /// + /// 上 + /// + Top = 1, + /// + /// 下 + /// + Bottom = 2, + /// + /// 左 + /// + Left = 4, + /// + /// 右 + /// + Right = 8, +} \ No newline at end of file diff --git a/CADShared/Algorithms/QuadTree/Rect.cs b/CADShared/Algorithms/QuadTree/Rect.cs new file mode 100644 index 0000000..583c07d --- /dev/null +++ b/CADShared/Algorithms/QuadTree/Rect.cs @@ -0,0 +1,742 @@ +using System.Diagnostics; +using System.Runtime.CompilerServices; + +namespace IFoxCAD.Cad; + +/// +/// Linq Distinct 消重比较两点在容差范围内就去除 +/// +public class TolerancePoint2d : IEqualityComparer +{ + readonly double _tolerance; + /// + /// 构造函数 + /// + /// 容差 + public TolerancePoint2d(double tolerance = 1e-6) + { + _tolerance = tolerance; + } + /// + /// 比较 + /// + /// + /// + /// + public bool Equals(Point2d a, Point2d b)// Point3d是struct不会为null + { + /*默认规则是==是0容差,Eq是有容差*/ + // 方形限定 + // 在 0~1e-6 范围实现 圆形限定 则计算部分在浮点数6位后,没有啥意义 + // 在 0~1e-6 范围实现 从时间和CPU消耗来说,圆形限定 都没有 方形限定 的好 + if (_tolerance <= 1e-6) + return Math.Abs(a.X - b.X) <= _tolerance && Math.Abs(a.Y - b.Y) <= _tolerance; + + // 圆形限定 + // DistanceTo 分别对XYZ进行了一次乘法,也是总数3次乘法,然后求了一次平方根 + // (X86.CPU.FSQRT指令用的牛顿迭代法/软件层面可以使用快速平方根....我还以为CPU会采取快速平方根这样的取表操作) + return a.IsEqualTo(b, new Tolerance(_tolerance, _tolerance)); + } + /// + /// 哈希 + /// + /// + /// + public int GetHashCode(Point2d obj) + { + // 结构体直接返回 obj.GetHashCode(); Point3d ToleranceDistinct3d + // 因为结构体是用可值叠加来判断?或者因为结构体兼备了一些享元模式的状态? + // 而类是构造的指针,所以取哈希值要改成x+y+z..s给Equals判断用,+是会溢出,所以用^ + return (int)obj.X ^ (int)obj.Y;// ^ (int)obj.Z; + } +} + +/// +/// 矩形范围类 +/// +[Serializable] +[StructLayout(LayoutKind.Sequential)] +[DebuggerDisplay("{DebuggerDisplay,nq}")] +[DebuggerTypeProxy(typeof(Rect))] +public class Rect : IEquatable, IComparable +{ + [DebuggerBrowsable(DebuggerBrowsableState.Never)] + private string DebuggerDisplay => ToString("f4"); + +#pragma warning disable CA2211 // 非常量字段应当不可见 + /// + /// 矩形容差 + /// + public static TolerancePoint2d RectTolerance = new(1e-6); + /// + /// cad容差 + /// + public static Tolerance CadTolerance = new(1e-6, 1e-6); +#pragma warning restore CA2211 // 非常量字段应当不可见 + + #region 字段 + // 这里的成员不要用{get}封装成属性,否则会导致跳转了一次函数, + // 10w图元将会从187毫秒变成400毫秒 + // 不用 protected 否则子类传入Rect对象进来无法用 + internal double _X; + internal double _Y; + internal double _Right; + internal double _Top; + #endregion + + #region 成员 + /// + /// X + /// + public double X => _X; + /// + /// Y + /// + public double Y => _Y; + /// + /// 左 + /// + public double Left => _X; + /// + /// 下 + /// + public double Bottom => _Y; + /// + /// 右 + /// + public double Right => _Right; + /// + /// 上 + /// + public double Top => _Top; + /// + /// 宽 + /// + public double Width => _Right - _X; + /// + /// 高 + /// + public double Height => _Top - _Y; + /// + /// 面积 + /// + public double Area + { + get + { + var ar = (_Right - _X) * (_Top - _Y); + return ar < 1e-10 ? 0 : ar; + } + } + /// + /// 左下Min + /// + public Point2d MinPoint => LeftLower; + /// + /// 右上Max + /// + public Point2d MaxPoint => RightUpper; + /// + /// 中间 + /// + public Point2d CenterPoint => Midst; + + /// + /// 左下Min + /// + public Point2d LeftLower => new(_X, _Y); + + /// + /// 左中 + /// + public Point2d LeftMidst => new(_X, Midst.Y); + + /// + /// 左上 + /// + public Point2d LeftUpper => new(_X, _Top); + + /// + /// 右上Max + /// + public Point2d RightUpper => new(_Right, _Top); + + /// + /// 右中 + /// + public Point2d RightMidst => new(_Right, Midst.Y); + + /// + /// 右下 + /// + public Point2d RightBottom => new(_Right, _Y); + + /// + /// 中间 + /// + public Point2d Midst => new(((_Right - _X) * 0.5) + _X, ((_Top - _Y) * 0.5) + _Y); + + /// + /// 中上 + /// + public Point2d MidstUpper => new(Midst.X, _Top); + + /// + /// 中下 + /// + public Point2d MidstBottom => new(Midst.X, _Y); + + /// + /// 是一个点 + /// 水平或垂直直线包围盒是面积是0,所以面积是0不一定是点 + /// + public bool IsPoint => Math.Abs(_X - _Right) < 1e-10 && Math.Abs(_Y - _Top) < 1e-10; + #endregion + + #region 构造 + /// + /// + /// + public Rect() + { + } + + /// + /// 矩形类 + /// + /// 左 + /// 下 + /// 右 + /// 上 + public Rect(double left, double bottom, double right, double top) + { + _X = left; + _Y = bottom; + _Right = right; + _Top = top; + } + + /// + /// 构造矩形类 + /// + /// + /// + /// 是否检查大小 + public Rect(Point2d p1, Point2d p3, bool check = false) + { + if (check) + { + _X = Math.Min(p1.X, p3.X); + _Y = Math.Min(p1.Y, p3.Y); + _Right = Math.Max(p1.X, p3.X); + _Top = Math.Max(p1.Y, p3.Y); + } + else + { + _X = p1.X; + _Y = p1.Y; + _Right = p3.X; + _Top = p3.Y; + } + } + #endregion + + #region 重载运算符_比较 + /// + /// + /// + /// + /// + public override bool Equals(object? obj) + { + return this.Equals(obj as Rect); + } + /// + /// + /// + /// + /// + public bool Equals(Rect? b) + { + return this.Equals(b, 1e-6);/*默认规则是==是0容差,Eq是有容差*/ + } + /// + /// + /// + /// + /// + /// + public static bool operator !=(Rect? a, Rect? b) + { + return !(a == b); + } + /// + /// + /// + /// + /// + /// + public static bool operator ==(Rect? a, Rect? b) + { + // 此处地方不允许使用==null,因为此处是定义 + if (b is null) + return a is null; + else if (a is null) + return false; + if (ReferenceEquals(a, b))// 同一对象 + return true; + + return a.Equals(b, 0); + } + + /// + /// 比较核心 + /// + public bool Equals(Rect? b, double tolerance = 1e-6) + { + if (b is null) + return false; + if (ReferenceEquals(this, b)) // 同一对象 + return true; + + return Math.Abs(_X - b._X) < tolerance && + Math.Abs(_Right - b._Right) < tolerance && + Math.Abs(_Top - b._Top) < tolerance && + Math.Abs(_Y - b._Y) < tolerance; + } + /// + /// + /// + /// + public override int GetHashCode() + { + return (((int)_X ^ (int)_Y).GetHashCode() ^ (int)_Right).GetHashCode() ^ (int)_Top; + } + #endregion + + #region 包含 + /// + /// + /// + /// + /// + public bool Contains(Point2d Point2d) + { + return Contains(Point2d.X, Point2d.Y); + } + /// + /// + /// + /// + /// + /// + public bool Contains(double x, double y) + { + return _X <= x && x <= _Right && + _Y <= y && y <= _Top; + } + + /// + /// 四个点都在内部就是包含 + /// + /// + /// + public bool Contains(Rect rect) + { + return _X <= rect._X && rect._Right <= _Right && + _Y <= rect._Y && rect._Top <= _Top; + } + + /// + /// 一个点在内部就是碰撞 + /// + /// + /// true内部 + [MethodImpl] + public bool IntersectsWith(Rect rect) + { + return rect._X <= _Right && _X <= rect._Right && + rect._Top >= _Y && rect._Y <= _Top; + } + #endregion + + #region 方法 + /// + /// 获取共点 + /// + /// + public Point2d[] GetCommonPoint(Rect other) + { + return ToPoints().Intersect(other.ToPoints(), RectTolerance).ToArray(); + } + /// + /// 转换为point2d数组 + /// + /// + public Point2d[] ToPoints() + { + Point2d a = MinPoint;// min + Point2d b = new(_Right, _Y); + Point2d c = MaxPoint;// max + Point2d d = new(_X, _Top); + return [a, b, c, d]; + } + /// + /// 转换为point2d元组 + /// + /// + public (Point2d boxMin, Point2d boxRigthDown, Point2d boxMax, Point2d boxLeftUp) ToPoints4() + { + Point2d a = MinPoint;// min + Point2d b = new(_Right, _Y); + Point2d c = MaxPoint;// max + Point2d d = new(_X, _Top); + return (a, b, c, d); + } + + /// + /// 四周膨胀 + /// + /// + public Rect Expand(double d) + { + return new Rect(_X - d, _Y - d, _Right + d, _Top + d); + } + + /// + /// 是否矩形(带角度) + /// + /// + /// + /// + public static bool IsRectAngle(List? ptList, double tolerance = 1e-8) + { + //if (ptList == null) + // throw new ArgumentNullException(nameof(ptList)); + + ArgumentNullEx.ThrowIfNull(ptList); + var pts = ptList.ToList(); + /* + * 消重,不这里设置,否则这不是一个正确的单元测试 + * // var ptList = pts.Distinct().ToList(); + * var ptList = pts.DistinctExBy((a, b) => a.DistanceTo(b) < 1e-6).ToList(); + */ + if (ptList.Count == 5) + { + // 首尾点相同移除最后 + if (pts[0].IsEqualTo(pts[^1], CadTolerance)) + pts.RemoveAt(pts.Count - 1); + } + if (pts.Count != 4) + return false; + + // 最快的方案 + // 点乘求值法:(为了处理 正梯形/平行四边形 需要三次) + // 这里的容差要在1e-8内,因为点乘的三次浮点数乘法会令精度变低 + var dot = DotProductValue(pts[0], pts[1], pts[3]); + if (Math.Abs(dot) < tolerance) + { + dot = DotProductValue(pts[1], pts[2], pts[0]); + if (Math.Abs(dot) < tolerance) + { + dot = DotProductValue(pts[2], pts[3], pts[1]); + return Math.Abs(dot) < tolerance; + } + } + return false; + } + + /// + /// 点积,求值 + /// 1.是两个向量的长度与它们夹角余弦的积 + /// 2.求四个点是否矩形使用 + /// + /// 原点 + /// 点 + /// 点 + /// 0方向相同,夹角0~90度;=0相互垂直;<0方向相反,夹角90~180度]]> + static double DotProductValue(Point2d o, Point2d a, Point2d b) + { + var oa = o.GetVectorTo(a); + var ob = o.GetVectorTo(b); + return (oa.X * ob.X) + (oa.Y * ob.Y); + } + + /// + /// 是否轴向矩形(无角度) + /// + public static bool IsRect(List? ptList, double tolerance = 1e-10) + { + //if (ptList == null) + // throw new ArgumentNullException(nameof(ptList)); + ArgumentNullEx.ThrowIfNull(ptList); + var pts = ptList.ToList(); + if (ptList.Count == 5) + { + // 首尾点相同移除最后 + if (pts[0].IsEqualTo(pts[^1], CadTolerance)) + pts.RemoveAt(pts.Count - 1); + } + if (pts.Count != 4) + return false; + + return Math.Abs(pts[0].X - pts[3].X) < tolerance && + Math.Abs(pts[0].Y - pts[1].Y) < tolerance && + Math.Abs(pts[1].X - pts[2].X) < tolerance && + Math.Abs(pts[2].Y - pts[3].Y) < tolerance; + } + + /// + /// 获取点集的包围盒的最小点和最大点(无角度) + /// + /// + public static (Point2d boxMin, Point2d boxMax) GetMinMax(IEnumerable pts) + { + var xMin = double.MaxValue; + var xMax = double.MinValue; + var yMin = double.MaxValue; + var yMax = double.MinValue; + // var zMin = double.MaxValue; + // var zMax = double.MinValue; + + pts.ForEach(p => { + xMin = Math.Min(p.X, xMin); + xMax = Math.Max(p.X, xMax); + yMin = Math.Min(p.Y, yMin); + yMax = Math.Max(p.Y, yMax); + // zMin = Math.Min(p.Z, zMin); + // zMax = Math.Max(p.Z, zMax); + }); + return (new Point2d(xMin, yMin), new Point2d(xMax, yMax)); + } + + /// + /// 矩形点序逆时针排列,将min点[0],max点是[3](带角度) + /// + /// + /// + public static bool RectAnglePointOrder(List? pts) + { + //if (pts == null) + // throw new ArgumentNullException(nameof(pts)); + ArgumentNullEx.ThrowIfNull(pts); + if (!Rect.IsRectAngle(pts)) + return false; + + // 获取min和max点(非包围盒) + pts = pts.OrderBy(a => a.X).ThenBy(a => a.Y).ToList(); + var minPt = pts.First(); + var maxPt = pts.Last(); + var link = new LoopList(); + link.AddRange(pts); + + pts.Clear(); + // 排序这四个点,左下/右下/右上/左上 + var node = link.Find(minPt); + for (int i = 0; i < 4; i++) + { + pts.Add(node!.Value); + node = node.Next; + } + // 保证是逆时针 + var isAcw = CrossAclockwise(pts[0], pts[1], pts[2]); + if (!isAcw) + (pts[3], pts[1]) = (pts[1], pts[3]); + return true; + } + + /// + /// 叉积,二维叉乘计算 + /// + /// 传参是向量,表示原点是0,0 + /// 传参是向量,表示原点是0,0 + /// 其模为a与b构成的平行四边形面积 + static double Cross(Vector2d a, Vector2d b) + { + return a.X * b.Y - a.Y * b.X; + } + + /// + /// 叉积,二维叉乘计算 + /// + /// 原点 + /// oa向量 + /// ob向量,此为判断点 + /// 返回值有正负,表示绕原点四象限的位置变换,也就是有向面积 + static double Cross(Point2d o, Point2d a, Point2d b) + { + return Cross(o.GetVectorTo(a), o.GetVectorTo(b)); + } + + /// + /// 叉积,逆时针方向为真 + /// + /// 直线点1 + /// 直线点2 + /// 判断点 + /// b点在oa的逆时针时为 + static bool CrossAclockwise(Point2d o, Point2d a, Point2d b) + { + return Cross(o, a, b) > -1e-6;// 浮点数容差考虑 + } + +#if !WinForm + /// + /// 创建矩形范围多段线 + /// + /// 多段线对象 + public Entity ToPolyLine() + { + List bv = []; + var pts = ToPoints(); + Polyline pl = new(); + pl.SetDatabaseDefaults(); + pts.ForEach((vertex, state, index) => { + pl.AddVertexAt(index, vertex, 0, 0, 0); + }); + return pl; + } +#endif + + /// + /// 列扫碰撞检测(碰撞算法) + /// 比四叉树还快哦~ + /// + /// + /// 继承Rect的集合 + /// 先处理集合每一个成员;返回true就跳过后续委托 + /// 碰撞,返回两个碰撞的成员;返回true就跳过后续委托 + /// 后处理集合每一个成员 + public static void XCollision(List box, + Func firstProcessing, + Func collisionProcessing, + Action lastProcessing) where T : Rect + { + // 先排序X:不需要Y排序,因为Y的上下浮动不共X .ThenBy(a => a.Box.Y) + // 因为先排序就可以有序遍历x区间,超过就break,达到更快 + box = box.OrderBy(a => a._X).ToList(); + + // 遍历所有图元 + for (int i = 0; i < box.Count; i++) + { + var oneRect = box[i]; + if (firstProcessing(oneRect)) + continue; + + bool actionlast = true; + + // 搜索范围要在 one 的头尾中间的部分 + for (int j = i + 1; j < box.Count; j++) + { + var twoRect = box[j]; + // x碰撞:矩形2的Left 在 矩形1[Left-Right]闭区间;穿过的话,也必然有自己的Left因此不需要处理 + if (oneRect._X <= twoRect._X && twoRect._X <= oneRect._Right) + { + // y碰撞,那就是真的碰撞了 + if ((oneRect._Top >= twoRect._Top && twoRect._Top >= oneRect._Y) /*包容上边*/ + || (oneRect._Top >= twoRect._Y && twoRect._Y >= oneRect._Y) /*包容下边*/ + || (twoRect._Top >= oneRect._Top && oneRect._Y >= twoRect._Y)) /*穿过*/ + { + if (collisionProcessing(oneRect, twoRect)) + actionlast = false; + } + // 这里想中断y高过它的无意义比较, + // 但是必须排序Y,而排序Y必须同X,而这里不是同X(而是同X区间),所以不能中断 + // 而做到X区间排序,就必须创造一个集合,再排序这个集合, + // 会导致每个图元都拥有一次X区间集合,开销更巨大(因此放弃). + } + else + break;// 因为已经排序了,后续的必然超过 x碰撞区间 + } + + if (actionlast) + lastProcessing(oneRect); + } + } + + #endregion + + #region 转换类型 +#if !WinForm + // 隐式转换(相当于是重载赋值运算符) + // public static implicit operator Rect(System.Windows.Rect rect) + // { + // return new Rect(rect.Left, rect.Bottom, rect.Right, rect.Top); + // } + /// + /// + /// + /// + public static implicit operator Rect(System.Drawing.RectangleF rect) + { + return new Rect(rect.Left, rect.Bottom, rect.Right, rect.Top); + } + /// + /// + /// + /// + public static implicit operator Rect(System.Drawing.Rectangle rect) + { + return new Rect(rect.Left, rect.Bottom, rect.Right, rect.Top); + } +#endif + + #region ToString + /// + /// + /// + /// + public sealed override string ToString() + { + return ToString(null, null); + } + /// + /// + /// + /// + /// + public string ToString(IFormatProvider? provider) + { + return ToString(null, provider); + } + /// + /// + /// + /// + /// + /// + public string ToString(string? format = null, IFormatProvider? formatProvider = null) + { + return $"({_X.ToString(format, formatProvider)},{_Y.ToString(format, formatProvider)})," + + $"({_Right.ToString(format, formatProvider)},{_Top.ToString(format, formatProvider)})"; + + // return $"X={_X.ToString(format, formatProvider)}," + + // $"Y={_Y.ToString(format, formatProvider)}," + + // $"Right={_Right.ToString(format, formatProvider)}," + + // $"Top={_Top.ToString(format, formatProvider)}"; + } + + /*为了红黑树,加入这个*/ + /// + /// + /// + /// + /// + public int CompareTo(Rect rect) + { + if (rect == null) + return -1; + if (_X < rect._X) + return -1; + else if (_X > rect._X) + return 1; + else if (_Y < rect._Y)/*x是一样的*/ + return -1; + else if (_Y > rect._Y) + return 1; + return 0;/*全部一样*/ + } + #endregion + + #endregion +} \ No newline at end of file diff --git a/CADShared/CADShared.projitems b/CADShared/CADShared.projitems index 9d58b70..0c4e0b9 100644 --- a/CADShared/CADShared.projitems +++ b/CADShared/CADShared.projitems @@ -9,6 +9,12 @@ CADShared + + + + + + -- Gitee From 2746387f5670378bc267808eadb0e107164b039b Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sun, 20 Oct 2024 21:13:05 +0800 Subject: [PATCH 324/453] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E5=BA=93=E5=AD=97=E5=85=B8=E7=9A=84=E4=BD=BF=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/ExtensionMethod/DBDictionaryEx.cs | 74 +++++---------------- CADShared/ResultData/XRecordDataList.cs | 20 +++++- 2 files changed, 32 insertions(+), 62 deletions(-) diff --git a/CADShared/ExtensionMethod/DBDictionaryEx.cs b/CADShared/ExtensionMethod/DBDictionaryEx.cs index ce1268f..de6f630 100644 --- a/CADShared/ExtensionMethod/DBDictionaryEx.cs +++ b/CADShared/ExtensionMethod/DBDictionaryEx.cs @@ -24,48 +24,6 @@ public static IEnumerable GetAllObjects(this DBDictionary dict) where T : } } - /// - /// 获取字典内指定key的对象 - /// - /// 对象类型的泛型 - /// 字典 - /// 指定的键值 - /// T 类型的对象 - [Obsolete] - public static T? GetAt(this DBDictionary dict, string key) where T : DBObject - { - var tr = DBTrans.GetTopTransaction(dict.Database); - if (dict.Contains(key)) - { - var id = dict.GetAt(key); - if (!id.IsNull) - return tr.GetObject(id); - } - - return null; - } - - /// - /// 添加条目(键值对)到字典 - /// - /// 对象类型 - /// 字典 - /// 键 - /// 值 - /// 字典项目的id - [Obsolete] - public static ObjectId SetAt(this DBDictionary dict, string key, T newValue) where T : DBObject - { - var tr = DBTrans.GetTopTransaction(dict.Database); - - using (dict.ForWrite()) - { - var id = dict.SetAt(key, newValue); - tr.AddNewlyCreatedDBObject(newValue, true); - return id; - } - } - /// /// 获取字典内指定key的对象 /// @@ -90,8 +48,8 @@ public static ObjectId SetAt(this DBDictionary dict, string key, T newValue) /// /// 对象类型的泛型 /// 字典 - /// 指定的键值 - /// T 类型的对象 + /// key + /// T类型的对象 public static T? GetData(this DBDictionary dict, string key) where T : DBObject { var tr = DBTrans.GetTopTransaction(dict.Database); @@ -99,7 +57,9 @@ public static ObjectId SetAt(this DBDictionary dict, string key, T newValue) { var id = dict.GetAt(key); if (!id.IsNull) + { return tr.GetObject(id); + } } return null; @@ -128,6 +88,7 @@ public static ObjectId SetData(this DBDictionary dict, string key, T newValue dict.Remove(key); } } + var id = dict.SetAt(key, newValue); tr.AddNewlyCreatedDBObject(newValue, true); return id; @@ -144,14 +105,10 @@ public static ObjectId SetData(this DBDictionary dict, string key, T newValue /// 字典 /// 键值 /// 扩展数据 + // ReSharper disable once ReturnTypeCanBeNotNullable public static XRecordDataList? GetXRecord(this DBDictionary dict, string key) { - if (dict.GetData(key) is Xrecord { Data: not null } xr) - { - return xr.Data; - } - - return null; + return dict.GetData(key) is Xrecord { Data: not null } xr ? xr.Data : null; } /// @@ -160,13 +117,14 @@ public static ObjectId SetData(this DBDictionary dict, string key, T newValue /// 扩展数据 /// 字典 /// 键值 - public static void SetXRecord(this DBDictionary dict, string key, XRecordDataList rb) + /// 字典项的Id + public static ObjectId SetXRecord(this DBDictionary dict, string key, XRecordDataList rb) { // DxfCode.300 字符串可以写 Data // DxfCode.1004 内存流不给写 Data,只能去写 XData Xrecord newValue = new(); newValue.Data = rb; - dict.SetData(key, newValue); + return dict.SetData(key, newValue); } #endregion @@ -184,7 +142,9 @@ public static DBDictionary GetXDictionary(this DBObject obj, OpenMode openMode = if (id.IsNull) { using (obj.ForWrite()) + { obj.CreateExtensionDictionary(); + } id = obj.ExtensionDictionary; } @@ -294,8 +254,7 @@ public static void SetValue(this DataCell cell, CellType type, object value) /// 是否创建子字典 /// 键值列表 /// 字典 - public static DBDictionary? GetSubDictionary(this DBDictionary dict, - bool createSubDictionary, + public static DBDictionary? GetSubDictionary(this DBDictionary dict, bool createSubDictionary, IEnumerable dictNames) { DBDictionary? newDict = null; @@ -387,8 +346,7 @@ public static ObjectId AddGroup(this DBDictionary dict, string name, IEnumerable /// 编组集合 public static IEnumerable GetGroups(this DBDictionary dict, Func func) { - return dict.GetAllObjects() - .Where(func); + return dict.GetAllObjects().Where(func); } /// @@ -398,9 +356,7 @@ public static IEnumerable GetGroups(this DBDictionary dict, Func编组集合 public static IEnumerable GetGroups(this Entity ent) { - return ent.GetPersistentReactorIds() - .Cast() - .Select(id => id.GetObject()) + return ent.GetPersistentReactorIds().Cast().Select(id => id.GetObject()) .OfType(); } diff --git a/CADShared/ResultData/XRecordDataList.cs b/CADShared/ResultData/XRecordDataList.cs index e36eb3e..37e4520 100644 --- a/CADShared/ResultData/XRecordDataList.cs +++ b/CADShared/ResultData/XRecordDataList.cs @@ -6,18 +6,25 @@ public class XRecordDataList : TypedValueList { #region 构造函数 + /// /// 扩展字典数据封装类 /// - public XRecordDataList() { } + public XRecordDataList() + { + } /// /// 扩展字典数据封装类 /// - public XRecordDataList(IEnumerable values) : base(values) { } + public XRecordDataList(IEnumerable values) : base(values) + { + } + #endregion #region 添加数据 + /// /// 添加数据 /// @@ -40,28 +47,35 @@ public void Add(DxfCode code, object obj) { Add((int)code, obj); } + #endregion #region 转换器 + /// /// ResultBuffer 隐式转换到 XRecordDataList /// /// ResultBuffer 实例 - public static implicit operator XRecordDataList(ResultBuffer buffer) => new(buffer.AsArray()); + public static implicit operator XRecordDataList(ResultBuffer? buffer) => + buffer is null ? new() : new(buffer.AsArray()); + /// /// XRecordDataList 隐式转换到 TypedValue 数组 /// /// TypedValueList 实例 public static implicit operator TypedValue[](XRecordDataList values) => values.ToArray(); + /// /// XRecordDataList 隐式转换到 ResultBuffer /// /// TypedValueList 实例s public static implicit operator ResultBuffer(XRecordDataList values) => new(values); + /// /// TypedValue 数组隐式转换到 XRecordDataList /// /// TypedValue 数组 public static implicit operator XRecordDataList(TypedValue[] values) => new(values); + #endregion } \ No newline at end of file -- Gitee From 0f7a5be7ba081d38402557dba154c340e33d5380 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sun, 20 Oct 2024 21:16:41 +0800 Subject: [PATCH 325/453] =?UTF-8?q?=E8=A1=A5=E5=85=85DBTrans=E6=89=A9?= =?UTF-8?q?=E5=B1=95=E5=92=8CDwgMark?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/CADShared.projitems | 2 + CADShared/ExtensionMethod/DBTransEx.cs | 94 ++++++++++++++++++++++++++ CADShared/ExtensionMethod/DwgMark.cs | 70 +++++++++++++++++++ 3 files changed, 166 insertions(+) create mode 100644 CADShared/ExtensionMethod/DBTransEx.cs create mode 100644 CADShared/ExtensionMethod/DwgMark.cs diff --git a/CADShared/CADShared.projitems b/CADShared/CADShared.projitems index 0c4e0b9..49ba9ae 100644 --- a/CADShared/CADShared.projitems +++ b/CADShared/CADShared.projitems @@ -33,7 +33,9 @@ + + diff --git a/CADShared/ExtensionMethod/DBTransEx.cs b/CADShared/ExtensionMethod/DBTransEx.cs new file mode 100644 index 0000000..d2652ee --- /dev/null +++ b/CADShared/ExtensionMethod/DBTransEx.cs @@ -0,0 +1,94 @@ +#define lack_test + +namespace IFoxCAD.Cad; + +#if lack_test +/// +/// 事务类扩展 +/// +public static class DBTransEx +{ + /* + * 0x01 + * db.Purge(ids)是获取未硬引用(无引用?)的对象,也就可以删除的. + * 0x02 + * 如果一个图元引用一个图层, + * 假设这个图元是可以删除的(实际上它可能来自词典记录的id) => 那么它被 db.Purge(ids) 识别, + * 但是这个图层因为有硬引用,所以不被 db.Purge(ids) 识别, + * 只能删除图元之后,循环第二次再通过 db.Purge(ids) 获取图层id. + * 0x03 + * 因为删除之后,符号表内的引用可能被修改,因此需要重复遍历符号表. + * 0x04 + * 试试循环事务 + * 0x05 + * 无法过滤外部参照图层,使得全部图层打开了 + */ + + /// + /// 清理符号表 + /// + /// + /// + /// 排除外部参照:默认true,为false时候会令图层全部显示再清理,包括冻结 + public static void Purge(this DBTrans tr, SymModes sym = SymModes.All, bool excludeXref = true) + { + using ObjectIdCollection ids = new(); + var db = tr.Database; + + if ((sym & SymModes.BlockTable) == SymModes.BlockTable) + { + if (!excludeXref) + GetAllIds(tr, tr.BlockTable, ids, excludeXref); + else + tr.BlockTable.ForEach(tabRec => { + if (!tabRec.IsFromExternalReference) + ids.Add(tabRec.Id); + }, checkIdOk: true); + } + if ((sym & SymModes.DimStyleTable) == SymModes.DimStyleTable) + GetAllIds(tr, tr.DimStyleTable, ids, excludeXref); + if ((sym & SymModes.LayerTable) == SymModes.LayerTable) + GetAllIds(tr, tr.LayerTable, ids, excludeXref); + if ((sym & SymModes.LinetypeTable) == SymModes.LinetypeTable) + GetAllIds(tr, tr.LinetypeTable, ids, excludeXref); + if ((sym & SymModes.TextStyleTable) == SymModes.TextStyleTable) + GetAllIds(tr, tr.TextStyleTable, ids, excludeXref); + if ((sym & SymModes.ViewportTable) == SymModes.ViewportTable) + GetAllIds(tr, tr.ViewportTable, ids, excludeXref); + if ((sym & SymModes.RegAppTable) == SymModes.RegAppTable) + GetAllIds(tr, tr.RegAppTable, ids, excludeXref); + + // SHUN007 说这两个表可能有错误 + if ((sym & SymModes.ViewTable) == SymModes.ViewTable) + GetAllIds(tr, tr.ViewTable, ids, excludeXref); + if ((sym & SymModes.UcsTable) == SymModes.UcsTable) + GetAllIds(tr, tr.UcsTable, ids, excludeXref); + + // Purge是查询能够清理的对象 + db.Purge(ids); + foreach (ObjectId id in ids) + id.Erase(); + } + + static void GetAllIds(DBTrans tr, + SymbolTable symbolTable, + ObjectIdCollection ids, + bool excludeXref = true) + where TTable : SymbolTable + where TRecord : SymbolTableRecord, new() + { + if (!excludeXref) + symbolTable.ForEach(id => ids.Add(id)); + else + { + symbolTable.ForEach(id => { + var tabRec = tr.GetObject(id); + if (tabRec == null) + return; + if (!tabRec.Name.Contains("|")) + ids.Add(tabRec.Id); + }); + } + } +} +#endif \ No newline at end of file diff --git a/CADShared/ExtensionMethod/DwgMark.cs b/CADShared/ExtensionMethod/DwgMark.cs new file mode 100644 index 0000000..501da98 --- /dev/null +++ b/CADShared/ExtensionMethod/DwgMark.cs @@ -0,0 +1,70 @@ +namespace IFoxCAD.Cad; + +/// +/// 为dwg文件添加标记 +/// +public static class DwgMark +{ + private const int kFreeSpace = 0x15; + private const int kFreeSpaceDefault = 0x00; + + /// + /// 为dwg文件添加标识 + /// + /// DWG文件 + /// ASCII标识字节0X00~0X7F + /// 非dwg文件会报错,给定bite超界限也报错 + public static void AddMark(FileInfo file, int bite) + { + if (file.Extension.ToLower() != ".dwg") + { + throw new ArgumentException("必须是dwg文件!"); + } + + if (bite > 0x7F || bite < 0x00) + { + throw new ArgumentException("字符必须在ASCII范围!"); + } + + using var bw = new BinaryWriter(File.Open(file.FullName, FileMode.Open)); + bw.BaseStream.Position = kFreeSpace; //文件头第21个字节 + bw.Write(bite); //写入数据,仅一个字节 + } + + /// + /// 将dwg文件标记恢复为默认值 + /// + /// 文件 + /// 非dwg文件会报错 + public static void RemoveMark(FileInfo file) + { + if (file.Extension.ToLower() != ".dwg") + { + throw new ArgumentException("必须是dwg文件!"); + } + + using var bw = new BinaryWriter(File.Open(file.FullName, FileMode.Open)); + bw.BaseStream.Position = kFreeSpace; //文件头第21个字节 + bw.Write(kFreeSpaceDefault); //写入数据,仅一个字节 + } + + /// + /// 获取设置的dwg文件标记 + /// + /// 文件 + /// + /// 非dwg文件会报错 + public static int GetMark(FileInfo file) + { + if (file.Extension.ToLower() != ".dwg") + { + throw new ArgumentException("必须是dwg文件!"); + } + + using var fs = File.OpenRead(file.FullName); + fs.Seek(kFreeSpace, SeekOrigin.Begin); + var mark = new byte[1]; + _ = fs.Read(mark, 0, mark.Length); + return mark[0]; + } +} \ No newline at end of file -- Gitee From b280810a5af43e80db022c387cda756c0464ff21 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sun, 20 Oct 2024 21:19:13 +0800 Subject: [PATCH 326/453] =?UTF-8?q?=E8=A1=A5=E5=85=85=E9=94=99=E8=AF=AF?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/CADShared.projitems | 1 + CADShared/ExtensionMethod/ErrorInfoEx.cs | 421 +++++++++++++++++++++++ 2 files changed, 422 insertions(+) create mode 100644 CADShared/ExtensionMethod/ErrorInfoEx.cs diff --git a/CADShared/CADShared.projitems b/CADShared/CADShared.projitems index 49ba9ae..8470753 100644 --- a/CADShared/CADShared.projitems +++ b/CADShared/CADShared.projitems @@ -45,6 +45,7 @@ + diff --git a/CADShared/ExtensionMethod/ErrorInfoEx.cs b/CADShared/ExtensionMethod/ErrorInfoEx.cs new file mode 100644 index 0000000..35c9512 --- /dev/null +++ b/CADShared/ExtensionMethod/ErrorInfoEx.cs @@ -0,0 +1,421 @@ +namespace IFoxCAD.Cad; + +/// +/// CAD错误大全 +/// +public static class ErrorInfoEx +{ + /// + /// 打印CAD错误信息到命令行 + /// 使用方法: + /// try + /// { + /// //你的代码 + /// } + /// catch (AcException acex) { acex.AcErrorInfo(); } + /// catch (Exception) { throw; } + /// + /// + /// AcException + internal static void AcErrorInfo(this AcException acex) + { + var infoStr = acex.Message switch + { + "eAlreadyInDb" => "已经在数据库中了", + "eAmbiguousInput" => "模糊不清的输入", + "eAmbiguousOutput" => "模糊不清的输出", + "eAnonymousEntry" => "多重入口", + "eBrokenHandle" => "损坏的句柄", + "eBufferTooSmall" => "缓冲区太小", + "eContainerNotEmpty" => "容器不为空", + "eDeletedEntry" => "已经删除的函数入口", + "eDuplicateDxfField" => "DXF字段重复", + "eDuplicateIndex" => "重复的索引", + "eDuplicateKey" => "重复的关键字", + "eEndOfFile" => "文件结束", + "eEndOfObject" => "对象结束", + "eEntityInInactiveLayout" => "实体不在活动布局上", + "eHandleExists" => "句柄已存在", + "eHandleInUse" => "句柄被占用", + "eIllegalEntityType" => "非法的实体类型", + "eIllegalReplacement" => "非法的替代者", + "eInvalidAdsName" => "无效的ADS名称", + "eInvalidBlockName" => "不合理的块名称", + "eInvalidDwgVersion" => "不合理的DWG版本", + "eInvalidDxfCode" => "不合理的DXF编码", + "eInvalidExtents" => "无效的空间范围", + "eInvalidIndex" => "无效的索引", + "eInvalidInput" => "无效的输入", + "eInvalidKey" => "无效的关键字", + "eInvalidOpenState" => "无效的打开状态", + "eInvalidSymbolTableName" => "无效的符号名称", + "eIsReading" => "正在读取", + "eIsWriting" => "正在写入", + "eKeyNotFound" => "关键字未找到", + "eMissingDxfField" => "DXF字段缺失", + "eNegativeValueNotAllowed" => "不允许输入负数", + "eNotApplicable" => "不合适的", + "eNotImplementedYet" => "尚未实现", + "eNotOpenForRead" => "不是只读打开", + "eNotOpenForWrite" => "不是可写打开", + "eNotThatKindOfClass" => "类型不匹配", + "eNullBlockName" => "块名称为空", + "eNullEntityPointer" => "实体指针为空", + "eNullHandle" => "空句柄", + "eNullObjectId" => "对象ID为空", + "eNullObjectPointer" => "对象指针为空", + "eObjectToBeDeleted" => "对象即将被删除", + "eOk" => "正确", + "eOutOfDisk" => "硬盘容量不足", + "eOutOfMemory" => "内存不足", + "eUnknownHandle" => "未知句柄", + "eWrongDatabase" => "错误的数据库", + "eWrongObjectType" => "错误的类型", + "eInvalidResBuf" => "不合理的ResBuf", + "eBadDxfSequence" => "不正确的DXF顺序", + "eFilerError" => "文件错误", + "eVertexAfterFace" => "顶点在面后面", + "eInvalidFaceVertexIndex" => "不合理的面顶点顺序", + "eInvalidMeshVertexIndex" => "不合理的mesh顺序", + "eOtherObjectsBusy" => "其它对象忙", + "eMustFirstAddBlockToDb" => "必须先把块加入到数据库", + "eCannotNestBlockDefs" => "不可以嵌套块定义", + "eDwgRecoveredOK" => "修复DWG完成", + "eDwgNotRecoverable" => "无法修复DWG", + "eDxfPartiallyRead" => "DXF部分读取", + "eDxfReadAborted" => "读取DXF终止", + "eDxbPartiallyRead" => "DXB部分读取", + "eDwgCRCDoesNotMatch" => "DWG文件的CRC不匹配", + "eDwgSentinelDoesNotMatch" => "DWG文件的校验不匹配", + "eDwgObjectImproperlyRead" => "DWG文件错误读取", + "eNoInputFiler" => "没有找到输入过滤", + "eDwgNeedsAFullSave" => "DWG需要完全保存", + "eDxbReadAborted" => "DXB读取终止", + "eFileLockedByACAD" => "文件被ACAD锁定", + "eFileAccessErr" => "无法读取文件", + "eFileSystemErr" => "文件系统错误", + "eFileInternalErr" => "文件内部错误", + "eFileTooManyOpen" => "文件被打开太多次", + "eFileNotFound" => "未找到文件", + "eDwkLockFileFound" => "找到DWG锁定文件", + "eWasErased" => "对象被删除", + "ePermanentlyErased" => "对象被永久删除", + "eWasOpenForRead" => "对象只读打开", + "eWasOpenForWrite" => "对象可写打开", + "eWasOpenForUndo" => "对象撤销打开", + "eWasNotifying" => "对象被通知", + "eWasOpenForNotify" => "对象通知打开", + "eOnLockedLayer" => "对象在锁定图层上", + "eMustOpenThruOwner" => "必须经过所有者打开", + "eSubentitiesStillOpen" => "子对象依然打开着", + "eAtMaxReaders" => "超过最大打开次数", + "eIsWriteProtected" => "对象被写保护", + "eIsXRefObject" => "对象是XRef", + "eNotAnEntity" => "对象不是实体", + "eHadMultipleReaders" => "被多重打开", + "eDuplicateRecordName" => "重复的记录名称", + "eXRefDependent" => "依赖于XREF", + "eSelfReference" => "引用自身", + "eMissingSymbolTable" => "丢失符号化表", + "eMissingSymbolTableRec" => "丢失符号化记录", + "eWasNotOpenForWrite" => "不是可写打开", + "eCloseWasNotifying" => "对象关闭,正在执行通知", + "eCloseModifyAborted" => "对象关闭,修改被取消", + "eClosePartialFailure" => "对象关闭,部分操作未成功", + "eCloseFailObjectDamaged" => "对象被损坏,关闭失败", + "eCannotBeErasedByCaller" => "对象不可以被当前呼叫者删除", + "eCannotBeResurrected" => "不可以复活", + "eWasNotErased" => "对象未删除", + "eInsertAfter" => "在后面插入", + "eFixedAllErrors" => "修复了所有错误", + "eLeftErrorsUnfixed" => "剩下一些错误未修复", + "eUnrecoverableErrors" => "不可恢复的错误", + "eNoDatabase" => "没有数据库", + "eXdataSizeExceeded" => "扩展数据长度太大", + "eRegappIdNotFound" => "没有找到扩展数据注册ID", + "eRepeatEntity" => "重复实体", + "eRecordNotInTable" => "表中未找到记录", + "eIteratorDone" => "迭代器完成", + "eNullIterator" => "空的迭代器", + "eNotInBlock" => "不在块中", + "eOwnerNotInDatabase" => "所有者不在数据库中", + "eOwnerNotOpenForRead" => "所有者不是只读打开", + "eOwnerNotOpenForWrite" => "所有者不是可写打开", + "eExplodeBeforeTransform" => "在变换之前就被炸开了", + "eCannotScaleNonUniformly" => "不可以不同比例缩放", + "eNotInDatabase" => "不在数据库中", + "eNotCurrentDatabase" => "不是当前数据库", + "eIsAnEntity" => "是一个实体", + "eCannotChangeActiveViewport" => "不可以改变活动视口", + "eNotInPaperspace" => "不在图纸空间中", + "eCommandWasInProgress" => "正在执行命令", + "eGeneralModelingFailure" => "创建模型失败", + "eOutOfRange" => "超出范围", + "eNonCoplanarGeometry" => "没有平面几何对象", + "eDegenerateGeometry" => "退化的几何对象", + "eInvalidAxis" => "无效的轴线", + "ePointNotOnEntity" => "点不在实体上", + "eSingularPoint" => "单一的点", + "eInvalidOffset" => "无效的偏移", + "eNonPlanarEntity" => "没有平面的实体", + "eCannotExplodeEntity" => "不可分解的实体", + "eStringTooLong" => "字符串太短", + "eInvalidSymTableFlag" => "无效的符号化表标志", + "eUndefinedLineType" => "没有定义的线型", + "eInvalidTextStyle" => "无效的字体样式", + "eTooFewLineTypeElements" => "太少的线型要素", + "eTooManyLineTypeElements" => "太多的线型要素", + "eExcessiveItemCount" => "过多的项目", + "eIgnoredLinetypeRedef" => "忽略线型定义描述", + "eBadUCS" => "不好的用户坐标系", + "eBadPaperspaceView" => "不好的图纸空间视图", + "eSomeInputDataLeftUnread" => "一些输入数据未被读取", + "eNoInternalSpace" => "不是内部空间", + "eInvalidDimStyle" => "无效的标注样式", + "eInvalidLayer" => "无效的图层", + "eUserBreak" => "用户打断", + "eDwgNeedsRecovery" => "DWG文件需要修复", + "eDeleteEntity" => "删除实体", + "eInvalidFix" => "无效的方位", + "eFSMError" => "FSM错误", + "eBadLayerName" => "不好的图层名称", + "eLayerGroupCodeMissing" => "图层分组编码丢失", + "eBadColorIndex" => "不好的颜色索引号", + "eBadLinetypeName" => "不好的线型名称", + "eBadLinetypeScale" => "不好的线型缩放比例", + "eBadVisibilityValue" => "不好的可见性值", + "eProperClassSeparatorExpected" => "本身类未找到预期的分割符号(?)", + "eBadLineWeightValue" => "不好的线宽值", + "eBadColor" => "不好的颜色", + "ePagerError" => "页面错误", + "eOutOfPagerMemory" => "页面内存不足", + "ePagerWriteError" => "页面不可写", + "eWasNotForwarding" => "不是促进(?)", + "eInvalidIdMap" => "无效的ID字典", + "eInvalidOwnerObject" => "无效的所有者", + "eOwnerNotSet" => "未设置所有者", + "eWrongSubentityType" => "错误的子对象类型", + "eTooManyVertices" => "太多节点", + "eTooFewVertices" => "太少节点", + "eNoActiveTransactions" => "不活动的事务", + "eNotTopTransaction" => "不是最顶层的事务", + "eTransactionOpenWhileCommandEnded" => "在命令结束的时候打开(/开始)事务", + "eInProcessOfCommitting" => "在提交事务的过程中", + "eNotNewlyCreated" => "不是新创建的", + "eLongTransReferenceError" => "长事务引用错误", + "eNoWorkSet" => "没有工作集", + "eAlreadyInGroup" => "已经在组中了", + "eNotInGroup" => "不在组中", + "eInvalidREFIID" => "无效的REFIID", + "eInvalidNormal" => "无效的标准", + "eInvalidStyle" => "无效的样式", + "eCannotRestoreFromAcisFile" => "不可以从Acis(?)文件中恢复", + "eMakeMeProxy" => "自我代理", + "eNLSFileNotAvailable" => "无效的NLS文件", + "eNotAllowedForThisProxy" => "不允许这个代理", + "eNotSupportedInDwgApi" => "在Dwg Api中不支持", + "ePolyWidthLost" => "多段线宽度丢失", + "eNullExtents" => "空的空间范围", + "eExplodeAgain" => "再一次分解", + "eBadDwgHeader" => "坏的DWG文件头", + "eLockViolation" => "锁定妨碍当前操作", + "eLockConflict" => "锁定冲突", + "eDatabaseObjectsOpen" => "数据库对象打开", + "eLockChangeInProgress" => "锁定改变中", + "eVetoed" => "禁止", + "eNoDocument" => "没有文档", + "eNotFromThisDocument" => "不是从这个文档", + "eLISPActive" => "LISP活动", + "eTargetDocNotQuiescent" => "目标文档活动中", + "eDocumentSwitchDisabled" => "禁止文档转换", + "eInvalidContext" => "无效的上下文环境", + "eCreateFailed" => "创建失败", + "eCreateInvalidName" => "创建无效名称", + "eSetFailed" => "设置失败", + "eDelDoesNotExist" => "删除对象不存在", + "eDelIsModelSpace" => "删除模型空间", + "eDelLastLayout" => "删除最后一个布局", + "eDelUnableToSetCurrent" => "删除后无法设置当前对象", + "eDelUnableToFind" => "没有找到删除对象", + "eRenameDoesNotExist" => "重命名对象不存在", + "eRenameIsModelSpace" => "不可以重命令模型空间", + "eRenameInvalidLayoutName" => "重命名无效的布局名称", + "eRenameLayoutAlreadyExists" => "重命名布局名称已存在", + "eRenameInvalidName" => "重命名无效名称", + "eCopyDoesNotExist" => "拷贝不存在", + "eCopyIsModelSpace" => "拷贝是模型空间", + "eCopyFailed" => "拷贝失败", + "eCopyInvalidName" => "拷贝无效名称", + "eCopyNameExists" => "拷贝名称存在", + "eProfileDoesNotExist" => "配置名称不存在", + "eInvalidFileExtension" => "无效的文件后缀名成", + "eInvalidProfileName" => "无效的配置文件名称", + "eFileExists" => "文件存在", + "eProfileIsInUse" => "配置文件存在", + "eCantOpenFile" => "打开文件失败", + "eNoFileName" => "没有文件名称", + "eRegistryAccessError" => "读取注册表错误", + "eRegistryCreateError" => "创建注册表项错误", + "eBadDxfFile" => "坏的DXF文件", + "eUnknownDxfFileFormat" => "未知的DXF文件格式", + "eMissingDxfSection" => "丢失DXF分段", + "eInvalidDxfSectionName" => "无效的DXF分段名称", + "eNotDxfHeaderGroupCode" => "无效的DXF组码", + "eUndefinedDxfGroupCode" => "没有定义DXF组码", + "eNotInitializedYet" => "没有初始化", + "eInvalidDxf2dPoint" => "无效的DXF二维点", + "eInvalidDxf3dPoint" => "无效的DXD三维点", + "eBadlyNestedAppData" => "坏的嵌套应用程序数据", + "eIncompleteBlockDefinition" => "不完整的块定义", + "eIncompleteComplexObject" => "不完整的合成(?复杂)对象", + "eBlockDefInEntitySection" => "块定义在实体段中", + "eNoBlockBegin" => "没有块开始", + "eDuplicateLayerName" => "重复的图层名称", + "eBadPlotStyleName" => "不好的打印样式名称", + "eDuplicateBlockName" => "重复的块名称", + "eBadPlotStyleType" => "不好的打印样式类型", + "eBadPlotStyleNameHandle" => "不好的打印样式名称句柄", + "eUndefineShapeName" => "没有定义形状名称", + "eDuplicateBlockDefinition" => "重复的块定义", + "eMissingBlockName" => "丢失了块名称", + "eBinaryDataSizeExceeded" => "二进制数据长度太长", + "eObjectIsReferenced" => "对象被引用", + "eNoThumbnailBitmap" => "没有缩略图", + "eGuidNoAddress" => "未找到GUID地址", + "eMustBe0to2" => "必须是0到2", + "eMustBe0to3" => "必须是0到3", + "eMustBe0to4" => "必须是0到4", + "eMustBe0to5" => "必须是0到5", + "eMustBe0to8" => "必须是0到8", + "eMustBe1to8" => "必须是1到8", + "eMustBe1to15" => "必须是1到15", + "eMustBePositive" => "必须为正数", + "eMustBeNonNegative" => "必须为非负数", + "eMustBeNonZero" => "不可以等于0", + "eMustBe1to6" => "必须是1到6", + "eNoPlotStyleTranslationTable" => "没有打印样式事务表(?)", + "ePlotStyleInColorDependentMode" => "打印样式依赖颜色", + "eMaxLayouts" => "最大布局数量", + "eNoClassId" => "没有类ID", + "eUndoOperationNotAvailable" => "撤销操作无效", + "eUndoNoGroupBegin" => "撤销操作没有组开始", + "eHatchTooDense" => "填充太密集", + "eOpenFileCancelled" => "打开文件取消", + "eNotHandled" => "没有处理", + "eMakeMeProxyAndResurrect" => "将自己变成代理然后复活", + "eFileMissingSections" => "文件丢失分段", + "eRepeatedDwgRead" => "重复的读取DWG文件", + "eWrongCellType" => "错误的单元格类型", + "eCannotChangeColumnType" => "不可以改变列类型", + "eRowsMustMatchColumns" => "行必须匹配列", + "eFileSharingViolation" => "文件共享妨碍", + "eUnsupportedFileFormat" => "不支持的文件格式", + "eObsoleteFileFormat" => "废弃的文件格式", + "eDwgShareDemandLoad" => "DWG共享要求加载(?)", + "eDwgShareReadAccess" => "DWG共享读取", + "eDwgShareWriteAccess" => "DWG共享写入", + "eLoadFailed" => "加载失败", + "eDeviceNotFound" => "驱动未找到", + "eNoCurrentConfig" => "没有当前配置", + "eNullPtr" => "空指针", + "eNoLayout" => "没有布局", + "eIncompatiblePlotSettings" => "不兼容的打印设置", + "eNonePlotDevice" => "没有打印驱动", + "eNoMatchingMedia" => "没有匹配的打印尺寸", + "eInvalidView" => "无效的视图", + "eInvalidWindowArea" => "无效的窗口范围", + "eInvalidPlotArea" => "无效的打印范围", + "eCustomSizeNotPossible" => "用户输入的打印尺寸不可能存在", + "ePageCancelled" => "纸张取消", + "ePlotCancelled" => "打印取消", + "eInvalidEngineState" => "无效的引擎状态", + "ePlotAlreadyStarted" => "已经开始在打印了", + "eNoErrorHandler" => "没有错误处理", + "eInvalidPlotInfo" => "无效的打印信息", + "eNumberOfCopiesNotSupported" => "不支持打印份数", + "eLayoutNotCurrent" => "不是当前布局", + "eGraphicsNotGenerated" => "绘图对象创建失败(?)", + "eCannotPlotToFile" => "不可以打印到文件", + "eMustPlotToFile" => "必须打印到文件", + "eNotMultiPageCapable" => "不支持多种纸张", + "eBackgroundPlotInProgress" => "正在后台打印", + "eSubSelectionSetEmpty" => "子选择集被设置为空", + "eInvalidObjectId" => "无效的对象ID或者对象ID不在当前数据库", + "eInvalidXrefObjectId" => "无效的XREF对象ID或者XREF对象ID不在当前数据库", + "eNoViewAssociation" => "未找到对应的视图对象", + "eNoLabelBlock" => "视口未找到关联的块", + "eUnableToSetViewAssociation" => "设置视图关联视口失败", + "eUnableToGetViewAssociation" => "无法找到关联的视图", + "eUnableToSetLabelBlock" => "无法设置关联的块", + "eUnableToGetLabelBlock" => "无法获取关联的块", + "eUnableToRemoveAssociation" => "无法移除视口关联对象", + "eUnableToSyncModelView" => "无法同步视口和模型空间视图", + "eSecInitializationFailure" => "SEC(?)初始化错误", + "eSecErrorReadingFile" => "SEC(?)读取文件错误", + "eSecErrorWritingFile" => "SEC(?)写入文件错误", + "eSecInvalidDigitalID" => "SEC(?)无效的数字ID", + "eSecErrorGeneratingTimestamp" => "SEC(?)创建时间戳错误", + "eSecErrorComputingSignature" => "SEC(?)电子签名错误", + "eSecErrorWritingSignature" => "SEC(?)写入签名错误", + "eSecErrorEncryptingData" => "SEC(?)加密数据错误", + "eSecErrorCipherNotSupported" => "SEC(?)不支持的密码", + "eSecErrorDecryptingData" => "SEC(?)解密数据错误", + "eInetBase" => "网络错误", + "eInetOk" => "网络正常", + "eInetInCache" => "在缓冲区中", + "eInetFileNotFound" => "网络文件不存在", + "eInetBadPath" => "不好的网络路径", + "eInetTooManyOpenFiles" => "打开太多网络文件", + "eInetFileAccessDenied" => "打开网络文件被拒绝", + "eInetInvalidFileHandle" => "无效的网络文件句柄", + "eInetDirectoryFull" => "网络文件夹目录已满", + "eInetHardwareError" => "网络硬件错误", + "eInetSharingViolation" => "违反网络共享", + "eInetDiskFull" => "网络硬盘满了", + "eInetFileGenericError" => "网络文件创建错误", + "eInetValidURL" => "无效的URL地址", + "eInetNotAnURL" => "不是URL地址", + "eInetNoWinInet" => "没有WinInet(?)", + "eInetOldWinInet" => "旧的WinInet(?)", + "eInetNoAcadInet" => "无法连接ACAD网站", + "eInetNotImplemented" => "无法应用网络", + "eInetProtocolNotSupported" => "网络协议不支持", + "eInetCreateInternetSessionFailed" => "创建网络会话失败", + "eInetInternetSessionConnectFailed" => "连接网络会话失败", + "eInetInternetSessionOpenFailed" => "打开网络会话失败", + "eInetInvalidAccessType" => "无效的网络接收类型", + "eInetFileOpenFailed" => "打开网络文件失败", + "eInetHttpOpenRequestFailed" => "打开HTTP协议失败", + "eInetUserCancelledTransfer" => "用户取消了网络传输", + "eInetHttpBadRequest" => "不合理的网络请求", + "eInetHttpAccessDenied" => "HTTP协议拒绝", + "eInetHttpPaymentRequired" => "HTTP协议要求付费", + "eInetHttpRequestForbidden" => "禁止HTTP请求", + "eInetHttpObjectNotFound" => "HTTP对象未找到", + "eInetHttpBadMethod" => "不合理的HTTP请求方法", + "eInetHttpNoAcceptableResponse" => "不接受的HTTP回复", + "eInetHttpProxyAuthorizationRequired" => "要求HTTP代理授权", + "eInetHttpTimedOut" => "HTTP超时", + "eInetHttpConflict" => "HTTP冲突", + "eInetHttpResourceGone" => "网络资源被用光", + "eInetHttpLengthRequired" => "HTTP请求长度是必须的", + "eInetHttpPreconditionFailure" => "HTTP预处理失败", + "eInetHttpRequestTooLarge" => "HTTP请求太大", + "eInetHttpUriTooLong" => "URL地址太长", + "eInetHttpUnsupportedMedia" => "HTTP不支持的媒体", + "eInetHttpServerError" => "HTTP服务器错误", + "eInetHttpNotSupported" => "HTTP不支持", + "eInetHttpBadGateway" => "HTTP网关错误", + "eInetHttpServiceUnavailable" => "HTTP服务当前不可用", + "eInetHttpGatewayTimeout" => "HTTP网关超时", + "eInetHttpVersionNotSupported" => "HTTP版本不支持", + "eInetInternetError" => "HTTP网络错误", + "eInetGenericException" => "HTTP常规异常", + "eInetUnknownError" => "HTTP未知错误", + "eAlreadyActive" => "已经是活动的了", + "eAlreadyInactive" => "已经是不活动的了", + _ => acex.Message, + }; + Acap.ShowAlertDialog($"{acex.Message}:{infoStr}"); + } +} \ No newline at end of file -- Gitee From 209552cabaf5a951706073d0a7c69f04e916cf84 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sun, 20 Oct 2024 21:24:50 +0800 Subject: [PATCH 327/453] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E7=AC=A6=E5=8F=B7?= =?UTF-8?q?=E8=A1=A8=E6=89=A9=E5=B1=95=E7=9A=84=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/ExtensionMethod/SymbolTableEx.cs | 212 +++++++++------------ 1 file changed, 95 insertions(+), 117 deletions(-) diff --git a/CADShared/ExtensionMethod/SymbolTableEx.cs b/CADShared/ExtensionMethod/SymbolTableEx.cs index 0a70da6..d059161 100644 --- a/CADShared/ExtensionMethod/SymbolTableEx.cs +++ b/CADShared/ExtensionMethod/SymbolTableEx.cs @@ -6,6 +6,7 @@ public static class SymbolTableEx { #region 图层表 + /// /// 添加图层 /// @@ -17,6 +18,7 @@ public static ObjectId Add(this SymbolTable table, { return table.Add(name, lt => lt.Color = color); } + /// /// 添加图层 /// @@ -24,28 +26,30 @@ public static ObjectId Add(this SymbolTable table, /// 图层名 /// 图层颜色索引值 /// 图层id - public static ObjectId Add(this SymbolTable table, string name, int colorIndex) + public static ObjectId Add(this SymbolTable table, string name, + int colorIndex) { - colorIndex %= 257;// 防止输入的颜色超出256 - colorIndex = Math.Abs(colorIndex);// 防止负数 + colorIndex %= 257; // 防止输入的颜色超出256 + colorIndex = Math.Abs(colorIndex); // 防止负数 return table.Add(name, lt => lt.Color = Color.FromColorIndex(ColorMethod.ByColor, (short)colorIndex)); } + /// /// 更改图层名 /// /// 图层符号表 /// 旧图层名 /// 新图层名 - public static ObjectId Rename(this SymbolTable table, string oldName, string newName) + public static ObjectId Rename(this SymbolTable table, string oldName, + string newName) { if (!table.Has(oldName)) return ObjectId.Null; - table.Change(oldName, layer => { - layer.Name = newName; - }); + table.Change(oldName, layer => { layer.Name = newName; }); return table[newName]; } + /// /// 删除图层 /// @@ -54,7 +58,8 @@ public static ObjectId Rename(this SymbolTable tab /// 成功返回 ,失败返回 public static bool Delete(this SymbolTable table, string name) { - if (name == "0" || name == "Defpoints" || !table.Has(name) || table[name] == table.Database.Clayer) + if (SymbolUtilityServices.IsLayerZeroName(name) || SymbolUtilityServices.IsLayerDefpointsName(name) || + !table.Has(name) || table[name] == table.Database.Clayer) return false; table.CurrentSymbolTable.GenerateUsageData(); @@ -68,9 +73,11 @@ public static bool Delete(this SymbolTable table, ltr.Erase(); return true; } + #endregion #region 块表 + /// /// 添加块定义 /// @@ -78,45 +85,44 @@ public static bool Delete(this SymbolTable table, /// 块名 /// 对所添加块表的委托n /// 添加图元的委托 - /// 添加属性定义的委托 + /// 添加属性定义的委托 /// 块定义id /// TODO: 需要测试匿名块等特殊的块是否能定义 - public static ObjectId Add(this SymbolTable table, - string name, - Action? action = null, - Func>? ents = null, - Func>? attdef = null) + public static ObjectId Add(this SymbolTable table, string name, + Action? action = null, Func>? ents = null, + Func>? attDef = null) { - return table.Add(name, btr => { + return table.Add(name, btr => + { action?.Invoke(btr); - var entsres = ents?.Invoke(); - if (entsres is not null) - btr.AddEntity(entsres); + var entsRes = ents?.Invoke(); + if (entsRes is not null) + btr.AddEntity(entsRes); - var adddefres = attdef?.Invoke(); - if (adddefres is not null) - btr.AddEntity(adddefres); + var addDefRes = attDef?.Invoke(); + if (addDefRes is not null) + btr.AddEntity(addDefRes); }); } + /// /// 添加块定义 /// /// 块表 /// 块名 /// 图元 - /// 属性定义 + /// 属性定义 /// - public static ObjectId Add(this SymbolTable table, - string name, - IEnumerable? ents = null, - IEnumerable? attdef = null) + public static ObjectId Add(this SymbolTable table, string name, + IEnumerable? ents = null, IEnumerable? attDef = null) { - return table.Add(name, btr => { + return table.Add(name, btr => + { if (ents is not null) btr.AddEntity(ents); - if (attdef is not null) - btr.AddEntity(attdef); + if (attDef is not null) + btr.AddEntity(attDef); }); } @@ -127,7 +133,8 @@ public static ObjectId Add(this SymbolTable table, /// 块名 /// 图元(包括属性) /// - public static ObjectId Add(this SymbolTable table, string name, params Entity[] ents) + public static ObjectId Add(this SymbolTable table, string name, + params Entity[] ents) { return table.Add(name, null, () => ents); } @@ -138,35 +145,32 @@ public static ObjectId Add(this SymbolTable table, /// 块表 /// 块定义id /// 属性列表 - public static void AddAttsToBlocks(this SymbolTable table, - ObjectId id, - List atts) + public static void AddAttsToBlocks(this SymbolTable table, ObjectId id, + List atts) { List attTags = []; table.Change(id, btr => { - btr.GetEntities() - .ForEach(def => attTags.Add(def.Tag.ToUpper())); + btr.GetEntities().ForEach(def => attTags.Add(def.Tag.ToUpper())); foreach (var t in atts.Where(t => !attTags.Contains(t.Tag.ToUpper()))) btr.AddEntity(t); }); } + /// /// 添加属性到块定义 /// /// 块表 /// 块定义名字 /// 属性列表 - public static void AddAttsToBlocks(this SymbolTable table, - string name, - List atts) + public static void AddAttsToBlocks(this SymbolTable table, string name, + List atts) { List attTags = []; table.Change(name, btr => { - btr.GetEntities() - .ForEach(def => attTags.Add(def.Tag.ToUpper())); + btr.GetEntities().ForEach(def => attTags.Add(def.Tag.ToUpper())); foreach (var t in atts.Where(t => !attTags.Contains(t.Tag.ToUpper()))) btr.AddEntity(t); @@ -180,14 +184,14 @@ public static void AddAttsToBlocks(this SymbolTable文件名 /// 是否覆盖 /// 块定义Id - public static ObjectId GetBlockFrom(this SymbolTable table, string fileName, bool over) + public static ObjectId GetBlockFrom(this SymbolTable table, string fileName, + bool over) { - - var blkdefname = SymbolUtilityServices.GetSymbolNameFromPathName(fileName, "dwg"); + var blkDefName = SymbolUtilityServices.GetSymbolNameFromPathName(fileName, "dwg"); #if acad - blkdefname = SymbolUtilityServices.RepairSymbolName(blkdefname, false); + blkDefName = SymbolUtilityServices.RepairSymbolName(blkDefName, false); #endif - var id = table[blkdefname]; + var id = table[blkDefName]; var has = id != ObjectId.Null; /* 每次看这里都要反应一阵 @@ -199,24 +203,24 @@ public static ObjectId GetBlockFrom(this SymbolTable /// 从文件中获取块定义 /// @@ -225,17 +229,17 @@ public static ObjectId GetBlockFrom(this SymbolTable块定义名 /// 是否覆盖 /// 块定义Id - public static ObjectId GetBlockFrom(this SymbolTable table, - string fileName, - string blockName, - bool over) + public static ObjectId GetBlockFrom(this SymbolTable table, string fileName, + string blockName, bool over) { return table.GetRecordFrom(t => t.BlockTable, fileName, blockName, over); } + #endregion #region 线型表 + /// /// 添加线型 /// @@ -245,64 +249,60 @@ public static ObjectId GetBlockFrom(this SymbolTable线型长度 /// 笔画长度数组 /// 线型id - public static ObjectId Add(this SymbolTable table, string name, string description, double length, double[] dash) + public static ObjectId Add(this SymbolTable table, string name, + string description, double length, double[] dash) { - return table.Add( - name, - ltt => { - ltt.AsciiDescription = description; - ltt.PatternLength = length; // 线型的总长度 - ltt.NumDashes = dash.Length; // 组成线型的笔画数目 - for (int i = 0; i < dash.Length; i++) - { - ltt.SetDashLengthAt(i, dash[i]); - } - // ltt.SetDashLengthAt(0, 0.5); // 0.5个单位的划线 - // ltt.SetDashLengthAt(1, -0.25); // 0.25个单位的空格 - // ltt.SetDashLengthAt(2, 0); // 一个点 - // ltt.SetDashLengthAt(3, -0.25); // 0.25个单位的空格 + return table.Add(name, ltt => + { + ltt.AsciiDescription = description; + ltt.PatternLength = length; // 线型的总长度 + ltt.NumDashes = dash.Length; // 组成线型的笔画数目 + for (int i = 0; i < dash.Length; i++) + { + ltt.SetDashLengthAt(i, dash[i]); } - ); + // ltt.SetDashLengthAt(0, 0.5); // 0.5个单位的划线 + // ltt.SetDashLengthAt(1, -0.25); // 0.25个单位的空格 + // ltt.SetDashLengthAt(2, 0); // 一个点 + // ltt.SetDashLengthAt(3, -0.25); // 0.25个单位的空格 + }); } + #endregion #region 文字样式表 + /// /// 添加文字样式记录 /// /// 文字样式表 /// 文字样式名 /// 字体名 - /// 宽度比例 + /// 宽度比例 /// 文字样式Id public static ObjectId Add(this SymbolTable table, - string textStyleName, - string font, - double xscale = 1.0) + string textStyleName, string font, double xScale = 1.0) { - return - table.Add( - textStyleName, - tstr => { - tstr.Name = textStyleName; - tstr.FileName = font; - tstr.XScale = xscale; - }); + return table.Add(textStyleName, tstr => + { + tstr.Name = textStyleName; + tstr.FileName = font; + tstr.XScale = xScale; + }); } + /// /// 添加文字样式记录 /// /// 文字样式表 /// 文字样式名 - /// 字体名枚举 - /// 宽度比例 + /// 字体名枚举 + /// 宽度比例 /// 文字样式Id public static ObjectId Add(this SymbolTable table, - string textStyleName, - FontTTF fontTTF, - double xscale = 1.0) + string textStyleName, FontTTF fontTtf, double xScale = 1.0) { - return table.Add(textStyleName, fontTTF.GetDescription(), xscale); + return table.Add(textStyleName, fontTtf.GetDescription(), xScale); } /// @@ -318,16 +318,13 @@ public static ObjectId Add(this SymbolTable是否强制替换 /// 文字样式Id public static ObjectId AddWithChange(this SymbolTable table, - string textStyleName, - string smallFont, - string bigFont = "", - double xScale = 1, - double height = 0, - bool forceChange = true) + string textStyleName, string smallFont, string bigFont = "", double xScale = 1, double height = 0, + bool forceChange = true) { if (forceChange && table.Has(textStyleName)) { - table.Change(textStyleName, ttr => { + table.Change(textStyleName, ttr => + { ttr.FileName = smallFont; ttr.XScale = xScale; ttr.TextSize = height; @@ -336,33 +333,14 @@ public static ObjectId AddWithChange(this SymbolTable { + + return table.Add(textStyleName, ttr => + { ttr.FileName = smallFont; ttr.XScale = xScale; ttr.TextSize = height; }); } - - #endregion - - #region 注册应用程序表 - - #endregion - - #region 标注样式表 - - #endregion - - #region 用户坐标系表 - - #endregion - - #region 视图表 - - #endregion - - #region 视口表 - #endregion -} +} \ No newline at end of file -- Gitee From b5c908f53609df5db085e1452374133ee0bc5d70 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sun, 20 Oct 2024 21:30:38 +0800 Subject: [PATCH 328/453] =?UTF-8?q?=E8=A1=A5=E5=85=85XrefEx=E6=89=A9?= =?UTF-8?q?=E5=B1=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/CADShared.projitems | 1 + CADShared/ExtensionMethod/XrefEx.cs | 679 ++++++++++++++++++++++++++++ 2 files changed, 680 insertions(+) create mode 100644 CADShared/ExtensionMethod/XrefEx.cs diff --git a/CADShared/CADShared.projitems b/CADShared/CADShared.projitems index 8470753..1ba9e37 100644 --- a/CADShared/CADShared.projitems +++ b/CADShared/CADShared.projitems @@ -63,6 +63,7 @@ + diff --git a/CADShared/ExtensionMethod/XrefEx.cs b/CADShared/ExtensionMethod/XrefEx.cs new file mode 100644 index 0000000..659ee6b --- /dev/null +++ b/CADShared/ExtensionMethod/XrefEx.cs @@ -0,0 +1,679 @@ +// ReSharper disable ForCanBeConvertedToForeach +namespace IFoxCAD.Cad; + +#region 参照工厂 + +/// +/// 参照绑定模式接口 +/// +public interface IXrefBindModes +{ + /// + /// 卸载 + /// + public void Unload(); + + /// + /// 重载 + /// + public void Reload(); + + /// + /// 拆离 + /// + public void Detach(); + + /// + /// 绑定 + /// + public void Bind(); +} + +/// +/// 参照工厂类 +/// +/// +/// 要处理的参照名称,就处理所有 +public class XrefFactory(DBTrans tr, HashSet? xrefNames = null) : IXrefBindModes +{ + #region 私有字段 + + private readonly DBTrans _tr = tr; + + /// + /// 要处理的参照名称,就处理所有 + /// + private readonly HashSet? _xrefNames = xrefNames; + + #endregion + + #region 公开字段 + + /// + /// 解析外部参照:线性引擎
    + /// 默认
    + /// 时会在cad命令历史打印一些AEC信息,并导致绑定慢一点...具体作用不详
    + ///
    + public readonly bool UseThreadEngine = false; + + /// + /// 解析外部参照:仅处理 Unresolved_未融入(未解析)的参照
    + /// 默认 + ///
    + public readonly bool DoNewOnly = true; + + /// + /// 解析外部参照:包含僵尸参照 + /// + public readonly bool IncludeGhosts = true; + + + /// + /// 绑定模式和双美元符号相关(与cad保持相同地默认)
    + /// 为绑定模式,产生双美元; + /// 为插入模式,块重名会以本图覆盖; + ///
    + public readonly bool BindOrInsert = false; + + /// + /// bind时候是否拆离参照
    + /// 默认:学官方的绑定后自动拆离 + ///
    + public readonly bool AutoDetach = true; + + /// + /// bind时候是否删除被卸载的嵌套参照
    + /// 默认 + ///
    + public readonly bool EraseNested = true; + + /// + /// bind时候控制绑定的符号表:请保持默认
    + /// 目前仅推荐用于
    + /// 其他项有异常:
    + ///
    + public readonly SymModes SymModesBind = SymModes.LayerTable; + + #endregion + + + #region 重写 + + /// + /// 绑定 + /// + public void Bind() + { + // 此功能有绑定出错的问题 + // db.BindXrefs(xrefIds, true); + + // 绑定后会自动拆离 + // 此功能修补了上面缺失 + DoubleBind(); + } + + /// + /// 分离 + /// + public void Detach() + { + using ObjectIdCollection xrefIds = new(); + GetAllXrefNode(xrefIds); + foreach (ObjectId id in xrefIds) + _tr.Database.DetachXref(id); + } + + /// + /// 重载 + /// + public void Reload() + { + using ObjectIdCollection xrefIds = new(); + GetAllXrefNode(xrefIds); + if (xrefIds.Count > 0) + _tr.Database.ReloadXrefs(xrefIds); + } + + /// + /// 卸载 + /// + public void Unload() + { + using ObjectIdCollection xrefIds = new(); + GetAllXrefNode(xrefIds); + if (xrefIds.Count > 0) + _tr.Database.UnloadXrefs(xrefIds); + } + + #endregion + + #region 双重绑定 + + /// + /// 获取参照 + /// + /// 返回全部参照id + private void GetAllXrefNode(ObjectIdCollection xrefIds) + { + // 储存要处理的参照id + //var xrefIds = new ObjectIdCollection(); + XrefNodeForEach((xNodeName, xNodeId, _, _) => + { + if (XrefNamesContains(xNodeName)) + xrefIds.Add(xNodeId); + }); + } + + private bool XrefNamesContains(string xNodeName) + { + // 为空的时候全部加入 || 有内容时候含有目标 + return _xrefNames is null || _xrefNames.Contains(xNodeName); + } + + /// + /// 遍历参照 + /// + /// (参照名,参照块表记录id,参照状态,是否嵌入) + private void XrefNodeForEach(Action action) + { + // btRec.IsFromOverlayReference 是覆盖 + // btRec.GetXrefDatabase(true) 外部参照数据库 + + + // 解析外部参照:此功能不能锁定文档 + _tr.Database.ResolveXrefs(UseThreadEngine, DoNewOnly); + + var xg = _tr.Database.GetHostDwgXrefGraph(IncludeGhosts); + for (int i = 0; i < xg.NumNodes; i++) + { + var xNode = xg.GetXrefNode(i); + if (!xNode.BlockTableRecordId.IsOk()) + continue; + + action.Invoke(xNode.Name, xNode.BlockTableRecordId, xNode.XrefStatus, xNode.IsNested); + } + } + + /// + /// 符号表记录加入容器 + /// + private static void AddedXBindIds(ObjectIdCollection xbindXrefsIds, + SymbolTable symbolTable) where TTable : SymbolTable + where TRecord : SymbolTableRecord, new() + { + symbolTable.ForEach(tabRec => + { + if (tabRec.IsResolved) + xbindXrefsIds.Add(tabRec.ObjectId); + }, checkIdOk: true); + } + + + private void GetXBindIds(ObjectIdCollection xbindIds) + { + // xbind + // 0x01 它是用来绑其他符号表,绑块表会有异常 + // 0x02 集合若有问题,就会出现eWrongObjectType + //var xbindIds = new ObjectIdCollection(); + + // 起初测试是将九大符号表记录均加入的,但经实测不行...(为什么?存疑) + + #region Option1 + + if ((SymModesBind & SymModes.LayerTable) == SymModes.LayerTable) + AddedXBindIds(xbindIds, _tr.LayerTable); + + if ((SymModesBind & SymModes.TextStyleTable) == SymModes.TextStyleTable) + AddedXBindIds(xbindIds, _tr.TextStyleTable); + + if ((SymModesBind & SymModes.RegAppTable) == SymModes.RegAppTable) + AddedXBindIds(xbindIds, _tr.RegAppTable); + + if ((SymModesBind & SymModes.DimStyleTable) == SymModes.DimStyleTable) + AddedXBindIds(xbindIds, _tr.DimStyleTable); + + if ((SymModesBind & SymModes.LinetypeTable) == SymModes.LinetypeTable) + AddedXBindIds(xbindIds, _tr.LinetypeTable); + + #endregion + + #region Option2 + + if ((SymModesBind & SymModes.UcsTable) == SymModes.UcsTable) + AddedXBindIds(xbindIds, _tr.UcsTable); + + if ((SymModesBind & SymModes.ViewTable) == SymModes.ViewTable) + AddedXBindIds(xbindIds, _tr.ViewTable); + + if ((SymModesBind & SymModes.ViewportTable) == SymModes.ViewportTable) + AddedXBindIds(xbindIds, _tr.ViewportTable); + + #endregion + } + + private void GetBindIds(ObjectIdCollection bindIds) + { + // bind 只绑块表 + //var bindIds = new ObjectIdCollection(); + + _tr.BlockTable.ForEach(btr => + { + if (btr.IsLayout) + return; + + // 外部参照 && 已融入 + if (btr is { IsFromExternalReference: true, IsResolved: true }) + bindIds.Add(btr.ObjectId); + }, checkIdOk: true); + } + + /// + /// 获取可以拆离的ids + /// + /// 返回已卸载中含有嵌套的参照,要重载之后才能绑定 + /// 返回未参照中嵌套的参照,直接拆离 + private List GetDetachIds(Dictionary nested) + { + // 直接拆离的id + List detachIds = new(); + + // 收集要处理的id + XrefNodeForEach((xNodeName, xNodeId, xNodeStatus, xNodeIsNested) => + { + switch (xNodeStatus) + { + case XrefStatus.Unresolved: // 未融入_ResolveXrefs参数2 + break; + case XrefStatus.FileNotFound: // 未融入(未解析)_未找到文件 + break; + case XrefStatus.Unreferenced: // 未参照 + { + // 为空的时候全部加入 || 有内容时候含有目标 + if (XrefNamesContains(xNodeName)) + detachIds.Add(xNodeId); + } + break; + case XrefStatus.Unloaded: // 已卸载 + { + // 为空的时候全部加入 || 有内容时候含有目标 + if (XrefNamesContains(xNodeName)) + { + var btr = _tr.GetObject(xNodeId); + if (btr != null && btr.IsFromExternalReference) + { + if (!xNodeIsNested) + detachIds.Add(xNodeId); + else if (!nested.ContainsKey(xNodeId)) + nested.Add(xNodeId, xNodeName); // 嵌套参照 + } + } + } + break; + case XrefStatus.Resolved: // 已融入_就是可以绑定的 + break; + case XrefStatus.NotAnXref: // 不是外部参照 + break; + } + }); + return detachIds; + } + + /// + /// 双重绑定参照 + /// 参考链接 + /// + private void DoubleBind() + { + Dictionary nested = new(); + var detachIds = GetDetachIds(nested); + + // 拆离:未参照的文件 + if (AutoDetach) + { + for (int i = 0; i < detachIds.Count; i++) + _tr.Database.DetachXref(detachIds[i]); + } + + // 重载:嵌套参照已卸载了,需要重载之后才能进行绑定 + var keys = nested.Keys; + if (keys.Count > 0) + { + using ObjectIdCollection idc = new(keys.ToArray()); + _tr.Database.ReloadXrefs(idc); + } + + // 绑定:切勿交换,否则会绑定无效 + using ObjectIdCollection bindIds = new(); + using ObjectIdCollection xbindIds = new(); + GetBindIds(bindIds); + GetXBindIds(xbindIds); + if (xbindIds.Count > 0) + _tr.Database.XBindXrefs(xbindIds, BindOrInsert); + if (bindIds.Count > 0) + _tr.Database.BindXrefs(bindIds, BindOrInsert); + + + // 内部删除嵌套参照的块操作 + if (EraseNested) + { + foreach (var item in nested) + { + var name = item.Value; + if (_tr.BlockTable.Has(name)) + _tr.GetObject(_tr.BlockTable[name], OpenMode.ForWrite)?.Erase(); + } + } + } + + #endregion +} + +/// +/// 参照扩展 +/// +public static class XrefEx +{ + /// + /// 外部参照工厂 + /// + /// + /// 处理参照的枚举 + /// 要处理的参照名称,就处理所有 + public static void XrefFactory(this DBTrans tr, XrefModes xrefModes, HashSet? xrefNames = null) + { + var xf = new XrefFactory(tr, xrefNames); + tr.Task(() => + { + switch (xrefModes) + { + case XrefModes.Unload: + xf.Unload(); + break; + case XrefModes.Reload: + xf.Reload(); + break; + case XrefModes.Detach: + xf.Detach(); + break; + case XrefModes.Bind: + xf.Bind(); + break; + } + }); + } +} + +#endregion + +#region 参照路径工具类 + +/// +/// 获取外部参照的路径 +/// +public class XrefPath +{ + #region 属性 + + /// + /// 基础路径 + /// + public readonly string? CurrentDatabasePath; + + /// + /// 是否外部参照 + /// + public bool IsFromExternalReference { get; private set; } + + /// + /// 外部参照保存的路径 + /// + /// 它们会是以下任一路径:
    + /// 0x01 相对路径
    + /// 0x02 绝对路径
    + /// 0x03 共目录优先找到的路径(文件夹整体移动会发生此类情况) + ///
    + ///
    + public string? PathSave { get; private set; } + + /// + /// 找到的路径(参照面板的名称) + /// 路径不存在时,返回是外部参照dwg文件路径 + /// + public string? PathDescribe { get; private set; } + + private string? _pathComplete; + + /// + /// 绝对路径 + /// + public string? PathComplete => + _pathComplete ??= PathConverter(CurrentDatabasePath, PathDescribe, PathConverterModes.Complete); + + private string? _pathRelative; + + /// + /// 相对路径 + /// + public string? PathRelative => + _pathRelative ??= PathConverter(CurrentDatabasePath, PathComplete, PathConverterModes.Relative); + + #endregion + + #region 构造 + + /// + /// 获取外部参照的路径 + /// + /// 外部参照图元 + /// 事务 + /// 是否外部参照 + public XrefPath(BlockReference brf, DBTrans tr) + { + //if (brf == null) + // throw new ArgumentNullException(nameof(brf)); + ArgumentNullEx.ThrowIfNull(brf); + CurrentDatabasePath = Path.GetDirectoryName(tr.Database.Filename); + + var btRec = tr.GetObject(brf.BlockTableRecord); // 块表记录 + if (btRec == null) + return; + + IsFromExternalReference = btRec.IsFromExternalReference; + if (!IsFromExternalReference) + return; + + // 相对路径==".\\AA.dwg" + // 无路径=="AA.dwg" + PathSave = btRec.PathName; + + if ((!string.IsNullOrEmpty(PathSave) && PathSave[0] == '.') || File.Exists(PathSave)) + { + // 相对路径||绝对路径 + PathDescribe = PathSave; + } + else + { + // 无路径 + var db = btRec.GetXrefDatabase(true); + PathDescribe = db.Filename; + } + } + + #endregion + + #region 静态函数 + + /// + /// 获取相对路径或者绝对路径 + /// 参考链接 + /// + /// 基础目录(末尾无斜杠) + /// 相对路径或者绝对路径 + /// 依照枚举返回对应的字符串 + /// + public static string? PathConverter(string? directory, string? fileRelations, + PathConverterModes converterModes) + { + //if (directory == null) + // throw new ArgumentNullException(nameof(directory)); + //if (fileRelations == null) + // throw new ArgumentNullException(nameof(fileRelations)); + + ArgumentNullEx.ThrowIfNull(directory); + ArgumentNullEx.ThrowIfNull(fileRelations); + + string? result = null; + switch (converterModes) + { + case PathConverterModes.Relative: + result = GetRelativePath(directory, fileRelations); + break; + case PathConverterModes.Complete: + result = GetCompletePath(directory, fileRelations); + break; + } + + return result; + } + +#if error_demo + /// + /// 绝对路径->相对路径 + /// + /// 绝对路径 + /// 相对关系 + /// + /// StringHelper.GetRelativePath("G:\\A1.项目\\20190920金山谷黄宅\\01.饰施图\\03.平面图", + /// "G:\\A1.项目\\20190920金山谷黄宅\\01.饰施图\\01.辅助文件\\图框\\A3图框.dwg"); + public static string GetRelativePath(string strDbPath, string strXrefPath) + { + Uri uri1 = new(strXrefPath); + Uri uri2 = new(strDbPath); + Uri relativeUri = uri2.MakeRelativeUri(uri1); + // 测试例子变成 01.%E8%BE%85%E5%8A%A9%E6%96%87%E4%BB%B6/%E5%9B%BE%E6%A1%86/A3%E5%9B%BE%E6%A1%86.dwg + string str = relativeUri.ToString(); + + // 因为这里不会实现".\A.dwg"而是"A.dwg",所以加入这个操作,满足同目录文件 + var strs = str.Split('\\'); + if (strs.Length == 1) + str = ".\\" + str; + return str; + } +#else + /// + /// 绝对路径->相对路径 + /// + /// 相对关系:文件夹路径 + /// 完整路径:文件路径 + /// 相对路径 + /// "..\\01.辅助文件\\图框\\A3图框.dwg" + /// ]]> + private static string GetRelativePath(string directory, string file) + { + string[] directories = directory.Split('\\'); + string[] files = file.Split('\\'); + // 获取两条路径中的最短路径 + int getMinLength = directories.Length < files.Length ? directories.Length : files.Length; + + // 用于确定我们退出的循环中的位置。 + int lastCommonRoot = -1; + int index; + // 找到共根 + for (index = 0; index < getMinLength; index++) + { + if (directories[index] != files[index]) + break; + lastCommonRoot = index; + } + + // 如果我们没有找到一个共同的前缀,那么抛出 + if (lastCommonRoot == -1) + throw new ArgumentException("路径没有公共相同路径部分"); + + // 建立相对路径 + var result = new StringBuilder(); + for (index = lastCommonRoot + 1; index < directories.Length; index++) + if (directories[index].Length > 0) + result.Append("..\\"); // 上级目录加入 + + // 添加文件夹 + for (index = lastCommonRoot + 1; index < files.Length - 1; index++) + result.Append(files[index] + "\\"); + + // 本级目录 + if (result.Length == 0) + result.Append(".\\"); + // result.Append(strXrefPaths[^1]);// 下级目录加入 + result.Append(files[^1]); // 下级目录加入 + return result.ToString(); + } +#endif + + /// + /// 相对路径->绝对路径 + /// + /// 文件夹路径 + /// 相对关系:有..的 + /// 完整路径 + /// "G:\\A1.项目\\20190920金山谷黄宅\\01.饰施图\\01.辅助文件\\图框\\A3图框.dwg" + /// ]]> + private static string? GetCompletePath(string directory, string relativePath) + { + if (relativePath.Trim() == string.Empty) + return null; + + var relativeName = Path.GetDirectoryName(relativePath); + if (relativeName is null) + return null; + + if (relativePath[0] != '.') + return relativePath; + + const char slash = '\\'; + + // 判断向上删除几个 + var slashes = relativeName.Split(slash); + int index = 0; + // ReSharper disable once ForCanBeConvertedToForeach + for (int i = 0; i < slashes.Length; i++) + { + if (slashes[i] != "..") + break; + index++; + } + + var result = new StringBuilder(); + // 前段 + var pathDwgs = directory.Split(slash); + pathDwgs = pathDwgs.Where(s => !string.IsNullOrEmpty(s)).ToArray(); // 清理空数组 + for (int i = 0; i < pathDwgs.Length - index; i++) + { + result.Append(pathDwgs[i]); + result.Append(slash); + } + + // 后段 + for (int i = 0; i < slashes.Length; i++) + { + var item = slashes[i]; + if (item != "." && item != "..") + { + result.Append(item); + result.Append(slash); + } + } + + result.Append(Path.GetFileName(relativePath)); + return result.ToString(); + } + + #endregion +} + +#endregion \ No newline at end of file -- Gitee From d541b2be36ef384585175ea2f9240339d7bbe27f Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sun, 20 Oct 2024 21:36:38 +0800 Subject: [PATCH 329/453] =?UTF-8?q?=E8=A1=A5=E5=85=85=E5=A1=AB=E5=85=85?= =?UTF-8?q?=EF=BC=8C=E4=BF=AE=E6=AD=A3=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/Algorithms/QuadTree/QuadTreeNode.cs | 32 +- CADShared/Algorithms/QuadTree/Rect.cs | 16 +- CADShared/Basal/General/LoopList.cs | 16 +- CADShared/Basal/Win/WindowsAPI.cs | 2 +- CADShared/CADShared.projitems | 4 + CADShared/ExtensionMethod/BulgeVertexWidth.cs | 92 ++++ CADShared/ExtensionMethod/CollectionEx.cs | 12 +- CADShared/ExtensionMethod/DBDictionaryEx.cs | 8 +- CADShared/ExtensionMethod/EditorEx.cs | 42 +- .../Entity/EntityBoundingInfo.cs | 6 +- .../ExtensionMethod/Geomerty/Curve2dEx.cs | 8 +- .../ExtensionMethod/Geomerty/Curve3dEx.cs | 22 +- .../ExtensionMethod/Geomerty/GeometryEx.cs | 32 +- CADShared/ExtensionMethod/Geomerty/PointEx.cs | 4 +- .../ExtensionMethod/Hatch/HatchConverter.cs | 452 ++++++++++++++++++ CADShared/ExtensionMethod/Hatch/HatchEx.cs | 365 ++++++++++++++ CADShared/ExtensionMethod/Hatch/HatchInfo.cs | 354 ++++++++++++++ .../ExtensionMethod/SingleKeyWordHook.cs | 2 +- CADShared/ExtensionMethod/SymbolTableEx.cs | 2 +- .../ExtensionMethod/SymbolTableRecordEx.cs | 6 +- CADShared/ExtensionMethod/XrefEx.cs | 16 +- CADShared/Initialize/AcadEMR.cs | 2 +- CADShared/PE/AcadPeInfo.cs | 2 +- CADShared/PE/PostCmd.cs | 8 +- CADShared/PE/ProgramPE.cs | 140 +++--- CADShared/Runtime/SymbolTable.cs | 4 +- 26 files changed, 1458 insertions(+), 191 deletions(-) create mode 100644 CADShared/ExtensionMethod/BulgeVertexWidth.cs create mode 100644 CADShared/ExtensionMethod/Hatch/HatchConverter.cs create mode 100644 CADShared/ExtensionMethod/Hatch/HatchEx.cs create mode 100644 CADShared/ExtensionMethod/Hatch/HatchInfo.cs diff --git a/CADShared/Algorithms/QuadTree/QuadTreeNode.cs b/CADShared/Algorithms/QuadTree/QuadTreeNode.cs index 315117f..7a37fdb 100644 --- a/CADShared/Algorithms/QuadTree/QuadTreeNode.cs +++ b/CADShared/Algorithms/QuadTree/QuadTreeNode.cs @@ -71,7 +71,7 @@ public void ContentsSubTree(List results) return; results.AddRange(Contents); var nodes = Nodes; - for (int i = 0; i < nodes.Length; i++) + for (var i = 0; i < nodes.Length; i++) nodes[i]?.ContentsSubTree(results); } @@ -84,10 +84,10 @@ public int CountSubTree { if (Contents is null) return 0; - int count = Contents.Count; + var count = Contents.Count; var nodes = Nodes; - for (int i = 0; i < nodes.Length; i++) + for (var i = 0; i < nodes.Length; i++) { var node = nodes[i]; if (node is null) @@ -137,7 +137,7 @@ public QuadTreeNode(Rect box, QuadTreeNode? parent, int depth) // 退出递归:4个节点都不完全包含 // 4个节点的上层 var nodes = Nodes; - for (int i = 0; i < nodes.Length; i++) + for (var i = 0; i < nodes.Length; i++) { var node = nodes[i]; if (node is null) @@ -219,7 +219,7 @@ public QuadTreeNode(Rect box, QuadTreeNode? parent, int depth) // 4个子节点开始递归 // 退出递归:4个节点都不完全包含,内容就是他们的父亲 var nodes = Nodes; - for (int i = 0; i < nodes.Length; i++) + for (var i = 0; i < nodes.Length; i++) { var node = nodes[i]; if (node is null) @@ -295,7 +295,7 @@ public bool Remove(TEntity easeEnt) // 2.递归子节点移除 var nodes = Nodes; - for (int i = 0; i < nodes.Length; i++) + for (var i = 0; i < nodes.Length; i++) { var node = nodes[i]; if (node is null) @@ -313,7 +313,7 @@ public bool Remove(TEntity easeEnt) void Clear(QuadTreeNode node) { var nodes = Nodes; - for (int i = 0; i < nodes.Length; i++) + for (var i = 0; i < nodes.Length; i++) nodes[i]?.Clear(nodes[i]); node.Contents.Clear(); @@ -335,7 +335,7 @@ public void Remove(Rect queryArea) // 本节点内容移除 if (Contents is not null && Contents.Count > 0)// 从最上层的根节点开始进入 { - for (int i = Contents.Count - 1; i >= 0; i--) + for (var i = Contents.Count - 1; i >= 0; i--) { var ent = Contents[i]; // 移除之后,如果容器是0,那么这里不能直接 Contents=null, @@ -350,7 +350,7 @@ public void Remove(Rect queryArea) // 同插入一样 // 跳到指定节点再搜索这个节点下面的图元 var nodes = Nodes; - for (int i = 0; i < nodes.Length; i++) + for (var i = 0; i < nodes.Length; i++) { var node = nodes[i]; if (node is null) @@ -396,7 +396,7 @@ public void Query(Rect queryArea, List results) // 遍历子节点 var nodes = Nodes; - for (int i = 0; i < nodes.Length; i++) + for (var i = 0; i < nodes.Length; i++) { var node = nodes[i]; if (node is null) @@ -436,7 +436,7 @@ void GetCurrentContents(Rect queryArea, List results) // 遍历当前节点内容,加入方式取决于碰撞模式 if (QuadTreeEvn.SelectMode == QuadTreeSelectMode.IntersectsWith) { - for (int i = 0; i < Contents.Count; i++) + for (var i = 0; i < Contents.Count; i++) { var ent = Contents[i]; if (queryArea.IntersectsWith(ent)) @@ -445,7 +445,7 @@ void GetCurrentContents(Rect queryArea, List results) } else { - for (int i = 0; i < Contents.Count; i++) + for (var i = 0; i < Contents.Count; i++) { var ent = Contents[i]; if (queryArea.Contains(ent)) @@ -484,7 +484,7 @@ void GetCurrentContents(Rect queryArea, List results) var maxPt = new Point2d(queryAreaCenter.X + hw, queryAreaCenter.Y + hh); List ents = []; Query(new Rect(minPt, maxPt), ents); - for (int i = 0; i < ents.Count; i++) + for (var i = 0; i < ents.Count; i++) { var ent = ents[i]; if (entDic.ContainsKey(ent)) @@ -521,7 +521,7 @@ void GetCurrentContents(Rect queryArea, List results) // 3.找到方向 findMode 拥有的节点,然后查找节点的内容 var queryNode = GetMinNode(queryArea); - bool whileFlag = true; + var whileFlag = true; // 同一个节点可能包含邻居,因为四叉树的加入是图元压线, // 那么就在这里搜就得了,用中心点决定空间位置 // 但是本空间的图元可能都比它矮,无法满足条件 @@ -673,7 +673,7 @@ void GetCurrentContents(Rect queryArea, List results) QuadTreeNode GetMinNode(Rect queryArea) { var nodes = Nodes; - for (int i = 0; i < nodes.Length; i++) + for (var i = 0; i < nodes.Length; i++) { var node = nodes[i]; if (node is null) @@ -804,7 +804,7 @@ public bool ForEach(QuadTree.QTAction action) // 递归执行本节点的子节点 var nodes = Nodes; - for (int i = 0; i < nodes.Length; i++) + for (var i = 0; i < nodes.Length; i++) { var node = nodes[i]; if (node is null) diff --git a/CADShared/Algorithms/QuadTree/Rect.cs b/CADShared/Algorithms/QuadTree/Rect.cs index 583c07d..30bb719 100644 --- a/CADShared/Algorithms/QuadTree/Rect.cs +++ b/CADShared/Algorithms/QuadTree/Rect.cs @@ -375,9 +375,9 @@ public Point2d[] GetCommonPoint(Rect other) /// public Point2d[] ToPoints() { - Point2d a = MinPoint;// min + var a = MinPoint;// min Point2d b = new(_Right, _Y); - Point2d c = MaxPoint;// max + var c = MaxPoint;// max Point2d d = new(_X, _Top); return [a, b, c, d]; } @@ -387,9 +387,9 @@ public Point2d[] ToPoints() /// public (Point2d boxMin, Point2d boxRigthDown, Point2d boxMax, Point2d boxLeftUp) ToPoints4() { - Point2d a = MinPoint;// min + var a = MinPoint;// min Point2d b = new(_Right, _Y); - Point2d c = MaxPoint;// max + var c = MaxPoint;// max Point2d d = new(_X, _Top); return (a, b, c, d); } @@ -533,7 +533,7 @@ public static bool RectAnglePointOrder(List? pts) pts.Clear(); // 排序这四个点,左下/右下/右上/左上 var node = link.Find(minPt); - for (int i = 0; i < 4; i++) + for (var i = 0; i < 4; i++) { pts.Add(node!.Value); node = node.Next; @@ -617,16 +617,16 @@ public static void XCollision(List box, box = box.OrderBy(a => a._X).ToList(); // 遍历所有图元 - for (int i = 0; i < box.Count; i++) + for (var i = 0; i < box.Count; i++) { var oneRect = box[i]; if (firstProcessing(oneRect)) continue; - bool actionlast = true; + var actionlast = true; // 搜索范围要在 one 的头尾中间的部分 - for (int j = i + 1; j < box.Count; j++) + for (var j = i + 1; j < box.Count; j++) { var twoRect = box[j]; // x碰撞:矩形2的Left 在 矩形1[Left-Right]闭区间;穿过的话,也必然有自己的Left因此不需要处理 diff --git a/CADShared/Basal/General/LoopList.cs b/CADShared/Basal/General/LoopList.cs index da1e258..58b450f 100644 --- a/CADShared/Basal/General/LoopList.cs +++ b/CADShared/Basal/General/LoopList.cs @@ -150,7 +150,7 @@ public void Reverse() if (first is null) return; var last = Last; - for (int i = 0; i < Count / 2; i++) + for (var i = 0; i < Count / 2; i++) { Swap(first!, last!); first = first!.Next; @@ -177,7 +177,7 @@ void ForEach(Func, bool> action) var node = First; if (node is null) return; - for (int i = 0; i < Count; i++) + for (var i = 0; i < Count; i++) { if (action(node!)) break; @@ -194,7 +194,7 @@ public void For(Func, bool> action) var node = First; if (node is null) return; - for (int i = 0; i < Count; i++) + for (var i = 0; i < Count; i++) { if (action(i, node!)) break; @@ -563,8 +563,8 @@ public void LinkTo(LoopListNode from, LoopListNode to) if (from != to && Contains(from) && Contains(to)) { LoopListNode node = from.Next!; - bool isFirstChanged = false; - int number = 0; + var isFirstChanged = false; + var number = 0; while (node != to) { @@ -636,7 +636,7 @@ public void LinkTo(LoopListNode from, LoopListNode to, int number, bool is public IEnumerable> GetNodes(LoopListNode from) { var node = from; - for (int i = 0; i < Count; i++) + for (var i = 0; i < Count; i++) { yield return node!; node = node!.Next; @@ -651,7 +651,7 @@ public IEnumerable> GetNodes(LoopListNode from) public IEnumerable> GetNodes() { LoopListNode node = First!; - for (int i = 0; i < Count; i++) + for (var i = 0; i < Count; i++) { yield return node!; node = node.Next!; @@ -666,7 +666,7 @@ public IEnumerable> GetNodes() public IEnumerator GetEnumerator() { LoopListNode node = First!; - for (int i = 0; i < Count; i++) + for (var i = 0; i < Count; i++) { yield return node!.Value; node = node.Next!; diff --git a/CADShared/Basal/Win/WindowsAPI.cs b/CADShared/Basal/Win/WindowsAPI.cs index 986a7f9..210ace1 100644 --- a/CADShared/Basal/Win/WindowsAPI.cs +++ b/CADShared/Basal/Win/WindowsAPI.cs @@ -117,7 +117,7 @@ public static bool GlobalLockTask(IntPtr data, Action task) // 安全写法效率太低了 // 分配结构体大小的内存空间 - IntPtr structPtr = Marshal.AllocHGlobal(typeSize); + var structPtr = Marshal.AllocHGlobal(typeSize); // 将byte数组拷到分配好的内存空间 Marshal.Copy(bytes, 0, structPtr, typeSize); diff --git a/CADShared/CADShared.projitems b/CADShared/CADShared.projitems index 1ba9e37..e42f1e3 100644 --- a/CADShared/CADShared.projitems +++ b/CADShared/CADShared.projitems @@ -30,6 +30,7 @@ + @@ -64,6 +65,9 @@ + + + diff --git a/CADShared/ExtensionMethod/BulgeVertexWidth.cs b/CADShared/ExtensionMethod/BulgeVertexWidth.cs new file mode 100644 index 0000000..4303fd3 --- /dev/null +++ b/CADShared/ExtensionMethod/BulgeVertexWidth.cs @@ -0,0 +1,92 @@ +namespace IFoxCAD.Cad; + +/// +/// 多段线的顶点,凸度,头宽,尾宽 +/// +[Serializable] +public class BulgeVertexWidth +{ + /// + /// 顶点X + /// + public double X; + /// + /// 顶点Y + /// + public double Y; + /// + /// 凸度 + /// + public double Bulge; + /// + /// 头宽 + /// + public double StartWidth; + /// + /// 尾宽 + /// + public double EndWidth; + /// + /// 顶点 + /// + public Point2d Vertex => new(X, Y); + /// + /// 默认构造 + /// + public BulgeVertexWidth() { } + + /// + /// 多段线的顶点,凸度,头宽,尾宽 + /// + public BulgeVertexWidth(double vertexX, double vertexY, + double bulge = 0, + double startWidth = 0, + double endWidth = 0) + { + X = vertexX; + Y = vertexY; + Bulge = bulge; + StartWidth = startWidth; + EndWidth = endWidth; + } + + /// + /// 多段线的顶点,凸度,头宽,尾宽 + /// + public BulgeVertexWidth(Point2d vertex, + double bulge = 0, + double startWidth = 0, + double endWidth = 0) + : this(vertex.X, vertex.Y, bulge, startWidth, endWidth) + { } + + /// + /// 多段线的顶点,凸度,头宽,尾宽 + /// + public BulgeVertexWidth(BulgeVertex bv) + : this(bv.Vertex.X, bv.Vertex.Y, bv.Bulge) + { } + + /// + /// 多段线的顶点,凸度,头宽,尾宽 + /// + /// 多段线 + /// 子段编号 + public BulgeVertexWidth(Polyline pl, int index) + { + var pt = pl.GetPoint2dAt(index);// 这里可以3d + X = pt.X; + Y = pt.Y; + Bulge = pl.GetBulgeAt(index); + StartWidth = pl.GetStartWidthAt(index); + EndWidth = pl.GetEndWidthAt(index); + } + /// + /// 转换为 BulgeVertex + /// + /// + public BulgeVertex ToBulgeVertex() + { + return new BulgeVertex(Vertex, Bulge); + } +} diff --git a/CADShared/ExtensionMethod/CollectionEx.cs b/CADShared/ExtensionMethod/CollectionEx.cs index 01e2801..9d3a867 100644 --- a/CADShared/ExtensionMethod/CollectionEx.cs +++ b/CADShared/ExtensionMethod/CollectionEx.cs @@ -163,7 +163,7 @@ public static void ForEach(this IEnumerable source, Action a [DebuggerStepThrough] public static void ForEach(this IEnumerable source, Action action) { - int i = 0; + var i = 0; LoopState state = new(); /*这种方式比Action改Func更友好*/ foreach (var element in source) { @@ -209,11 +209,11 @@ public enum KeywordName public static bool Contains(this KeywordCollection collection, string name, KeywordName keywordName = KeywordName.GlobalName) { - bool contains = false; + var contains = false; switch (keywordName) { case KeywordName.GlobalName: - for (int i = 0; i < collection.Count; i++) + for (var i = 0; i < collection.Count; i++) { var item = collection[i]; @@ -226,7 +226,7 @@ public static bool Contains(this KeywordCollection collection, string name, break; case KeywordName.LocalName: - for (int i = 0; i < collection.Count; i++) + for (var i = 0; i < collection.Count; i++) { var item = collection[i]; @@ -239,7 +239,7 @@ public static bool Contains(this KeywordCollection collection, string name, break; case KeywordName.DisplayName: - for (int i = 0; i < collection.Count; i++) + for (var i = 0; i < collection.Count; i++) { var item = collection[i]; @@ -266,7 +266,7 @@ public static bool Contains(this KeywordCollection collection, string name, public static Dictionary ToDictionary(this KeywordCollection collection) { Dictionary map = new(); - for (int i = 0; i < collection.Count; i++) + for (var i = 0; i < collection.Count; i++) { var item = collection[i]; diff --git a/CADShared/ExtensionMethod/DBDictionaryEx.cs b/CADShared/ExtensionMethod/DBDictionaryEx.cs index de6f630..266b294 100644 --- a/CADShared/ExtensionMethod/DBDictionaryEx.cs +++ b/CADShared/ExtensionMethod/DBDictionaryEx.cs @@ -171,10 +171,10 @@ public static DataTable CreateDataTable(Dictionary colTypes, o colTypes.Values.CopyTo(types, 0); var nRow = content.GetLength(0); - for (int i = 0; i < nRow; i++) + for (var i = 0; i < nRow; i++) { DataCellCollection row = new(); - for (int j = 0; j < nCol; j++) + for (var j = 0; j < nCol; j++) { var cell = new DataCell(); cell.SetValue(types[j], content[i, j]); @@ -264,7 +264,7 @@ public static void SetValue(this DataCell cell, CellType type, object value) using (dict.ForWrite()) dict.TreatElementsAsHard = true; - foreach (string name in dictNames) + foreach (var name in dictNames) { if (dict.Contains(name)) { @@ -281,7 +281,7 @@ public static void SetValue(this DataCell cell, CellType type, object value) } else { - foreach (string name in dictNames) + foreach (var name in dictNames) { if (dict.Contains(name)) newDict = dict.GetData(name); diff --git a/CADShared/ExtensionMethod/EditorEx.cs b/CADShared/ExtensionMethod/EditorEx.cs index 0b874c5..e99af58 100644 --- a/CADShared/ExtensionMethod/EditorEx.cs +++ b/CADShared/ExtensionMethod/EditorEx.cs @@ -165,7 +165,7 @@ public static void SsgetAddKeys(this PromptSelectionOptions pso, { Dictionary tmp = new(); // 后缀名的|号切割,移除掉,组合成新的加入tmp - for (int i = dicActions.Count - 1; i >= 0; i--) + for (var i = dicActions.Count - 1; i >= 0; i--) { var pair = dicActions.ElementAt(i); var key = pair.Key; @@ -173,12 +173,12 @@ public static void SsgetAddKeys(this PromptSelectionOptions pso, if (keySp.Length < 2) continue; - for (int j = 0; j < keySp.Length; j++) + for (var j = 0; j < keySp.Length; j++) { var item = keySp[j]; // 防止多个后缀通过|符越过词典约束同名 // 后缀(key)含有,而且Action(value)不同,就把Action(value)累加到后面. - if (dicActions.TryGetValue(item, out Action value)) + if (dicActions.TryGetValue(item, out var value)) { if (dicActions[item] != dicActions[key]) dicActions[item] += dicActions[key]; @@ -194,12 +194,12 @@ public static void SsgetAddKeys(this PromptSelectionOptions pso, dicActions.Add(item.Key, item.Value); // 去除关键字重复的,把重复的执行动作移动到前面 - for (int i = 0; i < dicActions.Count; i++) + for (var i = 0; i < dicActions.Count; i++) { var pair1 = dicActions.ElementAt(i); var key1 = pair1.Key; - for (int j = dicActions.Count - 1; j > i; j--) + for (var j = dicActions.Count - 1; j > i; j--) { var pair2 = dicActions.ElementAt(j); var key2 = pair2.Key; @@ -216,7 +216,7 @@ public static void SsgetAddKeys(this PromptSelectionOptions pso, foreach (var item in dicActions) { var keySplitS = item.Key.Split(new string[] { ",", "|" }, StringSplitOptions.RemoveEmptyEntries); - for (int i = 0; i < keySplitS.Length; i += 2) + for (var i = 0; i < keySplitS.Length; i += 2) pso.Keywords.Add(keySplitS[i], keySplitS[i], keySplitS[i + 1] + "(" + keySplitS[i] + ")"); } @@ -504,7 +504,7 @@ public static List GetLines(IEnumerable pnts, bool isClosed TypedValue tvFirst = new((int)LispDataType.Point2d, itor.Current); TypedValue tv1; - TypedValue tv2 = tvFirst; + var tv2 = tvFirst; while (itor.MoveNext()) { @@ -562,13 +562,13 @@ public static void DrawCircles(this Editor editor, IEnumerable pnts, sh var rlst = new LispList { { LispDataType.Int16, colorIndex } }; - foreach (Point2d pnt in pnts) + foreach (var pnt in pnts) { - Vector2d vec = Vector2d.XAxis * radius; - double angle = Math.PI * 2 / numEdges; + var vec = Vector2d.XAxis * radius; + var angle = Math.PI * 2 / numEdges; List tpnts = [pnt + vec]; - for (int i = 1; i < numEdges; i++) + for (var i = 1; i < numEdges; i++) { tpnts.Add(pnt + vec.RotateBy(angle * i)); } @@ -589,11 +589,11 @@ public static void DrawCircles(this Editor editor, IEnumerable pnts, sh /// 多边形边的个数 public static void DrawCircle(this Editor editor, Point2d pnt, short colorIndex, double radius, int numEdges) { - Vector2d vec = Vector2d.XAxis * radius; - double angle = Math.PI * 2 / numEdges; + var vec = Vector2d.XAxis * radius; + var angle = Math.PI * 2 / numEdges; List pnts = [pnt + vec]; - for (int i = 1; i < numEdges; i++) + for (var i = 1; i < numEdges; i++) pnts.Add(pnt + vec.RotateBy(angle * i)); editor.DrawVectors(pnts, colorIndex, true); @@ -702,7 +702,7 @@ public static Matrix3d GetMatrixFromMDcsToPDcs(this Editor editor) if ((short)Env.GetVar("TILEMODE") == 1) throw new ArgumentException("TILEMODE == 1..Espace papier uniquement"); - Matrix3d mat = Matrix3d.Identity; + var mat = Matrix3d.Identity; //using DBTrans tr = new(); var tr = DBTrans.GetTopTransaction(editor.Document.Database); var vp = tr.GetObject(editor.CurrentViewportObjectId); @@ -860,7 +860,7 @@ public static void ZoomWindow(this Editor ed, Point3d lpt, Point3d rpt, double o extents.AddPoint(rpt); rpt = extents.MaxPoint + new Vector3d(offsetDist, offsetDist, 0); lpt = extents.MinPoint - new Vector3d(offsetDist, offsetDist, 0); - Vector3d ver = rpt - lpt; + var ver = rpt - lpt; ed.Zoom(lpt + ver / 2, ver.X, ver.Y); } @@ -894,7 +894,7 @@ public static void ZoomWindow(this Editor ed, Point3d lpt, Point3d rpt, double o /// 偏移距离 public static void ZoomExtents(this Editor ed, double offsetDist = 0.00) { - Database db = ed.Document.Database; + var db = ed.Document.Database; // db.UpdateExt(true); // GetValidExtents3d内提供了 var dbExtent = db.GetValidExtents3d(); if (dbExtent == null) @@ -911,7 +911,7 @@ public static void ZoomExtents(this Editor ed, double offsetDist = 0.00) /// 偏移距离 public static void ZoomObject(this Editor ed, Entity ent, double offsetDist = 0.00) { - Extents3d ext = ent.GeometricExtents; + var ext = ent.GeometricExtents; ed.ZoomWindow(ext.MinPoint, ext.MaxPoint, offsetDist); } @@ -1061,7 +1061,7 @@ public enum RunLispFlag : byte if ((flag & RunLispFlag.AcedEvaluateLisp) == RunLispFlag.AcedEvaluateLisp) { - _ = AcedEvaluateLisp(lispCode, out IntPtr rb); + _ = AcedEvaluateLisp(lispCode, out var rb); if (rb != IntPtr.Zero) return (ResultBuffer)DisposableWrapper.Create(typeof(ResultBuffer), rb, true); } @@ -1123,8 +1123,8 @@ public static void ComExportWMF(this Editor editor, string saveFile, #else dynamic com = Acap.AcadApplication; #endif - dynamic doc = com.ActiveDocument; - dynamic wmfSet = doc.ActiveSelectionSet; + var doc = com.ActiveDocument; + var wmfSet = doc.ActiveSelectionSet; // TODO 20221007 导出wmf的bug // cad21 先net选择,再进行,此处再选择一次? // cad21 调试期间无法选择性粘贴? diff --git a/CADShared/ExtensionMethod/Entity/EntityBoundingInfo.cs b/CADShared/ExtensionMethod/Entity/EntityBoundingInfo.cs index a92534d..76d91a5 100644 --- a/CADShared/ExtensionMethod/Entity/EntityBoundingInfo.cs +++ b/CADShared/ExtensionMethod/Entity/EntityBoundingInfo.cs @@ -92,7 +92,7 @@ static void GetBlockBox(this Entity en, ref Extents3d ext, ref Matrix3d mat) var e = GetEntityBoxEx(en); if (e.HasValue) { - Extents3d entext = e.Value; + var entext = e.Value; entext.TransformBy(mat); if (ext.IsEmptyExt()) ext = entext; @@ -111,8 +111,8 @@ static void GetBlockBox(this Entity en, ref Extents3d ext, ref Matrix3d mat) /// 最小包围盒4点坐标 public static Point3d[] GetMTextBoxCorners(MText mtext) { - double width = mtext.ActualWidth; - double height = mtext.ActualHeight; + var width = mtext.ActualWidth; + var height = mtext.ActualHeight; Point3d point1, point2; switch (mtext.Attachment) { diff --git a/CADShared/ExtensionMethod/Geomerty/Curve2dEx.cs b/CADShared/ExtensionMethod/Geomerty/Curve2dEx.cs index 8dec36b..251969d 100644 --- a/CADShared/ExtensionMethod/Geomerty/Curve2dEx.cs +++ b/CADShared/ExtensionMethod/Geomerty/Curve2dEx.cs @@ -95,7 +95,7 @@ public static Circle ToCircle(this CircularArc2d c2d) public static Arc ToArc(this CircularArc2d a2d) { double startAngle, endAngle; - double refAngle = a2d.ReferenceVector.Angle; + var refAngle = a2d.ReferenceVector.Angle; if (a2d.IsClockWise) { @@ -269,15 +269,15 @@ public static Spline ToCurve(this NurbCurve2d nc2d, Matrix3d mat) public static Spline ToCurve(this NurbCurve2d nc2d) { using Point3dCollection ctlPts = new(); - for (int i = 0; i < nc2d.NumControlPoints; i++) + for (var i = 0; i < nc2d.NumControlPoints; i++) ctlPts.Add(new Point3d(_planeCache, nc2d.GetControlPointAt(i))); DoubleCollection knots = new(); - for (int i = 0; i < nc2d.Knots.Count; i++) + for (var i = 0; i < nc2d.Knots.Count; i++) knots.Add(nc2d.Knots[i]); DoubleCollection weights = new(); - for (int i = 0; i < nc2d.NumWeights; i++) + for (var i = 0; i < nc2d.NumWeights; i++) weights.Add(nc2d.GetWeightAt(i)); NurbCurve2dData nurbCurve2dData = nc2d.DefinitionData; diff --git a/CADShared/ExtensionMethod/Geomerty/Curve3dEx.cs b/CADShared/ExtensionMethod/Geomerty/Curve3dEx.cs index ac8b192..52a8e71 100644 --- a/CADShared/ExtensionMethod/Geomerty/Curve3dEx.cs +++ b/CADShared/ExtensionMethod/Geomerty/Curve3dEx.cs @@ -32,7 +32,7 @@ public static List GetParamsAtIntersectionPoints(this Curve3d c3d, bool { CurveCurveIntersector3d cci = new(c3d, c3d, Vector3d.ZAxis); List pars = []; - for (int i = 0; i < cci.NumberOfIntersectionPoints; i++) + for (var i = 0; i < cci.NumberOfIntersectionPoints; i++) pars.AddRange(cci.GetIntersectionParameters(i)); if (sort) pars.Sort(); @@ -49,8 +49,8 @@ public static List GetParamsAtIntersectionPoints(this Curve3d c3d, bool public static Curve3d GetSubCurve(this Curve3d curve, double from, double to) { Interval inter = curve.GetInterval(); - bool atStart = Tolerance.Global.IsEqualPoint(inter.LowerBound, from); - bool atEnd = Tolerance.Global.IsEqualPoint(inter.UpperBound, to); + var atStart = Tolerance.Global.IsEqualPoint(inter.LowerBound, from); + var atEnd = Tolerance.Global.IsEqualPoint(inter.UpperBound, to); if (atStart && atEnd) return (Curve3d)curve.Clone(); if (curve is NurbCurve3d) @@ -156,7 +156,7 @@ public static bool IsCircular(this Curve3d curve) if (pars.Count > 0) { pars.Sort(); - for (int i = pars.Count - 1; i > 0; i--) + for (var i = pars.Count - 1; i > 0; i--) if (Tolerance.Global.IsEqualPoint(pars[i], pars[i - 1])) pars.RemoveAt(i); } @@ -209,7 +209,7 @@ public static bool IsCircular(this Curve3d curve) List curves = new(); List cc3ds = new(); - for (int i = 0; i < pars.Count - 1; i++) + for (var i = 0; i < pars.Count - 1; i++) { cc3ds.Clear(); // 复合曲线参数转换到包含曲线参数 @@ -230,7 +230,7 @@ public static bool IsCircular(this Curve3d curve) cp1.LocalParameter, inter.UpperBound)); - for (int j = cp1.SegmentIndex + 1; j < cp2.SegmentIndex; j++) + for (var j = cp1.SegmentIndex + 1; j < cp2.SegmentIndex; j++) cc3ds.Add((Curve3d)c3ds[j].Clone()); inter = c3ds[cp2.SegmentIndex].GetInterval(); @@ -268,7 +268,7 @@ public static bool IsCircular(this Curve3d curve) if (cs.Length == 1) return ToCurve(cs[0]); - bool hasNurb = false; + var hasNurb = false; foreach (var c in cs) { @@ -302,12 +302,12 @@ public static Polyline ToPolyline(this CompositeCurve3d cc3d) Plane plane = pl.GetPlane(); Point2d endVer = Point2d.Origin; - int i = 0; + var i = 0; foreach (Curve3d c3d in cc3d.GetCurves()) { if (c3d is CircularArc3d ca3d) { - double b = Math.Tan(0.25 * (ca3d.EndAngle - ca3d.StartAngle)) * ca3d.Normal[2]; + var b = Math.Tan(0.25 * (ca3d.EndAngle - ca3d.StartAngle)) * ca3d.Normal[2]; pl.AddVertexAt(i, c3d.StartPoint.Convert2d(plane), b, 0, 0); endVer = c3d.EndPoint.Convert2d(plane); } @@ -411,7 +411,7 @@ public static Circle ToCircle(this CircularArc3d ca3d) => public static Arc ToArc(this CircularArc3d ca3d) { // 必须新建,而不能直接使用GetPlane()获取 - double angle = ca3d.ReferenceVector.AngleOnPlane(new Plane(ca3d.Center, ca3d.Normal)); + var angle = ca3d.ReferenceVector.AngleOnPlane(new Plane(ca3d.Center, ca3d.Normal)); return new Arc(ca3d.Center, ca3d.Normal, ca3d.Radius, ca3d.StartAngle + angle, ca3d.EndAngle + angle); } @@ -549,7 +549,7 @@ public static Polyline3d ToCurve(this PolylineCurve3d pl3d) for (var i = 0; i < pl3d.NumberOfControlPoints; i++) pt3dCollection.Add(pl3d.ControlPointAt(i)); - bool closed = false; + var closed = false; var n = pt3dCollection.Count - 1; if (pt3dCollection[0] == pt3dCollection[n]) { diff --git a/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs b/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs index 3d7040f..fe85b56 100644 --- a/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs +++ b/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs @@ -39,7 +39,7 @@ public static PointOnRegionType PointOnRegion(this IEnumerable pts, Poi return PointOnRegionType.Outside; // - bool flag = false; + var flag = false; foreach (var node in ptlst.GetNodes()) { var pt1 = node.Value; @@ -48,9 +48,9 @@ public static PointOnRegionType PointOnRegion(this IEnumerable pts, Poi continue; if (pt1.X < pt.X && pt2.X < pt.X) continue; - Vector2d vec = pt2 - pt1; - double t = (pt.X - pt1.X) / vec.X; - double y = t * vec.Y + pt1.Y; + var vec = pt2 - pt1; + var t = (pt.X - pt1.X) / vec.X; + var y = t * vec.Y + pt1.Y; if (y < pt.Y && t >= 0 && t <= 1) flag = !flag; } @@ -89,7 +89,7 @@ public static PointOnRegionType PointOnRegion(this IEnumerable pts, Poi return PointOnRegionType.Outside; // - bool flag = false; + var flag = false; foreach (var node in ptlst.GetNodes()) { var pt1 = node.Value; @@ -98,9 +98,9 @@ public static PointOnRegionType PointOnRegion(this IEnumerable pts, Poi continue; if (pt1.X < pt.X && pt2.X < pt.X) continue; - Vector3d vec = pt2 - pt1; - double t = (pt.X - pt1.X) / vec.X; - double y = t * vec.Y + pt1.Y; + var vec = pt2 - pt1; + var t = (pt.X - pt1.X) / vec.X; + var y = t * vec.Y + pt1.Y; if (y < pt.Y && t >= 0 && t <= 1) flag = !flag; } @@ -140,7 +140,7 @@ public static CircularArc2d GetMinCircle(Point2d pt1, Point2d pt2, Point2d pt3, ptlst = new LoopList { pt1, pt2, pt3 }; // 遍历各点与下一点的向量长度,找到距离最大的两个点 - LoopListNode maxNode = + var maxNode = ptlst.GetNodes().FindByMax ( out _, @@ -148,8 +148,8 @@ public static CircularArc2d GetMinCircle(Point2d pt1, Point2d pt2, Point2d pt3, ); // 以两点做最小包围圆 - CircularArc2d ca2d = - GetMinCircle(maxNode.Value, maxNode.Next!.Value, out LoopList tptlst); + var ca2d = + GetMinCircle(maxNode.Value, maxNode.Next!.Value, out var tptlst); // 如果另一点属于该圆 if (ca2d.IsIn(maxNode.Previous!.Value)) @@ -187,7 +187,7 @@ public static CircularArc2d GetMinCircle(Point2d pt1, Point2d pt2, Point2d pt3, // 获取各组合下三点的最小包围圆 var secondNode = firstNode.Next; var thirdNode = secondNode!.Next; - var tca2d = GetMinCircle(firstNode.Value, secondNode.Value, thirdNode!.Value, out LoopList tptlst); + var tca2d = GetMinCircle(firstNode.Value, secondNode.Value, thirdNode!.Value, out var tptlst); // 如果另一点属于该圆,并且半径小于当前值就把它做为候选解 if (!tca2d.IsIn(firstNode.Previous!.Value)) @@ -418,7 +418,7 @@ public static List ConvexHull(this List points) a.X == b.X ? a.Y.CompareTo(b.Y) : a.X.CompareTo(b.X)); // Build lower hull - for (int i = 0; i < n; ++i) + for (var i = 0; i < n; ++i) { while (k >= 2 && IsClockWise(H[k - 2], H[k - 1], points[i]) == OrientationType.CounterClockWise) k--; @@ -549,7 +549,7 @@ public static Vector3d Wcs2Dcs(this Vector3d vec, bool atPaperSpace) /// 三维矩阵 public static Matrix3d GetScaleMatrix(this Point3d point, double x, double y, double z) { - double[] matdata = new double[16]; + var matdata = new double[16]; matdata[0] = x; matdata[3] = point.X * (1 - x); matdata[5] = y; @@ -567,8 +567,8 @@ public static Matrix3d GetScaleMatrix(this Point3d point, double x, double y, do /// 尺寸对象 public static Size GetSize(this Extents3d ext) { - int width = (int)Math.Floor(ext.MaxPoint.X - ext.MinPoint.X); - int height = (int)Math.Ceiling(ext.MaxPoint.Y - ext.MinPoint.Y); + var width = (int)Math.Floor(ext.MaxPoint.X - ext.MinPoint.X); + var height = (int)Math.Ceiling(ext.MaxPoint.Y - ext.MinPoint.Y); return new(width, height); } diff --git a/CADShared/ExtensionMethod/Geomerty/PointEx.cs b/CADShared/ExtensionMethod/Geomerty/PointEx.cs index 6cbc060..c6455b1 100644 --- a/CADShared/ExtensionMethod/Geomerty/PointEx.cs +++ b/CADShared/ExtensionMethod/Geomerty/PointEx.cs @@ -237,7 +237,7 @@ public static void End2End(this Point2dCollection ptCollection) // 首尾不同,去加一个到最后 var lst = new Point2d[ptCollection.Count + 1]; - for (int i = 0; i < ptCollection.Count; i++) + for (var i = 0; i < ptCollection.Count; i++) lst[i] = ptCollection[i]; lst[^1] = lst[0]; @@ -257,7 +257,7 @@ public static void End2End(this Point3dCollection ptCollection) // 首尾不同,去加一个到最后 var lst = new Point3d[ptCollection.Count + 1]; - for (int i = 0; i < ptCollection.Count; i++) + for (var i = 0; i < ptCollection.Count; i++) lst[i] = ptCollection[i]; lst[^1] = lst[0]; diff --git a/CADShared/ExtensionMethod/Hatch/HatchConverter.cs b/CADShared/ExtensionMethod/Hatch/HatchConverter.cs new file mode 100644 index 0000000..716e963 --- /dev/null +++ b/CADShared/ExtensionMethod/Hatch/HatchConverter.cs @@ -0,0 +1,452 @@ +// ReSharper disable CompareOfFloatsByEqualityOperator +// ReSharper disable ForCanBeConvertedToForeach + +namespace IFoxCAD.Cad; + +using PointV = Point2d; + +/// +/// 填充边界转换器 +/// +public class HatchConverter +{ + #region 辅助类 + + /// + /// 生成圆形数据 + /// + class CircleData + { + public readonly PointV Center; + public readonly double Radius; + + /// + /// 生成圆形数据 + /// + /// 对称点1 + /// 对称点2 + public CircleData(PointV symmetryAxisPoint1, PointV symmetryAxisPoint2) + { + Center = symmetryAxisPoint1.GetMidPointTo(symmetryAxisPoint2); + Radius = symmetryAxisPoint1.GetDistanceTo(symmetryAxisPoint2) * 0.5; + } + } + + /// + /// 填充转换器的数据 + /// + class HatchConverterData + { + public readonly List PolyLineData; + public readonly List CircleConverterData; + public readonly List SplineData; + + /// + /// 填充转换器的数据 + /// + public HatchConverterData() + { + PolyLineData = new(); + CircleConverterData = new(); + SplineData = new(); + } + } + + #endregion + + #region 成员 + + /// + /// 外部只能调用id,否则跨事务造成错误 + /// + public ObjectId OldHatchId + { + get + { + if (_oldHatch is null) + return ObjectId.Null; + return _oldHatch.ObjectId; + } + } + + readonly Hatch? _oldHatch; + + readonly List _hcDatas; + + /// + /// 填充边界id(生成的/已存在反应器的直接提取) + /// + public readonly List BoundaryIds; + + #endregion + + #region 构造 + + /// + /// 填充边界转换器 + /// + HatchConverter() + { + _hcDatas = new(); + BoundaryIds = new(); + } + + /// + /// 填充边界转换器 + /// + /// 需要转化的Hatch对象 + public HatchConverter(Hatch hatch) : this() + { + _oldHatch = hatch; + + if (hatch.Associative) + { + // 填充边界反应器 + var assIds = hatch.GetAssociatedObjectIds(); + if (assIds != null) + { + foreach (ObjectId id in assIds) + if (id.IsOk()) + BoundaryIds.Add(id); + + if (BoundaryIds.Count == 0) + { + throw new ArgumentException("关联的填充边界被删除后没有清理反应器,请调用:" + + "\n hatch.RemoveAssociatedObjectIds()" + + "\n hatch.Associative = false"); + } + } + } + } + + /// + /// 提取边界信息 + /// + public void GetBoundarysData() + { + _oldHatch?.ForEach(loop => + { + HatchConverterData hcData = new(); + + var isCurve2d = true; + if (loop.IsPolyline) + { + // 边界是多段线 + HatchLoopIsPolyline(loop, hcData); + isCurve2d = false; + } + else + { + if (loop.Curves.Count == 2) // 1是不可能的,大于2的是曲线 + { + // 边界是曲线,过滤可能是圆形的情况 + var cir = TwoArcFormOneCircle(loop); + if (cir is not null) + { + hcData.CircleConverterData.Add(cir); + isCurve2d = false; + } + } + } + + // 边界是曲线 + if (isCurve2d) + HatchLoopIsCurve2d(loop, hcData); + + _hcDatas.Add(hcData); + }); + } + + #endregion + + #region 方法 + + /// + /// 多段线处理 + /// + /// 填充边界 + /// 收集图元信息 + static void HatchLoopIsPolyline(HatchLoop loop, HatchConverterData hcData) + { + //if (loop is null) + // throw new ArgumentNullException(nameof(loop)); + + //if (hcData is null) + // throw new ArgumentNullException(nameof(hcData)); + + ArgumentNullEx.ThrowIfNull(loop); + ArgumentNullEx.ThrowIfNull(hcData); + + + // 判断为圆形: + // 上下两个圆弧,然后填充,就会生成此种填充 + // 顶点数是3,凸度是半圆,两个半圆就是一个圆形 + if (loop.Polyline.Count == 3 && loop.Polyline[0].Bulge == 1 && loop.Polyline[1].Bulge == 1 || + loop.Polyline.Count == 3 && loop.Polyline[0].Bulge == -1 && loop.Polyline[1].Bulge == -1) + { + hcData.CircleConverterData.Add(new CircleData(loop.Polyline[0].Vertex, loop.Polyline[1].Vertex)); + } + else + { + // 遍历多段线信息 + var bvc = loop.Polyline; + for (var i = 0; i < bvc.Count; i++) + hcData.PolyLineData.Add(new BulgeVertexWidth(bvc[i])); + } + } + + /// + /// 两个圆弧组成圆形 + /// + /// + /// + static CircleData? TwoArcFormOneCircle(HatchLoop loop) + { + //if (loop is null) + // throw new ArgumentNullException(nameof(loop)); + + ArgumentNullEx.ThrowIfNull(loop); + + if (loop.Curves.Count != 2) + throw new ArgumentException("边界非多段线,而且点数!=2,点数为:" + nameof(loop.Curves.Count) + + ";两个矩形交集的时候会出现此情况."); + + CircleData? circular = null; + + // 判断为圆形: + // 用一条(不是两条)多段线画出两条圆弧为正圆,就会生成此种填充 + // 边界为曲线,数量为2,可能是两个半圆曲线,如果是,就加入圆形数据中 + + // 第一段 + var getCurves1Pts = loop.Curves[0].GetSamplePoints(3); // 曲线取样点分两份(3点) + var mid1Pt = getCurves1Pts[1]; // 腰点 + var bulge1 = loop.Curves[0].StartPoint.GetArcBulge(mid1Pt, loop.Curves[0].EndPoint); + + // 第二段 + var getCurves2Pts = loop.Curves[1].GetSamplePoints(3); + var mid2Pt = getCurves2Pts[1]; + var bulge2 = loop.Curves[1].StartPoint.GetArcBulge(mid2Pt, loop.Curves[1].EndPoint); + + // 第一段上弧&&第二段反弧 || 第一段反弧&&第二段上弧 + if (bulge1 == -1 && bulge2 == -1 || bulge1 == 1 && bulge2 == 1) + circular = new CircleData(loop.Curves[0].StartPoint, loop.Curves[1].StartPoint); // 两个起点就是对称点 + + return circular; + } + + /// + /// 处理边界曲线 + /// + /// 填充边界 + /// 收集图元信息 + static void HatchLoopIsCurve2d(HatchLoop loop, HatchConverterData hcData) + { + // 取每一段曲线,曲线可能是直线来的,但是圆弧会按照顶点来分段 + var curveIsClosed = 0; + + // 遍历边界的多个子段 + foreach (Curve2d curve in loop.Curves) + { + // 计数用于实现闭合 + curveIsClosed++; + if (curve is NurbCurve2d spl) + { + // 判断为样条曲线: + hcData.SplineData.Add(spl); + continue; + } + + var pts = curve.GetSamplePoints(3); + var midPt = pts[1]; + if (curve.StartPoint.IsEqualTo(curve.EndPoint, new Tolerance(1e-6, 1e-6))) // 首尾相同,就是圆形 + { + // 判断为圆形: + // 获取起点,然后采样三点,中间就是对称点(直径点) + hcData.CircleConverterData.Add(new CircleData(curve.StartPoint, midPt)); + continue; + } + + // 判断为多段线,圆弧: + var bulge = curve.StartPoint.GetArcBulge(midPt, curve.EndPoint); + hcData.PolyLineData.Add(new BulgeVertexWidth(curve.StartPoint, bulge)); + + // 末尾点,不闭合的情况下就要获取这个 + if (curveIsClosed == loop.Curves.Count) + hcData.PolyLineData.Add(new BulgeVertexWidth(curve.EndPoint)); + } + } + + /// + /// 创建边界图元 + /// + /// 返回图元 + [Obsolete("使用带返回值的CreateBoundary替代")] + public void CreateBoundary(List outEnts) + { + for (var i = 0; i < _hcDatas.Count; i++) + { + var data = _hcDatas[i]; + + // 生成边界:多段线 + if (data.PolyLineData.Count > 0) + { + Polyline pl = new(); + pl.SetDatabaseDefaults(); + for (var j = 0; j < data.PolyLineData.Count; j++) + { + pl.AddVertexAt(j, data.PolyLineData[j].Vertex, data.PolyLineData[j].Bulge, + data.PolyLineData[j].StartWidth, data.PolyLineData[j].EndWidth); + } + + outEnts.Add(pl); + } + + // 生成边界:圆 + data.CircleConverterData.ForEach(item => + { + outEnts.Add(new Circle(item.Center.Point3d(), Vector3d.ZAxis, item.Radius)); + }); + + // 生成边界:样条曲线 + data.SplineData.ForEach(item => { outEnts.Add(item.ToCurve()); }); + } + + if (_oldHatch is not null) + { + outEnts.ForEach(ent => + { + ent.Color = _oldHatch.Color; + ent.Layer = _oldHatch.Layer; + }); + } + } + + /// + /// 创建边界 + /// + /// + public List CreateBoundary() + { + var outEnts = new List(); + for (var i = 0; i < _hcDatas.Count; i++) + { + var data = _hcDatas[i]; + + // 生成边界:多段线 + if (data.PolyLineData.Count > 0) + { + Polyline pl = new(); + pl.SetDatabaseDefaults(); + for (var j = 0; j < data.PolyLineData.Count; j++) + { + pl.AddVertexAt(j, data.PolyLineData[j].Vertex, data.PolyLineData[j].Bulge, + data.PolyLineData[j].StartWidth, data.PolyLineData[j].EndWidth); + } + + outEnts.Add(pl); + } + + // 生成边界:圆 + data.CircleConverterData.ForEach(item => + { + outEnts.Add(new Circle(item.Center.Point3d(), Vector3d.ZAxis, item.Radius)); + }); + + // 生成边界:样条曲线 + data.SplineData.ForEach(item => { outEnts.Add(item.ToCurve()); }); + } + + if (_oldHatch is not null) + { + outEnts.ForEach(ent => + { + ent.Color = _oldHatch.Color; + ent.Layer = _oldHatch.Layer; + }); + } + + return outEnts; + } + + /// + /// 创建边界图元和新填充到当前空间 + /// + /// + /// 边界关联 + /// 是否创建填充,false则只创建边界 + /// 新填充id,边界在获取 + public ObjectId CreateBoundarysAndHatchToMsPs(BlockTableRecord btrOfAddEntitySpace, + bool boundaryAssociative = true, bool createHatchFlag = true) + { + var boEnts = CreateBoundary(); + boEnts.ForEach(ent => { BoundaryIds.Add(btrOfAddEntitySpace.AddEntity(ent)); }); + + if (!createHatchFlag) + return ObjectId.Null; + /* + * 此处为什么要克隆填充,而不是新建填充? + * 因为填充如果是新建的,那么将会丢失基点,概念如下: + * 两个一样的填充,平移其中一个,那么再提取他们的基点会是一样的! + * 所以生成时候就不等同于画面相同. + * 也因为我不知道什么新建方式可以新建一模一样的填充,因此使用了克隆 + * 那么它的平移后的基点在哪里呢? + */ + + using ObjectIdCollection idc = new(new ObjectId[] { OldHatchId }); + using IdMapping map = new(); + btrOfAddEntitySpace.DeepCloneEx(idc, map); + var newHatchId = map.GetValues()[0]; + var tr = DBTrans.GetTopTransaction(btrOfAddEntitySpace.Database); + + var openErased = false; + var openLockedLayer = false; + var hatchEnt = tr.GetObject(newHatchId, OpenMode.ForWrite, openErased, openLockedLayer); + if (hatchEnt != null) + { + ResetBoundary(hatchEnt, boundaryAssociative); + hatchEnt.DowngradeOpen(); + } + + return newHatchId; + } + + /// + /// 重设边界 + /// + /// + /// 边界关联 + void ResetBoundary(Hatch hatch, bool boundaryAssociative = true) + { + if (BoundaryIds.Count == 0) + return; + + // todo ------ acad08分离填充报错: Microsoft Visual Studio C 运行库在 acad.exe 中检测到一个错误 + // 0x01 测试命令 CmdTest_CreateHatch 创建是可以分离的, + // 那么可能是 克隆后 修改导致的, + // 我是克隆了之后移除原有边界,为了一些xdata之类的 + // 0x02 测试了 hatch.SetDatabaseDefaults(); 并不是因为这个 + // 0x03 测试了 v1110 不移除原有边界,而是加入了之后再移除旧的边界,也是一样 + // 要处理这个问题,我想:自己实现一个分离填充,不用cad自带的,然后单独填充每个. + // 填充边界的算法是扫描线算法.这样就可以绕过去了...发现过于麻烦,放弃... + + // v1110 删除原有边界 + while (hatch.NumberOfLoops != 0) + hatch.RemoveLoopAt(0); + + hatch.Associative = boundaryAssociative; + + using ObjectIdCollection obIds = new(); + for (var i = 0; i < BoundaryIds.Count; i++) + { + obIds.Clear(); + obIds.Add(BoundaryIds[i]); + // 要先添加最外面的边界 + hatch.AppendLoop(i == 0 ? HatchLoopTypes.Outermost : HatchLoopTypes.Default, obIds); + } + + // 计算填充并显示 + hatch.EvaluateHatch(true); + } + + #endregion +} \ No newline at end of file diff --git a/CADShared/ExtensionMethod/Hatch/HatchEx.cs b/CADShared/ExtensionMethod/Hatch/HatchEx.cs new file mode 100644 index 0000000..5e8311e --- /dev/null +++ b/CADShared/ExtensionMethod/Hatch/HatchEx.cs @@ -0,0 +1,365 @@ +// ReSharper disable CompareOfFloatsByEqualityOperator + +namespace IFoxCAD.Cad; + +/// +/// 充填扩展类 +/// +public static class HatchEx +{ + /// + /// 遍历填充每条边 + /// + /// + /// + public static void ForEach(this Hatch hatch, Action action) + { + for (var i = 0; i < hatch.NumberOfLoops; i++) + action.Invoke(hatch.GetLoopAt(i)); + } + + /// + /// 提取已存在的关联边界(一个边界环里所有的对象 id 组成一个 ObjectIdCollection) + /// + /// + /// + /// + public static List? GetAssociatedBoundaryIds(this Hatch hatch) + { + // if (!hatch.Id.IsOk()) + // throw new ArgumentException("填充未加入或不存在于数据库"); + + if (!hatch.Associative) + return null; + + var listObjIdColl = new List(); + + for (var i = 0; i < hatch.NumberOfLoops; i++) + { + var assIds = hatch.GetAssociatedObjectIdsAt(i); + if (assIds != null) + { + var objIds = new ObjectIdCollection(); + foreach (ObjectId id in assIds) + { + if (id.IsOk()) + objIds.Add(id); + } + + if (objIds.Count == 0) + { + throw new ArgumentException("关联的填充边界被删除后没有清理反应器,请调用:" + + "\n hatch.RemoveAssociatedObjectIds()" + + "\n hatch.Associative = false"); + } + + listObjIdColl.Add(objIds); + } + } + + return listObjIdColl; + } + + /// + /// 创建边界(仅创建于内存中,未加入数据库) + /// + /// + /// 边界环列表(一个边界环里所有的对象组成一个 DBObjectCollection) + public static List CreateBoundarys(this Hatch hatch) + { + // if (!hatch.Id.IsOk()) + // throw new ArgumentException("填充未加入或不存在于数据库"); + + var listDbObjColl = new List(); + + for (var i = 0; i < hatch.NumberOfLoops; i++) + { + var objColl = new DBObjectCollection(); + var loop = hatch.GetLoopAt(i); + var isCurve2d = true; + + if (loop.IsPolyline) + { + // 边界是多段线 + HatchLoopIsPolyline(loop, objColl); + isCurve2d = false; + } + else + { + // 1是不可能的,大于2的是曲线; + if (loop.Curves.Count == 2) + { + // 边界是曲线,过滤可能是圆形的情况 + var circle = TwoArcFormOneCircle(loop, objColl); + if (circle is not null) + { + objColl.Add(circle); + isCurve2d = false; + } + } + } + + // 边界是曲线 + if (isCurve2d) + HatchLoopIsCurve2d(loop, objColl); + + listDbObjColl.Add(objColl); + } + + return listDbObjColl; + } + + /// + /// 重新设置边界并计算 + /// + /// + /// 边界对象(一个边界环里所有的对象 id 组成一个 ObjectIdCollection) + ///
    边界必需是封闭的环, 可以是一条线围合而成也可以是多条线首尾相连围合而成
    + ///
    多个外边界的时候, 建议顺序为(外边界,外边界,外边界,普通边界....), 或(外边界, 普通边界.....外边界, 普通边界....)
    + /// + /// 关联边界(默认保持原样) + public static void ResetBoundarys(this Hatch hatch, List boundaryIds, + bool? associative = null) + { + // if (!hatch.Id.IsOk()) + // throw new ArgumentException("填充未加入或不存在于数据库"); + + boundaryIds.ForEach(ids => + { + foreach (ObjectId id in ids) + { + if (!id.IsOk()) + throw new ArgumentException("边界未加入或不存在于数据库"); + } + }); + + using (hatch.ForWrite()) + { + while (hatch.NumberOfLoops > 0) + hatch.RemoveLoopAt(0); + + if (associative != null) + hatch.Associative = associative == true; + + var isOutermost = true; + + boundaryIds.ForEach(ids => + { + try + { + // 要先添加最外面的边界 + if (isOutermost) + { + isOutermost = false; + hatch.AppendLoop(HatchLoopTypes.Outermost, ids); + } + else + { + // HatchLoopTypes.External 比 HatchLoopTypes.Default 似乎更不容易出问题 + hatch.AppendLoop(HatchLoopTypes.External, ids); + } + } + catch (Exception ex) + { + Env.Editor.WriteMessage(Environment.NewLine + "发生错误,传入的边界不符合要求,请核实传入的边界是否为封闭的"); + throw new Exception(ex.Message); + } + }); + + hatch.EvaluateHatch(true); + } + } + + #region 私有方法 + + /// + /// 处理边界多段线 + /// + /// 填充边界 + /// 收集边界图元 + private static void HatchLoopIsPolyline(HatchLoop loop, DBObjectCollection objColl) + { + // 判断为圆形: + // 上下两个圆弧,然后填充,就会生成此种填充 + // 顶点数是3,凸度是半圆,两个半圆就是一个圆形 + if (loop.Polyline.Count == 3 && loop.Polyline[0].Bulge == 1 && loop.Polyline[1].Bulge == 1 || + loop.Polyline.Count == 3 && loop.Polyline[0].Bulge == -1 && loop.Polyline[1].Bulge == -1) + { + var center = loop.Polyline[0].Vertex.GetMidPointTo(loop.Polyline[1].Vertex); + var radius = loop.Polyline[0].Vertex.GetDistanceTo(loop.Polyline[1].Vertex) * 0.5; + var circle = new Circle(center.Point3d(), Vector3d.ZAxis, radius); + objColl.Add(circle); + } + else + { + // 遍历多段线信息 + var bvc = loop.Polyline; + var pl = new Polyline(); + pl.SetDatabaseDefaults(); + for (var j = 0; j < bvc.Count; j++) + { + var bvw = new BulgeVertexWidth(bvc[j]); + pl.AddVertexAt(j, bvw.Vertex, bvw.Bulge, bvw.StartWidth, bvw.EndWidth); + } + + objColl.Add(pl); + } + } + + /// + /// 两个圆弧组成圆形 + /// + /// 填充边界 + /// 收集边界图元 + // ReSharper disable once UnusedParameter.Local + private static Circle? TwoArcFormOneCircle(HatchLoop loop, DBObjectCollection objColl) + { + if (loop.Curves.Count != 2) + { + throw new ArgumentException("边界非多段线,而且点数!=2,点数为:" + nameof(loop.Curves.Count) + + ";两个矩形交集的时候会出现此情况."); + } + + Circle? circle = null; + + // 判断为圆形: + // 用一条(不是两条)多段线画出两条圆弧为正圆,就会生成此种填充 + // 边界为曲线,数量为2,可能是两个半圆曲线,如果是,就加入圆形数据中 + + // 第一段 + var getCurves1Pts = loop.Curves[0].GetSamplePoints(3); // 曲线取样点分两份(3点) + var mid1Pt = getCurves1Pts[1]; // 腰点 + var bulge1 = loop.Curves[0].StartPoint.GetArcBulge(mid1Pt, loop.Curves[0].EndPoint); + + // 第二段 + var getCurves2Pts = loop.Curves[1].GetSamplePoints(3); + var mid2Pt = getCurves2Pts[1]; + var bulge2 = loop.Curves[1].StartPoint.GetArcBulge(mid2Pt, loop.Curves[1].EndPoint); + + // 第一段上弧&&第二段反弧 || 第一段反弧&&第二段上弧 + if (bulge1 == -1 && bulge2 == -1 || bulge1 == 1 && bulge2 == 1) + { + var center = loop.Curves[0].StartPoint.GetMidPointTo(loop.Curves[1].StartPoint); + var radius = loop.Curves[0].StartPoint.GetDistanceTo(loop.Curves[1].StartPoint) * 0.5; + circle = new Circle(center.Point3d(), Vector3d.ZAxis, radius); + } + + return circle; + } + + /// + /// 处理边界曲线 + /// + /// 填充边界 + /// 收集边界图元 + private static void HatchLoopIsCurve2d(HatchLoop loop, DBObjectCollection objColl) + { + var pLineCount = 0; //记录多段线数量 + var curveIsClosed = 0; // 取每一段曲线,曲线可能是直线来的,但是圆弧会按照顶点来分段 + var newPl = true; // 是否开始新的多段线(一个边界中可能有多条多段线) + var firstIsPl = false; //遍历边界的第一个子段为多段线(遍历时不一定从多段线的首段开始) + List? polyLineVertexes = null; + List> polyLineData = new(); + + // 遍历边界的多个子段 + foreach (Curve2d curve in loop.Curves) + { + // 计数用于实现闭合 + curveIsClosed++; + + if (curve is CircularArc2d or LineSegment2d) + { + var pts = curve.GetSamplePoints(3); + var midPt = pts[1]; + + // 判断为多段线圆: + // 首尾相同,就是圆形 + if (curve.StartPoint.IsEqualTo(curve.EndPoint, new Tolerance(1e-6, 1e-6))) + { + // 获取起点,然后采样三点,中间就是对称点(直径点) + var center = curve.StartPoint.GetMidPointTo(midPt); + var radius = curve.StartPoint.GetDistanceTo(midPt) * 0.5; + var circle = new Circle(center.Point3d(), Vector3d.ZAxis, radius); + objColl.Add(circle); + // 添加在中部的多段线末尾点 + if (curveIsClosed > 1 && !newPl) + polyLineVertexes?.Add(new BulgeVertexWidth(curve.StartPoint)); + // 开始新的多段线 + newPl = true; + continue; + } + + if (curveIsClosed == 1) + firstIsPl = true; + + if (newPl) + { + polyLineVertexes = new(); + polyLineData.Add(polyLineVertexes); + newPl = false; + pLineCount++; + } + + // 判断为多段线,圆弧或直线: + var bulge = curve.StartPoint.GetArcBulge(midPt, curve.EndPoint); + polyLineVertexes?.Add(new BulgeVertexWidth(curve.StartPoint, bulge)); + + // 末尾点,不闭合的情况下就要获取这个 + if (curveIsClosed == loop.Curves.Count) + { + if (firstIsPl && pLineCount > 1) + { + // 连接首尾多段线 + polyLineData[0].ForEach(bvw => polyLineData[^1].Add(bvw)); + polyLineData.RemoveAt(0); + } + else + polyLineVertexes?.Add(new BulgeVertexWidth(curve.EndPoint)); + } + + continue; + } + + // 判断为样条曲线: + if (curve is NurbCurve2d spl) + objColl.Add(spl.ToCurve()); + + // 判断为椭圆: + if (curve is EllipticalArc2d eArc2d) + { + var startParam = eArc2d.IsClockWise ? -eArc2d.EndAngle : eArc2d.StartAngle; + var endParam = eArc2d.IsClockWise ? -eArc2d.StartAngle : eArc2d.EndAngle; + var ellipse = new Ellipse(eArc2d.Center.Point3d(), Vector3d.ZAxis, + eArc2d.MajorAxis.Convert3d() * eArc2d.MajorRadius, + eArc2d.MinorRadius / eArc2d.MajorRadius, + Math.Atan2(Math.Sin(startParam) * eArc2d.MinorRadius, + Math.Cos(startParam) * eArc2d.MajorRadius), + Math.Atan2(Math.Sin(endParam) * eArc2d.MinorRadius, + Math.Cos(endParam) * eArc2d.MajorRadius)); + objColl.Add(ellipse); + } + + // 添加在中部的多段线末尾点 + if (curveIsClosed > 1 && !newPl) + polyLineVertexes?.Add(new BulgeVertexWidth(curve.StartPoint)); + // 开始新的多段线 + newPl = true; + } + + // 生成多段线 + polyLineData.ForEach(list => + { + if (list.Count == 0) return; + var pl = new Polyline(); + pl.SetDatabaseDefaults(); + for (var j = 0; j < list.Count; j++) + { + pl.AddVertexAt(j, list[j].Vertex, list[j].Bulge, list[j].StartWidth, list[j].EndWidth); + } + + objColl.Add(pl); + }); + } + + #endregion +} \ No newline at end of file diff --git a/CADShared/ExtensionMethod/Hatch/HatchInfo.cs b/CADShared/ExtensionMethod/Hatch/HatchInfo.cs new file mode 100644 index 0000000..d87d317 --- /dev/null +++ b/CADShared/ExtensionMethod/Hatch/HatchInfo.cs @@ -0,0 +1,354 @@ + + +namespace IFoxCAD.Cad; + +/* + * 添加的第一个边界必须是外边界,即用于定义图案填充最外面的边界。 + * 要添加外部边界,请使用添加环的类型为 HatchLoopTypes.Outermost 常量的 AppendLoop 方法, + * 一旦外边界被定义,就可以继续添加另外的边界。 + * 添加内部边界请使用带 HatchLoopTypes.Default 常量的 AppendLoop 方法。 + * + * 多个外边界的时候,添加的是(外边界,外边界,外边界,普通边界....) + * 多个外边界的时候,添加的是(外边界,普通边界.....外边界,普通边界....) + */ + +/// +/// 图案填充 +/// +public class HatchInfo +{ + #region 成员 + /// + /// 边界id(最外面放第一) + /// + readonly List _boundaryIds; + /// + /// 填充图元 + /// + readonly Hatch _hatch; + /// + /// 边界关联(此处不能直接=>给填充成员,因为它会加入反应器) + /// + readonly bool _boundaryAssociative; + /// + /// 填充的名称:用户定义(固定名称)/渐变/填充依据定义文件 + /// + string? _hatchName; + /// + /// 填充模式类型(预定义/用户定义/自定义) + /// + HatchPatternType _patternTypeHatch; + /// + /// 渐变模式类型 + /// + GradientPatternType _patternTypeGradient; + /// + /// 比例/间距 + /// + double Scale => _hatch.PatternScale; + /// + /// 角度 + /// + double Angle => _hatch.PatternAngle; + + // 延后处理角度 + private double _angle; + #endregion + + #region 构造 + HatchInfo() + { + _hatch = new Hatch(); + _hatch.SetDatabaseDefaults(); + _boundaryIds = new(); + } + + /// + /// 图案填充 + /// + /// 关联边界 + /// 填充原点 + /// 比例 + /// 角度 + public HatchInfo(bool boundaryAssociative = true, + Point2d? hatchOrigin = null, + double hatchScale = 1, + double hatchAngle = 0) : this() + { + if (hatchScale <= 0) + throw new ArgumentException("填充比例不允许小于等于0"); + + _hatch.PatternScale = hatchScale;// 填充比例 + _angle = hatchAngle;// 填充角度 + _boundaryAssociative = boundaryAssociative; + + hatchOrigin ??= Point2d.Origin; + _hatch.Origin = hatchOrigin.Value; // 填充原点 + } + + /// + /// 图案填充 + /// + /// 边界 + /// 关联边界 + /// 填充原点 + /// 比例 + /// 角度 + public HatchInfo(IEnumerable boundaryIds, + bool boundaryAssociative = true, + Point2d? hatchOrigin = null, + double hatchScale = 1, + double hatchAngle = 0) + : this(boundaryAssociative, hatchOrigin, hatchScale, hatchAngle) + { + _boundaryIds.AddRange(boundaryIds); + } + + #endregion + + #region 方法 + /// + /// 模式1:预定义 + /// + public HatchInfo Mode1PreDefined(string name) + { + _hatchName = name; + _hatch.HatchObjectType = HatchObjectType.HatchObject; // 对象类型(填充/渐变) + _patternTypeHatch = HatchPatternType.PreDefined; + return this; + } + + /// + /// 模式2:用户定义 + /// + /// 是否双向 + public HatchInfo Mode2UserDefined(bool patternDouble = true) + { + _hatchName = "_USER"; + _hatch.HatchObjectType = HatchObjectType.HatchObject; // 对象类型(填充/渐变) + _patternTypeHatch = HatchPatternType.UserDefined; + + _hatch.PatternDouble = patternDouble; // 是否双向(必须写在 SetHatchPattern 之前) + _hatch.PatternSpace = Scale; // 间距(必须写在 SetHatchPattern 之前) + return this; + } + + /// + /// 模式3:自定义 + /// + /// + public HatchInfo Mode3UserDefined(string name) + { + _hatchName = name; + _hatch.HatchObjectType = HatchObjectType.HatchObject; // 对象类型(填充/渐变) + _patternTypeHatch = HatchPatternType.CustomDefined; + return this; + } + + /// + /// 模式4:渐变填充 + /// + /// 渐变填充名称 + /// 渐变色起始颜色 + /// 渐变色结束颜色 + /// 渐变移动 + /// 色调值 + /// 单色双色 + public HatchInfo Mode4Gradient(GradientName name, Color colorStart, Color colorEnd, + float gradientShift = 0, + float shadeTintValue = 0, + bool gradientOneColorMode = false) + { + // entget渐变的名字必然是"SOLID",但是这里作为"渐变"名,而不是"填充"名 + _hatchName = name.ToString(); + _hatch.HatchObjectType = HatchObjectType.GradientObject; // 对象类型(填充/渐变) + _patternTypeGradient = GradientPatternType.PreDefinedGradient;// 模式4:渐变 + // _patternTypeGradient = GradientPatternType.UserDefinedGradient;// 模式5:渐变..这种模式干啥用呢 + + // 设置渐变色填充的起始和结束颜色 + var gColor1 = new GradientColor(colorStart, 0); + var gColor2 = new GradientColor(colorEnd, 1); + _hatch.SetGradientColors(new GradientColor[] { gColor1, gColor2 }); + + _hatch.GradientShift = gradientShift; // 梯度位移 + _hatch.ShadeTintValue = shadeTintValue; // 阴影色值 + _hatch.GradientOneColorMode = gradientOneColorMode;// 渐变单色/双色 + _hatch.GradientAngle = Angle; // 渐变角度 + + return this; + } + + /// + /// 构建 + /// + /// 将填充加入此空间 + public ObjectId Build(BlockTableRecord btrOfAddEntitySpace) + { + // 加入数据库 + var hatchId = btrOfAddEntitySpace.AddEntity(_hatch); + + // 设置模式:渐变/填充 + if (_hatch.HatchObjectType == HatchObjectType.GradientObject) + _hatch.SetGradient(_patternTypeGradient, _hatchName); + else + _hatch.SetHatchPattern(_patternTypeHatch, _hatchName); + + // 处理充填角度 + _hatch.PatternAngle = _angle; + + + // 关联边界,如果不先添加数据库空间内就会出错 + // 为 true 会加入反应器,因此比较慢(二维码将会十几秒才生成好),视需求而定. + _hatch.Associative = _boundaryAssociative; + + // 利用 AppendLoop 重载加入,这里就不处理 + if (_boundaryIds.Count > 0) + AppendLoop(_boundaryIds, HatchLoopTypes.Default); + + // 计算填充并显示(若边界出错,这句会异常) + _hatch.EvaluateHatch(true); + + return hatchId; + } + + /// + /// 执行图元的属性修改 + /// + /// 扔出填充实体 + public HatchInfo Action(Action action) + { + action(_hatch); + return this; + } + + /// + /// 清空边界集合 + /// + public HatchInfo ClearBoundary() + { + _boundaryIds.Clear(); + return this; + } + + /// + /// 删除边界图元 + /// + public HatchInfo EraseBoundary() + { + for (var i = 0; i < _boundaryIds.Count; i++) + _boundaryIds[i].Erase(); + return this; + } + + /// + /// 加入边界 + /// + /// 边界id + /// 加入方式 + void AppendLoop(IEnumerable boundaryIds, + HatchLoopTypes hatchLoopTypes = HatchLoopTypes.Default) + { + ObjectIdCollection obIds = new(); + // 边界是闭合的,而且已经加入数据库 + // 填充闭合环类型.最外面 + + // 此段代码会出错的原因在于 如果是直线围成的闭合区域, + // 那么每次添加的其实一条直线,而直线不构成loop,所以不符合预期的数据,出错 + try + { + foreach (var border in boundaryIds) + { + obIds.Clear(); + obIds.Add(border); + _hatch.AppendLoop(hatchLoopTypes, obIds); + } // 此段代码会出错 + } + catch (Exception ex) + { + + Env.Print(ex.Message); + Env.Print("发生错误,传入的边界不符合要求,请核实传入的边界是否为闭合边界列表,而不是组成边界的图元列表"); + throw; + } + + // 下面这行代码出错的原因是: 添加了重复的线条,需要进行剔除 + // _hatch.AppendLoop(hatchLoopTypes, boundaryIds.ToCollection()); + + // 这个函数还需要进行改造: + // 1. 明确传入的 boundaryIds 到底是多个边界,还是一个边界的子图元 + // 2. 根据传入的参数的不同 需要不同的处理措施 + // 3. 临时性措施 try一下抛异常,让用户确保传入的参数是准确的 + + } + + /// + /// 加入边界(仿高版本的填充函数) + /// + /// 点集 + /// 凸度集 + /// 加入此空间 + /// 加入方式 + /// + public HatchInfo AppendLoop(Point2dCollection pts, + DoubleCollection bluges, + BlockTableRecord btrOfAddEntitySpace, + HatchLoopTypes hatchLoopTypes = HatchLoopTypes.Default) + { + //if (pts == null) + // throw new ArgumentNullException(nameof(pts)); + ArgumentNullEx.ThrowIfNull(pts); + pts.End2End(); + // 2011新增API,可以不生成图元的情况下加入边界, + // 通过这里进入的话,边界 _boundaryIds 是空的,那么 Build() 时候就需要过滤空的 + _hatch.AppendLoop(hatchLoopTypes, pts, bluges); + return this; + } + + + #endregion + + #region 枚举 + /// + /// 渐变色填充的图案名称 + /// + public enum GradientName + { + /// + /// 线状渐变 + /// + Linear, + /// + /// 圆柱状渐变 + /// + Cylinder, + /// + /// 反圆柱状渐变 + /// + Invcylinder, + /// + /// 球状渐变 + /// + Spherical, + /// + /// 反球状渐变 + /// + Invspherical, + /// + /// 半球状渐变 + /// + Hemisperical, + /// + /// 反半球状渐变 + /// + InvHemisperical, + /// + /// 抛物面状渐变 + /// + Curved, + /// + /// 反抛物面状渐变 + /// + Incurved + } + #endregion +} \ No newline at end of file diff --git a/CADShared/ExtensionMethod/SingleKeyWordHook.cs b/CADShared/ExtensionMethod/SingleKeyWordHook.cs index d231e51..8616c37 100644 --- a/CADShared/ExtensionMethod/SingleKeyWordHook.cs +++ b/CADShared/ExtensionMethod/SingleKeyWordHook.cs @@ -135,7 +135,7 @@ private void Acap_PreTranslateMessage(object sender, PreTranslateMessageEventArg { if (!_working || e.Message.message != 256) return; var tempKey = IntPtr.Size == 4 ? (Keys)e.Message.wParam.ToInt32() : (Keys)e.Message.wParam.ToInt64(); - bool contains = _keyWords.Contains(tempKey); + var contains = _keyWords.Contains(tempKey); if (contains) { // 标记为true,表示此按键已经被处理,Windows不会再进行处理 diff --git a/CADShared/ExtensionMethod/SymbolTableEx.cs b/CADShared/ExtensionMethod/SymbolTableEx.cs index d059161..867c9be 100644 --- a/CADShared/ExtensionMethod/SymbolTableEx.cs +++ b/CADShared/ExtensionMethod/SymbolTableEx.cs @@ -257,7 +257,7 @@ public static ObjectId Add(this SymbolTable ltt.AsciiDescription = description; ltt.PatternLength = length; // 线型的总长度 ltt.NumDashes = dash.Length; // 组成线型的笔画数目 - for (int i = 0; i < dash.Length; i++) + for (var i = 0; i < dash.Length; i++) { ltt.SetDashLengthAt(i, dash[i]); } diff --git a/CADShared/ExtensionMethod/SymbolTableRecordEx.cs b/CADShared/ExtensionMethod/SymbolTableRecordEx.cs index 43b8043..4f37358 100644 --- a/CADShared/ExtensionMethod/SymbolTableRecordEx.cs +++ b/CADShared/ExtensionMethod/SymbolTableRecordEx.cs @@ -171,7 +171,7 @@ public static IEnumerable GetEntities(this BlockTableRecord btr, /// 实体Id集合 public static IEnumerable GetObjectIds(this BlockTableRecord btr) where T : Entity { - string dxfName = RXClass.GetClass(typeof(T)).DxfName; + var dxfName = RXClass.GetClass(typeof(T)).DxfName; return btr.Cast() .Where(id => id.ObjectClass.DxfName == dxfName); } @@ -284,7 +284,7 @@ public static ObjectId InsertBlock(this BlockTableRecord blockTableRecord, attref.SetDatabaseDefaults(); attref.SetAttributeFromBlock(attdef, blockRef.BlockTransform); attref.Position = attdef.Position.TransformBy(blockRef.BlockTransform); - if (atts is not null && atts.TryGetValue(attdef.Tag, out string str)) + if (atts is not null && atts.TryGetValue(attdef.Tag, out var str)) { attref.TextString = str; } @@ -348,7 +348,7 @@ public static void ForEach(this TRecord record, Action action) _tr.Database.ResolveXrefs(UseThreadEngine, DoNewOnly); var xg = _tr.Database.GetHostDwgXrefGraph(IncludeGhosts); - for (int i = 0; i < xg.NumNodes; i++) + for (var i = 0; i < xg.NumNodes; i++) { var xNode = xg.GetXrefNode(i); if (!xNode.BlockTableRecordId.IsOk()) @@ -330,7 +330,7 @@ private void DoubleBind() // 拆离:未参照的文件 if (AutoDetach) { - for (int i = 0; i < detachIds.Count; i++) + for (var i = 0; i < detachIds.Count; i++) _tr.Database.DetachXref(detachIds[i]); } @@ -576,10 +576,10 @@ private static string GetRelativePath(string directory, string file) string[] directories = directory.Split('\\'); string[] files = file.Split('\\'); // 获取两条路径中的最短路径 - int getMinLength = directories.Length < files.Length ? directories.Length : files.Length; + var getMinLength = directories.Length < files.Length ? directories.Length : files.Length; // 用于确定我们退出的循环中的位置。 - int lastCommonRoot = -1; + var lastCommonRoot = -1; int index; // 找到共根 for (index = 0; index < getMinLength; index++) @@ -639,9 +639,9 @@ private static string GetRelativePath(string directory, string file) // 判断向上删除几个 var slashes = relativeName.Split(slash); - int index = 0; + var index = 0; // ReSharper disable once ForCanBeConvertedToForeach - for (int i = 0; i < slashes.Length; i++) + for (var i = 0; i < slashes.Length; i++) { if (slashes[i] != "..") break; @@ -652,14 +652,14 @@ private static string GetRelativePath(string directory, string file) // 前段 var pathDwgs = directory.Split(slash); pathDwgs = pathDwgs.Where(s => !string.IsNullOrEmpty(s)).ToArray(); // 清理空数组 - for (int i = 0; i < pathDwgs.Length - index; i++) + for (var i = 0; i < pathDwgs.Length - index; i++) { result.Append(pathDwgs[i]); result.Append(slash); } // 后段 - for (int i = 0; i < slashes.Length; i++) + for (var i = 0; i < slashes.Length; i++) { var item = slashes[i]; if (item != "." && item != "..") diff --git a/CADShared/Initialize/AcadEMR.cs b/CADShared/Initialize/AcadEMR.cs index c4db286..889b99a 100644 --- a/CADShared/Initialize/AcadEMR.cs +++ b/CADShared/Initialize/AcadEMR.cs @@ -65,7 +65,7 @@ public static void Remove(bool echoes = false) return; } - string funcName = Encoding.Unicode.GetString(new byte[] { 63 }); + var funcName = Encoding.Unicode.GetString(new byte[] { 63 }); if (IntPtr.Size == 4) funcName += "isEMR@AcDbDatabase@@QBE_NXZ"; else diff --git a/CADShared/PE/AcadPeInfo.cs b/CADShared/PE/AcadPeInfo.cs index df72756..0b3fa58 100644 --- a/CADShared/PE/AcadPeInfo.cs +++ b/CADShared/PE/AcadPeInfo.cs @@ -262,7 +262,7 @@ public string? CName if (_CName is null && MethodName is not null) { _CName = MethodName.Replace("?", string.Empty); // 剔除cpp前缀 - int num = _CName.IndexOf("@"); + var num = _CName.IndexOf("@"); if (num > -1) _CName = _CName.Substring(0, num); // 剔除参数部分 } diff --git a/CADShared/PE/PostCmd.cs b/CADShared/PE/PostCmd.cs index 7e70074..4882b6d 100644 --- a/CADShared/PE/PostCmd.cs +++ b/CADShared/PE/PostCmd.cs @@ -32,7 +32,7 @@ static PromptStatus AcedCmd(ResultBuffer args) return 0; if (acedCmd is null) { - string str = nameof(acedCmd); + var str = nameof(acedCmd); if (Acap.Version.Major >= 20)// 2015.+ str += "S"; @@ -83,7 +83,7 @@ static PromptStatus AcedPostCommand(string args) nameof(acedPostCommand), AcadPeEnum.ExeAndCore); // 不然到CAD之后会乱码 - byte[] bytes = Encoding.Unicode.GetBytes(args); + var bytes = Encoding.Unicode.GetBytes(args); if (acedPostCommand is null) return PromptStatus.Error; return (PromptStatus)acedPostCommand.Invoke(bytes);// 调用方法 @@ -100,7 +100,7 @@ static PromptStatus AcedInvoke(string args) nameof(acedInvoke), AcadPeEnum.ExeAndCore); // 不然到CAD之后会乱码 - byte[] bytes = Encoding.Unicode.GetBytes(args); + var bytes = Encoding.Unicode.GetBytes(args); if (acedInvoke is null) return PromptStatus.Error; @@ -185,7 +185,7 @@ public static PromptStatus SendCommand(IntPtr args) /// public static PromptStatus SendCommand(string args, RunCmdFlag flag) { - PromptStatus ret = PromptStatus.OK; + var ret = PromptStatus.OK; if (!Acap.DocumentManager.IsApplicationContext) { if ((flag & RunCmdFlag.AcedCmd) == RunCmdFlag.AcedCmd) diff --git a/CADShared/PE/ProgramPE.cs b/CADShared/PE/ProgramPE.cs index 32208fc..831f94d 100644 --- a/CADShared/PE/ProgramPE.cs +++ b/CADShared/PE/ProgramPE.cs @@ -86,7 +86,7 @@ public class PeInfo public PeInfo(string fullName) { if (fullName is null) - throw new ArgumentException(nameof(fullName)); ; + throw new ArgumentException(nameof(fullName)); FullName = fullName; FileStream? file = null; @@ -165,7 +165,7 @@ private void LoadDosStub() if (DosHeader is null) return; - long Size = GetLong(DosHeader.e_PESTAR) - _PEFileIndex; // 获得SUB的大小 + var Size = GetLong(DosHeader.e_PESTAR) - _PEFileIndex; // 获得SUB的大小 DosStub = new DosStub(Size) { FileStarIndex = _PEFileIndex @@ -257,8 +257,8 @@ private void LoadOptionalDirAttrib() FileStarIndex = _PEFileIndex }; - long DirCount = GetLong(OptionalHeader.NumberOfRvaAndSizes);// 这里导致无法使用64位 - for (int i = 0; i != DirCount; i++) + var DirCount = GetLong(OptionalHeader.NumberOfRvaAndSizes);// 这里导致无法使用64位 + for (var i = 0; i != DirCount; i++) { OptionalDirAttrib.DirAttrib? directAttrib = new(); Loadbyte(ref directAttrib.DirRva); @@ -277,7 +277,7 @@ private void LoadSectionTable() return; SectionTable = new SectionTable(); - long Count = GetLong(PEHeader.NumberOfSections); + var Count = GetLong(PEHeader.NumberOfSections); SectionTable.FileStarIndex = _PEFileIndex; for (long i = 0; i != Count; i++) { @@ -312,19 +312,19 @@ private void LoadExportDirectory() GetLong(exporRVA.DirRva) == 0) return; - long exporAddress = GetLong(exporRVA.DirRva); // 获取的位置 + var exporAddress = GetLong(exporRVA.DirRva); // 获取的位置 ExportDirectory = new ExportDirectory(); if (SectionTable is null) return; - for (int i = 0; i != SectionTable.Section.Count; i++) // 循环节表 + for (var i = 0; i != SectionTable.Section.Count; i++) // 循环节表 { if (SectionTable.Section[i] is not SectionTable.SectionData sect) continue; - long starRva = GetLong(sect.SizeOfRawDataRVA); - long endRva = GetLong(sect.SizeOfRawDataSize); + var starRva = GetLong(sect.SizeOfRawDataRVA); + var endRva = GetLong(sect.SizeOfRawDataSize); if (exporAddress >= starRva && exporAddress < starRva + endRva) { @@ -346,11 +346,11 @@ private void LoadExportDirectory() Loadbyte(ref ExportDirectory.AddressOfNameOrdinals); _PEFileIndex = GetLong(ExportDirectory.AddressOfFunctions) - GetLong(sect.SizeOfRawDataRVA) + GetLong(sect.PointerToRawData); - long endIndex = GetLong(ExportDirectory.AddressOfNames) - GetLong(sect.SizeOfRawDataRVA) + GetLong(sect.PointerToRawData); - long numb = (endIndex - _PEFileIndex) / 4; + var endIndex = GetLong(ExportDirectory.AddressOfNames) - GetLong(sect.SizeOfRawDataRVA) + GetLong(sect.PointerToRawData); + var numb = (endIndex - _PEFileIndex) / 4; for (long z = 0; z != numb; z++) { - byte[] Data = new byte[4]; + var Data = new byte[4]; Loadbyte(ref Data); ExportDirectory.AddressOfFunctionsList.Add(Data); } @@ -360,7 +360,7 @@ private void LoadExportDirectory() numb = (endIndex - _PEFileIndex) / 4; for (long z = 0; z != numb; z++) { - byte[] Data = new byte[4]; + var Data = new byte[4]; Loadbyte(ref Data); ExportDirectory.AddressOfNamesList.Add(Data); } @@ -370,7 +370,7 @@ private void LoadExportDirectory() numb = (endIndex - _PEFileIndex) / 2; for (long z = 0; z != numb; z++) { - byte[] Data = new byte[2]; + var Data = new byte[2]; Loadbyte(ref Data); ExportDirectory.AddressOfNameOrdinalsList.Add(Data); } @@ -414,10 +414,10 @@ private void LoadImportDirectory() if (OptionalDirAttrib.DirByte[1] is not OptionalDirAttrib.DirAttrib ImporRVA) return; - long ImporAddress = GetLong(ImporRVA.DirRva); // 获取的位置 + var ImporAddress = GetLong(ImporRVA.DirRva); // 获取的位置 if (ImporAddress == 0) return; - long ImporSize = GetLong(ImporRVA.DirSize); // 获取大小 + var ImporSize = GetLong(ImporRVA.DirSize); // 获取大小 ImportDirectory = new ImportDirectory(); @@ -430,7 +430,7 @@ private void LoadImportDirectory() #region 获取位置 if (SectionTable is null) return; - for (int i = 0; i != SectionTable.Section.Count; i++) // 循环节表 + for (var i = 0; i != SectionTable.Section.Count; i++) // 循环节表 { if (SectionTable.Section[i] is not SectionTable.SectionData Sect) continue; @@ -472,12 +472,12 @@ private void LoadImportDirectory() #region 获取输入DLL名称 - for (int z = 0; z != ImportDirectory.ImportList.Count; z++) // 获取引入DLL名字 + for (var z = 0; z != ImportDirectory.ImportList.Count; z++) // 获取引入DLL名字 { if (ImportDirectory.ImportList[z] is not ImportDirectory.ImportDate Import) continue; - long ImportDLLName = GetLong(Import.Name) - SizeRva + PointerRva; + var ImportDLLName = GetLong(Import.Name) - SizeRva + PointerRva; _PEFileIndex = ImportDLLName; long ReadCount = 0; while (_PEFileByte is not null) // 获取引入名 @@ -494,28 +494,28 @@ private void LoadImportDirectory() #endregion #region 获取引入方法 先获取地址 然后获取名字和头 - for (int z = 0; z != ImportDirectory.ImportList.Count; z++) // 获取引入方法 + for (var z = 0; z != ImportDirectory.ImportList.Count; z++) // 获取引入方法 { if (ImportDirectory.ImportList[z] is not ImportDirectory.ImportDate import) continue; - long importDLLName = GetLong(import.OriginalFirstThunk) - SizeRva + PointerRva; + var importDLLName = GetLong(import.OriginalFirstThunk) - SizeRva + PointerRva; _PEFileIndex = importDLLName; while (true) { var function = new ImportDirectory.ImportDate.FunctionList(); Loadbyte(ref function.OriginalFirst); - long loadIndex = GetLong(function.OriginalFirst); + var loadIndex = GetLong(function.OriginalFirst); if (loadIndex == 0) break; - long oldIndex = _PEFileIndex; + var oldIndex = _PEFileIndex; _PEFileIndex = loadIndex - SizeRva + PointerRva; if (loadIndex >= StarRva && loadIndex < StarRva + EndRva) // 发现有些数字超级大 { - int ReadCount = 0; + var ReadCount = 0; while (_PEFileByte is not null) { @@ -523,7 +523,7 @@ private void LoadImportDirectory() Loadbyte(ref function.FunctionHead); if (_PEFileByte[_PEFileIndex + ReadCount] == 0) { - byte[] FunctionName = new byte[ReadCount]; + var FunctionName = new byte[ReadCount]; Loadbyte(ref FunctionName); function.FunctionName = FunctionName; @@ -555,10 +555,10 @@ private void LoadResourceDirectory() if (OptionalDirAttrib.DirByte[2] is not OptionalDirAttrib.DirAttrib ImporRVA) return; - long ImporAddress = GetLong(ImporRVA.DirRva); // 获取的位置 + var ImporAddress = GetLong(ImporRVA.DirRva); // 获取的位置 if (ImporAddress == 0) return; - long ImporSize = GetLong(ImporRVA.DirSize); // 获取大小 + var ImporSize = GetLong(ImporRVA.DirSize); // 获取大小 ResourceDirectory = new ResourceDirectory(); @@ -572,7 +572,7 @@ private void LoadResourceDirectory() if (SectionTable is null) return; - for (int i = 0; i != SectionTable.Section.Count; i++) // 循环节表 + for (var i = 0; i != SectionTable.Section.Count; i++) // 循环节表 { if (SectionTable.Section[i] is not SectionTable.SectionData sect) continue; @@ -615,34 +615,34 @@ private void AddResourceNode(ResourceDirectory node, long PEIndex, long RVA, lon Loadbyte(ref node.NumberOfNamedEntries); Loadbyte(ref node.NumberOfIdEntries); - long NameRVA = GetLong(node.NumberOfNamedEntries); - for (int i = 0; i != NameRVA; i++) + var NameRVA = GetLong(node.NumberOfNamedEntries); + for (var i = 0; i != NameRVA; i++) { var Entry = new ResourceDirectory.DirectoryEntry(); Loadbyte(ref Entry.Name); Loadbyte(ref Entry.Id); - byte[] temp = new byte[2]; + var temp = new byte[2]; temp[0] = Entry.Name[0]; temp[1] = Entry.Name[1]; if (_PEFileByte is null) return; - long NameIndex = GetLong(temp) + PEIndex; + var NameIndex = GetLong(temp) + PEIndex; temp[0] = _PEFileByte[NameIndex + 0]; temp[1] = _PEFileByte[NameIndex + 1]; - long NameCount = GetLong(temp); + var NameCount = GetLong(temp); node.Name = new byte[NameCount * 2]; - for (int z = 0; z != node.Name.Length; z++) + for (var z = 0; z != node.Name.Length; z++) node.Name[z] = _PEFileByte[NameIndex + 2 + z]; // System.Windows.Forms.MessageBox.Show(GetString(Entry.ID)); temp[0] = Entry.Id[2]; temp[1] = Entry.Id[3]; - long oldIndex = _PEFileIndex; + var oldIndex = _PEFileIndex; if (GetLong(temp) == 0) { @@ -675,19 +675,19 @@ private void AddResourceNode(ResourceDirectory node, long PEIndex, long RVA, lon node.EntryList.Add(Entry); } - long Count = GetLong(node.NumberOfIdEntries); - for (int i = 0; i != Count; i++) + var Count = GetLong(node.NumberOfIdEntries); + for (var i = 0; i != Count; i++) { var entry = new ResourceDirectory.DirectoryEntry(); Loadbyte(ref entry.Name); Loadbyte(ref entry.Id); // System.Windows.Forms.MessageBox.Show(GetString(Entry.Name)+"_"+GetString(Entry.Id)); - byte[] temp = new byte[2]; + var temp = new byte[2]; temp[0] = entry.Id[2]; temp[1] = entry.Id[3]; - long OldIndex = _PEFileIndex; + var OldIndex = _PEFileIndex; if (GetLong(temp) == 0) { @@ -702,7 +702,7 @@ private void AddResourceNode(ResourceDirectory node, long PEIndex, long RVA, lon Loadbyte(ref dataRVA.ResourTest); Loadbyte(ref dataRVA.ResourWen); - long FileRva = GetLong(dataRVA.ResourRVA) - resourSectRva + PEIndex; + var FileRva = GetLong(dataRVA.ResourRVA) - resourSectRva + PEIndex; dataRVA.FileStarIndex = FileRva; dataRVA.FileEndIndex = FileRva + GetLong(dataRVA.ResourSize); @@ -736,7 +736,7 @@ private void Loadbyte(ref byte[] data) if (_PEFileByte is null) return; - for (int i = 0; i != data.Length; i++) + for (var i = 0; i != data.Length; i++) { data[i] = _PEFileByte[_PEFileIndex]; _PEFileIndex++; @@ -749,8 +749,8 @@ private void Loadbyte(ref byte[] data) /// AA BB CC DD private string GetString(byte[] data) { - string Temp = ""; - for (int i = 0; i != data.Length - 1; i++) + var Temp = ""; + for (var i = 0; i != data.Length - 1; i++) Temp += data[i].ToString("X02") + " "; Temp += data[data.Length - 1].ToString("X02"); @@ -773,8 +773,8 @@ private string GetString(byte[] data, string type) return System.Text.Encoding.Unicode.GetString(data); if (type.Trim().ToUpper() == "BYTE") { - string Temp = ""; - for (int i = data.Length - 1; i != 0; i--) + var Temp = ""; + for (var i = data.Length - 1; i != 0; i--) Temp += data[i].ToString("X02") + " "; Temp += data[0].ToString("X02"); return Temp; @@ -788,13 +788,13 @@ private string GetString(byte[] data, string type) /// static string GetInt(byte[] data) { - string Temp = ""; - for (int i = 0; i != data.Length - 1; i++) + var Temp = ""; + for (var i = 0; i != data.Length - 1; i++) { - int ByteInt = (int)data[i]; + var ByteInt = (int)data[i]; Temp += ByteInt.ToString() + " "; } - int EndByteInt = (int)data[data.Length - 1]; + var EndByteInt = (int)data[data.Length - 1]; // int EndByteInt = (int)data[^1]; Temp += EndByteInt.ToString(); return Temp; @@ -809,9 +809,9 @@ private long GetLong(byte[] data) if (data.Length > 4) return 0; - string MC = ""; + var MC = ""; // if (data.Length <= 4) - for (int i = data.Length - 1; i != -1; i--) + for (var i = data.Length - 1; i != -1; i--) MC += data[i].ToString("X02"); return Convert.ToInt64(MC, 16); } @@ -1038,7 +1038,7 @@ private void AddTableRow(DataTable refTable, byte[]? data, string name, string d { 15, "其他表5" } }; - for (int i = 0; i != OptionalDirAttrib.DirByte.Count; i++) + for (var i = 0; i != OptionalDirAttrib.DirByte.Count; i++) { if (OptionalDirAttrib.DirByte[i] is not OptionalDirAttrib.DirAttrib MyDirByte) continue; @@ -1073,7 +1073,7 @@ private void AddTableRow(DataTable refTable, byte[]? data, string name, string d returnTable.Columns.Add("ASCII"); returnTable.Columns.Add("Describe"); - for (int i = 0; i != SectionTable.Section.Count; i++) + for (var i = 0; i != SectionTable.Section.Count; i++) { if (SectionTable.Section[i] is not SectionTable.SectionData SectionDate) continue; @@ -1137,7 +1137,7 @@ private void AddTableRow(DataTable refTable, byte[]? data, string name, string d returnTable.Columns.Add("ASCII"); returnTable.Columns.Add("Describe"); - for (int i = 0; i != ExportDirectory.FunctionNamesByte.Count; i++) + for (var i = 0; i != ExportDirectory.FunctionNamesByte.Count; i++) { AddTableRow(returnTable, ExportDirectory.FunctionNamesByte[i], @@ -1145,21 +1145,21 @@ private void AddTableRow(DataTable refTable, byte[]? data, string name, string d "_ExportDirectory.Name-Sect.SizeOfRawDataRVA+Sect.PointerToRawData"); } - for (int i = 0; i != ExportDirectory.AddressOfNamesList.Count; i++) + for (var i = 0; i != ExportDirectory.AddressOfNamesList.Count; i++) { if (ExportDirectory.AddressOfNamesList[i] is not byte[] a) continue; AddTableRow(returnTable, a, "NamesList", ""); } - for (int i = 0; i != ExportDirectory.AddressOfFunctionsList.Count; i++) + for (var i = 0; i != ExportDirectory.AddressOfFunctionsList.Count; i++) { if (ExportDirectory.AddressOfFunctionsList[i] is not byte[] a) continue; AddTableRow(returnTable, a, "Functions", ""); } - for (int i = 0; i != ExportDirectory.AddressOfNameOrdinalsList.Count; i++) + for (var i = 0; i != ExportDirectory.AddressOfNameOrdinalsList.Count; i++) { if (ExportDirectory.AddressOfNameOrdinalsList[i] is not byte[] a) continue; @@ -1180,7 +1180,7 @@ private void AddTableRow(DataTable refTable, byte[]? data, string name, string d returnTable.Columns.Add("ASCII"); returnTable.Columns.Add("Describe"); - for (int i = 0; i != ImportDirectory.ImportList.Count; i++) + for (var i = 0; i != ImportDirectory.ImportList.Count; i++) { if (ImportDirectory.ImportList[i] is not ImportDirectory.ImportDate ImportByte) continue; @@ -1208,14 +1208,14 @@ private void AddTableRow(DataTable refTable, byte[]? data, string name, string d returnTable.Columns.Add("ASCII"); returnTable.Columns.Add("Describe"); - for (int i = 0; i != ImportDirectory.ImportList.Count; i++) + for (var i = 0; i != ImportDirectory.ImportList.Count; i++) { if (ImportDirectory.ImportList[i] is not ImportDirectory.ImportDate ImportByte) continue; AddTableRow(returnTable, ImportByte.DLLName, "DLL-Name", "**********"); - for (int z = 0; z != ImportByte.DLLFunctionList.Count; z++) + for (var z = 0; z != ImportByte.DLLFunctionList.Count; z++) { if (ImportByte.DLLFunctionList[z] is not ImportDirectory.ImportDate.FunctionList Function) continue; @@ -1240,20 +1240,20 @@ private void AddTableRow(DataTable refTable, byte[]? data, string name, string d } private void AddResourceDirectoryRow(DataTable myTable, ResourceDirectory Node, string parentID) { - string Name = ""; + var Name = ""; if (Node.Name is not null) Name = GetString(Node.Name, "UNICODE"); - for (int i = 0; i != Node.EntryList.Count; i++) + for (var i = 0; i != Node.EntryList.Count; i++) { if (Node.EntryList[i] is not ResourceDirectory.DirectoryEntry Entry) continue; - long ID = GetLong(Entry.Name); + var ID = GetLong(Entry.Name); - string GUID = Guid.NewGuid().ToString(); + var GUID = Guid.NewGuid().ToString(); - string IDNAME = "ID{" + ID + "}"; + var IDNAME = "ID{" + ID + "}"; if (Name.Length != 0) IDNAME += "Name{" + Name + "}"; @@ -1283,17 +1283,17 @@ private void AddResourceDirectoryRow(DataTable myTable, ResourceDirectory Node, myTable.Rows.Add(new string[] { GUID, IDNAME, parentID }); - for (int z = 0; z != Entry.DataEntryList.Count; z++) + for (var z = 0; z != Entry.DataEntryList.Count; z++) { if (Entry.DataEntryList[z] is not ResourceDirectory.DirectoryEntry.DataEntry Data) continue; - string Text = "Address{" + GetString(Data.ResourRVA) + "} Size{" + GetString(Data.ResourSize) + "} FileBegin{" + Data.FileStarIndex.ToString() + "-" + Data.FileEndIndex.ToString() + "}"; + var Text = "Address{" + GetString(Data.ResourRVA) + "} Size{" + GetString(Data.ResourSize) + "} FileBegin{" + Data.FileStarIndex.ToString() + "-" + Data.FileEndIndex.ToString() + "}"; myTable.Rows.Add(new string[] { Guid.NewGuid().ToString(), Text, GUID }); } - for (int z = 0; z != Entry.NodeDirectoryList.Count; z++) + for (var z = 0; z != Entry.NodeDirectoryList.Count; z++) { if (Entry.NodeDirectoryList[z] is not ResourceDirectory a) continue; @@ -1419,7 +1419,7 @@ public OptionalHeader(bool is32) // X64没有了,但是为了代码保留修改幅度不大,所以置0 BaseOfData = new byte[0];// x64必须置于0 // x64长度增加的 - int ulonglong = 8; + var ulonglong = 8; ImageBase = new byte[ulonglong]; // 数据基址(RVA) SizeOfStackReserve = new byte[ulonglong]; // 保留栈的大小 SizeOfStackCommit = new byte[ulonglong]; // 初始时指定栈大小 @@ -1501,7 +1501,7 @@ public class ExportDirectory public HashSet FunctionNames() { HashSet names = new(); - for (int i = 0; i < FunctionNamesByte.Count; i++) + for (var i = 0; i < FunctionNamesByte.Count; i++) names.Add(Encoding.Default.GetString(FunctionNamesByte[i])); return names; } diff --git a/CADShared/Runtime/SymbolTable.cs b/CADShared/Runtime/SymbolTable.cs index 6ee557d..4e4e15e 100644 --- a/CADShared/Runtime/SymbolTable.cs +++ b/CADShared/Runtime/SymbolTable.cs @@ -309,7 +309,7 @@ private ObjectId GetRecordFrom(SymbolTable table, string name, ArgumentNullEx.ThrowIfNull(table); var rid = this[name]; - bool has = rid != ObjectId.Null; + var has = rid != ObjectId.Null; if ((!has || !over) && has) return rid; var id = table[name]; using IdMapping map = new(); @@ -403,7 +403,7 @@ public void ForEach(Action task, // throw new ArgumentNullException(nameof(task)); ArgumentNullEx.ThrowIfNull(task); LoopState state = new(); /*这种方式比Action改Func更友好*/ - int i = 0; + var i = 0; foreach (var id in this) { if (checkIdOk && !id.IsOk()) -- Gitee From e6bd9c124dbba659cb8b6d3e190d4c1904fe3349 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sun, 20 Oct 2024 21:42:07 +0800 Subject: [PATCH 330/453] =?UTF-8?q?=E8=A1=A5=E5=85=85EntityEx=EF=BC=8C?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/Algorithms/QuadTree/QuadTree.cs | 2 +- CADShared/Algorithms/QuadTree/QuadTreeNode.cs | 18 +- CADShared/Algorithms/QuadTree/Rect.cs | 6 +- CADShared/Assoc/AssocPersSubentityIdPEEx.cs | 2 +- CADShared/Basal/General/EnumEx.cs | 2 +- CADShared/Basal/General/LoopList.cs | 2 +- CADShared/CADShared.projitems | 4 + CADShared/ExtensionMethod/CollectionEx.cs | 4 +- CADShared/ExtensionMethod/DBDictionaryEx.cs | 4 +- CADShared/ExtensionMethod/DBObjectEx.cs | 4 +- CADShared/ExtensionMethod/DBTransEx.cs | 16 +- CADShared/ExtensionMethod/DatabaseEx.cs | 207 ++++++++++++++++++ CADShared/ExtensionMethod/EditorEx.cs | 20 +- CADShared/ExtensionMethod/Entity/ArcEx.cs | 88 ++++++++ CADShared/ExtensionMethod/Entity/DBTextEx.cs | 60 +++++ .../Entity/EntityBoundingInfo.cs | 8 +- CADShared/ExtensionMethod/Entity/MTextEx.cs | 73 ++++++ CADShared/ExtensionMethod/ErrorInfoEx.cs | 2 +- .../ExtensionMethod/Geomerty/Curve3dEx.cs | 4 +- .../ExtensionMethod/Geomerty/GeometryEx.cs | 10 +- .../ExtensionMethod/Hatch/HatchConverter.cs | 12 +- CADShared/ExtensionMethod/Hatch/HatchEx.cs | 4 +- CADShared/ExtensionMethod/Hatch/HatchInfo.cs | 4 +- CADShared/ExtensionMethod/IFoxUtils.cs | 2 +- CADShared/ExtensionMethod/Jig/JigEx.cs | 2 +- .../ExtensionMethod/Jig/JigExTransient.cs | 2 +- CADShared/ExtensionMethod/ObjectIdEx.cs | 2 +- CADShared/ExtensionMethod/RedrawEx.cs | 4 +- .../ExtensionMethod/SingleKeyWordHook.cs | 8 +- .../ExtensionMethod/SymbolTableRecordEx.cs | 4 +- CADShared/ExtensionMethod/TransactionEx.cs | 12 +- CADShared/ExtensionMethod/WindowEx.cs | 2 +- CADShared/ExtensionMethod/XrefEx.cs | 2 +- CADShared/Initialize/AcadEMR.cs | 2 +- CADShared/Initialize/CheckFactory.cs | 2 +- CADShared/PE/AcadPeInfo.cs | 6 +- CADShared/PE/DBmod.cs | 4 +- CADShared/PE/PostCmd.cs | 10 +- CADShared/PE/ProgramPE.cs | 12 +- CADShared/ResultData/LispList.cs | 2 +- CADShared/ResultData/XDataList.cs | 4 +- CADShared/ResultData/XRecordDataList.cs | 2 +- CADShared/Runtime/DBTrans.cs | 2 +- CADShared/Runtime/IdleAction.cs | 2 +- CADShared/Runtime/IdleNoCommandAction.cs | 8 +- CADShared/Runtime/SystemVariableManager.cs | 126 +++++------ 46 files changed, 603 insertions(+), 175 deletions(-) create mode 100644 CADShared/ExtensionMethod/DatabaseEx.cs create mode 100644 CADShared/ExtensionMethod/Entity/ArcEx.cs create mode 100644 CADShared/ExtensionMethod/Entity/DBTextEx.cs create mode 100644 CADShared/ExtensionMethod/Entity/MTextEx.cs diff --git a/CADShared/Algorithms/QuadTree/QuadTree.cs b/CADShared/Algorithms/QuadTree/QuadTree.cs index 2872540..4ef6568 100644 --- a/CADShared/Algorithms/QuadTree/QuadTree.cs +++ b/CADShared/Algorithms/QuadTree/QuadTree.cs @@ -51,7 +51,7 @@ public class QuadTree where TEntity : QuadEntity public QuadTree(Rect rect) { _rootNode = new QuadTreeNode(rect, null, 0);// 初始化根节点 - _points = new(); + _points = []; } #endregion diff --git a/CADShared/Algorithms/QuadTree/QuadTreeNode.cs b/CADShared/Algorithms/QuadTree/QuadTreeNode.cs index 7a37fdb..a926bda 100644 --- a/CADShared/Algorithms/QuadTree/QuadTreeNode.cs +++ b/CADShared/Algorithms/QuadTree/QuadTreeNode.cs @@ -32,13 +32,13 @@ QuadTreeNode[] Nodes { get { - return new QuadTreeNode[] - { - RightTopTree!, + return + [ + RightTopTree!, LeftTopTree!, LeftBottomTree!, - RightBottomTree!, - }; + RightBottomTree! + ]; } } /// @@ -115,7 +115,7 @@ public QuadTreeNode(Rect box, QuadTreeNode? parent, int depth) Parent = parent; Depth = depth; - Contents = new(); + Contents = []; } #endregion @@ -232,7 +232,7 @@ public QuadTreeNode(Rect box, QuadTreeNode? parent, int depth) // 为什么要用容器? // 相同包围盒或者四叉树分割线压着多个. - this.Contents.Add(ent); + Contents.Add(ent); return this; } @@ -268,7 +268,7 @@ static Rect[] RectSplit(Rect box) var lowerRight = new Rect(box._X + halfWidth, box._Y, box._Right, box._Top - halfHeight); // 依照象限顺序输出 - return new Rect[] { upperRight, upperLeft, lowerleft, lowerRight }; + return [upperRight, upperLeft, lowerleft, lowerRight]; } #endregion @@ -289,7 +289,7 @@ public bool Remove(TEntity easeEnt) if (Contents.Remove(easeEnt)) { if (CountSubTree == 0) - this.Clear(this); + Clear(this); return true; } diff --git a/CADShared/Algorithms/QuadTree/Rect.cs b/CADShared/Algorithms/QuadTree/Rect.cs index 30bb719..60f92f9 100644 --- a/CADShared/Algorithms/QuadTree/Rect.cs +++ b/CADShared/Algorithms/QuadTree/Rect.cs @@ -249,7 +249,7 @@ public Rect(Point2d p1, Point2d p3, bool check = false) /// public override bool Equals(object? obj) { - return this.Equals(obj as Rect); + return Equals(obj as Rect); } /// /// @@ -258,7 +258,7 @@ public override bool Equals(object? obj) /// public bool Equals(Rect? b) { - return this.Equals(b, 1e-6);/*默认规则是==是0容差,Eq是有容差*/ + return Equals(b, 1e-6);/*默认规则是==是0容差,Eq是有容差*/ } /// /// @@ -520,7 +520,7 @@ public static bool RectAnglePointOrder(List? pts) //if (pts == null) // throw new ArgumentNullException(nameof(pts)); ArgumentNullEx.ThrowIfNull(pts); - if (!Rect.IsRectAngle(pts)) + if (!IsRectAngle(pts)) return false; // 获取min和max点(非包围盒) diff --git a/CADShared/Assoc/AssocPersSubentityIdPEEx.cs b/CADShared/Assoc/AssocPersSubentityIdPEEx.cs index 2efdbc5..cc1cdfa 100644 --- a/CADShared/Assoc/AssocPersSubentityIdPEEx.cs +++ b/CADShared/Assoc/AssocPersSubentityIdPEEx.cs @@ -15,7 +15,7 @@ public static class AssocPersSubentityIdPEEx public static AssocPersSubentityIdPE? GetPersSubentityIdPE(this Entity entity) { var intPtr = entity.QueryX(_acdbAssocPersSubentityIdPEClass); - return AssocPersSubentityIdPE.Create(intPtr, false) as AssocPersSubentityIdPE; + return RXObject.Create(intPtr, false) as AssocPersSubentityIdPE; } /// diff --git a/CADShared/Basal/General/EnumEx.cs b/CADShared/Basal/General/EnumEx.cs index 34a81ef..4d1cb6c 100644 --- a/CADShared/Basal/General/EnumEx.cs +++ b/CADShared/Basal/General/EnumEx.cs @@ -36,7 +36,7 @@ public static void CleanCache() return null!; // 注释存放的容器 - HashSet nodes = new(); + HashSet nodes = []; if (Attribute.GetCustomAttribute(fieldInfo, typeof(T)) is T attribute) { nodes.Add(attribute.Description); diff --git a/CADShared/Basal/General/LoopList.cs b/CADShared/Basal/General/LoopList.cs index 58b450f..78355d5 100644 --- a/CADShared/Basal/General/LoopList.cs +++ b/CADShared/Basal/General/LoopList.cs @@ -286,7 +286,7 @@ public bool Contains(T value) if (node is null) return null; - List> result = new(); + List> result = []; var c = EqualityComparer.Default; if (value is not null) { diff --git a/CADShared/CADShared.projitems b/CADShared/CADShared.projitems index e42f1e3..7ff0f7e 100644 --- a/CADShared/CADShared.projitems +++ b/CADShared/CADShared.projitems @@ -32,17 +32,21 @@ + + + + diff --git a/CADShared/ExtensionMethod/CollectionEx.cs b/CADShared/ExtensionMethod/CollectionEx.cs index 9d3a867..f015ecb 100644 --- a/CADShared/ExtensionMethod/CollectionEx.cs +++ b/CADShared/ExtensionMethod/CollectionEx.cs @@ -289,7 +289,7 @@ public static Dictionary ToDictionary(this KeywordCollection col [DebuggerStepThrough] public static List GetKeys(this IdMapping idMapping) { - List ids = new(); + List ids = []; foreach (IdPair item in idMapping) ids.Add(item.Key); return ids; @@ -303,7 +303,7 @@ public static List GetKeys(this IdMapping idMapping) [DebuggerStepThrough] public static List GetValues(this IdMapping idMapping) { - List ids = new(); + List ids = []; foreach (IdPair item in idMapping) { ids.Add(item.Value); diff --git a/CADShared/ExtensionMethod/DBDictionaryEx.cs b/CADShared/ExtensionMethod/DBDictionaryEx.cs index 266b294..829b1ae 100644 --- a/CADShared/ExtensionMethod/DBDictionaryEx.cs +++ b/CADShared/ExtensionMethod/DBDictionaryEx.cs @@ -367,7 +367,7 @@ public static IEnumerable GetGroups(this Entity ent) public static List RemoveNullGroup(this DBDictionary dict) { var groups = dict.GetGroups(g => g.NumEntities < 2); - List names = new(); + List names = []; foreach (var g in groups) { names.Add(g.Name); @@ -392,7 +392,7 @@ public static List RemoveNullGroup(this DBDictionary dict) public static List RemoveNullGroup(this DBDictionary dict, Func func) { var groups = dict.GetGroups(g => g.NumEntities < 2); - List names = new(); + List names = []; foreach (var g in groups) { if (func(g.Name)) diff --git a/CADShared/ExtensionMethod/DBObjectEx.cs b/CADShared/ExtensionMethod/DBObjectEx.cs index 8cb764a..162575c 100644 --- a/CADShared/ExtensionMethod/DBObjectEx.cs +++ b/CADShared/ExtensionMethod/DBObjectEx.cs @@ -41,7 +41,7 @@ public static void RemoveXData(this DBObject obj, string appName, DxfCode dxfCod XDataList data = obj.XData; // 移除指定App的扩展 - var indexes = data.GetXdataAppIndex(appName, new DxfCode[] { dxfCode }); + var indexes = data.GetXdataAppIndex(appName, [dxfCode]); if (indexes.Count == 0) return; @@ -92,7 +92,7 @@ public static void ChangeXData(this DBObject obj, string appName, DxfCode dxfCod return; XDataList data = obj.XData; - var indexes = data.GetXdataAppIndex(appName, new DxfCode[] { dxfCode }); + var indexes = data.GetXdataAppIndex(appName, [dxfCode]); if (indexes.Count == 0) return; diff --git a/CADShared/ExtensionMethod/DBTransEx.cs b/CADShared/ExtensionMethod/DBTransEx.cs index d2652ee..8838267 100644 --- a/CADShared/ExtensionMethod/DBTransEx.cs +++ b/CADShared/ExtensionMethod/DBTransEx.cs @@ -40,11 +40,13 @@ public static void Purge(this DBTrans tr, SymModes sym = SymModes.All, bool excl if (!excludeXref) GetAllIds(tr, tr.BlockTable, ids, excludeXref); else - tr.BlockTable.ForEach(tabRec => { + tr.BlockTable.ForEach(tabRec => + { if (!tabRec.IsFromExternalReference) ids.Add(tabRec.Id); }, checkIdOk: true); } + if ((sym & SymModes.DimStyleTable) == SymModes.DimStyleTable) GetAllIds(tr, tr.DimStyleTable, ids, excludeXref); if ((sym & SymModes.LayerTable) == SymModes.LayerTable) @@ -70,18 +72,16 @@ public static void Purge(this DBTrans tr, SymModes sym = SymModes.All, bool excl id.Erase(); } - static void GetAllIds(DBTrans tr, - SymbolTable symbolTable, - ObjectIdCollection ids, - bool excludeXref = true) - where TTable : SymbolTable - where TRecord : SymbolTableRecord, new() + static void GetAllIds(DBTrans tr, SymbolTable symbolTable, + ObjectIdCollection ids, bool excludeXref = true) where TTable : SymbolTable + where TRecord : SymbolTableRecord, new() { if (!excludeXref) symbolTable.ForEach(id => ids.Add(id)); else { - symbolTable.ForEach(id => { + symbolTable.ForEach(id => + { var tabRec = tr.GetObject(id); if (tabRec == null) return; diff --git a/CADShared/ExtensionMethod/DatabaseEx.cs b/CADShared/ExtensionMethod/DatabaseEx.cs new file mode 100644 index 0000000..c3bf399 --- /dev/null +++ b/CADShared/ExtensionMethod/DatabaseEx.cs @@ -0,0 +1,207 @@ +namespace IFoxCAD.Cad; + +/// +/// 数据库扩展函数 +/// +public static class DatabaseEx +{ + /// + /// 打开切换活动数据库 + /// + /// 当前数据库 + /// 切换数据库对象 + public static SwitchDatabase SwitchDatabase(this Database db) => new(db); + + + /// + /// 保存文件 + /// + /// 数据库 + /// 文件版本 + public static void SaveDwgFile(this Database db, DwgVersion version = DwgVersion.AC1800) + { + db.SaveFile(version); + } + + /// + /// 保存文件
    + ///
    + /// 数据库 + /// 默认2004dwg;若保存dxf则需要在路径输入扩展名 + /// 为true时候无效,将变为自动识别环境变量 + /// 另存为文件,前台将调用时它将无效,将变为弹出面板 + /// 保存路径失败的提示 + public static void SaveFile(this Database db, DwgVersion version = DwgVersion.AC1800, + bool automatic = true, string? saveAsFile = null, bool echoes = true) + { + // 遍历当前所有文档,文档必然是前台的 + Document? doc = null; + foreach (Document docItem in Acaop.DocumentManager) + { + if (docItem.Database.Filename == db.Filename) + { + doc = docItem; + break; + } + } + + // 前台开图,使用命令保存;不需要切换文档 + if (doc != null) + { + // 无法把 给这个面板 + doc.SendStringToExecute(saveAsFile == null ? "_qSave\n" : $"_SaveAs\n", false, true, true); + return; + } + + // 后台开图,用数据库保存 + string? fileMsg; + var creatFlag = false; + if (string.IsNullOrWhiteSpace(saveAsFile)) + { + fileMsg = db.Filename; + saveAsFile = fileMsg; + //creatFlag = true; + } + else + { + fileMsg = saveAsFile; + + // 路径失败也保存到桌面 + var path = Path.GetDirectoryName(saveAsFile); + if (string.IsNullOrWhiteSpace(path)) + { + creatFlag = true; + } + else if (!Directory.Exists(path)) + { + try + { + Directory.CreateDirectory(path); + } + catch + { + creatFlag = true; + } + } + + // 文件名缺失时 + if (!creatFlag && string.IsNullOrWhiteSpace(Path.GetFileName(saveAsFile))) + creatFlag = true; + } + + if (saveAsFile != null) + { + var fileNameWith = Path.GetFileNameWithoutExtension(saveAsFile); + if (string.IsNullOrWhiteSpace(fileNameWith)) + creatFlag = true; + } + else + { + creatFlag = true; + } + + if (creatFlag) + { + var (error, file) = db.GetOrCreateSaveAsFile(); + if (echoes && error) + System.Windows.Forms.MessageBox.Show($@"错误参数: +{fileMsg} + +它将保存: +{file}", "错误的文件路径"); + saveAsFile = file; + } + + if (Path.GetExtension(saveAsFile)!.ToLower().Contains("dxf")) + { + // dxf用任何版本号都会报错 +#if acad || gcad + db.DxfOut(saveAsFile, 7, true); +#endif + +#if zcad // 中望这里没有测试 + db.DxfOut(saveAsFile, 7, version, true); +#endif + return; + } + + if (automatic) + version = Env.GetDefaultDwgVersion(); + + // dwg需要版本号,而dxf不用,dwg用dxf版本号会报错 + // 若扩展名和版本号冲突,按照扩展名为准 + if (version.IsDxfVersion()) + version = DwgVersion.Current; + + db.SaveAs(saveAsFile, version); + } + + /// + /// 获取文件名,无效的话就制造 + /// + /// + private static (bool error, string path) GetOrCreateSaveAsFile(this Database db) + { + var file = db.Filename; + if (!string.IsNullOrWhiteSpace(file)) + return (false, file); + + // 为了防止用户输入了错误的路径造成无法保存, + // 所以此处将进行保存到桌面, + // 而不是弹出警告就结束 + // 防止前台关闭了所有文档导致没有Editor,所以使用 MessageBox 发送警告 + var fileName = Path.GetFileNameWithoutExtension(file); + var fileExt = Path.GetExtension(file); + + if (string.IsNullOrWhiteSpace(fileName)) + // ReSharper disable once StringLiteralTypo + fileName = DateTime.Now.ToString("--yyMMdd--hhmmssffff"); + if (string.IsNullOrWhiteSpace(fileExt)) + fileExt = ".dwg"; + + // 构造函数(fileName)用了不存在的路径进行后台打开,就会出现此问题 + // 测试命令 FileNotExist + var dir = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + "\\后台保存出错的文件\\"; + + if (!Directory.Exists(dir)) + Directory.CreateDirectory(dir); + + file = dir + fileName + fileExt; + while (File.Exists(file)) + { + // ReSharper disable once StringLiteralTypo + var time = DateTime.Now.ToString("--yyMMdd--hhmmssffff"); + file = dir + fileName + time + fileExt; + Thread.Sleep(100); + } + + return (true, file); + } +} + +/// +/// 自动切换活动数据库 +/// +public class SwitchDatabase : IDisposable +{ + private readonly Database _db; + + /// + /// 切换活动数据库 + /// + /// 当前数据库 + public SwitchDatabase(Database database) + { + _db = HostApplicationServices.WorkingDatabase; + HostApplicationServices.WorkingDatabase = database; + } + + /// + /// 恢复活动数据库为默认 + /// + public void Dispose() + { + HostApplicationServices.WorkingDatabase = _db; + GC.SuppressFinalize(this); + } +} \ No newline at end of file diff --git a/CADShared/ExtensionMethod/EditorEx.cs b/CADShared/ExtensionMethod/EditorEx.cs index e99af58..3290bfb 100644 --- a/CADShared/ExtensionMethod/EditorEx.cs +++ b/CADShared/ExtensionMethod/EditorEx.cs @@ -215,7 +215,7 @@ public static void SsgetAddKeys(this PromptSelectionOptions pso, foreach (var item in dicActions) { - var keySplitS = item.Key.Split(new string[] { ",", "|" }, StringSplitOptions.RemoveEmptyEntries); + var keySplitS = item.Key.Split([",", "|"], StringSplitOptions.RemoveEmptyEntries); for (var i = 0; i < keySplitS.Length; i += 2) pso.Keywords.Add(keySplitS[i], keySplitS[i], keySplitS[i + 1] + "(" + keySplitS[i] + ")"); @@ -445,7 +445,7 @@ public static void WriteMessage(string message) try { if (Acceptable()) - Acap.DocumentManager.MdiActiveDocument.Editor.WriteMessage("\n" + message); + Acaop.DocumentManager.MdiActiveDocument.Editor.WriteMessage("\n" + message); } catch (Exception ex) { @@ -469,9 +469,9 @@ public static void WriteMessage(string format, params object[] args) /// 有,没有 public static bool HasEditor() { - return Acap.DocumentManager.MdiActiveDocument is not null - && Acap.DocumentManager.Count != 0 - && Acap.DocumentManager.MdiActiveDocument.Editor is not null; + return Acaop.DocumentManager.MdiActiveDocument is not null + && Acaop.DocumentManager.Count != 0 + && Acaop.DocumentManager.MdiActiveDocument.Editor is not null; } /// @@ -481,7 +481,7 @@ public static bool HasEditor() public static bool Acceptable() { return HasEditor() - && !Acap.DocumentManager.MdiActiveDocument.Editor.IsDragging; + && !Acaop.DocumentManager.MdiActiveDocument.Editor.IsDragging; } #endregion Info @@ -498,9 +498,9 @@ public static List GetLines(IEnumerable pnts, bool isClosed { using var itor = pnts.GetEnumerator(); if (!itor.MoveNext()) - return new List(); + return []; - List values = new(); + List values = []; TypedValue tvFirst = new((int)LispDataType.Point2d, itor.Current); TypedValue tv1; @@ -1068,7 +1068,7 @@ public enum RunLispFlag : byte if ((flag & RunLispFlag.SendStringToExecute) == RunLispFlag.SendStringToExecute) { - var dm = Acap.DocumentManager; + var dm = Acaop.DocumentManager; var doc = dm.MdiActiveDocument; doc?.SendStringToExecute(lispCode + "\n", false, false, false); } @@ -1097,7 +1097,7 @@ public static void ComExportWMF(this Editor editor, string saveFile, if (File.Exists(saveFile)) throw new FileFormatException("文件重复:" + saveFile); - var dm = Acap.DocumentManager; + var dm = Acaop.DocumentManager; if (dm.Count == 0) return; diff --git a/CADShared/ExtensionMethod/Entity/ArcEx.cs b/CADShared/ExtensionMethod/Entity/ArcEx.cs new file mode 100644 index 0000000..49922f4 --- /dev/null +++ b/CADShared/ExtensionMethod/Entity/ArcEx.cs @@ -0,0 +1,88 @@ +namespace IFoxCAD.Cad; + +/// +/// 圆弧扩展类 +/// +public static class ArcEx +{ + #region 圆弧 + + /// + /// 根据圆心、起点、终点来创建圆弧(二维) + /// + /// 起点 + /// 圆心 + /// 终点 + /// 圆弧 + public static Arc CreateArcSCE(Point3d startPoint, Point3d centerPoint, Point3d endPoint) + { + Arc arc = new(); + arc.SetDatabaseDefaults(); + arc.Center = centerPoint; + arc.Radius = centerPoint.DistanceTo(startPoint); + Vector2d startVector = new(startPoint.X - centerPoint.X, startPoint.Y - centerPoint.Y); + Vector2d endVector = new(endPoint.X - centerPoint.X, endPoint.Y - centerPoint.Y); + // 计算起始和终止角度 + arc.StartAngle = startVector.Angle; + arc.EndAngle = endVector.Angle; + return arc; + } + + /// + /// 三点法创建圆弧(二维) + /// + /// 起点 + /// 圆弧上的点 + /// 终点 + /// 圆弧 + public static Arc CreateArc(Point3d startPoint, Point3d pointOnArc, Point3d endPoint) + { + // 创建一个几何类的圆弧对象 + CircularArc3d geArc = new(startPoint, pointOnArc, endPoint); + // 将几何类圆弧对象的圆心和半径赋值给圆弧 +#if !gcad + + return (Arc)Curve.CreateFromGeCurve(geArc); +#else + return (Arc)geArc.ToCurve(); +#endif + } + + /// + /// 根据起点、圆心和圆弧角度创建圆弧(二维) + /// + /// 起点 + /// 圆心 + /// 圆弧角度 + /// 圆弧 + public static Arc CreateArc(Point3d startPoint, Point3d centerPoint, double angle) + { + Arc arc = new(); + arc.SetDatabaseDefaults(); + arc.Center = centerPoint; + arc.Radius = centerPoint.DistanceTo(startPoint); + Vector2d startVector = new(startPoint.X - centerPoint.X, startPoint.Y - centerPoint.Y); + arc.StartAngle = startVector.Angle; + arc.EndAngle = startVector.Angle + angle; + return arc; + } + + /// + /// 圆弧转为多段线 + /// + /// 圆弧 + /// 多段线 + public static Polyline ToPolyline(this Arc arc) + { + var plane = new Plane(arc.Center, arc.Normal); + var pl = new Polyline(); + pl.Normal = arc.Normal; + pl.AddVertexAt(0, arc.StartPoint.Convert2d(plane), Math.Tan(arc.TotalAngle * 0.25), 0, 0); + pl.AddVertexAt(1, arc.EndPoint.Convert2d(plane), 0, 0, 0); + pl.TransformBy(Matrix3d.Displacement(pl.StartPoint.GetVectorTo(arc.StartPoint))); + pl.SetPropertiesFrom(arc); + return pl; + } + + #endregion +} \ No newline at end of file diff --git a/CADShared/ExtensionMethod/Entity/DBTextEx.cs b/CADShared/ExtensionMethod/Entity/DBTextEx.cs new file mode 100644 index 0000000..00042bf --- /dev/null +++ b/CADShared/ExtensionMethod/Entity/DBTextEx.cs @@ -0,0 +1,60 @@ +namespace IFoxCAD.Cad; + +/// +/// 单行文字扩展类 +/// +public static class DBTextEx +{ + /// + /// 创建单行文字 + /// + /// 插入点 + /// 文本内容 + /// 文字高度 + /// 对齐方式 + /// 文字所在的数据库 + /// 文字属性设置委托 + /// 文字对象 + /// + public static DBText CreateDBText(Point3d position, string text, double height, + AttachmentPoint justify = AttachmentPoint.BaseLeft, Database? database = null, + Action? action = null) + { + if (string.IsNullOrEmpty(text)) + throw new ArgumentNullException(nameof(text), "创建文字无内容"); + + var workingDatabase = database ?? HostApplicationServices.WorkingDatabase; + using var _ = new SwitchDatabase(workingDatabase); + + var acText = new DBText(); + acText.SetDatabaseDefaults(workingDatabase); + + acText.Height = height; + acText.TextString = text; + acText.Position = position; // 插入点(一定要先设置) + + acText.Justify = justify; // 使他们对齐 + + action?.Invoke(acText); + + if (acText.Justify != AttachmentPoint.BaseLeft) + acText.AlignmentPoint = position; + + acText.AdjustAlignment(workingDatabase); + + return acText; + } + + /// + /// 更正单行文字的镜像属性 + /// + /// 单行文字 + public static void ValidateMirror(this DBText txt) + { + if (!txt.Database.Mirrtext) + { + txt.IsMirroredInX = false; + txt.IsMirroredInY = false; + } + } +} \ No newline at end of file diff --git a/CADShared/ExtensionMethod/Entity/EntityBoundingInfo.cs b/CADShared/ExtensionMethod/Entity/EntityBoundingInfo.cs index 76d91a5..c239ce4 100644 --- a/CADShared/ExtensionMethod/Entity/EntityBoundingInfo.cs +++ b/CADShared/ExtensionMethod/Entity/EntityBoundingInfo.cs @@ -160,13 +160,13 @@ public static Point3d[] GetMTextBoxCorners(MText mtext) Matrix3d.Rotation(mtext.Rotation, mtext.Normal, Point3d.Origin) * Matrix3d.PlaneToWorld(new Plane(Point3d.Origin, mtext.Normal)); - return new[] - { - point1.TransformBy(xform), + return + [ + point1.TransformBy(xform), new Point3d(point2.X, point1.Y, 0.0).TransformBy(xform), point2.TransformBy(xform), new Point3d(point1.X, point2.Y, 0.0).TransformBy(xform) - }; + ]; } /// /// 获取实体包围盒 diff --git a/CADShared/ExtensionMethod/Entity/MTextEx.cs b/CADShared/ExtensionMethod/Entity/MTextEx.cs new file mode 100644 index 0000000..027793c --- /dev/null +++ b/CADShared/ExtensionMethod/Entity/MTextEx.cs @@ -0,0 +1,73 @@ +namespace IFoxCAD.Cad; + +/// +/// 多行文字扩展类 +/// +public static class MTextEx +{ + /// + /// 创建多行文字 + /// + /// 插入点 + /// 文本内容 + /// 文字高度 + /// 文字所在的数据库 + /// 文字属性设置委托 + /// 文字对象id + /// + public static MText CreateMText(Point3d position, string text, double height, Database? database = null, + Action? action = null) + { + if (string.IsNullOrEmpty(text)) + throw new ArgumentNullException(nameof(text), "创建文字无内容"); + + var db = database ?? DBTrans.Top.Database; + using var _ = new SwitchDatabase(db); + + var mText = new MText(); + + mText.SetDatabaseDefaults(db); + + mText.TextHeight = height; // 高度 + mText.Contents = text; // 内容 + mText.Location = position; // 插入点 + + action?.Invoke(mText); + + return mText; + } + + /// + /// 炸散多行文字 + /// + /// 存储多行文字炸散之后的对象的类型 + /// 多行文字 + /// 存储对象变量 + /// 回调函数,用于处理炸散之后的对象 + /// + /// 多行文字炸散后的对象
    + /// 回调函数处理的结果 + ///
    + /// + public static void ExplodeFragments(this MText mt, T obj, + Func mTextFragmentCallback) + { + mt.ExplodeFragments((f, o) => mTextFragmentCallback(f, (T)o), obj); + } + + /// + /// 获取多行文字的无格式文本 + /// + /// 多行文字 + /// 文本 + public static string GetUnFormatString(this MText mt) + { + List strs = []; + mt.ExplodeFragments(strs, (f, o) => + { + o.Add(f.Text); + return MTextFragmentCallbackStatus.Continue; + }); + return string.Join("", strs.ToArray()); + } +} \ No newline at end of file diff --git a/CADShared/ExtensionMethod/ErrorInfoEx.cs b/CADShared/ExtensionMethod/ErrorInfoEx.cs index 35c9512..9462d79 100644 --- a/CADShared/ExtensionMethod/ErrorInfoEx.cs +++ b/CADShared/ExtensionMethod/ErrorInfoEx.cs @@ -416,6 +416,6 @@ internal static void AcErrorInfo(this AcException acex) "eAlreadyInactive" => "已经是不活动的了", _ => acex.Message, }; - Acap.ShowAlertDialog($"{acex.Message}:{infoStr}"); + Acaop.ShowAlertDialog($"{acex.Message}:{infoStr}"); } } \ No newline at end of file diff --git a/CADShared/ExtensionMethod/Geomerty/Curve3dEx.cs b/CADShared/ExtensionMethod/Geomerty/Curve3dEx.cs index 52a8e71..6cbcbfb 100644 --- a/CADShared/ExtensionMethod/Geomerty/Curve3dEx.cs +++ b/CADShared/ExtensionMethod/Geomerty/Curve3dEx.cs @@ -207,8 +207,8 @@ public static bool IsCircular(this Curve3d curve) pars.Add(inter.UpperBound); } - List curves = new(); - List cc3ds = new(); + List curves = []; + List cc3ds = []; for (var i = 0; i < pars.Count - 1; i++) { cc3ds.Clear(); diff --git a/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs b/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs index fe85b56..46e9c6d 100644 --- a/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs +++ b/CADShared/ExtensionMethod/Geomerty/GeometryEx.cs @@ -118,7 +118,7 @@ public static PointOnRegionType PointOnRegion(this IEnumerable pts, Poi /// 解析类圆对象 public static CircularArc2d GetMinCircle(Point2d pt1, Point2d pt2, out LoopList ptlst) { - ptlst = new LoopList { pt1, pt2 }; + ptlst = [pt1, pt2]; return new CircularArc2d ( @@ -137,7 +137,7 @@ public static CircularArc2d GetMinCircle(Point2d pt1, Point2d pt2, out LoopList< /// 解析类圆对象 public static CircularArc2d GetMinCircle(Point2d pt1, Point2d pt2, Point2d pt3, out LoopList ptlst) { - ptlst = new LoopList { pt1, pt2, pt3 }; + ptlst = [pt1, pt2, pt3]; // 遍历各点与下一点的向量长度,找到距离最大的两个点 var maxNode = @@ -160,7 +160,7 @@ public static CircularArc2d GetMinCircle(Point2d pt1, Point2d pt2, Point2d pt3, } // 否则按三点做圆 // ptlst.SetFirst(maxNode); - ptlst = new LoopList { maxNode.Value, maxNode.Next.Value, maxNode.Previous.Value }; + ptlst = [maxNode.Value, maxNode.Next.Value, maxNode.Previous.Value]; ca2d = new CircularArc2d(pt1, pt2, pt3); ca2d.SetAngles(0, Math.PI * 2); return ca2d; @@ -348,7 +348,7 @@ public static OrientationType IsClockWise(this IEnumerable pnts) return null; case 1: - ptlst = new LoopList { pnts[0] }; + ptlst = [pnts[0]]; return new CircularArc2d(pnts[0], 0); case 2: @@ -412,7 +412,7 @@ public static List ConvexHull(this List points) return points; int n = points.Count, k = 0; - List H = new(new Point2d[2 * n]); + List H = [..new Point2d[2 * n]]; points.Sort((a, b) => a.X == b.X ? a.Y.CompareTo(b.Y) : a.X.CompareTo(b.X)); diff --git a/CADShared/ExtensionMethod/Hatch/HatchConverter.cs b/CADShared/ExtensionMethod/Hatch/HatchConverter.cs index 716e963..915cda8 100644 --- a/CADShared/ExtensionMethod/Hatch/HatchConverter.cs +++ b/CADShared/ExtensionMethod/Hatch/HatchConverter.cs @@ -46,9 +46,9 @@ class HatchConverterData ///
    public HatchConverterData() { - PolyLineData = new(); - CircleConverterData = new(); - SplineData = new(); + PolyLineData = []; + CircleConverterData = []; + SplineData = []; } } @@ -87,8 +87,8 @@ public ObjectId OldHatchId ///
    HatchConverter() { - _hcDatas = new(); - BoundaryIds = new(); + _hcDatas = []; + BoundaryIds = []; } /// @@ -392,7 +392,7 @@ public ObjectId CreateBoundarysAndHatchToMsPs(BlockTableRecord btrOfAddEntitySpa * 那么它的平移后的基点在哪里呢? */ - using ObjectIdCollection idc = new(new ObjectId[] { OldHatchId }); + using ObjectIdCollection idc = new([OldHatchId]); using IdMapping map = new(); btrOfAddEntitySpace.DeepCloneEx(idc, map); var newHatchId = map.GetValues()[0]; diff --git a/CADShared/ExtensionMethod/Hatch/HatchEx.cs b/CADShared/ExtensionMethod/Hatch/HatchEx.cs index 5e8311e..5d6ccd0 100644 --- a/CADShared/ExtensionMethod/Hatch/HatchEx.cs +++ b/CADShared/ExtensionMethod/Hatch/HatchEx.cs @@ -259,7 +259,7 @@ private static void HatchLoopIsCurve2d(HatchLoop loop, DBObjectCollection objCol var newPl = true; // 是否开始新的多段线(一个边界中可能有多条多段线) var firstIsPl = false; //遍历边界的第一个子段为多段线(遍历时不一定从多段线的首段开始) List? polyLineVertexes = null; - List> polyLineData = new(); + List> polyLineData = []; // 遍历边界的多个子段 foreach (Curve2d curve in loop.Curves) @@ -294,7 +294,7 @@ private static void HatchLoopIsCurve2d(HatchLoop loop, DBObjectCollection objCol if (newPl) { - polyLineVertexes = new(); + polyLineVertexes = []; polyLineData.Add(polyLineVertexes); newPl = false; pLineCount++; diff --git a/CADShared/ExtensionMethod/Hatch/HatchInfo.cs b/CADShared/ExtensionMethod/Hatch/HatchInfo.cs index d87d317..88c0886 100644 --- a/CADShared/ExtensionMethod/Hatch/HatchInfo.cs +++ b/CADShared/ExtensionMethod/Hatch/HatchInfo.cs @@ -60,7 +60,7 @@ public class HatchInfo { _hatch = new Hatch(); _hatch.SetDatabaseDefaults(); - _boundaryIds = new(); + _boundaryIds = []; } /// @@ -168,7 +168,7 @@ public HatchInfo Mode4Gradient(GradientName name, Color colorStart, Color colorE // 设置渐变色填充的起始和结束颜色 var gColor1 = new GradientColor(colorStart, 0); var gColor2 = new GradientColor(colorEnd, 1); - _hatch.SetGradientColors(new GradientColor[] { gColor1, gColor2 }); + _hatch.SetGradientColors([gColor1, gColor2]); _hatch.GradientShift = gradientShift; // 梯度位移 _hatch.ShadeTintValue = shadeTintValue; // 阴影色值 diff --git a/CADShared/ExtensionMethod/IFoxUtils.cs b/CADShared/ExtensionMethod/IFoxUtils.cs index 7a90b57..5d08312 100644 --- a/CADShared/ExtensionMethod/IFoxUtils.cs +++ b/CADShared/ExtensionMethod/IFoxUtils.cs @@ -19,7 +19,7 @@ public static void RegenLayers(IEnumerable objectIds) var mi = type?.GetMethods().FirstOrDefault(e => e.Name == "RegenLayers"); var pi = type?.GetProperties().FirstOrDefault(e => e.Name == "RegenPending"); var regenPending = (int)(pi?.GetValue(null) ?? 0); - mi?.Invoke(null, new object[] { objectIds.ToArray(), regenPending }); + mi?.Invoke(null, [objectIds.ToArray(), regenPending]); } /// diff --git a/CADShared/ExtensionMethod/Jig/JigEx.cs b/CADShared/ExtensionMethod/Jig/JigEx.cs index 8c8d185..f484156 100644 --- a/CADShared/ExtensionMethod/Jig/JigEx.cs +++ b/CADShared/ExtensionMethod/Jig/JigEx.cs @@ -259,7 +259,7 @@ public void SetOptions(Action action) public PromptResult Drag() { // jig功能必然是当前前台文档,所以封装内部更好调用 - var dm = Acap.DocumentManager; + var dm = Acaop.DocumentManager; var doc = dm.MdiActiveDocument; var ed = doc.Editor; var dr = ed.Drag(this); diff --git a/CADShared/ExtensionMethod/Jig/JigExTransient.cs b/CADShared/ExtensionMethod/Jig/JigExTransient.cs index 3e388d5..e0bfeb0 100644 --- a/CADShared/ExtensionMethod/Jig/JigExTransient.cs +++ b/CADShared/ExtensionMethod/Jig/JigExTransient.cs @@ -43,7 +43,7 @@ public class JigExTransient : IDisposable public JigExTransient() { _integerCollection = new(); - _drawableSet = new(); + _drawableSet = []; _manager = TransientManager.CurrentTransientManager; } diff --git a/CADShared/ExtensionMethod/ObjectIdEx.cs b/CADShared/ExtensionMethod/ObjectIdEx.cs index e5540d8..b305350 100644 --- a/CADShared/ExtensionMethod/ObjectIdEx.cs +++ b/CADShared/ExtensionMethod/ObjectIdEx.cs @@ -89,7 +89,7 @@ public static IEnumerable GetObject(this ObjectIdCollection ids, /// 对象id集合 public static IEnumerable IsDerivedFrom(this IEnumerable ids, bool exactMatch = false) where T : DBObject { - var rxc = RXClass.GetClass(typeof(T)); + var rxc = RXObject.GetClass(typeof(T)); if (exactMatch) { var dxfName = rxc.DxfName; diff --git a/CADShared/ExtensionMethod/RedrawEx.cs b/CADShared/ExtensionMethod/RedrawEx.cs index 2e42c47..3cda7fa 100644 --- a/CADShared/ExtensionMethod/RedrawEx.cs +++ b/CADShared/ExtensionMethod/RedrawEx.cs @@ -99,7 +99,7 @@ public static void Redraw(this Editor ed, Entity? ent = null) * tm.FlushGraphics(); // 将当前 刷新队列 的图形提交到显示器 * ed.UpdateScreen(); // 仅刷新屏幕,图元不生成(例如块还是旧的显示) */ - var dm = Acap.DocumentManager; + var dm = Acaop.DocumentManager; var doc = dm.MdiActiveDocument; var tm = doc.TransactionManager; tm.QueueForGraphicsFlush(); @@ -127,7 +127,7 @@ public static void Redraw(this Editor ed, BrightEditor bright) ed.Regen(); if ((bright & BrightEditor.SelectionClean) == BrightEditor.SelectionClean) - ed.SetImpliedSelection(Array.Empty()); + ed.SetImpliedSelection([]); if ((bright & BrightEditor.ViewportsFrom) == BrightEditor.ViewportsFrom) ed.UpdateTiledViewportsFromDatabase(); // 更新视口外 diff --git a/CADShared/ExtensionMethod/SingleKeyWordHook.cs b/CADShared/ExtensionMethod/SingleKeyWordHook.cs index 8616c37..a0071db 100644 --- a/CADShared/ExtensionMethod/SingleKeyWordHook.cs +++ b/CADShared/ExtensionMethod/SingleKeyWordHook.cs @@ -58,12 +58,12 @@ public SingleKeyWordHook(SingleKeyWordWorkType workType = SingleKeyWordWorkType. { IsDisposed = false; _isResponsed = false; - _keyWords = new HashSet(); + _keyWords = []; _key = Keys.None; _working = true; _workType = workType; - Acap.PreTranslateMessage -= Acap_PreTranslateMessage; - Acap.PreTranslateMessage += Acap_PreTranslateMessage; + Acaop.PreTranslateMessage -= Acap_PreTranslateMessage; + Acaop.PreTranslateMessage += Acap_PreTranslateMessage; } #endregion @@ -185,7 +185,7 @@ private void Dispose(bool disposing) if (IsDisposed) return; - Acap.PreTranslateMessage -= Acap_PreTranslateMessage; + Acaop.PreTranslateMessage -= Acap_PreTranslateMessage; if (disposing) { _keyWords.Clear(); diff --git a/CADShared/ExtensionMethod/SymbolTableRecordEx.cs b/CADShared/ExtensionMethod/SymbolTableRecordEx.cs index 4f37358..42cadaa 100644 --- a/CADShared/ExtensionMethod/SymbolTableRecordEx.cs +++ b/CADShared/ExtensionMethod/SymbolTableRecordEx.cs @@ -171,7 +171,7 @@ public static IEnumerable GetEntities(this BlockTableRecord btr, /// 实体Id集合 public static IEnumerable GetObjectIds(this BlockTableRecord btr) where T : Entity { - var dxfName = RXClass.GetClass(typeof(T)).DxfName; + var dxfName = RXObject.GetClass(typeof(T)).DxfName; return btr.Cast() .Where(id => id.ObjectClass.DxfName == dxfName); } @@ -341,7 +341,7 @@ public static void ForEach(this TRecord record, Action /// 符号表记录 /// 要执行的委托 - [System.Diagnostics.DebuggerStepThrough] + [DebuggerStepThrough] public static void ForEach(this TRecord record, Action task) where TRecord : SymbolTableRecord, IEnumerable { diff --git a/CADShared/ExtensionMethod/TransactionEx.cs b/CADShared/ExtensionMethod/TransactionEx.cs index 5d2438e..be152b6 100644 --- a/CADShared/ExtensionMethod/TransactionEx.cs +++ b/CADShared/ExtensionMethod/TransactionEx.cs @@ -14,10 +14,8 @@ public static class TransactionEx /// 是否打开已删除对象,默认为不打开 /// 是否打开锁定图层对象,默认为不打开 /// 数据库DBObject对象 - public static DBObject GetObject(this Transaction tr, ObjectId id, - OpenMode openMode = OpenMode.ForRead, - bool openErased = false, - bool openLockedLayer = false) + public static DBObject GetObject(this Transaction tr, ObjectId id, OpenMode openMode = OpenMode.ForRead, + bool openErased = false, bool openLockedLayer = false) { return tr.GetObject(id, openMode, openErased, openLockedLayer); } @@ -32,10 +30,8 @@ public static DBObject GetObject(this Transaction tr, ObjectId id, /// 是否打开已删除对象,默认为不打开 /// 是否打开锁定图层对象,默认为不打开 /// 图元对象,类型不匹配时抛异常 - public static T? GetObject(this Transaction tr, ObjectId id, - OpenMode openMode = OpenMode.ForRead, - bool openErased = false, - bool openLockedLayer = false) where T : DBObject + public static T? GetObject(this Transaction tr, ObjectId id, OpenMode openMode = OpenMode.ForRead, + bool openErased = false, bool openLockedLayer = false) where T : DBObject { return tr.GetObject(id, openMode, openErased, openLockedLayer) as T; } diff --git a/CADShared/ExtensionMethod/WindowEx.cs b/CADShared/ExtensionMethod/WindowEx.cs index 92c3fe5..ef0b46c 100644 --- a/CADShared/ExtensionMethod/WindowEx.cs +++ b/CADShared/ExtensionMethod/WindowEx.cs @@ -67,7 +67,7 @@ public static Size GetScreenResolutionFromWindowHandle(IntPtr windowHandle) /// 高度 public static void SetSizeByScreenResolution(this PaletteSet paletteSet, int width, int height) { - var size = GetScreenResolutionFromWindowHandle(Acap.MainWindow.Handle); + var size = GetScreenResolutionFromWindowHandle(Acaop.MainWindow.Handle); var scale = size.Height * 1d / 1080; var newWidth = Convert.ToInt32(width * scale); if (newWidth > size.Width) diff --git a/CADShared/ExtensionMethod/XrefEx.cs b/CADShared/ExtensionMethod/XrefEx.cs index 54b722f..39a3008 100644 --- a/CADShared/ExtensionMethod/XrefEx.cs +++ b/CADShared/ExtensionMethod/XrefEx.cs @@ -275,7 +275,7 @@ private void GetBindIds(ObjectIdCollection bindIds) private List GetDetachIds(Dictionary nested) { // 直接拆离的id - List detachIds = new(); + List detachIds = []; // 收集要处理的id XrefNodeForEach((xNodeName, xNodeId, xNodeStatus, xNodeIsNested) => diff --git a/CADShared/Initialize/AcadEMR.cs b/CADShared/Initialize/AcadEMR.cs index 889b99a..18eac5a 100644 --- a/CADShared/Initialize/AcadEMR.cs +++ b/CADShared/Initialize/AcadEMR.cs @@ -65,7 +65,7 @@ public static void Remove(bool echoes = false) return; } - var funcName = Encoding.Unicode.GetString(new byte[] { 63 }); + var funcName = Encoding.Unicode.GetString([63]); if (IntPtr.Size == 4) funcName += "isEMR@AcDbDatabase@@QBE_NXZ"; else diff --git a/CADShared/Initialize/CheckFactory.cs b/CADShared/Initialize/CheckFactory.cs index ab326b0..ae66f98 100644 --- a/CADShared/Initialize/CheckFactory.cs +++ b/CADShared/Initialize/CheckFactory.cs @@ -36,7 +36,7 @@ public static void CheckDuplicateCommand(Assembly? assembly = null) continue; if (!dic.ContainsKey(att.GlobalName)) { - dic.Add(att.GlobalName, new()); + dic.Add(att.GlobalName, []); } dic[att.GlobalName].Add(type.Name + "." + method.Name); diff --git a/CADShared/PE/AcadPeInfo.cs b/CADShared/PE/AcadPeInfo.cs index 0b3fa58..ffda2d5 100644 --- a/CADShared/PE/AcadPeInfo.cs +++ b/CADShared/PE/AcadPeInfo.cs @@ -102,7 +102,7 @@ public static PeInfo? PeForAcdbDll { // 获取此dll所有的函数名 var file = Process.GetCurrentProcess().MainModule.FileName; - var dll = Path.GetDirectoryName(file) + $"\\acdb{Acap.Version.Major}.dll"; + var dll = Path.GetDirectoryName(file) + $"\\acdb{Acaop.Version.Major}.dll"; if (File.Exists(dll)) _PeForAcdbDll = new PeInfo(dll); } @@ -120,7 +120,7 @@ public List? Methods { if (_Methods is null) { - _Methods = new(); + _Methods = []; if ((_acadPeEnum & AcadPeEnum.AcadExe) == AcadPeEnum.AcadExe) GetPeMethod(PeForAcadExe); @@ -193,7 +193,7 @@ GetMethodErrorNum GetPeMethod(PeInfo? peInfo) } else { - _Methods ??= new(); + _Methods ??= []; try { PeFunction.Finds(peInfo, _findFuncName, _Methods); diff --git a/CADShared/PE/DBmod.cs b/CADShared/PE/DBmod.cs index b45a033..3886bd9 100644 --- a/CADShared/PE/DBmod.cs +++ b/CADShared/PE/DBmod.cs @@ -72,7 +72,7 @@ public static long AcdbSetDbmod(IntPtr db, DBmod newValue) /// public static void DBmodTask(Action action) { - var dm = Acap.DocumentManager; + var dm = Acaop.DocumentManager; if (dm.Count == 0) return; var doc = dm.MdiActiveDocument; @@ -94,7 +94,7 @@ public static void DatabaseNoModifies() { if (_flag)// 仅执行一次,在初始化时候 { - var dm = Acap.DocumentManager; + var dm = Acaop.DocumentManager; if (dm.Count == 0) return; var doc = dm.MdiActiveDocument; diff --git a/CADShared/PE/PostCmd.cs b/CADShared/PE/PostCmd.cs index 4882b6d..3929b67 100644 --- a/CADShared/PE/PostCmd.cs +++ b/CADShared/PE/PostCmd.cs @@ -28,12 +28,12 @@ public class PostCmd /// static PromptStatus AcedCmd(ResultBuffer args) { - if (Acap.DocumentManager.IsApplicationContext) + if (Acaop.DocumentManager.IsApplicationContext) return 0; if (acedCmd is null) { var str = nameof(acedCmd); - if (Acap.Version.Major >= 20)// 2015.+ + if (Acaop.Version.Major >= 20)// 2015.+ str += "S"; acedCmd = AcadPeInfo.GetDelegate( @@ -112,7 +112,7 @@ static PromptStatus AcedInvoke(string args) /// static void AsyncCommand(string args) { - object[] commandArray = { args + "\n" }; + object[] commandArray = [args + "\n"]; #if zcad var com = Acap.ZcadApplication; #else @@ -186,7 +186,7 @@ public static PromptStatus SendCommand(IntPtr args) public static PromptStatus SendCommand(string args, RunCmdFlag flag) { var ret = PromptStatus.OK; - if (!Acap.DocumentManager.IsApplicationContext) + if (!Acaop.DocumentManager.IsApplicationContext) { if ((flag & RunCmdFlag.AcedCmd) == RunCmdFlag.AcedCmd) { @@ -216,7 +216,7 @@ public static PromptStatus SendCommand(string args, RunCmdFlag flag) } else { - var dm = Acap.DocumentManager; + var dm = Acaop.DocumentManager; var doc = dm.MdiActiveDocument; if (doc == null) return PromptStatus.Error; diff --git a/CADShared/PE/ProgramPE.cs b/CADShared/PE/ProgramPE.cs index 831f94d..fc9587d 100644 --- a/CADShared/PE/ProgramPE.cs +++ b/CADShared/PE/ProgramPE.cs @@ -766,11 +766,11 @@ private string GetString(byte[] data) private string GetString(byte[] data, string type) { if (type.Trim().ToUpper() == "ASCII") - return System.Text.Encoding.ASCII.GetString(data); + return Encoding.ASCII.GetString(data); if (type.Trim().ToUpper() == "DEFAULT") - return System.Text.Encoding.Default.GetString(data); + return Encoding.Default.GetString(data); if (type.Trim().ToUpper() == "UNICODE") - return System.Text.Encoding.Unicode.GetString(data); + return Encoding.Unicode.GetString(data); if (type.Trim().ToUpper() == "BYTE") { var Temp = ""; @@ -1417,7 +1417,7 @@ public OptionalHeader(bool is32) if (!is32) { // X64没有了,但是为了代码保留修改幅度不大,所以置0 - BaseOfData = new byte[0];// x64必须置于0 + BaseOfData = [];// x64必须置于0 // x64长度增加的 var ulonglong = 8; ImageBase = new byte[ulonglong]; // 数据基址(RVA) @@ -1491,7 +1491,7 @@ public class ExportDirectory /// /// 函数指针名称集合 /// - public List FunctionNamesByte = new(); + public List FunctionNamesByte = []; public long FileStarIndex = 0; public long FileEndIndex = 0; @@ -1500,7 +1500,7 @@ public class ExportDirectory /// public HashSet FunctionNames() { - HashSet names = new(); + HashSet names = []; for (var i = 0; i < FunctionNamesByte.Count; i++) names.Add(Encoding.Default.GetString(FunctionNamesByte[i])); return names; diff --git a/CADShared/ResultData/LispList.cs b/CADShared/ResultData/LispList.cs index b097d9d..9de3669 100644 --- a/CADShared/ResultData/LispList.cs +++ b/CADShared/ResultData/LispList.cs @@ -164,7 +164,7 @@ public void Add(double x, double y, double z) /// lisp 列表 public void Add(LispList value) { - this.AddRange(value.Value); + AddRange(value.Value); } #endregion diff --git a/CADShared/ResultData/XDataList.cs b/CADShared/ResultData/XDataList.cs index 11f9754..ba4758c 100644 --- a/CADShared/ResultData/XDataList.cs +++ b/CADShared/ResultData/XDataList.cs @@ -90,7 +90,7 @@ public bool Contains(string appName, object value) /// 返回任务组码的索引 public List GetXdataAppIndex(string appName, DxfCode[] dxfCodes) { - List indexes = new(); + List indexes = []; RangeTask(appName, (tv, _, i) => { if (dxfCodes.Contains((DxfCode)tv.TypeCode)) @@ -109,7 +109,7 @@ private void RangeTask(string appName, Action action LoopState state = new(); // 在名称和名称之间找 var appNameIndex = -1; - for (var i = 0; i < this.Count; i++) + for (var i = 0; i < Count; i++) { if (this[i].TypeCode == (short)DxfCode.ExtendedDataRegAppName) { diff --git a/CADShared/ResultData/XRecordDataList.cs b/CADShared/ResultData/XRecordDataList.cs index 37e4520..10b95ba 100644 --- a/CADShared/ResultData/XRecordDataList.cs +++ b/CADShared/ResultData/XRecordDataList.cs @@ -57,7 +57,7 @@ public void Add(DxfCode code, object obj) ///
    /// ResultBuffer 实例 public static implicit operator XRecordDataList(ResultBuffer? buffer) => - buffer is null ? new() : new(buffer.AsArray()); + buffer is null ? [] : new(buffer.AsArray()); /// /// XRecordDataList 隐式转换到 TypedValue 数组 diff --git a/CADShared/Runtime/DBTrans.cs b/CADShared/Runtime/DBTrans.cs index e882e6b..bb951bc 100644 --- a/CADShared/Runtime/DBTrans.cs +++ b/CADShared/Runtime/DBTrans.cs @@ -166,7 +166,7 @@ public DBTrans(Document? doc = null, bool commit = true, bool docLock = false) public DBTrans(Database database, bool commit = true) { Database = database; - Document = Acap.DocumentManager.GetDocument(database); + Document = Acaop.DocumentManager.GetDocument(database); Editor = Document?.Editor; Transaction = Database.TransactionManager.StartTransaction(); _commit = commit; diff --git a/CADShared/Runtime/IdleAction.cs b/CADShared/Runtime/IdleAction.cs index ebcb297..7779641 100644 --- a/CADShared/Runtime/IdleAction.cs +++ b/CADShared/Runtime/IdleAction.cs @@ -31,7 +31,7 @@ public static class IdleAction public static void Add(Action action) { _actions.Enqueue(action); - if (alreadyLoad) + if (alreadyLoad) return; Acaop.Idle -= Acap_Idle; Acaop.Idle += Acap_Idle; diff --git a/CADShared/Runtime/IdleNoCommandAction.cs b/CADShared/Runtime/IdleNoCommandAction.cs index fde2f52..0767ea4 100644 --- a/CADShared/Runtime/IdleNoCommandAction.cs +++ b/CADShared/Runtime/IdleNoCommandAction.cs @@ -33,8 +33,8 @@ public static void Add(Action action) _actions.Enqueue(action); if (!alreadyLoad) { - Acap.Idle -= Acap_Idle; - Acap.Idle += Acap_Idle; + Acaop.Idle -= Acap_Idle; + Acaop.Idle += Acap_Idle; alreadyLoad = true; } } @@ -49,12 +49,12 @@ private static void Acap_Idle(object sender, EventArgs e) if (Count == 0) { alreadyLoad = false; - Acap.Idle -= Acap_Idle; + Acaop.Idle -= Acap_Idle; return; } // 判断是否有活动的命令 - if (Convert.ToBoolean(Acap.GetSystemVariable(CmdActiveName))) + if (Convert.ToBoolean(Acaop.GetSystemVariable(CmdActiveName))) return; #if RELEASE try diff --git a/CADShared/Runtime/SystemVariableManager.cs b/CADShared/Runtime/SystemVariableManager.cs index 967e509..d0b6506 100644 --- a/CADShared/Runtime/SystemVariableManager.cs +++ b/CADShared/Runtime/SystemVariableManager.cs @@ -14,8 +14,8 @@ public class SystemVariableManager /// public bool ApBox { - get => Convert.ToBoolean(Acap.GetSystemVariable(nameof(ApBox))); - set => Acap.SetSystemVariable(nameof(ApBox), Convert.ToInt32(value)); + get => Convert.ToBoolean(Acaop.GetSystemVariable(nameof(ApBox))); + set => Acaop.SetSystemVariable(nameof(ApBox), Convert.ToInt32(value)); } /// @@ -23,8 +23,8 @@ public bool ApBox /// public int Aperture { - get => Convert.ToInt32(Acap.GetSystemVariable(nameof(Aperture))); - set => Acap.SetSystemVariable(nameof(Aperture), value); + get => Convert.ToInt32(Acaop.GetSystemVariable(nameof(Aperture))); + set => Acaop.SetSystemVariable(nameof(Aperture), value); } /// @@ -32,8 +32,8 @@ public int Aperture /// public int Aunits { - get => Convert.ToInt32(Acap.GetSystemVariable(nameof(Aunits))); - set => Acap.SetSystemVariable(nameof(Aunits), value); + get => Convert.ToInt32(Acaop.GetSystemVariable(nameof(Aunits))); + set => Acaop.SetSystemVariable(nameof(Aunits), value); } /// @@ -41,8 +41,8 @@ public int Aunits /// public int Auprec { - get => Convert.ToInt32(Acap.GetSystemVariable(nameof(Auprec))); - set => Acap.SetSystemVariable(nameof(Auprec), value); + get => Convert.ToInt32(Acaop.GetSystemVariable(nameof(Auprec))); + set => Acaop.SetSystemVariable(nameof(Auprec), value); } #endregion @@ -52,7 +52,7 @@ public int Auprec /// /// 是否在块编辑器中 /// - public bool BlockEditor => Acap.GetSystemVariable(nameof(BlockEditor)) is 1; + public bool BlockEditor => Acaop.GetSystemVariable(nameof(BlockEditor)) is 1; #endregion @@ -61,25 +61,25 @@ public int Auprec /// /// 用于设置当前空间的当前注释比例的值 /// - public static string CanNoScale => Acap.GetSystemVariable(nameof(CanNoScale)).ToString(); + public static string CanNoScale => Acaop.GetSystemVariable(nameof(CanNoScale)).ToString(); /// /// 用于显示当前的注释性比例 /// - public static double CanNoScaleValue => Convert.ToDouble(Acap.GetSystemVariable(nameof(CanNoScale))); + public static double CanNoScaleValue => Convert.ToDouble(Acaop.GetSystemVariable(nameof(CanNoScale))); /// /// 储存以公元纪年为基准的日历数据和时间 /// - public static double CDate => Convert.ToDouble(Acap.GetSystemVariable(nameof(CDate))); + public static double CDate => Convert.ToDouble(Acaop.GetSystemVariable(nameof(CDate))); /// /// 设置新对象的颜色 /// public static string CEColor { - get => Acap.GetSystemVariable(nameof(CEColor)).ToString(); - set => Acap.SetSystemVariable(nameof(CEColor), value); + get => Acaop.GetSystemVariable(nameof(CEColor)).ToString(); + set => Acaop.SetSystemVariable(nameof(CEColor), value); } /// @@ -87,8 +87,8 @@ public static string CEColor /// public static double CELtScale { - get => Convert.ToDouble(Acap.GetSystemVariable(nameof(CELtScale))); - set => Acap.SetSystemVariable(nameof(CELtScale), value); + get => Convert.ToDouble(Acaop.GetSystemVariable(nameof(CELtScale))); + set => Acaop.SetSystemVariable(nameof(CELtScale), value); } /// @@ -96,8 +96,8 @@ public static double CELtScale /// public static string CELType { - get => Acap.GetSystemVariable(nameof(CELType)).ToString(); - set => Acap.SetSystemVariable(nameof(CELType), value); + get => Acaop.GetSystemVariable(nameof(CELType)).ToString(); + set => Acaop.SetSystemVariable(nameof(CELType), value); } /// @@ -105,8 +105,8 @@ public static string CELType /// public static double CELWeight { - get => Convert.ToDouble(Acap.GetSystemVariable(nameof(CELWeight))); - set => Acap.SetSystemVariable(nameof(CELWeight), value); + get => Convert.ToDouble(Acaop.GetSystemVariable(nameof(CELWeight))); + set => Acaop.SetSystemVariable(nameof(CELWeight), value); } /// @@ -114,8 +114,8 @@ public static double CELWeight /// public static double CircleRad { - get => Convert.ToDouble(Acap.GetSystemVariable(nameof(CircleRad))); - set => Acap.SetSystemVariable(nameof(CircleRad), value); + get => Convert.ToDouble(Acaop.GetSystemVariable(nameof(CircleRad))); + set => Acaop.SetSystemVariable(nameof(CircleRad), value); } /// @@ -123,51 +123,51 @@ public static double CircleRad /// public static string CLayer { - get => Acap.GetSystemVariable(nameof(CLayer)).ToString(); - set => Acap.SetSystemVariable(nameof(CLayer), value); + get => Acaop.GetSystemVariable(nameof(CLayer)).ToString(); + set => Acaop.SetSystemVariable(nameof(CLayer), value); } /// /// 用于确定全屏显示是打开或关闭状态 /// - public static bool CleanScreenState => Convert.ToBoolean(Acap.GetSystemVariable(nameof(CleanScreenState))); + public static bool CleanScreenState => Convert.ToBoolean(Acaop.GetSystemVariable(nameof(CleanScreenState))); /// /// 指示命令窗口是隐藏还是显示状态 /// - public static bool CliState => Convert.ToBoolean(Acap.GetSystemVariable(nameof(CliState))); + public static bool CliState => Convert.ToBoolean(Acaop.GetSystemVariable(nameof(CliState))); /// /// 存在活动命令 /// - public static bool CmdActive => Convert.ToBoolean(Acap.GetSystemVariable(nameof(CmdActive))); + public static bool CmdActive => Convert.ToBoolean(Acaop.GetSystemVariable(nameof(CmdActive))); /// /// 控制是否要打开对话框来显示命令 /// public static bool CmdDia { - get => Convert.ToBoolean(Acap.GetSystemVariable(nameof(CmdDia))); - set => Acap.SetSystemVariable(nameof(CmdDia), Convert.ToInt32(value)); + get => Convert.ToBoolean(Acaop.GetSystemVariable(nameof(CmdDia))); + set => Acaop.SetSystemVariable(nameof(CmdDia), Convert.ToInt32(value)); } /// /// 在使用 LISP 的函数时,切换回应为打开或关闭 /// - public static bool CmdEcho => Convert.ToBoolean(Acap.GetSystemVariable(nameof(CmdEcho))); + public static bool CmdEcho => Convert.ToBoolean(Acaop.GetSystemVariable(nameof(CmdEcho))); /// /// 当前的命令 /// - public static string CmdNames => Acap.GetSystemVariable(nameof(CmdNames)).ToString(); + public static string CmdNames => Acaop.GetSystemVariable(nameof(CmdNames)).ToString(); /// /// 返回图形中的当前选项卡(模型或布局)的名称 /// public static string CTab { - get => Acap.GetSystemVariable(nameof(CTab)).ToString(); - set => Acap.SetSystemVariable(nameof(CTab), value); + get => Acaop.GetSystemVariable(nameof(CTab)).ToString(); + set => Acaop.SetSystemVariable(nameof(CTab), value); } /// @@ -176,8 +176,8 @@ public static string CTab /// public static int CursorSize { - get => Convert.ToInt32(Acap.GetSystemVariable(nameof(CursorSize))); - set => Acap.SetSystemVariable(nameof(CursorSize), value); + get => Convert.ToInt32(Acaop.GetSystemVariable(nameof(CursorSize))); + set => Acaop.SetSystemVariable(nameof(CursorSize), value); } /// @@ -185,8 +185,8 @@ public static int CursorSize /// public static short CVPort { - get => Convert.ToInt16(Acap.GetSystemVariable(nameof(CVPort))); - set => Acap.SetSystemVariable(nameof(CVPort), value); + get => Convert.ToInt16(Acaop.GetSystemVariable(nameof(CVPort))); + set => Acaop.SetSystemVariable(nameof(CVPort), value); } #endregion @@ -198,22 +198,22 @@ public static short CVPort ///
    public static bool DblClick { - get => Convert.ToBoolean(Acap.GetSystemVariable(nameof(DblClick))); - set => Acap.SetSystemVariable(nameof(DblClick), Convert.ToInt32(value)); + get => Convert.ToBoolean(Acaop.GetSystemVariable(nameof(DblClick))); + set => Acaop.SetSystemVariable(nameof(DblClick), Convert.ToInt32(value)); } /// /// 指示图形的修改状态 /// - public static DBmod DBMod => (DBmod)Acap.GetSystemVariable(nameof(DBMod)); + public static DBmod DBMod => (DBmod)Acaop.GetSystemVariable(nameof(DBMod)); /// /// 动态输入 /// public static int DynMode { - get => Convert.ToInt32(Acap.GetSystemVariable(nameof(DynMode))); - set => Acap.SetSystemVariable(nameof(DynMode), value); + get => Convert.ToInt32(Acaop.GetSystemVariable(nameof(DynMode))); + set => Acaop.SetSystemVariable(nameof(DynMode), value); } /// @@ -221,8 +221,8 @@ public static int DynMode /// public static bool DynPrompt { - get => Convert.ToBoolean(Acap.GetSystemVariable(nameof(DynPrompt))); - set => Acap.SetSystemVariable(nameof(DynPrompt), Convert.ToInt32(value)); + get => Convert.ToBoolean(Acaop.GetSystemVariable(nameof(DynPrompt))); + set => Acaop.SetSystemVariable(nameof(DynPrompt), Convert.ToInt32(value)); } #endregion @@ -234,8 +234,8 @@ public static bool DynPrompt ///
    public bool GridMode { - get => Acap.GetSystemVariable(nameof(GridMode)) is 1; - set => Acap.SetSystemVariable(nameof(GridMode), Convert.ToInt32(value)); + get => Acaop.GetSystemVariable(nameof(GridMode)) is 1; + set => Acaop.SetSystemVariable(nameof(GridMode), Convert.ToInt32(value)); } #endregion @@ -247,12 +247,12 @@ public bool GridMode ///
    public static double HPScale { - get => Convert.ToDouble(Acap.GetSystemVariable(nameof(HPScale))); + get => Convert.ToDouble(Acaop.GetSystemVariable(nameof(HPScale))); set { if (value <= 0) throw new ArgumentOutOfRangeException(nameof(HPScale), "HPScale必须大于0"); - Acap.SetSystemVariable(nameof(HPScale), value); + Acaop.SetSystemVariable(nameof(HPScale), value); } } @@ -265,8 +265,8 @@ public static double HPScale ///
    public UnitsValue Insunits { - get => (UnitsValue)Acap.GetSystemVariable(nameof(Insunits)); - set => Acap.SetSystemVariable(nameof(Insunits), (int)value); + get => (UnitsValue)Acaop.GetSystemVariable(nameof(Insunits)); + set => Acaop.SetSystemVariable(nameof(Insunits), (int)value); } #endregion @@ -278,8 +278,8 @@ public UnitsValue Insunits ///
    public Point3d LastPoint { - get => (Point3d)Acap.GetSystemVariable(nameof(LastPoint)); - set => Acap.SetSystemVariable(nameof(LastPoint), value); + get => (Point3d)Acaop.GetSystemVariable(nameof(LastPoint)); + set => Acaop.SetSystemVariable(nameof(LastPoint), value); } /// @@ -287,8 +287,8 @@ public Point3d LastPoint /// public int Lunits { - get => Convert.ToInt32(Acap.GetSystemVariable(nameof(Lunits))); - set => Acap.SetSystemVariable(nameof(Lunits), value); + get => Convert.ToInt32(Acaop.GetSystemVariable(nameof(Lunits))); + set => Acaop.SetSystemVariable(nameof(Lunits), value); } /// @@ -296,8 +296,8 @@ public int Lunits /// public int Luprec { - get => Convert.ToInt32(Acap.GetSystemVariable(nameof(Luprec))); - set => Acap.SetSystemVariable(nameof(Luprec), value); + get => Convert.ToInt32(Acaop.GetSystemVariable(nameof(Luprec))); + set => Acaop.SetSystemVariable(nameof(Luprec), value); } #endregion @@ -309,8 +309,8 @@ public int Luprec ///
    public MeasurementValue Measurement { - get => (MeasurementValue)Acap.GetSystemVariable(nameof(Measurement)); - set => Acap.SetSystemVariable(nameof(Measurement), Convert.ToInt32(value)); + get => (MeasurementValue)Acaop.GetSystemVariable(nameof(Measurement)); + set => Acaop.SetSystemVariable(nameof(Measurement), Convert.ToInt32(value)); } #endregion @@ -322,8 +322,8 @@ public MeasurementValue Measurement ///
    public static bool OrthoMode { - get => Convert.ToBoolean(Acap.GetSystemVariable(nameof(OrthoMode))); - set => Acap.SetSystemVariable(nameof(OrthoMode), Convert.ToInt32(value)); + get => Convert.ToBoolean(Acaop.GetSystemVariable(nameof(OrthoMode))); + set => Acaop.SetSystemVariable(nameof(OrthoMode), Convert.ToInt32(value)); } #endregion @@ -335,15 +335,15 @@ public static bool OrthoMode ///
    public static bool PickFirst { - get => Convert.ToBoolean(Acap.GetSystemVariable(nameof(PickFirst))); - set => Acap.SetSystemVariable(nameof(PickFirst), Convert.ToInt32(value)); + get => Convert.ToBoolean(Acaop.GetSystemVariable(nameof(PickFirst))); + set => Acaop.SetSystemVariable(nameof(PickFirst), Convert.ToInt32(value)); } #endregion #region T - public static Point3d Target => (Point3d)Acap.GetSystemVariable(nameof(Target)); + public static Point3d Target => (Point3d)Acaop.GetSystemVariable(nameof(Target)); #endregion } \ No newline at end of file -- Gitee From 4a5cebdbc2c3c8fd084ec5d0062272df9d11f097 Mon Sep 17 00:00:00 2001 From: DYH <1742647821@qq.com> Date: Sun, 20 Oct 2024 21:45:38 +0800 Subject: [PATCH 331/453] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=9B=86=E5=90=88?= =?UTF-8?q?=E8=A1=A8=E8=BE=BE=E5=BC=8F=E4=BA=8C=E4=B9=89=E6=80=A7=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CADShared/ExtensionMethod/RedrawEx.cs | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/CADShared/ExtensionMethod/RedrawEx.cs b/CADShared/ExtensionMethod/RedrawEx.cs index 3cda7fa..e1deab2 100644 --- a/CADShared/ExtensionMethod/RedrawEx.cs +++ b/CADShared/ExtensionMethod/RedrawEx.cs @@ -1,4 +1,5 @@ namespace IFoxCAD.Cad; + /// /// 亮显模式 /// @@ -9,35 +10,43 @@ public enum BrightEntity /// 块更新 ///