1.exchange
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using Macad.Core;
-
- namespace Macad.Core
- {
- // 交换器注册表
- public static class ExchangeRegistry
- {
- // 交换器字典
- static readonly Dictionary
> _Exchangers = new Dictionary>(); -
- // 设置面板字典
- static readonly Dictionary
_ExchangerSettingPanels = new Dictionary(); -
- // 枚举和创建区域
-
- // 枚举指定类型的所有交换器
- public static IEnumerable<T> EnumerateExchanger<T>() where T : IExchanger
- {
- if (_Exchangers.TryGetValue(typeof(T), out var list))
- return list.Cast
(); - return new List
(); - }
-
- // 查找指定类型的交换器
- public static T FindExchanger<T>(string extension) where T : class, IExchanger
- {
- if (!_Exchangers.TryGetValue(typeof(T), out var list))
- return null;
-
- var lowerExtension = extension.ToLower();
- return list.FirstOrDefault(exchanger => exchanger.Extensions.Contains(lowerExtension)) as T;
- }
-
- // 判断指定类型的交换器是否支持导出到剪贴板
- public static bool CanExportToClipboard<T>() where T : IExchanger
- {
- if (!_Exchangers.TryGetValue(typeof(T), out var list))
- return false;
- return list.Any(exchanger => exchanger.CanExportToClipboard());
- }
-
- // 判断指定类型的交换器是否支持从剪贴板导入
- public static bool CanImportFromClipboard<T>(Clipboard clipboard) where T : IExchanger
- {
- if (!_Exchangers.TryGetValue(typeof(T), out var list))
- return false;
- return list.Any(exchanger => exchanger.CanImportFromClipboard(clipboard));
- }
-
- // 注册区域
-
- // 添加交换器到字典
- static void _AddExchanger(IExchanger exchanger, Type interfaceType)
- {
- if (!_Exchangers.TryGetValue(interfaceType, out var list))
- {
- list = new List
(); - _Exchangers.Add(interfaceType, list);
- }
-
- if (list.Exists(ex => ex.GetType() == exchanger.GetType()))
- {
- Messages.Warning($"Exchanger {exchanger.GetType().FullName} already registered for type {interfaceType.Name}");
- return;
- }
-
- list.Add(exchanger);
- }
-
- // 注册交换器
- public static void Register(IExchanger exchanger)
- {
- var interfaces = exchanger.GetType().GetInterfaces();
-
- foreach (var interfaceType in interfaces)
- {
- _AddExchanger(exchanger, interfaceType);
- }
- }
-
- // 注册设置面板
- public static void Register(IExchangerSettingsPanelCreator panelCreator)
- {
- if (_ExchangerSettingPanels.TryGetValue(panelCreator.ExchangerType, out var firstPanel))
- {
- Messages.Error($"Multiple setting panels registered for exchanger {panelCreator.ExchangerType.FullName}: {firstPanel.GetType().FullName} / {panelCreator.GetType().FullName}.");
- return;
- }
-
- _ExchangerSettingPanels.Add(panelCreator.ExchangerType, panelCreator);
- }
-
- // 查找交换器设置面板
- public static IExchangerSettingsPanelCreator FindExchangerSettingsPanel(IExchanger exchanger)
- {
- if (_ExchangerSettingPanels.TryGetValue(exchanger.GetType(), out var panelCreator))
- {
- return panelCreator;
- }
-
- return null;
- }
-
- // 设置区域
-
- // 保存设置
- public static void SaveSettings()
- {
- try
- {
- var settingsList = new Dictionary<string, IExchangerSettings>();
- var exchangers = _Exchangers.Values.SelectMany(list => list).Distinct();
- foreach (var exchanger in exchangers)
- {
- if (exchanger.Settings != null)
- settingsList.Add(exchanger.GetType().Name, exchanger.Settings);
- }
-
- CoreContext.Current.SaveLocalSettings("ExchangerSettings", settingsList);
- }
- catch (Exception)
- {
- return;
- }
- }
-
- // 加载设置
- public static void LoadSettings()
- {
- try
- {
- var settingsList = CoreContext.Current.LoadLocalSettings
string, IExchangerSettings>>("ExchangerSettings"); - if (settingsList == null || settingsList.Count == 0)
- return;
-
- var exchangers = _Exchangers.Values.SelectMany(list => list).Distinct();
- foreach (var exchanger in exchangers)
- {
- if (settingsList.TryGetValue(exchanger.GetType().Name, out var settingObj))
- exchanger.Settings = settingObj;
- }
- }
- catch (Exception)
- {
- return;
- }
- }
- }
- }
这段代码实现了一个交换器注册表,其中包含了注册、枚举、查找、设置保存和加载等功能:
2.
- using System;
- using System.Collections.Generic;
- using Macad.Common.Serialization;
-
- namespace Macad.Core
- {
- // 交换器设置接口
- [SerializeType]
- public interface IExchangerSettings
- {}
-
- //--------------------------------------------------------------------------------------------------
-
- // 交换器接口
- public interface IExchanger
- {
- string Description { get; } // 获取交换器描述
- string[] Extensions { get; } // 获取支持的文件扩展名
- IExchangerSettings Settings { get; set; } // 获取或设置交换器设置
-
- // 判断是否可以导出到剪贴板
- bool CanExportToClipboard();
-
- // 判断是否可以从剪贴板导入
- bool CanImportFromClipboard(Clipboard clipboard);
- }
-
- //--------------------------------------------------------------------------------------------------
-
- // 实体导出器接口
- public interface IBodyExporter : IExchanger
- {
- // 导出实体
- bool DoExport(string fileName, IEnumerable
bodies ); - }
-
- //--------------------------------------------------------------------------------------------------
-
- // 实体导入器接口
- public interface IBodyImporter : IExchanger
- {
- // 导入实体
- bool DoImport(string fileName, out IEnumerable
bodies ); - }
-
- //--------------------------------------------------------------------------------------------------
-
- // 草图导出器接口
- public interface ISketchExporter : IExchanger
- {
- // 导出草图到文件
- bool DoExport(string fileName, Shapes.Sketch sketch);
-
- // 导出草图到剪贴板
- bool DoExport(Clipboard clipboard, Shapes.Sketch sketch);
- }
-
- //--------------------------------------------------------------------------------------------------
-
- // 草图导入器接口
- public interface ISketchImporter : IExchanger
- {
- // 从文件导入草图
- bool DoImport(string fileName, out IDictionary<int, Occt.Pnt2d> points, out IDictionary<int, Shapes.SketchSegment> segments,
- out IEnumerable
constraints); -
- // 从剪贴板导入草图
- bool DoImport(Clipboard clipboard, out IDictionary<int, Occt.Pnt2d> points, out IDictionary<int, Shapes.SketchSegment> segments,
- out IEnumerable
constraints); - }
-
- //--------------------------------------------------------------------------------------------------
-
- // 绘图导出器接口
- public interface IDrawingExporter : IExchanger
- {
- // 导出绘图
- bool DoExport(string fileName, Drawing.Drawing drawing);
- }
-
- //--------------------------------------------------------------------------------------------------
-
- // 交换器设置面板创建器接口
- public interface IExchangerSettingsPanelCreator
- {
- Type ExchangerType { get; } // 获取交换器类型
- object CreatePanel<T>(IExchanger exchanger); // 创建交换器设置面板
- }
-
- //--------------------------------------------------------------------------------------------------
-
- }
这段代码定义了一系列交换器接口,包括实体导入导出器、草图导入导出器、绘图导出器以及交换器设置面板创建器。每个接口都定义了相应的方法,用于实现具体的导入导出操作。
3.framework
- using System;
- using Macad.Occt;
-
- namespace Macad.Core
- {
- // Bnd_Box 类型的扩展方法
- public static class BndBoxExtensions
- {
- // 获取边界框的中心点
- public static Pnt Center(this Bnd_Box box)
- {
- double xMin = 0, yMin = 0, zMin = 0, xMax = 0, yMax = 0, zMax = 0;
- box.Get(ref xMin, ref yMin, ref zMin, ref xMax, ref yMax, ref zMax );
- return new Pnt(
- xMin + (xMax - xMin) / 2,
- yMin + (yMax - yMin) / 2,
- zMin + (zMax - zMin) / 2 );
- }
-
- //--------------------------------------------------------------------------------------------------
-
- // 获取边界框的尺寸
- public static (double X, double Y, double Z) Extents(this Bnd_Box box)
- {
- double xMin = 0, yMin = 0, zMin = 0, xMax = 0, yMax = 0, zMax = 0;
- box.Get(ref xMin, ref yMin, ref zMin, ref xMax, ref yMax, ref zMax );
-
- return (Math.Abs(xMax - xMin), Math.Abs(yMax - yMin), Math.Abs(zMax - zMin));
- }
-
- //--------------------------------------------------------------------------------------------------
-
- // 获取边界框的最小和最大坐标值
- public static (double minX, double minY, double minZ, double maxX, double maxY, double maxZ) MinMax(this Bnd_Box box)
- {
- double xMin = 0, yMin = 0, zMin = 0, xMax = 0, yMax = 0, zMax = 0;
- box.Get(ref xMin, ref yMin, ref zMin, ref xMax, ref yMax, ref zMax );
-
- return (xMin, yMin, zMin, xMax, yMax, zMax);
- }
-
- //--------------------------------------------------------------------------------------------------
-
- }
- }
这段代码定义了针对 Bnd_Box 类型的扩展方法。这些方法使得可以方便地获取边界框的中心点、尺寸以及最小和最大坐标值。
4.
- using System;
- using Macad.Occt;
-
- namespace Macad.Core
- {
- // gp 类型的扩展方法
- public static class gpExtensions
- {
- #region Pnt
-
- // 将点坐标各维度取整
- public static Pnt Rounded(this Pnt pnt)
- {
- return new Pnt(pnt.X.Round(), pnt.Y.Round(), pnt.Z.Round());
- }
-
- //--------------------------------------------------------------------------------------------------
-
- // 交换两个点的值
- public static void Swap(this ref Pnt value, ref Pnt other)
- {
- Pnt temp = value;
- value = other;
- other = temp;
- }
-
- //--------------------------------------------------------------------------------------------------
-
- // 缩放点坐标
- public static Pnt Scaled(this Pnt pnt, double scale)
- {
- return new Pnt(pnt.X * scale, pnt.Y * scale, pnt.Z * scale);
- }
-
- //--------------------------------------------------------------------------------------------------
-
- #endregion
-
- #region Pnt2d
-
- // 将二维点坐标各维度取整
- public static Pnt2d Rounded(this Pnt2d pnt)
- {
- return new (pnt.X.Round(), pnt.Y.Round());
- }
-
- //--------------------------------------------------------------------------------------------------
-
- // 交换两个二维点的值
- public static void Swap(this ref Pnt2d value, ref Pnt2d other)
- {
- Pnt2d temp = value;
- value = other;
- other = temp;
- }
-
- //--------------------------------------------------------------------------------------------------
-
- // 两点之间进行线性插值
- public static Pnt2d Lerped(this Pnt2d value, Pnt2d other, double amount)
- {
- return new Pnt2d(value.X.Lerp(other.X, amount), value.Y.Lerp(other.Y, amount));
- }
-
- //--------------------------------------------------------------------------------------------------
-
- #endregion
-
- #region Vec2d
-
- // 两向量之间进行线性插值
- public static Vec2d Lerped(this Vec2d value, Vec2d other, double amount)
- {
- return new Vec2d(value.X.Lerp(other.X, amount), value.Y.Lerp(other.Y, amount));
- }
-
- //--------------------------------------------------------------------------------------------------
-
- #endregion
-
- #region Dir
-
- // 两个方向之间进行球形线性插值
- public static Dir Slerped(this Dir value, Dir other, double amount)
- {
- double dotProduct = value.Dot(other);
-
- // 确定两个向量之间的最短旋转方向
- if (dotProduct < 0)
- {
- other.Reverse();
- dotProduct = -dotProduct;
- }
-
- double angle = Math.Acos(dotProduct);
-
- if (Math.Abs(angle) < 0.000001f)
- {
- return value;
- }
-
- double invSinAngle = 1f / Math.Sin(angle);
- double factorA = Math.Sin((1f - amount) * angle) * invSinAngle;
- double factorB = Math.Sin(amount * angle) * invSinAngle;
-
- return new Dir(value.ToVec(factorA) + other.ToVec(factorB));
- }
-
- //--------------------------------------------------------------------------------------------------
-
- #endregion
-
- #region Pln
-
- // 获取平面的旋转四元数
- public static Quaternion Rotation(this Pln plane)
- {
- var mat = new Mat(
- plane.XAxis.Direction.Coord,
- plane.YAxis.Direction.Coord,
- plane.Axis.Direction.Coord);
- return new Quaternion(mat);
- }
-
- //--------------------------------------------------------------------------------------------------
-
- // 检查两个平面是否相等
- public static bool IsEqual(this Pln pln1, Pln pln2)
- {
- return pln1.Location.IsEqual(pln2.Location, Double.Epsilon)
- && pln1.Rotation().IsEqual(pln2.Rotation());
- }
-
- //--------------------------------------------------------------------------------------------------
-
- // 计算点在平面上的参数值
- public static Pnt2d Parameters(this Pln pln, Pnt pnt)
- {
- double u = 0, v = 0;
- ElSLib.Parameters(pln, pnt, ref u, ref v);
- return new Pnt2d(u, v);
- }
-
- //--------------------------------------------------------------------------------------------------
-
- // 计算平面上参数对应的点坐标
- public static Pnt Value(this Pln pln, Pnt2d uv)
- {
- return ElSLib.Value(uv.X, uv.Y, pln);
- }
-
- //--------------------------------------------------------------------------------------------------
-
- #endregion
-
- #region Quaternion
-
- // 将四元数转换为轴-角表示
- public static Ax3 ToAx3(this Quaternion rotation, Pnt location)
- {
- return new Ax3(location,
- rotation.Multiply(new Vec(0, 0, 1)).ToDir(),
- rotation.Multiply(new Vec(1, 0, 0)).ToDir());
- }
-
- //--------------------------------------------------------------------------------------------------
-
- // 将四元数转换为欧拉角表示
- public static (double yaw, double pitch, double roll) ToEuler(this Quaternion rotation)
- {
- double y = 0, p = 0, r = 0;
- rotation.GetEulerAngles(ref y, ref p, ref r);
- return (y, p, r);
- }
-
- //--------------------------------------------------------------------------------------------------
-
- #endregion
-
- #region Ax22d
-
- // 计算二维轴的方向
- public static int Sense(this Ax22d ax)
- {
- return ax.YAxis.Angle(ax.XAxis) > 0 ? 1 : -1;
- }
-
- //--------------------------------------------------------------------------------------------------
-
- #endregion
- }
- }
这段代码定义了针对 Pnt、Pnt2d、Vec2d、Dir、Pln、Quaternion 和 Ax22d 类型的扩展方法,提供了各种便捷的数学计算和操作功能。
5.
- using System;
- using System.Collections.Generic;
- using Macad.Occt;
-
- namespace Macad.Core
- {
- public static class ListExtensions
- {
- ///
- /// 检查 IEnumerable 中是否包含与给定的 TopoDS_Shape 相同的形状对象。
- ///
- public static bool ContainsSame<T>(this IEnumerable
list, TopoDS_Shape shape ) where T : TopoDS_Shape - {
- if (shape == null)
- {
- // 如果给定的形状为空,检查集合中是否存在空形状对象
- foreach (var item in list)
- {
- if (item == null)
- return true;
- }
- return false;
- }
- else
- {
- // 否则,检查集合中是否存在与给定形状相同的形状对象
- foreach (var item in list)
- {
- if (shape.IsSame(item))
- return true;
- }
- return false;
- }
- }
-
- ///
- /// 检查 IEnumerable 中是否包含与给定的 TopoDS_Shape 相似(partner)的形状对象。
- ///
- public static bool ContainsPartner<T>(this IEnumerable
list, TopoDS_Shape shape ) where T : TopoDS_Shape - {
- if (shape == null)
- {
- // 如果给定的形状为空,检查集合中是否存在空形状对象
- foreach (var item in list)
- {
- if (item == null)
- return true;
- }
- return false;
- }
- else
- {
- // 否则,检查集合中是否存在与给定形状相似(partner)的形状对象
- foreach (var item in list)
- {
- if (shape.IsPartner(item))
- return true;
- }
- return false;
- }
- }
-
- ///
- /// 返回 IList 中与给定的 TopoDS_Shape 相同的形状对象的索引。
- ///
- public static int IndexOfSame<T>(this IList
list, TopoDS_Shape item ) where T : TopoDS_Shape - {
- int size = list.Count;
- if (item == null)
- {
- // 如果给定的形状为空,返回列表中第一个空形状对象的索引
- for (int i = 0; i < size; i++)
- if (list[i] == null)
- return i;
- return -1;
- }
- else
- {
- // 否则,返回列表中与给定形状相同的形状对象的索引
- for (int i = 0; i < size; i++)
- {
- if (item.IsSame(list[i]))
- return i;
- }
- return -1;
- }
- }
- }
- }
这段代码定义了针对 IEnumerable 和 IList 接口的扩展方法,用于处理 TopoDS_Shape 类型的对象。
ContainsSame:检查 IEnumerable 中是否包含与给定的 TopoDS_Shape 相同的形状对象。
ContainsPartner:检查 IEnumerable 中是否包含与给定的 TopoDS_Shape 相似(partner)的形状对象。
IndexOfSame:返回 IList 中与给定的 TopoDS_Shape 相同的形状对象的索引。
这些方法允许在集合中查找相同或相似的形状对象,并提供了方便的方式来处理形状对象的列表。
6.
- using Macad.Occt;
-
- namespace Macad.Core
- {
- public static class TopLocExtension
- {
- ///
- /// 将 TopLoc_Location 对象转换为 Ax3 对象。
- ///
- public static Ax3 ToAx3(this TopLoc_Location rotation)
- {
- // 获取变换矩阵
- var trsf = rotation.Transformation();
- // 获取旋转部分并将其转换为 Ax3 对象,使用平移部分的 Pnt 作为位置点
- return trsf.GetRotation().ToAx3(trsf.TranslationPart().ToPnt());
- }
- }
- }
这个扩展方法允许将 TopLoc_Location 对象转换为 Ax3 对象,从而简化了代码中的操作。
7.
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.Linq;
- using Macad.Occt;
-
- namespace Macad.Core
- {
- public static class TopoDSShapeExtensions
- {
- ///
- /// 获取组合实体。
- ///
- public static List
CompSolids(this TopoDS_Shape shape, bool distinct = true) - {
- // 省略内容
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 获取实体。
- ///
- public static List
Solids(this TopoDS_Shape shape, bool distinct = true) - {
- // 省略内容
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 获取壳体。
- ///
- public static List
Shells(this TopoDS_Shape shape, bool distinct = true) - {
- // 省略内容
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 获取面。
- ///
- public static List
Faces(this TopoDS_Shape shape, bool distinct = true) - {
- Debug.Assert(shape != null);
-
- // 省略内容
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 获取线框。
- ///
- public static List
Wires(this TopoDS_Shape shape, bool distinct = true) - {
- // 省略内容
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 获取边。
- ///
- public static List
Edges(this TopoDS_Shape shape, bool distinct = true) - {
- // 省略内容
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 获取顶点。
- ///
- public static List
Vertices(this TopoDS_Shape shape, bool distinct = true) - {
- // 省略内容
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 获取质心。
- ///
- public static Pnt CenterOfMass(this TopoDS_Shape shape)
- {
- // 省略内容
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 获取面积。
- ///
- public static double Area(this TopoDS_Shape shape)
- {
- // 省略内容
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 获取体积。
- ///
- public static double Volume(this TopoDS_Shape shape)
- {
- // 省略内容
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 获取包围盒。
- ///
- public static Bnd_Box BoundingBox(this TopoDS_Shape shape)
- {
- // 省略内容
- }
-
- //--------------------------------------------------------------------------------------------------
-
- // 省略其他扩展方法
- }
- }
这些扩展方法用于检索给定形状(TopoDS_Shape)中包含的不同类型的子形状,例如组合实体、实体、壳体、面、线框、边和顶点。此外,还提供了一些计算几何特性的方法,如质心、面积、体积和包围盒。
8.
- using System;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.ComponentModel;
- using System.Linq;
- using System.Runtime.CompilerServices;
- using Macad.Core.Topology;
- using Macad.Occt;
- using Macad.Occt.Helper;
-
- namespace Macad.Core
- {
- public sealed class MessageHandler : IDisposable
- {
- #region Properties
-
- ///
- /// 获取或设置消息项集合。
- ///
- public ObservableCollection
MessageItems - {
- get { return _MessageItems; }
- set
- {
- if (_MessageItems != value)
- {
- _MessageItems = value;
- RaiseStaticPropertyChanged();
- }
- }
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 获取当前引用实体。
- ///
- public Entity CurrentReferenceEntity
- {
- get { return _ProcessingEntitiesStack.Count > 0 ? _ProcessingEntitiesStack.Peek() : null; }
- }
-
- //--------------------------------------------------------------------------------------------------
-
- #endregion
-
- #region Member
-
- ObservableCollection
_MessageItems; - ConditionalWeakTable
> _EntityMessages; -
- readonly Stack
_ProcessingEntitiesStack = new Stack(); -
- MessageRouter _MessageRouter;
-
- [ThreadStatic]
- static readonly bool _IsMainThread = true;
-
- //--------------------------------------------------------------------------------------------------
-
- #endregion
-
- #region Initialization and Property handling
-
- ///
- /// 构造函数。
- ///
- public MessageHandler()
- {
- _MessageItems = new ObservableCollection
(); - _EntityMessages = new ConditionalWeakTable
>(); -
- _MessageRouter = new MessageRouter();
- _MessageRouter.MessageArrived += _MessageRouter_MessageArrived;
- _MessageRouter.TraceLevel = Message_Gravity.Warning;
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 析构函数。
- ///
- ~MessageHandler()
- {
- Dispose(false);
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 释放资源。
- ///
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- //--------------------------------------------------------------------------------------------------
-
- void Dispose(bool disposing)
- {
- _MessageRouter?.Dispose();
- _MessageRouter = null;
- }
-
- //--------------------------------------------------------------------------------------------------
-
- void _MessageRouter_MessageArrived(string text, Message_Gravity gravity)
- {
- if (!_IsMainThread)
- {
- // 只接受主线程之外的其他线程发送的消息
- return;
- }
-
- MessageSeverity severity;
- switch (gravity)
- {
- case Message_Gravity.Trace:
- severity = MessageSeverity.Trace;
- break;
- case Message_Gravity.Info:
- severity = MessageSeverity.Info;
- break;
- case Message_Gravity.Warning:
- case Message_Gravity.Alarm:
- severity = MessageSeverity.Warning;
- break;
- case Message_Gravity.Fail:
- severity = MessageSeverity.Error;
- break;
- default:
- throw new ArgumentOutOfRangeException(nameof(gravity), gravity, null);
- }
-
- AddMessage(new MessageItem(severity, text));
- }
-
- //--------------------------------------------------------------------------------------------------
-
- public event EventHandler
StaticPropertyChanged; -
- public void RaiseStaticPropertyChanged([CallerMemberName] String propertyName = "")
- {
- StaticPropertyChanged?.Invoke(null, new PropertyChangedEventArgs(propertyName));
- }
-
- //--------------------------------------------------------------------------------------------------
-
- #endregion
-
- #region Messages
-
- public event EventHandler
MessageThrown; -
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 添加消息项。
- ///
- public void AddMessage(MessageItem message)
- {
- if (message.Sender != null && message.Sender.TryGetTarget(out var entity))
- {
- var list = _EntityMessages.GetValue(entity, key => new List
()); - list.Add(message);
- }
-
- _MessageItems.Add(message);
- MessageThrown?.Invoke(message.Sender, message);
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 清除指定实体的所有消息。
- ///
- public void ClearEntityMessages(Entity entity)
- {
- if (!_EntityMessages.TryGetValue(entity, out var messages))
- {
- return;
- }
-
- messages.ForEach(item => _MessageItems.Remove(item));
- _EntityMessages.Remove(entity);
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 清除所有实体的消息。
- ///
- public void ClearAllEntityMessages()
- {
- foreach (var item in _MessageItems.ToArray())
- {
- if(item.Sender == null)
- continue;
-
- _MessageItems.Remove(item);
- }
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 获取指定实体的消息。
- ///
- public List
GetEntityMessages(Entity entity) - {
- return _EntityMessages.TryGetValue(entity, out var list) ? list : null;
- }
-
- //--------------------------------------------------------------------------------------------------
-
- #endregion
-
- #region Processing
-
- ///
- /// 处理消息事件的原因。
- ///
- public enum ProgressMessageEventReason
- {
- ProcessingStarted,
- ProcessingStopped
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 处理消息事件参数。
- ///
- public class ProgressMessageEventArgs : EventArgs
- {
- public ProgressMessageEventReason Reason;
- public string Description;
-
- public ProgressMessageEventArgs(ProgressMessageEventReason reason, string description)
- {
- Reason = reason;
- Description = description;
- }
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 进度消息事件。
- ///
- public event EventHandler
ProgressMessage; -
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 当处理开始时调用。
- ///
- public void OnProcessingStarted(Entity referenceEntity, string description)
- {
- _ProcessingEntitiesStack.Push(referenceEntity);
-
- if (_ProcessingEntitiesStack.Count == 1)
- {
- ProgressMessage?.Invoke(this, new ProgressMessageEventArgs(ProgressMessageEventReason.ProcessingStarted, description));
- }
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 当处理结束时调用。
- ///
- public void OnProcessingStopped()
- {
- if (_ProcessingEntitiesStack.Count > 0)
- {
- _ProcessingEntitiesStack.Pop();
- }
-
- if (_ProcessingEntitiesStack.Count == 0)
- {
- ProgressMessage?.Invoke(this, new ProgressMessageEventArgs(ProgressMessageEventReason.ProcessingStopped, null));
- }
- }
-
- //--------------------------------------------------------------------------------------------------
-
- #endregion
- }
- }
这是一个用于处理消息的类。它包含了一些属性和方法来管理消息集合、处理消息的事件等。其中包括了消息的添加、清除、获取等操作,以及处理过程的开始和结束。
9.
- using System;
- using System.Text;
- using Macad.Core.Topology;
-
- namespace Macad.Core
- {
- ///
- /// 消息严重性级别枚举。
- ///
- public enum MessageSeverity
- {
- Trace = 0,
- Info = 1,
- Warning = 2,
- Error = 3
- }
-
- //--------------------------------------------------------------------------------------------------
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 消息项类。
- ///
- public class MessageItem
- {
- ///
- /// 获取时间戳。
- ///
- public DateTime TimeStamp { get; }
-
- ///
- /// 获取消息文本。
- ///
- public string Text { get; }
-
- ///
- /// 获取消息严重性级别。
- ///
- public MessageSeverity Severity { get; }
-
- ///
- /// 获取消息解释。
- ///
- public string[] Explanation { get; }
-
- ///
- /// 获取消息发送者的弱引用。
- ///
- public WeakReference
Sender { get; } -
- //--------------------------------------------------------------------------------------------------
-
- static readonly char[] _LineBreaks = { '\n', '\r' };
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 构造函数。
- ///
- public MessageItem(MessageSeverity severity, string text, string explanation=null, Entity sender=null)
- {
- TimeStamp = DateTime.Now;
- Severity = severity;
- Text = text;
- Sender = sender != null ? new WeakReference
(sender) : null; - Explanation = explanation?.Split(_LineBreaks, StringSplitOptions.RemoveEmptyEntries);
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 返回消息的字符串表示形式。
- ///
- public override string ToString()
- {
- var sb = new StringBuilder();
- switch (Severity)
- {
- case MessageSeverity.Trace:
- sb.Append("Trace: ");
- break;
- case MessageSeverity.Info:
- sb.Append("Info: ");
- break;
- case MessageSeverity.Warning:
- sb.Append("Warning: ");
- break;
- case MessageSeverity.Error:
- sb.Append("Error: ");
- break;
- }
-
- if (Sender != null && Sender.TryGetTarget(out var senderEntity))
- {
- sb.Append('[');
- sb.Append(senderEntity.Name);
- sb.Append("] ");
- }
-
- sb.AppendLine(Text);
- if (Explanation != null)
- {
- foreach (var s in Explanation)
- {
- sb.AppendLine(s);
- }
- }
-
- return sb.ToString();
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 返回消息的简略字符串表示形式。
- ///
- public string ToShortString()
- {
- string result;
- switch (Severity)
- {
- case MessageSeverity.Trace:
- result = "Trace: ";
- break;
- case MessageSeverity.Info:
- result = "Info: ";
- break;
- case MessageSeverity.Warning:
- result = "Warning: ";
- break;
- case MessageSeverity.Error:
- result = "Error: ";
- break;
- default:
- result = "";
- break;
- }
-
- return result + Text;
- }
-
- //--------------------------------------------------------------------------------------------------
-
- }
-
- }
这段代码定义了消息项类 MessageItem 和消息严重性级别枚举 MessageSeverity。消息项类包含了消息的时间戳、文本、严重性级别、解释和发送者的信息。
10.
- using System;
- using System.Runtime.InteropServices;
- using Macad.Core.Topology;
- using Macad.Occt;
-
- namespace Macad.Core
- {
- ///
- /// 消息类,提供发送各种消息的静态方法。
- ///
- public static class Messages
- {
- ///
- /// 发送跟踪消息。
- ///
- public static void Trace(string line, string explanation = null, Entity sender = null)
- {
- var handler = CoreContext.Current?.MessageHandler;
- handler?.AddMessage(new MessageItem(MessageSeverity.Trace, line, explanation, sender ?? handler.CurrentReferenceEntity));
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 发送信息消息。
- ///
- public static void Info(string line, string explanation = null, Entity sender = null)
- {
- var handler = CoreContext.Current?.MessageHandler;
- handler?.AddMessage(new MessageItem(MessageSeverity.Info, line, explanation, sender ?? handler.CurrentReferenceEntity));
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 发送警告消息。
- ///
- public static void Warning(string line, string explanation = null, Entity sender = null)
- {
- var handler = CoreContext.Current?.MessageHandler;
- handler?.AddMessage(new MessageItem(MessageSeverity.Warning, line, explanation, sender ?? handler.CurrentReferenceEntity));
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 发送错误消息。
- ///
- public static void Error(string line, string explanation = null, Entity sender = null)
- {
- var handler = CoreContext.Current?.MessageHandler;
- handler?.AddMessage(new MessageItem(MessageSeverity.Error, line, explanation, sender ?? handler.CurrentReferenceEntity));
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 发送异常消息。
- ///
- public static void Exception(string line, Exception exception, Entity sender = null)
- {
- string msg;
- if (exception is SEHException)
- {
- // 尝试从本地获取信息
- var info = Interop.ExceptionHelper.GetNativeExceptionInfo(Marshal.GetExceptionPointers());
- if (info != null)
- {
- msg = $"{info.Message} [{info.Source}]";
- }
- else
- {
- msg = "未知本地异常。";
- }
- }
- else
- {
- msg = $"{exception.Message} [ {exception.GetType().FullName} ]";
- }
-
- string expl = "异常: " + msg + "\n" + exception.StackTrace;
- var handler = CoreContext.Current?.MessageHandler;
- handler?.AddMessage(new MessageItem(MessageSeverity.Error, line, expl, sender ?? handler.CurrentReferenceEntity));
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 发送报告消息。
- ///
- public static void Report(Message_Report report)
- {
- report.SendMessages(Message.DefaultMessenger());
- }
-
- //--------------------------------------------------------------------------------------------------
-
- }
- }
这段代码定义了一个静态类 Messages,其中包含了用于发送各种消息的静态方法,如跟踪消息、信息消息、警告消息、错误消息、异常消息和报告消息。
11.
- using System;
- using Macad.Core.Topology;
-
- namespace Macad.Core
- {
- ///
- /// 表示一个处理范围,用于在其范围内开始和结束处理。
- ///
- public sealed class ProcessingScope : IDisposable
- {
- ///
- /// 初始化处理范围并开始处理。
- ///
- /// 参考实体。
- /// 描述处理的信息。
- public ProcessingScope(Entity referenceEntity, string description)
- {
- CoreContext.Current?.MessageHandler?.OnProcessingStarted(referenceEntity, description);
- }
-
- ///
- /// 处理范围的析构函数,结束处理。
- ///
- ~ProcessingScope()
- {
- Dispose();
- }
-
- ///
- public void Dispose()
- {
- CoreContext.Current?.MessageHandler?.OnProcessingStopped();
- GC.SuppressFinalize(this);
- }
- }
- }
这段代码定义了一个 ProcessingScope 类,它表示一个处理范围,用于在其范围内开始和结束处理。
12.
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using Macad.Core.Geom;
- using Macad.Core.Shapes;
- using Macad.Common;
- using Macad.Occt;
-
- namespace Macad.Core
- {
- #region 类 BRepTopologyTreeNodes
-
- ///
- /// 表示 BRepTopologyTreeNode 实例的集合。
- ///
- public class BRepTopologyTreeNodes : List<BRepTopologyTreeNode>
- {
- ///
- /// 使用指定的容量初始化 BRepTopologyTreeNodes 类的新实例。
- ///
- /// 列表可以包含的初始元素数。
- public BRepTopologyTreeNodes(int capacity)
- : base(capacity)
- {
- }
-
- ///
- /// 初始化 BRepTopologyTreeNodes 类的新实例。
- ///
- public BRepTopologyTreeNodes()
- {
- }
-
- ///
- /// 初始化 BRepTopologyTreeNodes 类的新实例,并将元素添加到指定的集合。
- ///
- /// 要复制到新列表中的集合的元素。
- public BRepTopologyTreeNodes(IEnumerable
collection ) - : base(collection)
- {
- }
- }
-
- #endregion
-
- #region 类 BRepTopologyTreeProperty
-
- ///
- /// 表示 B-Rep 拓扑树节点的属性。
- ///
- public class BRepTopologyTreeProperty
- {
- ///
- /// 获取属性的类别。
- ///
- public string Category { get; }
-
- ///
- /// 获取属性的名称。
- ///
- public string Name { get; }
-
- ///
- /// 获取属性的值。
- ///
- public string Value { get; }
-
- ///
- /// 使用指定的类别、名称和值初始化 BRepTopologyTreeProperty 类的新实例。
- ///
- /// 属性的类别。
- /// 属性的名称。
- /// 属性的值。
- public BRepTopologyTreeProperty(string category, string name, string value)
- {
- Category = category;
- Name = name;
- Value = value;
- }
- }
-
- #endregion
-
- #region 类 BRepTopologyTreeNode
-
- ///
- /// 表示 B-Rep 拓扑树中的节点。
- ///
- public class BRepTopologyTreeNode
- {
- #region 属性
-
- ///
- /// 获取节点的名称。
- ///
- public string Name { get; private set; }
-
- ///
- /// 获取节点的子节点。
- ///
- public BRepTopologyTreeNodes Children
- {
- get
- {
- // 如果子节点尚未初始化,则初始化它们
- if (_Children is null)
- _InitChildren();
- return _Children;
- }
- }
-
- ///
- /// 获取与节点关联的 B-Rep 形状。
- ///
- public TopoDS_Shape BrepShape { get; }
-
- ///
- /// 获取与节点关联的属性。
- ///
- public List
Properties - {
- get
- {
- // 如果属性尚未初始化,则初始化它们
- if (_Properties is null)
- _InitProperties();
- return _Properties;
- }
- }
-
- ///
- /// 获取与节点关联的形状。
- ///
- public Shape Shape { get; }
-
- #endregion
-
- #region 构造函数和设置器
-
- ///
- /// 使用指定的形状初始化 BRepTopologyTreeNode 类的新实例。
- ///
- /// 与节点关联的形状。
- public BRepTopologyTreeNode(Shape shape)
- {
- Shape = shape;
- BrepShape = shape?.GetBRep();
- _TopLevelShape = BrepShape;
-
- Name = "无效形状";
- if (BrepShape != null)
- {
- Name = _GetShapeTypeName(BrepShape.ShapeType());
- }
- }
-
- ///
- /// 使用指定的 B-Rep 形状初始化 BRepTopologyTreeNode 类的新实例。
- ///
- /// 与节点关联的 B-Rep 形状。
- /// 与节点关联的顶级形状。
- /// 与节点关联的形状。
- public BRepTopologyTreeNode(TopoDS_Shape brepShape, TopoDS_Shape topLevelShape = null, Shape shape = null)
- {
- Shape = shape;
- BrepShape = brepShape;
- _TopLevelShape = topLevelShape ?? brepShape;
-
- Name = "无效形状";
- if (brepShape != null)
- {
- Name = _GetShapeTypeName(brepShape.ShapeType());
- }
- }
-
- ///
- /// 使用指定的名称、包含的节点和顶级形状初始化 BRepTopologyTreeNode 类的新实例。
- ///
- /// 节点的名称。
- /// 此节点中包含的子节点。
- /// 与节点关联的顶级形状。
- /// 与节点关联的形状。
- public BRepTopologyTreeNode(string name, BRepTopologyTreeNodes containedNodes, TopoDS_Shape topLevelShape, Shape shape = null)
- {
- Shape = shape;
- Name = $"{name} ({containedNodes.Count})";
- _Children = containedNodes;
- _TopLevelShape = topLevelShape;
- _Properties = new List
(); - }
-
- ///
- /// 向节点名称添加索引前缀。
- ///
- /// 要添加为前缀的索引。
- public void AddIndexPrefix(int i)
- {
- Name = $"[{i}] {Name}";
- }
-
- #endregion
-
- #region 成员
-
- BRepTopologyTreeNodes _Children;
- List
_Properties; - readonly TopoDS_Shape _TopLevelShape;
-
- #endregion
-
- #region 子节点
-
- ///
- /// 初始化子节点。
- ///
- void _InitChildren()
- {
- if (_Children != null)
- return;
-
- if (BrepShape == null)
- return;
-
- _Children = new BRepTopologyTreeNodes();
-
- switch (BrepShape.ShapeType())
- {
- case TopAbs_ShapeEnum.COMPOUND:
- _AddShapeCollection(BrepShape.Solids(), true);
- _AddShapeCollection(BrepShape.Shells(), true);
- _AddShapeCollection(BrepShape.Faces(), true);
- _AddShapeCollection(BrepShape.Wires(), true);
- _AddShapeCollection(BrepShape.Edges(), true);
- _AddShapeCollection(BrepShape.Vertices(), true);
- break;
-
- case TopAbs_ShapeEnum.COMPSOLID:
- _AddShapeCollection(BrepShape.Solids());
- break;
-
- case TopAbs_ShapeEnum.SOLID:
- _AddShapeCollection(BrepShape.Shells(), true);
- _AddShapeCollection(BrepShape.Faces(), true);
- _AddShapeCollection(BrepShape.Wires(), true);
- _AddShapeCollection(BrepShape.Edges(), true);
- _AddShapeCollection(BrepShape.Vertices(), true);
- break;
-
- case TopAbs_ShapeEnum.SHELL:
- _AddShapeCollection(BrepShape.Faces(), true);
- _AddShapeCollection(BrepShape.Wires(), true);
- _AddShapeCollection(BrepShape.Edges(), true);
- _AddShapeCollection(BrepShape.Vertices(), true);
- break;
-
- case TopAbs_ShapeEnum.FACE:
- _AddShapeCollection(BrepShape.Wires());
- break;
-
- case TopAbs_ShapeEnum.WIRE:
- _AddShapeCollection(BrepShape.Edges());
- break;
-
- case TopAbs_ShapeEnum.EDGE:
- _AddShapeCollection(BrepShape.Vertices());
- break;
- }
- }
-
- #endregion
-
- #region 属性列表
-
- ///
- /// 初始化属性列表。
- ///
- void _InitProperties()
- {
- if (_Properties != null)
- return;
-
- _Properties = new List
(); - try
- {
- _AddDefaultProperties();
-
- switch (BrepShape.ShapeType())
- {
- case TopAbs_ShapeEnum.SHELL:
- _AddShellProperties(BrepShape as TopoDS_Shell ?? TopoDS.Shell(BrepShape));
- break;
-
- case TopAbs_ShapeEnum.FACE:
- _AddFaceProperties(BrepShape as TopoDS_Face ?? TopoDS.Face(BrepShape));
- break;
-
- case TopAbs_ShapeEnum.WIRE:
- _AddWireProperties(BrepShape as TopoDS_Wire ?? TopoDS.Wire(BrepShape));
- break;
-
- case TopAbs_ShapeEnum.EDGE:
- _AddEdgeProperties(BrepShape as TopoDS_Edge ?? TopoDS.Edge(BrepShape));
- break;
-
- case TopAbs_ShapeEnum.VERTEX:
- _AddVertexProperties(BrepShape as TopoDS_Vertex ?? TopoDS.Vertex(BrepShape));
- break;
- }
- }
- catch (Exception e)
- {
- Messages.Exception($"获取 B-Rep 形状 {Name} 的属性时出错", e);
- }
- }
-
- #endregion
-
- #region 集合
-
- ///
- /// 将形状集合添加到子节点。
- ///
- ///
形状的类型。 - /// 要添加到子节点的形状集合。
- /// 指示是否对集合进行分组。
- void _AddShapeCollection
(IReadOnlyList shapeList, bool group = false) where T: TopoDS_Shape - {
- if (!shapeList.Any())
- return;
-
- var collection = group ? new BRepTopologyTreeNodes() : _Children;
- for (var i = 0; i < shapeList.Count; i++)
- {
- var treeNode = new BRepTopologyTreeNode(shapeList[i], _TopLevelShape, Shape);
- treeNode.AddIndexPrefix(i);
- collection.Add(treeNode);
- }
-
- if (group)
- {
- var name = typeof(T).Name.TrimPrefixes("TopoDS_") + "s";
- if (name == "Vertexs")
- name = "Vertices";
-
- _Children.Add(new BRepTopologyTreeNode(name, collection, _TopLevelShape, Shape));
- }
- }
-
- #endregion
- }
-
- #endregion
- }
这段代码定义了一个名为BRepTopologyTreeNode的类,用于表示 B-Rep(Boundary Representation)拓扑树中的节点。B-Rep是一种用于描述实体几何形状的方法,它通过表示实体的边界以及边界之间的关系来描述几何形状。
该类的主要作用包括:
总之,该类用于构建和管理B-Rep拓扑树的节点,使用户能够方便地表示和操作复杂的几何形状结构。
13.
- using Macad.Common;
- using Macad.Occt;
-
- namespace Macad.Core
- {
- public static class OcctColorUtils
- {
- public static Color Color(Quantity_Color color)
- {
- var red = (float)color.Red();
- var green = (float)color.Green();
- var blue = (float)color.Blue();
- return new Color(red, green, blue);
- }
-
- //--------------------------------------------------------------------------------------------------
-
- public static Color Color(Quantity_NameOfColor colorName)
- {
- return Color(new Quantity_Color(colorName));
- }
-
- //--------------------------------------------------------------------------------------------------
-
- public static Quantity_Color ToColor(this Quantity_NameOfColor colorName)
- {
- return new Quantity_Color(colorName);
- }
-
- //--------------------------------------------------------------------------------------------------
-
- public static Graphic3d_MaterialAspect ToAspect(this Graphic3d_NameOfMaterial materialName)
- {
- return new Graphic3d_MaterialAspect(materialName);
- }
-
- //--------------------------------------------------------------------------------------------------
-
- public static Quantity_Color ToQuantityColor(this Color color)
- {
- return new Quantity_Color(color.Red, color.Green, color.Blue, Quantity_TypeOfColor.sRGB);
- }
-
- //--------------------------------------------------------------------------------------------------
- }
- }
整段代码的作用是提供了一些用于颜色和材质转换的工具方法。这些方法包括:
Quantity_Color类型的颜色转换为Color类型的颜色。Quantity_NameOfColor类型的颜色名称转换为Color类型的颜色。Quantity_NameOfColor类型的颜色名称转换为Quantity_Color类型的颜色。Graphic3d_NameOfMaterial类型的材质名称转换为Graphic3d_MaterialAspect类型的材质属性。Color类型的颜色转换为Quantity_Color类型的颜色。14.
- using System.Diagnostics; // 导入System.Diagnostics命名空间,提供Debug类的定义
- using Macad.Common.Serialization; // 导入Macad.Common.Serialization命名空间,提供序列化相关的类和接口
- using Macad.Occt; // 导入Macad.Occt命名空间,提供OpenCASCADE的类型定义
-
- namespace Macad.Core
- {
- public class OcctSerializers // 定义名为OcctSerializers的类,用于提供OpenCASCADE类型的序列化器
- {
- class OcctSerializer_Pnt2d : ISerializer // 定义内部类OcctSerializer_Pnt2d,实现ISerializer接口,用于Pnt2d类型的序列化
- {
- public bool Write(Writer writer, object obj, SerializationContext context)
- {
- var pnt2d = (Pnt2d)obj; // 将传入的对象转换为Pnt2d类型
- double[] values = { pnt2d.X, pnt2d.Y }; // 提取Pnt2d对象的坐标值
- return _DoubleArraySerializer.Write(writer, values, context); // 调用_DoubleArraySerializer对坐标值进行序列化
- }
-
- public object Read(Reader reader, object obj, SerializationContext context)
- {
- var values = (double[])_DoubleArraySerializer.Read(reader, null, context); // 从Reader中读取序列化的坐标值
- if ((values != null) && (values.Length == 2)) // 验证读取的坐标值是否正确
- {
- return new Pnt2d(values[0], values[1]); // 创建新的Pnt2d对象并返回
- }
- return null; // 如果读取的坐标值不正确,则返回null
- }
- }
-
- //--------------------------------------------------------------------------------------------------
-
- // 类似地定义其他OpenCASCADE类型的序列化器,包括Pnt、Vec、Dir、Quaternion、Ax1、Ax2和Pln
- // 每个序列化器都包括Write和Read方法,用于将对象序列化为数组或从数组中反序列化为对象
-
- //--------------------------------------------------------------------------------------------------
-
- static bool _IsInitialized; // 静态变量,标识是否已初始化
- static ISerializer _DoubleArraySerializer; // 静态变量,用于序列化double数组
-
- public static void Init() // 初始化方法,用于注册OpenCASCADE类型的序列化器
- {
- Debug.Assert(!_IsInitialized); // 确保尚未初始化
-
- _DoubleArraySerializer = Serializer.GetSerializer(typeof(double[])); // 获取序列化double数组的序列化器
-
- // 注册各个OpenCASCADE类型的序列化器
- Serializer.AddSerializer(typeof(Pnt), new OcctSerializer_Pnt());
- Serializer.AddSerializer(typeof(Pnt2d), new OcctSerializer_Pnt2d());
- Serializer.AddSerializer(typeof(Vec), new OcctSerializer_Vec());
- Serializer.AddSerializer(typeof(Dir), new OcctSerializer_Dir());
- Serializer.AddSerializer(typeof(Quaternion), new OcctSerializer_Quaternion());
- Serializer.AddSerializer(typeof(Ax1), new OcctSerializer_Ax1());
- Serializer.AddSerializer(typeof(Ax2), new OcctSerializer_Ax2());
- Serializer.AddSerializer(typeof(Pln), new OcctSerializer_Pln());
-
- _IsInitialized = true; // 设置初始化标志为true
- }
-
- //--------------------------------------------------------------------------------------------------
-
- }
- }
这段代码定义了一系列用于OpenCASCADE类型的序列化器,包括Pnt、Pnt2d、Vec、Dir、Quaternion、Ax1、Ax2和Pln。每个序列化器都实现了ISerializer接口,包括Write方法用于将对象序列化为数组,以及Read方法用于从数组中反序列化为对象。在初始化方法Init中,这些序列化器被注册到了全局的Serializer对象中,以便在序列化和反序列化过程中使用。
15.
- using System; // 导入System命名空间,提供基本的系统类型和功能
- using Macad.Common.Serialization; // 导入Macad.Common.Serialization命名空间,提供序列化相关的类和接口
- using Macad.Occt; // 导入Macad.Occt命名空间,提供OpenCASCADE的类型定义
-
- namespace Macad.Core
- {
- [SerializeType] // 标记该枚举类型可被序列化
- public enum SubshapeType // 定义名为SubshapeType的枚举类型,用于表示子形状的类型
- {
- Vertex, // 顶点
- Edge, // 边
- Wire, // 线
- Face // 面
- }
-
- //--------------------------------------------------------------------------------------------------
-
- [SerializeType] // 标记该枚举类型可被序列化
- [Flags] // 标记该枚举为位标志枚举
- public enum SubshapeTypes // 定义名为SubshapeTypes的枚举类型,用于表示多个子形状的组合类型
- {
- None = 0, // 无
- Vertex = 1 << 0, // 顶点
- Edge = 1 << 1, // 边
- Wire = 1 << 2, // 线
- Face = 1 << 4, // 面
- All = Vertex | Edge | Wire | Face // 全部类型的组合
- }
-
- //--------------------------------------------------------------------------------------------------
-
- public static class SubshapeTypeHelper // 定义名为SubshapeTypeHelper的静态类,包含一些用于子形状类型操作的方法
- {
- public static SubshapeTypes GetTypes(SubshapeType topAbsShapeEnum) // 返回给定SubshapeType枚举值对应的SubshapeTypes位标志值
- {
- switch (topAbsShapeEnum)
- {
- case SubshapeType.Face:
- return SubshapeTypes.Face;
-
- case SubshapeType.Edge:
- return SubshapeTypes.Edge;
-
- case SubshapeType.Wire:
- return SubshapeTypes.Wire;
-
- case SubshapeType.Vertex:
- return SubshapeTypes.Vertex;
-
- default:
- throw new NotImplementedException(); // 抛出未实现异常
- }
- }
-
- //--------------------------------------------------------------------------------------------------
-
- // 类似地定义其他用于获取子形状类型的方法,包括GetType和GetTypes方法
-
- //--------------------------------------------------------------------------------------------------
-
- public static TopAbs_ShapeEnum ToTopAbs(this SubshapeType type) // 将SubshapeType枚举值转换为TopAbs_ShapeEnum值
- {
- switch (type)
- {
- case SubshapeType.Vertex:
- return TopAbs_ShapeEnum.VERTEX;
- case SubshapeType.Edge:
- return TopAbs_ShapeEnum.EDGE;
- case SubshapeType.Wire:
- return TopAbs_ShapeEnum.WIRE;
- case SubshapeType.Face:
- return TopAbs_ShapeEnum.FACE;
- default:
- throw new NotImplementedException(); // 抛出未实现异常
- }
- }
-
- //--------------------------------------------------------------------------------------------------
-
- // 类似地定义其他用于转换子形状类型的方法,包括ToAisSelectionMode和Count方法
-
- //--------------------------------------------------------------------------------------------------
-
- }
- }
这段代码定义了用于处理子形状类型的枚举和辅助方法。首先定义了SubshapeType枚举,表示子形状的具体类型,包括顶点、边、线和面。然后定义了SubshapeTypes枚举,表示多个子形状类型的组合,使用了位标志枚举的特性。接着定义了SubshapeTypeHelper静态类,包含了一系列用于处理子形状类型的方法,包括获取子形状类型、转换类型以及计数等。这些方法可以方便地处理子形状类型的操作和转换。
16.
- using System; // 导入System命名空间,提供基本的系统类型和功能
- using System.Collections.Generic; // 导入System.Collections.Generic命名空间,提供泛型集合类型的支持
- using Macad.Occt; // 导入Macad.Occt命名空间,提供OpenCASCADE的类型定义
-
- namespace Macad.Core // 声明名为Macad.Core的命名空间,该类位于Macad.Core命名空间下
- {
- public class TopoDSShapeComparer : IEqualityComparer<TopoDS_Shape> // 定义名为TopoDSShapeComparer的类,实现了IEqualityComparer
接口,用于比较TopoDS_Shape对象 - {
- public enum CompareMode // 定义名为CompareMode的枚举类型,表示比较模式
- {
- Equal, // 相等
- Same, // 相同
- Partner // 伙伴
- }
-
- //--------------------------------------------------------------------------------------------------
-
- CompareMode _Mode = CompareMode.Equal; // 声明名为_Mode的字段,用于存储比较模式,默认为Equal
-
- //--------------------------------------------------------------------------------------------------
-
- public TopoDSShapeComparer(CompareMode mode) // 定义TopoDSShapeComparer类的构造函数,初始化比较模式
- {
- _Mode = mode; // 将传入的比较模式赋值给_Mode字段
- }
-
- //--------------------------------------------------------------------------------------------------
-
- public bool Equals(TopoDS_Shape x, TopoDS_Shape y) // 实现IEqualityComparer
接口中的Equals方法,用于比较两个TopoDS_Shape对象是否相等 - {
- if (x == null) // 如果第一个对象为null
- return y == null; // 则当第二个对象也为null时返回true,否则返回false
-
- return _Mode switch // 根据比较模式进行比较
- {
- CompareMode.Equal => x.Equals(y), // 如果比较模式为Equal,则调用Equals方法比较对象是否相等
- CompareMode.Same => x.IsSame(y), // 如果比较模式为Same,则调用IsSame方法比较对象是否相同
- CompareMode.Partner => x.IsPartner(y), // 如果比较模式为Partner,则调用IsPartner方法比较对象是否为伙伴
- _ => false // 默认情况下返回false
- };
- }
-
- //--------------------------------------------------------------------------------------------------
-
- public int GetHashCode(TopoDS_Shape obj) // 实现IEqualityComparer
接口中的GetHashCode方法,用于获取对象的哈希码 - {
- return _Mode switch // 根据比较模式获取哈希码
- {
- CompareMode.Equal => obj.GetHashCode(), // 如果比较模式为Equal,则直接返回对象的哈希码
- CompareMode.Same => obj.TShape().GetHashCode() ^ obj.Location().GetHashCode(), // 如果比较模式为Same,则获取对象的TShape和Location的哈希码,并进行异或操作
- CompareMode.Partner => obj.TShape().GetHashCode(), // 如果比较模式为Partner,则只获取对象的TShape的哈希码
- _ => 0 // 默认情况下返回0
- };
- }
- }
- }
这段代码定义了一个名为TopoDSShapeComparer的类,用于比较TopoDS_Shape对象。它实现了IEqualityComparer接口,其中T是TopoDS_Shape类型。类中包含了一个枚举CompareMode,表示比较模式,包括相等、相同和伙伴。类中包含了一个字段 _Mode,用于存储比较模式,默认为相等。类中包含了构造函数用于初始化比较模式,以及Equals方法用于比较两个对象是否相等,GetHashCode方法用于获取对象的哈希码。
17.
- using System; // 导入System命名空间,提供基本的系统类型和功能
- using System.Collections.Generic; // 导入System.Collections.Generic命名空间,提供泛型集合类型的支持
- using System.IO; // 导入System.IO命名空间,提供文件和流的操作功能
-
- namespace Macad.Core // 声明名为Macad.Core的命名空间,该类位于Macad.Core命名空间下
- {
- internal static class ScriptCache // 声明名为ScriptCache的静态类,用于脚本缓存管理
- {
- struct CachedScriptFileInfo // 定义名为CachedScriptFileInfo的结构体,用于存储缓存的脚本文件信息
- {
- internal string FileName; // 存储文件名
- internal long Length; // 存储文件长度
- internal DateTime LastWriteTime; // 存储文件最后写入时间
- }
-
- class CachedScript // 定义名为CachedScript的内部类,用于存储缓存的脚本实例及其文件信息
- {
- internal ScriptInstance Instance; // 存储脚本实例
- internal CachedScriptFileInfo[] FileInfos; // 存储脚本文件信息数组
- }
-
- //--------------------------------------------------------------------------------------------------
-
- static readonly Dictionary<string, CachedScript> _CachedScripts = new Dictionary<string, CachedScript>(); // 声明名为_CachedScripts的静态只读字典,用于存储缓存的脚本信息
-
- //--------------------------------------------------------------------------------------------------
-
- internal static void Add(ScriptInstance scriptInstance, List<string> fileList) // 声明名为Add的静态方法,用于向脚本缓存中添加脚本实例及其文件信息
- {
- var entry = new CachedScript // 创建CachedScript实例
- {
- Instance = scriptInstance, // 设置脚本实例
- FileInfos = new CachedScriptFileInfo[fileList.Count], // 创建缓存的脚本文件信息数组
- };
-
- for (var i = 0; i < fileList.Count; i++) // 遍历文件列表
- {
- var fi = new FileInfo(fileList[i]); // 获取文件信息
- var info = new CachedScriptFileInfo() // 创建CachedScriptFileInfo实例
- {
- FileName = fileList[i], // 设置文件名
- Length = fi.Length, // 设置文件长度
- LastWriteTime = fi.LastWriteTimeUtc // 设置文件最后写入时间
- };
- entry.FileInfos[i] = info; // 将文件信息添加到缓存的文件信息数组中
- }
-
- _CachedScripts[scriptInstance.Path] = entry; // 将脚本实例路径及其对应的缓存信息添加到缓存字典中
- }
-
- //--------------------------------------------------------------------------------------------------
-
- internal static ScriptInstance Find(string filename) // 声明名为Find的静态方法,用于在缓存中查找指定路径的脚本实例
- {
- try
- {
- filename = Path.GetFullPath(filename); // 获取指定路径的绝对路径
- if (!_CachedScripts.TryGetValue(filename, out CachedScript entry)) // 判断缓存字典中是否包含指定路径的缓存信息
- return null; // 如果不包含,则返回null
-
- foreach (var info in entry.FileInfos) // 遍历缓存的文件信息数组
- {
- var fi = new FileInfo(info.FileName); // 获取文件信息
- if (fi.Length != info.Length // 检查文件长度和最后写入时间是否匹配
- || fi.LastWriteTimeUtc != info.LastWriteTime)
- {
- // Cache miss,如果不匹配,则返回null
- return null;
- }
- }
-
- // Cache hit,如果匹配,则返回对应的脚本实例
- return entry.Instance;
- }
- catch (Exception)
- {
- return null; // 发生异常时返回null
- }
- }
-
- //--------------------------------------------------------------------------------------------------
-
- internal static void Clear() // 声明名为Clear的静态方法,用于清空缓存字典
- {
- _CachedScripts.Clear(); // 清空缓存字典
- }
-
- //--------------------------------------------------------------------------------------------------
-
- }
- }
这段代码定义了一个名为 ScriptCache 的静态类,用于管理脚本的缓存。它包含了一个内部结构 CachedScriptFileInfo,用于存储缓存的脚本文件信息,以及一个内部类 CachedScript,用于存储缓存的脚本实例及其文件信息。类中声明了一个静态只读字典 _CachedScripts,用于存储缓存的脚本信息。还包含了方法 Add 用于向缓存中添加脚本实例及其文件信息,方法 Find 用于在缓存中查找指定路径的脚本实例,以及方法 Clear 用于清空缓存字典。
18.
- using System; // 导入 System 命名空间,提供基本的系统类型和功能
- using System.Collections.Generic; // 导入 System.Collections.Generic 命名空间,提供泛型集合类型的支持
- using System.Collections.Immutable; // 导入 System.Collections.Immutable 命名空间,提供不可变集合类型的支持
- using System.Globalization; // 导入 System.Globalization 命名空间,提供区域性特定信息的功能
- using System.IO; // 导入 System.IO 命名空间,提供文件和流的操作功能
- using System.Linq; // 导入 System.Linq 命名空间,提供 LINQ 查询功能
- using System.Reflection; // 导入 System.Reflection 命名空间,提供反射操作的功能
- using System.Runtime.Loader; // 导入 System.Runtime.Loader 命名空间,提供程序集加载器的功能
- using System.Text; // 导入 System.Text 命名空间,提供字符串处理功能
- using Microsoft.CodeAnalysis; // 导入 Microsoft.CodeAnalysis 命名空间,提供编译代码分析的功能
- using Microsoft.CodeAnalysis.CSharp; // 导入 Microsoft.CodeAnalysis.CSharp 命名空间,提供 C# 编译器的功能
- using Microsoft.CodeAnalysis.CSharp.Scripting; // 导入 Microsoft.CodeAnalysis.CSharp.Scripting 命名空间,提供 C# 脚本编译的功能
- using Microsoft.CodeAnalysis.Scripting; // 导入 Microsoft.CodeAnalysis.Scripting 命名空间,提供脚本编译的功能
- using Macad.Common; // 导入 Macad.Common 命名空间,提供通用功能
- using Macad.Occt; // 导入 Macad.Occt 命名空间,提供 OCC 相关功能
- using Microsoft.CodeAnalysis.Scripting.Hosting; // 导入 Microsoft.CodeAnalysis.Scripting.Hosting 命名空间,提供脚本主机环境的功能
-
- namespace Macad.Core // 声明名为 Macad.Core 的命名空间,该类位于 Macad.Core 命名空间下
- {
- internal sealed class ScriptCompiler // 声明名为 ScriptCompiler 的密封类,用于编译脚本
- {
- static readonly string[] _DefaultReferenceAppAssemblies = // 默认的引用应用程序集
- {
- "Macad.Occt.dll",
- "Macad.Managed.dll",
- "Macad.Common.dll",
- "Macad.Core.dll",
- "Macad.Presentation.dll",
- "Macad.Interaction.dll",
- "Macad.Resources.dll"
- };
-
- static readonly string[] _DefaultImports = // 默认的导入命名空间
- {
- "System",
- "Macad.Common",
- "Macad.Core",
- "Macad.Core.Shapes",
- "Macad.Core.Toolkits",
- "Macad.Core.Topology",
- "Macad.Occt",
- };
-
- static readonly string[] _MetadataSearchPaths = // 元数据搜索路径
- {
- Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
- Path.GetDirectoryName(typeof(object).Assembly.Location)
- };
-
- //--------------------------------------------------------------------------------------------------
-
- static float _Version; // 版本号
-
- //--------------------------------------------------------------------------------------------------
-
- static ScriptCompiler() // 静态构造函数
- {
- var version = Assembly.GetExecutingAssembly().GetName().Version; // 获取当前程序集的版本
- _Version = float.Parse($"{version.Major}.{version.Minor}", CultureInfo.InvariantCulture); // 解析版本号
- }
-
- //--------------------------------------------------------------------------------------------------
-
- internal static void OverrideVersion(float version) // 重写版本号
- {
- _Version = version; // 设置版本号
- }
-
- //--------------------------------------------------------------------------------------------------
-
- internal static bool Compile(ScriptInstance scriptInstance) // 编译脚本
- {
- var compiler = new ScriptCompiler(scriptInstance); // 创建 ScriptCompiler 实例
- if (!compiler._Compile()) // 调用 _Compile 方法进行编译
- return false; // 如果编译失败,返回 false
-
- ScriptCache.Add(scriptInstance, compiler._FileList); // 将编译结果添加到脚本缓存中
-
- return true; // 返回编译成功
- }
-
- //--------------------------------------------------------------------------------------------------
-
- readonly ScriptInstance _ScriptInstance; // 脚本实例
- readonly List<string> _FileList = new List<string>(); // 文件列表
- readonly bool _EnableDebugging = true; // 是否启用调试
-
- //--------------------------------------------------------------------------------------------------
-
- ScriptCompiler(ScriptInstance scriptInstance) // ScriptCompiler 构造函数
- {
- _ScriptInstance = scriptInstance; // 设置脚本实例
- }
-
- //--------------------------------------------------------------------------------------------------
-
- bool _Compile() // 编译
- {
- try
- {
- var codeStream = _ReadAndPreprocessFile(_ScriptInstance.Path); // 读取并预处理文件
- if (codeStream == null)
- return false;
-
- var baseDirectory = Path.GetDirectoryName(_ScriptInstance.Path); // 获取基目录
-
- var metadataResolver = ScriptMetadataResolver.Default // 元数据解析器
- .WithSearchPaths(_MetadataSearchPaths)
- .WithBaseDirectory(baseDirectory);
-
- var sourceResolver = new ScriptSourceResolver(baseDirectory, _ReadAndPreprocessFile); // 源代码解析器
-
- var options = ScriptOptions.Default // 脚本选项
- .WithWarningLevel(4)
- .WithReferences(_DefaultReferenceAppAssemblies)
- .WithMetadataResolver(metadataResolver)
- .WithSourceResolver(sourceResolver)
- .WithImports(_DefaultImports)
- .WithEmitDebugInformation(_EnableDebugging)
- .WithLanguageVersion(LanguageVersion.Latest);
-
- var assemblyLoader = new InteractiveAssemblyLoader(); // 装载程序集
- foreach (var defaultAssembly in AssemblyLoadContext.Default.Assemblies) // 加载默认程序集
- {
- assemblyLoader.RegisterDependency(defaultAssembly);
- }
- // This extra reference is needed for unit test runner which isolate this assembly
- assemblyLoader.RegisterDependency(Assembly.GetExecutingAssembly()); // 注册依赖程序集
-
- var script = CSharpScript.Create(codeStream, options, _ScriptInstance.ContextInstance.GetType(), assemblyLoader); // 创建脚本
- var results = script.Compile(); // 编译脚本
- codeStream.Dispose(); // 释放流资源
-
- var hasErrors = _ReportResults(results); // 检查编译结果
- if (!hasErrors) // 如果没有错误
- {
- return _ScriptInstance.Init(script.CreateDelegate()); // 初始化脚本实例
- }
- }
- catch (Exception e) // 捕获异常
- {
- Messages.Exception("Script compilation failed. Scriptfile: " + _ScriptInstance.Path, e); // 报告异常
- }
- return false; // 返回编译失败
- }
-
- //--------------------------------------------------------------------------------------------------
-
- Stream _ReadAndPreprocessFile(string filename) // 读取并预处理文件
- {
- if (!File.Exists(filename)) // 检查文件是否存在
- {
- Messages.Error($"Script imported file {filename} not found. Scriptfile: {_ScriptInstance.Path}"); // 报告错误
- return null; // 返回空流
- }
-
- if (!_FileList.Contains(filename)) // 检查文件列表中是否包含该文件
- {
- _FileList.Add(filename); // 添加文件到文件列表
- }
-
- var ms = new MemoryStream(); // 创建内存流
- using StreamWriter sw = new StreamWriter(ms, Encoding.Unicode, 1024, true); // 创建写入器
-
- sw.WriteLine($"#line 1 \"{Path.GetFileName(filename)}\""); // 写入 #line 指令
-
- bool inComment = false; // 是否在注释中
- int lineNumber = 0; // 行号
- using (var reader = File.OpenText(filename)) // 使用文件读取器读取文件
- {
- while (!reader.EndOfStream) // 循环读取每行
- {
- var rawLine = reader.ReadLine(); // 读取原始行
- if (rawLine == null)
- break;
- var line = rawLine.Trim().ToLower(); // 去除首尾空白并转换为小写
-
- lineNumber++; // 行号递增
-
- if (line.IsNullOrWhiteSpace()) // 检查是否为空行
- {
- sw.WriteLine(rawLine); // 写入空行
- continue;
- }
-
- // We are in a comment block
- if (inComment) // 如果在注释块中
- {
- var posStart = line.LastIndexOf("/*", StringComparison.Ordinal); // 获取注释块起始位置
- var posEnd = line.LastIndexOf("*/", StringComparison.Ordinal); // 获取注释块结束位置
- if (posEnd > posStart) // 如果结束位置大于起始位置
- {
- // Comment closed
- inComment = false; // 标记注释块关闭
-
- // only continue if no code follows
- if (!line.EndsWith("*/")) // 如果注释块后还有代码
- continue;
- }
-
- // Comment continues
- sw.WriteLine(rawLine); // 写入注释行
- continue;
- }
-
- // Pragma
- if (line.StartsWith("#")) // 如果是 #pragma 指令
- {
- if (line.StartsWith("#if ") || line.StartsWith("#elif ")) // 如果是条件编译指令
- {
- var second = line.Substring(line.IndexOf(' ') + 1).Trim(); // 获取条件表达式
- if (second.StartsWith("version ")) // 如果是版本判断
- {
- var value = second.Substring(8); // 获取版本号值
- var substitute = _ProcessVersion(value); // 处理版本号
- if (substitute == null) // 如果处理失败
- {
- Messages.Error($"Script error in line {lineNumber}: The version expression is invalid. Scriptfile: {_ScriptInstance.Path}."); // 报告错误
- ms.Close(); // 关闭流
- return null; // 返回空流
- }
-
- sw.Write(rawLine.Substring(0, rawLine.IndexOf('#'))); // 写入 #pragma 指令之前的部分
- sw.Write(line.Substring(0, line.IndexOf(' ') + 1)); // 写入 #pragma 指令
- sw.WriteLine(substitute + " // version " + value); // 写入替换后的版本号表达式
- continue;
- }
- }
-
- // non-directive for us, just skip
- sw.WriteLine(rawLine); // 写入 #pragma 指令
- continue;
- }
-
- // Single comment line
- if (line.StartsWith("//")) // 如果是单行注释
- {
- // non-directive comment line, just skip
- sw.WriteLine(rawLine); // 写入单行注释
- continue;
- }
-
- // Comment starting
- if (line.StartsWith("/*")) // 如果是注释块起始
- {
- var posStart = line.LastIndexOf("/*", StringComparison.Ordinal); // 获取注释块起始位置
- var posEnd = line.LastIndexOf("*/", StringComparison.Ordinal); // 获取注释块结束位置
- if (posEnd < posStart) // 如果结束位置小于起始位置
- {
- // Comment opened, but not closed
- inComment = true; // 标记注释块开启
- }
- else
- {
- // Comment opened and closed
- // only continue if no code follows
- if (!line.EndsWith("*/")) // 如果注释块后还有代码
- continue;
- }
-
- sw.WriteLine(rawLine); // 写入注释行
- continue;
- }
-
- sw.WriteLine(rawLine); // 写入原始行
- }
- }
-
- return ms; // 返回内存流
- }
-
- //--------------------------------------------------------------------------------------------------
-
- static readonly char[] _VersionOperands = {'<', '>', '=', '!', ' '}; // 版本号操作符
-
- string _ProcessVersion(string line) // 处理版本号
- {
- var splitIndex = line.LastIndexOfAny(_VersionOperands); // 查找操作符位置
- if (splitIndex < 0) // 如果操作符位置小于 0
- return null;
-
- var value = line.Substring(splitIndex + 1); // 获取版本号值
- if (!float.TryParse(value, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out var version)) // 解析版本号
- return null;
-
- bool result;
- var operand = line.Substring(0, splitIndex + 1).Trim(); // 获取操作符
- switch (operand) // 判断操作符
- {
- case "==":
- result = version.IsEqual(_Version, 0.001f); // 判断是否相等
- break;
- case "!=":
- result = !version.IsEqual(_Version, 0.001f); // 判断是否不相等
- break;
- case "<":
- result = _Version < version; // 判断是否小于
- break;
- case "<=":
- result = _Version < version || version.IsEqual(_Version, 0.001f); // 判断是否小于等于
- break;
- case ">":
- result = _Version > version; // 判断是否大于
- break;
- case ">=":
- result = _Version > version || version.IsEqual(_Version, 0.001f); // 判断是否大于等于
- break;
- default:
- return null;
- }
-
- return result ? "true" : "false"; // 返回处理结果
- }
-
- //--------------------------------------------------------------------------------------------------
-
- bool _ReportResults(ImmutableArray
errors) // 报告编译结果 - {
- DiagnosticSeverity severity = DiagnosticSeverity.Info; // 默认的诊断级别为 Info
- var sb = new StringBuilder(); // 创建字符串构建器
- foreach (var diag in errors) // 遍历诊断信息
- {
- if (diag.Severity < DiagnosticSeverity.Warning) // 如果诊断级别低于警告
- continue;
- if (diag.Severity > severity) // 如果诊断级别高于当前级别
- severity = diag.Severity; // 更新诊断级别
-
- if (diag.Location != null) // 如果有位置信息
- {
- var location = diag.Location.GetMappedLineSpan(); // 获取映射的行范围
- if (location.IsValid && !location.Path.IsNullOrEmpty()) // 如果有效且路径不为空
- {
- sb.Append(Path.GetFileName(location.Path)); // 添加文件名
- sb.Append($" ({location.Span.Start.Line},{location.Span.Start.Character}): "); // 添加行号和字符位置
- }
- }
-
- sb.Append(severity == DiagnosticSeverity.Error ? "Error " : "Warning "); // 添加错误或警告信息
- sb.Append(diag.Id); // 添加诊断标识
- sb.Append(": ");
- sb.AppendLine(diag.GetMessage(CultureInfo.InvariantCulture)); // 添加诊断消息
- }
-
- if (severity == DiagnosticSeverity.Error) // 如果诊断级别为错误
- {
- Messages.Error("Script compilation failed with errors.", sb.ToString()); // 报告编译错误
- }
- else if(severity == DiagnosticSeverity.Warning) // 如果诊断级别为警告
- {
- Messages.Warning("Script compiled with warnings.", sb.ToString()); // 报告编译警告
- }
-
- return severity == DiagnosticSeverity.Error; // 返回是否有错误
- }
-
- }
- }
以上代码是一个用于编译脚本的 C# 类 ScriptCompiler,它负责读取、预处理、编译脚本文件,并提供一些额外的功能,如版本控制和诊断报告。下面是代码的注释说明:
ScriptCompiler 类包含了用于编译脚本的各种方法和功能。Compile 方法用于编译脚本实例。_Compile 方法实现了脚本的实际编译过程,包括读取、预处理文件,设置编译选项,编译脚本,并处理编译结果。_ReadAndPreprocessFile 方法用于读取和预处理文件,包括处理注释、#pragma 指令和版本号条件等。_ProcessVersion 方法用于处理版本号条件表达式。_ReportResults 方法用于报告编译结果,包括错误和警告信息。这个类的主要功能是将脚本文件编译成可执行的代码,并提供错误和警告信息以供调试和修复。
19.
- using Macad.Core.Topology;
-
- namespace Macad.Core
- {
- ///
- /// 脚本上下文类,作为所有脚本的基类,在应用程序中提供对各种组件的访问。
- ///
- public class ScriptContext
- {
- ///
- /// 默认的脚本上下文实例,允许无需实例化新的对象即可访问其成员。
- ///
- internal static ScriptContext Default { get; } = new ScriptContext();
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 模型对象,包含应用程序中的所有实体和对每个实体的引用。
- ///
- public Model Document => CoreContext.Current.Document;
-
- ///
- /// 图层集合,定义了与实体的可见性、交互性和可视化相关的共享属性。
- ///
- public LayerCollection Layers => CoreContext.Current.Layers;
-
- ///
- /// 工作空间,包含应用程序内部用于可视化和交互的所有功能。
- ///
- public Workspace Workspace => CoreContext.Current.Workspace;
-
- ///
- /// 视口,是工作空间的窗口,用于用户在图形环境中查看和操作对象。
- ///
- public Viewport Viewport => CoreContext.Current.Viewport;
- }
- }
这段代码定义了名为 ScriptContext 的类,它作为脚本的基类,在应用程序中提供对各种组件的访问。下面是对其成员的解释:
Default 属性:
ScriptContext 的静态实例,允许在不需要实例化新的 ScriptContext 对象的情况下轻松访问其成员。Document 属性:
Layers 属性:
Workspace 属性:
Viewport 属性:
这些属性为脚本提供了对应用程序环境中关键组件的访问,使其能够有效地执行操作并在 CAD 模型中操作数据。
20.
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Reflection;
- using Microsoft.CodeAnalysis.Scripting;
-
- namespace Macad.Core
- {
- ///
- /// 表示一个脚本实例,可以加载、编译和运行脚本文件。
- ///
- public sealed class ScriptInstance
- {
- ///
- /// 从文件加载脚本实例。
- ///
- /// 脚本文件路径。
- /// 是否强制重新加载。
- ///
加载的脚本实例。 - public static ScriptInstance LoadScriptFromFile(string filename, bool forceReload = false)
- {
- return LoadScriptFromFile(filename, ScriptContext.Default, forceReload);
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 从文件加载脚本实例。
- ///
- /// 脚本文件路径。
- /// 脚本上下文实例。
- /// 是否强制重新加载。
- ///
加载的脚本实例。 - public static ScriptInstance LoadScriptFromFile(string filename, ScriptContext contextInstance, bool forceReload=false)
- {
- if (!File.Exists(filename))
- {
- Messages.Error( "Script file does not exist: " + filename);
- }
-
- ScriptInstance scriptInstance;
- if (!forceReload)
- {
- scriptInstance = ScriptCache.Find(filename);
- if (scriptInstance != null)
- return scriptInstance;
- }
-
- scriptInstance = new ScriptInstance(filename, contextInstance);
- if(ScriptCompiler.Compile(scriptInstance))
- {
- return scriptInstance;
- }
- return null;
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 获取当前正在运行的脚本实例。
- ///
- public static ScriptInstance Current
- {
- get { return _RunningScripts.Any() ? _RunningScripts.Peek() : null; }
- }
-
- static readonly Stack
_RunningScripts = new Stack(); -
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 脚本名称。
- ///
- public string Name { get; }
-
- ///
- /// 脚本文件路径。
- ///
- public string Path { get; }
-
- ///
- /// 脚本上下文实例。
- ///
- public ScriptContext ContextInstance { get; }
-
- //--------------------------------------------------------------------------------------------------
-
- ScriptRunner<object> _RunnerDelegate;
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 初始化脚本实例。
- ///
- internal ScriptInstance(string filename, ScriptContext contextInstance)
- {
- Name = System.IO.Path.GetFileName(filename);
- Path = System.IO.Path.GetFullPath(filename);
- ContextInstance = contextInstance;
- _Reset();
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 重置脚本实例。
- ///
- void _Reset()
- {
- _RunnerDelegate = null;
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 设置脚本运行器委托。
- ///
- internal bool Init(ScriptRunner<object> runnerDelegate)
- {
- _Reset();
-
- _RunnerDelegate = runnerDelegate;
-
- return true;
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 运行脚本。
- ///
- ///
指示脚本是否成功运行。 - public bool Run()
- {
- bool result = false;
- if (_RunnerDelegate == null)
- return false;
-
- _RunningScripts.Push(this);
- try
- {
- _RunnerDelegate(ContextInstance).Wait();
- result = true;
- }
- catch (Exception e)
- {
- Messages.Exception($"The executed script '{Name}' throwed an exception.", e);
- }
- finally
- {
- }
- _RunningScripts.Pop();
-
- // Only commit after the last script has ended.
- if(_RunningScripts.Count == 0)
- CoreContext.Current?.UndoHandler?.Commit();
-
- return result;
- }
- }
- }
以上代码是用于处理脚本的加载、编译和运行的类 ScriptInstance。下面是逐行注释和说明:
using 指令:引入了一系列命名空间,包括必要的系统命名空间和 Microsoft.CodeAnalysis.Scripting 用于动态编译和运行脚本的命名空间。
namespace Macad.Core:定义了 Macad.Core 命名空间,包含了整个脚本实例类。
public sealed class ScriptInstance:定义了 ScriptInstance 类,用于表示一个脚本实例。
public static ScriptInstance LoadScriptFromFile(string filename, bool forceReload = false) 方法:从文件加载脚本实例的静态方法。根据提供的文件名加载脚本,并可以选择是否强制重新加载。返回加载的脚本实例。
public static ScriptInstance LoadScriptFromFile(string filename, ScriptContext contextInstance, bool forceReload=false) 方法:从文件加载脚本实例的静态方法,可以指定脚本上下文实例。返回加载的脚本实例。
ScriptInstance(string filename, ScriptContext contextInstance) 构造函数:初始化脚本实例的私有构造函数。用于创建脚本实例对象。
public static ScriptInstance Current 属性:获取当前正在运行的脚本实例。使用栈来存储运行的脚本实例,从而支持嵌套调用。
_RunningScripts 字段:用于存储当前正在运行的脚本实例的栈。
public string Name { get; } 属性:脚本名称。
public string Path { get; } 属性:脚本文件路径。
public ScriptContext ContextInstance { get; } 属性:脚本上下文实例。
_RunnerDelegate 字段:脚本运行器委托,用于执行脚本的方法。
_Reset() 方法:重置脚本实例,清空运行器委托。
internal bool Init(ScriptRunner 方法:初始化脚本实例,设置运行器委托。
public bool Run() 方法:运行脚本的方法。使用运行器委托来执行脚本的逻辑,并处理可能发生的异常。最终返回指示脚本是否成功运行的布尔值。
以上就是 ScriptInstance 类的代码及其注释说明。
21.
- using System;
- using System.Collections.Immutable;
- using System.IO;
- using Microsoft.CodeAnalysis;
-
- namespace Macad.Core
- {
- ///
- /// 表示用于解析脚本源文件的解析器。
- ///
- public sealed class ScriptSourceResolver : SourceFileResolver
- {
- Func<string, Stream> _ReadFunc;
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 构造函数,初始化脚本源文件解析器。
- ///
- /// 基本目录。
- /// 读取文件的方法。
- public ScriptSourceResolver(string baseDirectory, Func<string, Stream> readFunc)
- : base(ImmutableArray<string>.Empty, baseDirectory)
- {
- _ReadFunc = readFunc;
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 打开指定路径的文件流。
- ///
- /// 已解析的文件路径。
- ///
文件流。 - public override Stream OpenRead(string resolvedPath)
- {
- return _ReadFunc(Path.GetFullPath(resolvedPath));
- }
- }
- }
逐行注释和说明如下:
using 指令:引入了必要的命名空间。
namespace Macad.Core:定义了 Macad.Core 命名空间,包含了整个脚本源文件解析器类。
public sealed class ScriptSourceResolver : SourceFileResolver:定义了 ScriptSourceResolver 类,用于解析脚本的源文件。
Func:私有字段,用于存储读取文件的方法。
构造函数 ScriptSourceResolver(string baseDirectory, Func:初始化脚本源文件解析器的构造函数,设置基本目录和读取文件的方法。
public override Stream OpenRead(string resolvedPath) 方法:重写了基类的打开读取方法,根据解析后的文件路径调用存储的读取文件方法获取文件流。
以上是 ScriptSourceResolver 类的代码及其注释说明。
22.
- using System;
- using System.Diagnostics;
- using Macad.Core.Topology;
-
- namespace Macad.Core
- {
- public class DataBlobUndoAction : UndoAction
- {
- byte[] _StoredData;
-
- //--------------------------------------------------------------------------------------------------
-
- public DataBlobUndoAction(Guid instanceGuid)
- {
- InstanceGuid = instanceGuid;
- }
-
- //--------------------------------------------------------------------------------------------------
-
- public bool Set(IUndoableDataBlob dataBlobOwner)
- {
- InstanceGuid = dataBlobOwner.Guid;
-
- var data = dataBlobOwner.GetUndoDataBlob();
- if (data != null)
- {
- _StoredData = data;
- //Debug.WriteLine(_StoredData);
- return true;
- }
- return false;
- }
-
- //--------------------------------------------------------------------------------------------------
-
- public override void Restore(Entity instance, UndoHandler undoHandler)
- {
- var dataBlobOwner = instance as IUndoableDataBlob;
- Debug.Assert(dataBlobOwner != null);
-
- dataBlobOwner.SetUndoDataBlob(_StoredData);
- }
- }
- }
逐行注释和说明如下:
using 指令:引入了必要的命名空间。
namespace Macad.Core:定义了 Macad.Core 命名空间,包含了整个类的定义。
public class DataBlobUndoAction : UndoAction:定义了 DataBlobUndoAction 类,表示数据块撤销操作。
_StoredData:私有字段,存储撤销操作的数据块。
构造函数 DataBlobUndoAction(Guid instanceGuid):初始化具有指定实例 GUID 的 DataBlobUndoAction 类的新实例。
public bool Set(IUndoableDataBlob dataBlobOwner) 方法:设置数据块的撤销操作,参数为拥有数据块的对象。
public override void Restore(Entity instance, UndoHandler undoHandler) 方法:重写了基类的恢复方法,用于恢复撤销的操作。
以上是 DataBlobUndoAction 类的代码及其注释说明。
23.
- using System;
-
- namespace Macad.Core
- {
- ///
- /// 定义了可撤销数据块的接口。
- ///
- public interface IUndoableDataBlob
- {
- ///
- /// 获取数据块的 GUID。
- ///
- Guid Guid { get; }
-
- ///
- /// 获取数据块的撤销数据。
- ///
- ///
表示数据块的字节数组。 - byte[] GetUndoDataBlob();
-
- ///
- /// 设置数据块的撤销数据。
- ///
- /// 要设置的数据块的字节数组。
- void SetUndoDataBlob(byte[] dataBlob);
- }
- }
逐行注释和说明如下:
using 指令:引入了必要的命名空间。
namespace Macad.Core:定义了 Macad.Core 命名空间,包含了整个接口的定义。
public interface IUndoableDataBlob:定义了 IUndoableDataBlob 接口,表示可撤销数据块的接口。
Guid Guid { get; } 属性:获取数据块的唯一标识符(GUID)。
byte[] GetUndoDataBlob() 方法:获取数据块的撤销数据,返回表示数据块的字节数组。
void SetUndoDataBlob(byte[] dataBlob) 方法:设置数据块的撤销数据,参数为要设置的数据块的字节数组。
以上是 IUndoableDataBlob 接口的代码及其注释说明。
24.
- using System;
- using Macad.Core.Topology;
-
- namespace Macad.Core
- {
- ///
- /// 定义了可撤销拓扑操作的接口。
- ///
- public interface IUndoableTopology
- {
- ///
- /// 获取拓扑操作的唯一标识符(GUID)。
- ///
- Guid Guid { get; }
-
- ///
- /// 根据实例的 GUID 查找实体。
- ///
- /// 要查找的实例的 GUID。
- ///
找到的实体,如果未找到则为 null。 - Entity FindInstance(Guid instanceGuid);
-
- ///
- /// 获取实例的父实体。
- ///
- /// 要获取父实体的实例。
- ///
实例的父实体。 - Entity GetParent(Entity instance);
-
- ///
- /// 从撤销操作中添加子实体。
- ///
- /// 要添加的子实体。
- /// 子实体的父实体。
- void AddChildFromUndo(Entity instance, Entity parent);
-
- ///
- /// 从撤销操作中移除子实体。
- ///
- /// 要移除的子实体。
- void RemoveChildFromUndo(Entity instance);
-
- ///
- /// 从撤销操作中移动子实体到新的父实体。
- ///
- /// 要移动的子实体。
- /// 子实体的新父实体。
- void MoveChildFromUndo(Entity instance, Entity newParent);
- }
- }
逐行注释和说明如下:
using 指令:引入了必要的命名空间。
namespace Macad.Core:定义了 Macad.Core 命名空间,包含了整个接口的定义。
public interface IUndoableTopology:定义了 IUndoableTopology 接口,表示可撤销拓扑操作的接口。
Guid Guid { get; } 属性:获取拓扑操作的唯一标识符(GUID)。
Entity FindInstance(Guid instanceGuid) 方法:根据实例的 GUID 查找实体。
Entity GetParent(Entity instance) 方法:获取实例的父实体。
void AddChildFromUndo(Entity instance, Entity parent) 方法:从撤销操作中添加子实体。
void RemoveChildFromUndo(Entity instance) 方法:从撤销操作中移除子实体。
void MoveChildFromUndo(Entity instance, Entity newParent) 方法:从撤销操作中移动子实体到新的父实体。
以上是 IUndoableTopology 接口的代码及其注释说明。
25.
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Reflection;
- using System.Runtime.InteropServices;
- using Macad.Core.Topology;
-
- namespace Macad.Core
- {
- ///
- /// 表示属性的撤销操作。
- ///
- public class PropertyUndoAction : UndoAction
- {
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 表示属性值的更改。
- ///
- class PropertyValueChange
- {
- readonly PropertyInfo _PropertyInfo; // 属性信息
- object _Value; // 属性值
- bool _IsEntityReference; // 属性是否引用了实体
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 构造函数,初始化 PropertyValueChange 的新实例。
- ///
- /// 要更改的属性信息。
- public PropertyValueChange(PropertyInfo propertyInfo)
- {
- _PropertyInfo = propertyInfo;
- _IsEntityReference = typeof(Entity).IsAssignableFrom(_PropertyInfo.DeclaringType)
- && typeof(Entity).IsAssignableFrom(_PropertyInfo.PropertyType);
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 判断属性是否相等。
- ///
- /// 要比较的属性信息。
- ///
如果属性相等,则为 true,否则为 false。 - public bool IsEqual(PropertyInfo propInfo)
- {
- return _PropertyInfo.Equals(propInfo);
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 更新属性的值。
- ///
- /// 属性所在的实例。
- /// 要设置的属性值。
- public void Update(object instance, object value = null)
- {
- if (value != null)
- {
- _Value = value;
- }
- else
- {
- if (_IsEntityReference)
- {
- // 仅保存引用
- var entity = _PropertyInfo.GetValue(instance) as Entity;
- _Value = entity?.Guid;
- }
- else
- {
- _Value = _PropertyInfo.GetValue(instance);
- }
- }
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 还原属性的值。
- ///
- /// 属性所在的实例。
- public void RestoreValue(object instance)
- {
- if (_IsEntityReference)
- {
- // 通过引用还原
- var document = (instance as Entity)?.Document;
- if (document != null && _Value != null && _Value is Guid guid)
- {
- _PropertyInfo.SetValue(instance, document.FindInstance(guid));
- }
- else
- {
- _PropertyInfo.SetValue(instance, null);
- }
- }
- else
- {
- _PropertyInfo.SetValue(instance, _Value);
- }
- }
-
- //--------------------------------------------------------------------------------------------------
- }
-
- //--------------------------------------------------------------------------------------------------
- //--------------------------------------------------------------------------------------------------
-
- readonly List
_ChangeList = new List(); // 属性值更改列表 -
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 初始化 PropertyUndoAction 类的新实例。
- ///
- /// 操作实例的 GUID。
- public PropertyUndoAction(Guid instanceGuid)
- {
- InstanceGuid = instanceGuid;
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 设置属性的撤销操作。
- ///
- /// 要设置的属性信息。
- /// 属性所在的实例。
- /// 要设置的属性值。
- public void Set(PropertyInfo propertyInfo, Entity instance, object value = null)
- {
- // 注意:只保存第一个值更改,否则原始状态将会丢失。
- var change = _ChangeList.FirstOrDefault(pvc => pvc.IsEqual(propertyInfo));
-
- if(change != null)
- return;
-
- change = new PropertyValueChange(propertyInfo);
- change.Update(instance, value);
- _ChangeList.Add(change);
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 还原属性的撤销操作。
- ///
- /// 操作实例。
- /// 撤销处理程序。
- public override void Restore(Entity instance, UndoHandler undoHandler)
- {
- _ChangeList.ForEach( change => change.RestoreValue(instance));
-
- var shape = instance as Shapes.Shape;
- shape?.Invalidate();
- }
-
- //--------------------------------------------------------------------------------------------------
-
- }
- }
逐行注释和说明如下:
using 指令:引入了必要的命名空间。
namespace Macad.Core:定义了 Macad.Core 命名空间,包含了整个类的定义。
public class PropertyUndoAction : UndoAction:定义了表示属性撤销操作的 PropertyUndoAction 类。
class PropertyValueChange:表示属性值的更改,是 PropertyUndoAction 类的嵌套类。
readonly List:属性值更改列表,用于保存属性值的更改。
public PropertyUndoAction(Guid instanceGuid):PropertyUndoAction 类的构造函数,初始化实例的 GUID。
public void Set(PropertyInfo propertyInfo, Entity instance, object value = null):设置属性的撤销操作,记录属性值的更改。
public override void Restore(Entity instance, UndoHandler undoHandler):还原属性的撤销操作,将属性值还原到之前的状态,并在需要时更新形状的无效状态。
以上是 PropertyUndoAction 类的代码及其注释说明。
26.
- using System;
- using System.Diagnostics;
- using Macad.Core.Topology;
- using Macad.Common.Serialization;
- using Macad.Core.Shapes;
- using Macad.Common;
-
- namespace Macad.Core
- {
- ///
- /// 表示拓扑操作的撤销动作。
- ///
- public class TopologyUndoAction : UndoAction
- {
- string _StoredData; // 存储的数据
- UndoHandler.TopologyAction _TopoAction; // 拓扑操作类型
- Guid _ChildGuid; // 子实体的 GUID
- Guid? _ParentGuid; // 父实体的 GUID
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 初始化 TopologyUndoAction 类的新实例。
- ///
- /// 实例的 GUID。
- public TopologyUndoAction(Guid instanceGuid)
- {
- InstanceGuid = instanceGuid;
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 设置拓扑操作的撤销动作。
- ///
- /// 子实体。
- /// 包含子实体的容器。
- /// 拓扑操作类型。
- ///
如果设置成功,则为 true,否则为 false。 - public bool Set(Entity child, IUndoableTopology container, UndoHandler.TopologyAction action)
- {
- _ChildGuid = child.Guid;
- InstanceGuid = container.Guid;
-
- _ParentGuid = null;
- var parent = container.GetParent(child);
- if (parent != null)
- _ParentGuid = parent.Guid;
-
- _TopoAction = action;
- _StoredData = null;
-
- switch (action)
- {
- case UndoHandler.TopologyAction.Added:
- // 逆操作:移除。我们只需要实例以便稍后移除。
- return true;
-
- case UndoHandler.TopologyAction.Removed:
- // 逆操作:添加。我们需要实例、父实体和其数据以便稍后添加。
- var data = Serializer.Serialize(child, new SerializationContext(SerializationScope.UndoRedo));
- if (!data.IsNullOrEmpty())
- {
- _StoredData = data;
- return true;
- }
- break;
-
- case UndoHandler.TopologyAction.Moved:
- // 逆操作:移动回。我们需要实例和父实体。
- return true;
- }
-
- return false;
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 还原拓扑操作的撤销动作。
- ///
- /// 操作实例。
- /// 撤销处理程序。
- public override void Restore(Entity instance, UndoHandler undoHandler)
- {
- var container = undoHandler.FindEntityInstance(InstanceGuid) as IUndoableTopology;
- Debug.Assert(container != null, "container != null");
-
- var child = undoHandler.FindEntityInstance(_ChildGuid);
- var parent = _ParentGuid.HasValue ? undoHandler.FindEntityInstance(_ParentGuid.Value) : null;
-
- switch (_TopoAction)
- {
- case UndoHandler.TopologyAction.Added:
- Debug.Assert(child != null);
-
- // 逆操作:移除。
- container.RemoveChildFromUndo(child);
- break;
-
- case UndoHandler.TopologyAction.Removed:
- Debug.Assert(child == null);
-
- // 逆操作:添加。
- var context = new SerializationContext(SerializationScope.UndoRedo);
- context.SetInstance(CoreContext.Current.Document);
- context.SetInstance
(CoreContext.Current.Document); - context.SetInstance(CoreContext.Current.Workspace);
-
- child = Serializer.Deserialize
(_StoredData, context); - if (child != null)
- {
- container.AddChildFromUndo(child, parent);
-
- // 更新可视化状态
- foreach(var entity in context.GetInstanceList
()) - entity.RaiseVisualChanged();
- }
- break;
-
- case UndoHandler.TopologyAction.Moved:
- Debug.Assert(child != null);
-
- // 逆操作:移动回。
- undoHandler.AddTopologyChange(UndoHandler.TopologyAction.Moved, container, child);
-
- container.MoveChildFromUndo(child, parent);
- break;
- }
- }
- }
- }
逐行注释和说明如下:
using 指令:引入了必要的命名空间。
namespace Macad.Core:定义了 Macad.Core 命名空间,包含了整个类的定义。
public class TopologyUndoAction : UndoAction:定义了表示拓扑操作的撤销动作的 TopologyUndoAction 类。
string _StoredData;:存储数据,用于保存被移除的实体的数据。
UndoHandler.TopologyAction _TopoAction;:拓扑操作类型,表示进行的拓扑操作。
Guid _ChildGuid;:子实体的 GUID。
Guid? _ParentGuid;:父实体的 GUID。
public TopologyUndoAction(Guid instanceGuid):TopologyUndoAction 类的构造函数,初始化实例的 GUID。
public bool Set(Entity child, IUndoableTopology container, UndoHandler.TopologyAction action):设置拓扑操作的撤销动作,记录进行的拓扑操作及相关信息。
public override void Restore(Entity instance, UndoHandler undoHandler):还原拓扑操作的撤销动作,执行相应的逆操作,并在需要时更新可视化状态。
27.
- using System;
- using Macad.Core.Topology;
-
- namespace Macad.Core
- {
- ///
- /// 表示撤销动作的抽象基类。
- ///
- public abstract class UndoAction
- {
- ///
- /// 获取或设置实例的 GUID。
- ///
- public Guid InstanceGuid { get; protected set; }
-
- ///
- /// 还原撤销动作。
- ///
- /// 应用撤销动作的实例。
- /// 撤销处理程序。
- public abstract void Restore(Entity instance, UndoHandler undoHandler);
- }
- }
逐行注释和说明如下:
using 指令:引入了必要的命名空间。
namespace Macad.Core:定义了 Macad.Core 命名空间,包含了整个类的定义。
public abstract class UndoAction:定义了表示撤销动作的抽象基类 UndoAction。
public Guid InstanceGuid { get; protected set; }:表示实例的 GUID 属性,用于标识要执行撤销动作的实例。
public abstract void Restore(Entity instance, UndoHandler undoHandler);:抽象方法,表示还原撤销动作的操作,需要由派生类实现具体的还原逻辑。
28.
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Reflection;
- using System.Runtime.CompilerServices;
- using Macad.Core.Topology;
- using Macad.Common;
- using Macad.Common.Serialization;
-
- namespace Macad.Core
- {
- ///
- /// 处理撤销和重做操作的管理器。
- ///
- public class UndoHandler : BaseObject
- {
- #region Enums
-
- ///
- /// 表示拓扑操作的枚举。
- ///
- public enum TopologyAction
- {
- Added,
- Removed,
- Moved
- }
-
- #endregion
-
- #region Properties
-
- ///
- /// 获取一个值,该值指示是否可以执行撤销操作。
- ///
- public bool CanUndo
- {
- get { return _UndoStack.Count > 0; }
- }
-
- ///
- /// 获取一个值,该值指示是否可以执行重做操作。
- ///
- public bool CanRedo
- {
- get { return _RedoStack.Count > 0; }
- }
-
- ///
- /// 获取用于存储撤销操作的栈。
- ///
- public LimitedStack
UndoStack - {
- get { return _UndoStack; }
- }
-
- ///
- /// 获取用于存储重做操作的栈。
- ///
- public LimitedStack
RedoStack - {
- get { return _RedoStack; }
- }
-
- #endregion
-
- readonly IUndoableTopology _Document;
- readonly LimitedStack
_RedoStack; - readonly LimitedStack
_UndoStack; - readonly List
_PendingActions = new List(); - bool _IsRestoring;
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 初始化
类的新实例。 - ///
- /// 撤销处理器所属的文档。
- public UndoHandler(IUndoableTopology document)
- {
- _Document = document;
- _UndoStack = new LimitedStack
(500); - _RedoStack = new LimitedStack
(500); - }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 引发属性更改事件。
- ///
- void RaisePropertyChanged()
- {
- RaisePropertyChanged("CanUndo");
- RaisePropertyChanged("CanRedo");
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 提交挂起的撤销操作。
- ///
- public void Commit()
- {
- if (!_IsRestoring)
- {
- Commit(false);
- _RedoStack.Clear();
- }
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 提交挂起的撤销操作。
- ///
- /// 指示是否提交到重做操作的栈。
- void Commit(bool toRedoStack)
- {
- var stack = toRedoStack ? _RedoStack : _UndoStack;
- if (_PendingActions.Count > 0)
- {
- // 反转动作列表以便首先撤销最后一个动作
- _PendingActions.Reverse();
- stack.Push(_PendingActions.ToArray());
- _PendingActions.Clear();
- }
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 添加属性更改的撤销操作。
- ///
- /// 发生属性更改的实例。
- /// 更改的属性名称。
- /// 属性的克隆值。
- public void AddPropertyChange(Entity instance, [CallerMemberName] string propertyName = "", object clone = null)
- {
- var propInfo = instance.GetType().GetProperty(propertyName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
- if (propInfo == null)
- return;
-
- if (!propInfo.GetCustomAttributes(typeof(SerializeMemberAttribute), true).Any())
- return;
-
- var action = (PropertyUndoAction)_PendingActions.FirstOrDefault(a => a.InstanceGuid.Equals(instance.Guid) && a is PropertyUndoAction);
- if (action == null)
- {
- action = new PropertyUndoAction(instance.Guid);
- _PendingActions.Add(action);
- }
- action.Set(propInfo, instance, clone);
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 添加数据块更改的撤销操作。
- ///
- /// 数据块实例。
- public void AddDataBlockChange(IUndoableDataBlob instance)
- {
- var action = (DataBlobUndoAction)_PendingActions.FirstOrDefault(a => a.InstanceGuid.Equals(instance.Guid) && a is DataBlobUndoAction);
- if (action != null)
- return;
-
- action = new DataBlobUndoAction(instance.Guid);
- if (action.Set(instance))
- {
- _PendingActions.Add(action);
- }
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 添加拓扑更改的撤销操作。
- ///
- /// 拓扑操作类型。
- /// 容器实例。
- /// 拓扑实例。
- public void AddTopologyChange(TopologyAction topologyAction, IUndoableTopology container, Entity instance)
- {
- var action = new TopologyUndoAction(container.Guid);
- if (action.Set(instance, container, topologyAction))
- {
- _PendingActions.Add(action);
- }
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 执行指定步数的撤销操作。
- ///
- /// 撤销步数。
- public void DoUndo(int steps)
- {
- while ((steps > 0) && (_UndoStack.Count > 0))
- {
- Restore(false);
- steps--;
- }
-
- Commit(true);
- RaisePropertyChanged();
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 执行指定步数的重做操作。
- ///
- /// 重做步数。
- public void DoRedo(int steps)
- {
- while ((steps > 0) && (_RedoStack.Count > 0))
- {
- Restore(true);
- steps--;
- }
-
- Commit(false);
- RaisePropertyChanged();
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 还原撤销操作。
- ///
- /// 指示是否从重做操作的栈中还原。
- void Restore(bool fromRedoStack)
- {
- var stack = fromRedoStack ? _RedoStack : _UndoStack;
-
- _IsRestoring = true;
- var actions = stack.Pop();
- foreach (var action in actions)
- {
- var instance = FindEntityInstance(action.InstanceGuid);
-
- // 如果未找到实例,则跳过,因为它必须是拓扑操作的一部分
- if(instance == null)
- continue;
-
- instance.OnBeforeUndo();
- action.Restore(instance, this);
- instance.OnAfterUndo();
- }
- _IsRestoring = false;
- }
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 根据实例的 GUID 查找实例。
- ///
- /// 实例的 GUID。
- ///
找到的实例,如果未找到则为 null。 - public Entity FindEntityInstance(Guid instanceGuid)
- {
- return _Document.FindInstance(instanceGuid);
- }
- }
- }
逐行注释和说明如下:
using 指令:引入了必要的命名空间。
namespace Macad.Core:定义了 Macad.Core 命名空间,包含了整个类的定义。
public class UndoHandler : BaseObject:定义了处理撤销和重做操作的管理器 UndoHandler,它继承自 BaseObject 类。
public enum TopologyAction:定义了表示拓扑操作的枚举类型 TopologyAction,包括 Added、Removed 和 Moved。
IUndoableTopology _Document:存储撤销处理器所属的文档。
LimitedStack 和 LimitedStack:分别用于存储重做操作和撤销操作的栈。
List:存储待提交的撤销动作列表。
public UndoHandler(IUndoableTopology document):构造函数,初始化撤销处理器。
void RaisePropertyChanged():引发属性更改事件。
public void Commit() 和 void Commit(bool toRedoStack):提交挂起的撤销操作。
public void AddPropertyChange(Entity instance, [CallerMemberName] string propertyName = "", object clone = null):添加属性更改的撤销操作。
public void AddDataBlockChange(IUndoableDataBlob instance):添加数据块更改的撤销操作。
public void AddTopologyChange(TopologyAction topologyAction, IUndoableTopology container, Entity instance):添加拓扑更改的撤销操作。
public void DoUndo(int steps) 和 public void DoRedo(int steps):执行指定步数的撤销和重做操作。
void Restore(bool fromRedoStack):还原撤销操作。
public Entity FindEntityInstance(Guid instanceGuid):根据实例的 GUID 查找实例。
29.
- using System.IO;
- using System.Text;
- using Macad.Common;
-
- namespace Macad.Core
- {
- ///
- /// 抽象类,表示剪贴板操作。
- ///
- public abstract class Clipboard
- {
- ///
- /// 获取或设置当前剪贴板实例。
- ///
- public static Clipboard Current { get; protected set; }
-
- ///
- /// 检查剪贴板中是否包含指定格式的数据。
- ///
- /// 数据格式。
- ///
如果剪贴板中包含指定格式的数据,则为 true;否则为 false。 - public abstract bool ContainsData(in string format);
-
- ///
- /// 从剪贴板中获取指定格式的数据流。
- ///
- /// 数据格式。
- ///
数据流。 - public abstract MemoryStream GetDataStream(in string format);
-
- ///
- /// 将数据写入剪贴板。
- ///
- /// 数据格式。
- /// 数据流。
- public abstract void SetData(in string format, in MemoryStream data);
-
- //--------------------------------------------------------------------------------------------------
-
- ///
- /// 将字符串数据写入剪贴板。
- ///
- /// 数据格式。
- /// 字符串数据。
- public void SetData(in string format, in string data)
- {
- SetData(format, new MemoryStream(Encoding.Unicode.GetBytes(data)));
- }
-
- ///
- /// 从剪贴板中获取指定格式的数据并转换为字符串。
- ///
- /// 数据格式。
- ///
数据字符串。 - public string GetDataAsString(in string format)
- {
- var memstream = GetDataStream(format);
-
- return Encoding.Unicode.GetString(memstream.ToArray());
- }
- }
- }
逐行注释和说明如下:
using 指令:引入了必要的命名空间。
namespace Macad.Core:定义了 Macad.Core 命名空间,包含了整个类的定义。
public abstract class Clipboard:定义了抽象类 Clipboard,表示剪贴板操作。
public static Clipboard Current { get; protected set; }:获取或设置当前剪贴板实例。
public abstract bool ContainsData(in string format):抽象方法,检查剪贴板中是否包含指定格式的数据。
public abstract MemoryStream GetDataStream(in string format):抽象方法,从剪贴板中获取指定格式的数据流。
public abstract void SetData(in string format, in MemoryStream data):抽象方法,将数据写入剪贴板。
public void SetData(in string format, in string data):将字符串数据写入剪贴板。
public string GetDataAsString(in string format):从剪贴板中获取指定格式的数据并转换为字符串。