惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - 司徒正美
大猫的无限游戏
大猫的无限游戏
Scott Helme
Scott Helme
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
S
Secure Thoughts
Google DeepMind News
Google DeepMind News
博客园_首页
Hacker News: Ask HN
Hacker News: Ask HN
量子位
Jina AI
Jina AI
I
InfoQ
V
V2EX
Martin Fowler
Martin Fowler
Y
Y Combinator Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
人人都是产品经理
人人都是产品经理
B
Blog
IT之家
IT之家
云风的 BLOG
云风的 BLOG
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
博客园 - Franky
博客园 - 【当耐特】
N
Netflix TechBlog - Medium
Cloudbric
Cloudbric
H
Heimdal Security Blog
TaoSecurity Blog
TaoSecurity Blog
S
Security @ Cisco Blogs
U
Unit 42
Project Zero
Project Zero
Webroot Blog
Webroot Blog
The Register - Security
The Register - Security
N
News | PayPal Newsroom
Microsoft Security Blog
Microsoft Security Blog
H
Help Net Security
Forbes - Security
Forbes - Security
宝玉的分享
宝玉的分享
Last Week in AI
Last Week in AI
C
Check Point Blog
博客园 - 聂微东
M
MIT News - Artificial intelligence
有赞技术团队
有赞技术团队
D
DataBreaches.Net
Cyberwarzone
Cyberwarzone
N
News and Events Feed by Topic
N
News and Events Feed by Topic
Simon Willison's Weblog
Simon Willison's Weblog
J
Java Code Geeks
G
Google Developers Blog
GbyAI
GbyAI
T
Threatpost

博客园 - 我才是银古

第16章:常见问题、排错与最佳实践 第15章:扩展生态、MCAD 与外部集成 第12章:实战案例:机械结构与 3D 打印零件 第14章:构建、测试、调试与贡献流程 第13章:OpenSCAD 源码架构与核心执行流程 第11章:预览、渲染、网格精度与性能优化 第09章:列表推导、递归与算法建模 第08章:参数化零件库与复用设计 第10章:导入导出、命令行与自动化 第06章:CSG 布尔建模方法 第07章:二维图形、拉伸、旋转与投影 第05章:基础几何、坐标系与变换 第04章:参数、变量、函数、模块与作用域 OpenSCAD 教程目录 第03章:OpenSCAD 语言基础 第02章:安装、环境配置与开发工作流 第01章:OpenSCAD 项目全景与学习路线 第02章:源码获取、编译与开发环境配置 第01章:OCCT项目全景与学习路线 第18章:二次开发实战与综合案例 第18章:综合实战案例 第17章:数据交换与协同 第16章:源码架构与二次开发 第15章:插件与自定义工作台开发 第14章:Python脚本宏与自动化 第13章:FEM仿真分析 第12章:CAM数控加工 第11章:SurfaceMesh与逆向工程 第10章:Draft二维绘图与BIM建筑 第09章:工程图TechDraw 第07章:参数化表达式与Spreadsheet 第08章:装配设计Assembly 第06章:Part工作台与几何内核 第05章:PartDesign实体特征建模 第04章:草图Sketcher约束建模 第02章:安装版本与工作环境配置 第03章:界面工作台与基础操作 第01章:项目全景与学习路线 第十二章:插件开发、研究功能与最佳实践 第十章:定时任务与自动化(Cron) 第七章:技能、记忆与自学习闭环 第八章:MCP 集成与上下文文件 第六章:工具系统与终端后端 第五章:模型供应商与配置体系 Hermes Agent 教程目录 第十一章:语音、视觉、浏览器与子代理协作 第四章:CLI/TUI 与会话管理 第十二章:学习路线、实战方案与最佳实践 第十一章:源码结构、开发调试与插件开发 第十章:自动化、远程访问、日志与排障 第九章:Control UI、节点、Canvas 与语音能力 第七章:工具、技能、插件与能力扩展 第八章:安全模型、访问控制与沙箱实践 第六章:Agent 工作区、会话与多智能体路由 第五章:多通道消息接入与聊天平台配置 第四章:配置体系、模型接入与认证管理 第三章:Gateway 架构、协议与运行机制 第二章:安装、环境准备与快速上手 第一章:OpenClaw 项目概览与核心定位 oh-my-openagent 教程目录 09-命令模型回退与配置参考 10-实战案例最佳实践与故障排除 05-工作模式-Ultrawork-Prometheus-Atlas 08-Hooks与MCP系统 06-Category与Skill系统 07-核心工具链 04-智能体全景详解 03-安装与环境配置 02-整体架构与多模型编排机制 01-项目简介与核心理念 01-项目概览与学习路线 02-安装部署与工具适配 03-Skill机制与using-superpowers 05-TDD系统化调试与完成前验证 04-需求澄清方案设计与计划编写 07-并行智能体子智能体与Git-Worktree 第六章:代码审查、反馈处理与分支收尾 08-中国特色Skills与本土团队落地 09-MCP构建工作流执行与自定义Skill 第23章:FreeCAD-Python-API Clipper2 C# 源码解读教程 第19章:PolyTree 多边形树结构 第20章:实际应用与最佳实践 第18章:Minkowski 和与差 第17章:RectClip 矩形裁剪优化 第16章:ClipperOffset 偏移类详解 第15章:填充规则详解 第14章:布尔运算执行流程 第13章:ClipperD 浮点裁剪类 第11章:OutRec 与 OutPt 输出结构 第9章:Active 活动边结构 第10章:Vertex 顶点与 LocalMinima 局部极小值 第12章:Clipper64 裁剪类详解 第7章:高精度运算与128位整数 第8章:ClipperBase 基类详解 第5章:枚举类型与常量定义 第6章:InternalClipper 内部工具类 第2章:核心数据结构 - Point64、PointD 第3章:路径与多边形表示 - Path64、PathD、Paths64、PathsD 第4章:矩形边界 - Rect64、RectD
核心数据模型详解
我才是银古 · 2026-06-19 · via 博客园 - 我才是银古

第五章:核心数据模型详解

5.1 Core模块概述

5.1.1 LightCAD.Core的定位

LightCAD.Core是整个CAD系统的数据基础层,定义了所有图元实体、文档结构和元素类型系统。它位于MathLib之上、RenderUtils之下,是连接数学计算和图形显示的关键桥梁。

5.1.2 核心职责

  • 实体定义:定义所有2D和3D图元的数据结构
  • 文档管理:提供CAD文档的容器和组织结构
  • 元素类型系统:支持自定义元素类型的注册和管理
  • 属性系统:为实体提供可扩展的属性机制
  • 变更通知:通过IUpdateObject接口实现变更追踪

5.1.3 依赖关系

LightCAD.Core
├── 依赖: LightCAD.MathLib(数学计算)
└── 依赖: ThreeJs4Net.dll(字体管理 FontManager)

架构说明:Core对ThreeJs4Net的依赖主要来自字体管理功能(FontManager),这也是设计RenderUtils中间层的原因之一——使得在某些场景下可以绕过这个依赖。

5.2 文档模型(LcDocument)

5.2.1 文档结构

LcDocument是LightCAD中最顶层的数据容器,代表一个完整的CAD文档:

public class LcDocument
{
    /// <summary>
    /// 文档唯一标识
    /// </summary>
    public LcGuid Guid { get; set; }

    /// <summary>
    /// 文档名称
    /// </summary>
    public string Name { get; set; }

    /// <summary>
    /// 文档中的所有实体
    /// </summary>
    public EntityCollection Entities { get; }

    /// <summary>
    /// 图层管理器
    /// </summary>
    public LayerManager Layers { get; }

    /// <summary>
    /// 块定义集合
    /// </summary>
    public BlockCollection Blocks { get; }

    /// <summary>
    /// 线型管理
    /// </summary>
    public LineTypeManager LineTypes { get; }

    /// <summary>
    /// 文字样式管理
    /// </summary>
    public TextStyleManager TextStyles { get; }

    /// <summary>
    /// 标注样式管理
    /// </summary>
    public DimStyleManager DimStyles { get; }

    /// <summary>
    /// 文档单位设置
    /// </summary>
    public UnitSettings Units { get; set; }

    /// <summary>
    /// 文档变量
    /// </summary>
    public DocumentVariables Variables { get; }
}

5.2.2 实体集合管理

public class EntityCollection : IEnumerable<LcEntity>
{
    private readonly List<LcEntity> entities = new();

    /// <summary>
    /// 添加实体
    /// </summary>
    public void Add(LcEntity entity)
    {
        entity.Document = ownerDocument;
        entity.Handle = GenerateHandle();
        entities.Add(entity);
        OnEntityAdded(entity);
    }

    /// <summary>
    /// 删除实体
    /// </summary>
    public bool Remove(LcEntity entity)
    {
        if (entities.Remove(entity))
        {
            entity.Document = null;
            OnEntityRemoved(entity);
            return true;
        }
        return false;
    }

    /// <summary>
    /// 按类型查询
    /// </summary>
    public IEnumerable<T> OfType<T>() where T : LcEntity
    {
        return entities.OfType<T>();
    }

    /// <summary>
    /// 空间查询(包围盒过滤)
    /// </summary>
    public IEnumerable<LcEntity> FindInBounds(BoundingBox2d bounds)
    {
        return entities.Where(e => e.Bounds.Intersects(bounds));
    }
}

5.2.3 图层系统

public class LayerManager
{
    private readonly Dictionary<string, Layer> layers = new();

    /// <summary>
    /// 默认图层 "0"
    /// </summary>
    public Layer DefaultLayer { get; }

    /// <summary>
    /// 当前活动图层
    /// </summary>
    public Layer CurrentLayer { get; set; }

    /// <summary>
    /// 创建新图层
    /// </summary>
    public Layer Create(string name)
    {
        var layer = new Layer(name);
        layers[name] = layer;
        return layer;
    }

    /// <summary>
    /// 获取图层
    /// </summary>
    public Layer Get(string name)
    {
        return layers.TryGetValue(name, out var layer) ? layer : null;
    }
}

public class Layer
{
    public string Name { get; set; }
    public Color Color { get; set; }
    public string LineType { get; set; }
    public double LineWeight { get; set; }
    public bool IsVisible { get; set; } = true;
    public bool IsLocked { get; set; } = false;
    public bool IsFrozen { get; set; } = false;
}

5.3 实体基类(LcEntity)

5.3.1 实体基类定义

LcEntity是所有CAD实体的基类,定义了实体的通用属性和行为:

public abstract class LcEntity
{
    /// <summary>
    /// 实体的唯一句柄
    /// </summary>
    public long Handle { get; internal set; }

    /// <summary>
    /// 全局唯一标识符
    /// </summary>
    public LcGuid Guid { get; set; }

    /// <summary>
    /// 所属文档
    /// </summary>
    public LcDocument Document { get; internal set; }

    /// <summary>
    /// 所在图层
    /// </summary>
    public string LayerName { get; set; } = "0";

    /// <summary>
    /// 颜色
    /// </summary>
    public LcColor Color { get; set; }

    /// <summary>
    /// 线型
    /// </summary>
    public string LineType { get; set; }

    /// <summary>
    /// 线宽
    /// </summary>
    public double LineWeight { get; set; }

    /// <summary>
    /// 是否可见
    /// </summary>
    public bool IsVisible { get; set; } = true;

    /// <summary>
    /// 包围盒
    /// </summary>
    public abstract BoundingBox2d Bounds { get; }

    /// <summary>
    /// 实体类型标识
    /// </summary>
    public abstract string TypeName { get; }

    /// <summary>
    /// 几何变换
    /// </summary>
    public abstract void TransformBy(Matrix4d matrix);

    /// <summary>
    /// 克隆实体
    /// </summary>
    public abstract LcEntity Clone();

    /// <summary>
    /// 计算与点的最近距离
    /// </summary>
    public abstract double DistanceTo(Point2d point);
}

5.3.2 实体类层次结构

LcEntity(抽象基类)
│
├── 二维基本图元
│   ├── LcLine           # 直线
│   ├── LcArc            # 圆弧
│   ├── LcCircle         # 圆
│   ├── LcEllipse        # 椭圆
│   ├── LcPolyline       # 多段线
│   ├── LcPolygon        # 多边形
│   └── LcSpline         # 样条曲线
│
├── 三维图元
│   ├── LcLine3d         # 三维直线
│   ├── LcArc3d          # 三维圆弧
│   ├── LcCircle3d       # 三维圆
│   ├── LcCurve3d        # 三维曲线
│   ├── LcProfile3d      # 三维轮廓
│   ├── LcWorkPlane3d    # 工作平面
│   ├── LcGroup3         # 三维组
│   ├── LcArray3         # 三维阵列
│   └── LcContianerRef3  # 容器引用
│
├── 实体建模
│   ├── LcSolid3d        # 实体基类(26KB)
│   ├── LcExtrude3d      # 拉伸体
│   ├── LcRevolve3d      # 旋转体
│   ├── LcLoft3d         # 放样体
│   ├── LcBlend3d        # 融合体
│   ├── LcSweptBlend3d   # 扫掠融合体
│   ├── LcPushPull3d     # 推拉体
│   ├── LcMesh3d         # 网格体
│   └── LcCombination    # 布尔运算组合体
│
├── 标注元素
│   ├── LcDimension      # 标注基类
│   ├── LcDimLinear      # 线性标注
│   ├── LcDimAngular     # 角度标注
│   ├── LcDimRadial      # 半径标注
│   ├── LcDimDiameter    # 直径标注
│   └── LcDim3d          # 三维标注
│
├── 文本和表格
│   ├── LcText           # 文本(15KB)
│   └── LcTable          # 表格
│
└── 引用元素
    ├── LcBlockRef       # 块引用
    └── LcComponentRef   # 组件引用

5.4 元素类型系统(ElementType)

5.4.1 ElementType类

ElementType是LightCAD中定义自定义元素类型的核心机制。每个自定义元素都需要对应一个ElementType实例:

public class ElementType
{
    /// <summary>
    /// 唯一标识符
    /// </summary>
    public LcGuid Guid { get; set; }

    /// <summary>
    /// 内部名称(用于代码引用)
    /// </summary>
    public string Name { get; set; }

    /// <summary>
    /// 显示名称(用于UI显示)
    /// </summary>
    public string DisplayName { get; set; }

    /// <summary>
    /// 元素类别
    /// </summary>
    public string Category { get; set; }

    /// <summary>
    /// 创建器(工厂方法)
    /// </summary>
    public Func<LcEntity> Creator { get; set; }

    /// <summary>
    /// 属性定义集合
    /// </summary>
    public List<PropertyDefinition> Properties { get; set; }

    /// <summary>
    /// 图标资源路径
    /// </summary>
    public string IconPath { get; set; }

    /// <summary>
    /// 是否为三维元素
    /// </summary>
    public bool Is3D { get; set; }
}

5.4.2 元素类型注册

public class ElementTypeRegistry
{
    private static readonly Dictionary<LcGuid, ElementType> types = new();

    /// <summary>
    /// 注册元素类型
    /// </summary>
    public static void Register(ElementType type)
    {
        if (types.ContainsKey(type.Guid))
            throw new InvalidOperationException(
                $"元素类型 {type.Name} 已注册");

        types[type.Guid] = type;
    }

    /// <summary>
    /// 按GUID获取元素类型
    /// </summary>
    public static ElementType GetByGuid(LcGuid guid)
    {
        return types.TryGetValue(guid, out var type) ? type : null;
    }

    /// <summary>
    /// 按名称获取元素类型
    /// </summary>
    public static ElementType GetByName(string name)
    {
        return types.Values.FirstOrDefault(t => t.Name == name);
    }

    /// <summary>
    /// 获取某个类别下的所有类型
    /// </summary>
    public static IEnumerable<ElementType> GetByCategory(string category)
    {
        return types.Values.Where(t => t.Category == category);
    }
}

5.4.3 自定义元素类型示例

// 注册一个自定义的"门"元素类型
var doorType = new ElementType
{
    Guid = new LcGuid("door-standard-001"),
    Name = "Door",
    DisplayName = "标准门",
    Category = "建筑",
    Is3D = true,
    Creator = () => new DoorEntity(),
    Properties = new List<PropertyDefinition>
    {
        new PropertyDefinition("Width", typeof(double), 900.0),
        new PropertyDefinition("Height", typeof(double), 2100.0),
        new PropertyDefinition("OpenDirection", typeof(string), "左开"),
        new PropertyDefinition("Material", typeof(string), "木质")
    }
};

ElementTypeRegistry.Register(doorType);

5.5 属性系统

5.5.1 属性定义

public class PropertyDefinition
{
    /// <summary>
    /// 属性名称
    /// </summary>
    public string Name { get; set; }

    /// <summary>
    /// 属性类型
    /// </summary>
    public Type ValueType { get; set; }

    /// <summary>
    /// 默认值
    /// </summary>
    public object DefaultValue { get; set; }

    /// <summary>
    /// 显示名称
    /// </summary>
    public string DisplayName { get; set; }

    /// <summary>
    /// 属性分组
    /// </summary>
    public string Group { get; set; }

    /// <summary>
    /// 是否只读
    /// </summary>
    public bool IsReadOnly { get; set; }

    /// <summary>
    /// 值验证器
    /// </summary>
    public Func<object, bool> Validator { get; set; }

    public PropertyDefinition(string name, Type valueType, object defaultValue)
    {
        Name = name;
        ValueType = valueType;
        DefaultValue = defaultValue;
        DisplayName = name;
    }
}

5.5.2 属性值存储

public class PropertyBag
{
    private readonly Dictionary<string, object> values = new();
    private readonly List<PropertyDefinition> definitions;

    public PropertyBag(List<PropertyDefinition> definitions)
    {
        this.definitions = definitions;
        // 初始化默认值
        foreach (var def in definitions)
        {
            values[def.Name] = def.DefaultValue;
        }
    }

    /// <summary>
    /// 获取属性值
    /// </summary>
    public T Get<T>(string name)
    {
        if (values.TryGetValue(name, out var value))
            return (T)value;
        throw new KeyNotFoundException($"属性 {name} 不存在");
    }

    /// <summary>
    /// 设置属性值
    /// </summary>
    public void Set(string name, object value)
    {
        var def = definitions.Find(d => d.Name == name);
        if (def == null)
            throw new KeyNotFoundException($"属性 {name} 未定义");

        if (def.IsReadOnly)
            throw new InvalidOperationException($"属性 {name} 为只读");

        if (def.Validator != null && !def.Validator(value))
            throw new ArgumentException($"属性 {name} 的值无效");

        values[name] = value;
    }
}

5.6 变更通知系统

5.6.1 IUpdateObject接口

/// <summary>
/// 实体变更通知接口
/// </summary>
public interface IUpdateObject
{
    /// <summary>
    /// 当实体属性或几何发生变化时调用
    /// </summary>
    void OnUpdate(UpdateContext context);

    /// <summary>
    /// 是否需要更新
    /// </summary>
    bool NeedsUpdate { get; }
}

public class UpdateContext
{
    /// <summary>
    /// 更新类型
    /// </summary>
    public UpdateType Type { get; set; }

    /// <summary>
    /// 更新来源
    /// </summary>
    public object Source { get; set; }

    /// <summary>
    /// 更新数据
    /// </summary>
    public Dictionary<string, object> Data { get; set; }
}

public enum UpdateType
{
    GeometryChanged,    // 几何数据改变
    PropertyChanged,    // 属性改变
    StyleChanged,       // 样式改变
    TransformChanged,   // 变换改变
    VisibilityChanged,  // 可见性改变
    ParentChanged       // 父级改变
}

5.6.2 实体变更通知流程

public class LcLine : LcEntity, IUpdateObject
{
    private Point2d startPoint;
    private Point2d endPoint;

    public Point2d StartPoint
    {
        get => startPoint;
        set
        {
            if (!startPoint.IsEqualTo(value))
            {
                startPoint = value;
                NeedsUpdate = true;
                OnUpdate(new UpdateContext
                {
                    Type = UpdateType.GeometryChanged,
                    Source = this,
                    Data = new Dictionary<string, object>
                    {
                        ["Property"] = nameof(StartPoint)
                    }
                });
            }
        }
    }

    public bool NeedsUpdate { get; private set; }

    public void OnUpdate(UpdateContext context)
    {
        // 重新计算包围盒
        RecalculateBounds();

        // 通知文档
        Document?.OnEntityChanged(this, context);

        NeedsUpdate = false;
    }
}

5.7 LcGuid标识系统

5.7.1 LcGuid设计

LightCAD使用自定义的LcGuid类型来标识实体和元素类型,而不是直接使用System.Guid:

public struct LcGuid : IEquatable<LcGuid>
{
    private readonly string value;

    public LcGuid(string value)
    {
        this.value = value ?? throw new ArgumentNullException(nameof(value));
    }

    public static LcGuid NewGuid()
    {
        return new LcGuid(Guid.NewGuid().ToString());
    }

    public bool Equals(LcGuid other)
    {
        return string.Equals(value, other.value,
            StringComparison.OrdinalIgnoreCase);
    }

    public override int GetHashCode()
    {
        return value?.GetHashCode(StringComparison.OrdinalIgnoreCase) ?? 0;
    }

    public override string ToString() => value;
}

5.8 颜色系统

5.8.1 LcColor

public struct LcColor
{
    public byte R { get; set; }
    public byte G { get; set; }
    public byte B { get; set; }
    public byte A { get; set; }

    /// <summary>
    /// 颜色来源
    /// </summary>
    public ColorSource Source { get; set; }

    /// <summary>
    /// AutoCAD颜色索引
    /// </summary>
    public int AciIndex { get; set; }

    // 预定义颜色
    public static readonly LcColor Red = new LcColor(255, 0, 0);
    public static readonly LcColor Green = new LcColor(0, 255, 0);
    public static readonly LcColor Blue = new LcColor(0, 0, 255);
    public static readonly LcColor White = new LcColor(255, 255, 255);
    public static readonly LcColor Black = new LcColor(0, 0, 0);
    public static readonly LcColor ByLayer = new LcColor { Source = ColorSource.ByLayer };
    public static readonly LcColor ByBlock = new LcColor { Source = ColorSource.ByBlock };
}

public enum ColorSource
{
    Explicit,   // 直接指定颜色
    ByLayer,    // 随层颜色
    ByBlock     // 随块颜色
}

5.9 坐标系与单位

5.9.1 坐标系统

LightCAD使用标准的右手坐标系:

    Y
    ↑
    |
    |
    +------→ X
   /
  /
 Z(指向屏幕外)

5.9.2 单位系统

public class UnitSettings
{
    /// <summary>
    /// 长度单位
    /// </summary>
    public LengthUnit LengthUnit { get; set; } = LengthUnit.Millimeter;

    /// <summary>
    /// 角度单位
    /// </summary>
    public AngleUnit AngleUnit { get; set; } = AngleUnit.Degree;

    /// <summary>
    /// 显示精度(小数位数)
    /// </summary>
    public int Precision { get; set; } = 4;

    /// <summary>
    /// 单位转换
    /// </summary>
    public double ConvertTo(double value, LengthUnit targetUnit)
    {
        // 先转换为毫米,再转换为目标单位
        var mmValue = value * GetMillimeterFactor(LengthUnit);
        return mmValue / GetMillimeterFactor(targetUnit);
    }
}

public enum LengthUnit
{
    Millimeter,  // 毫米
    Centimeter,  // 厘米
    Meter,       // 米
    Inch,        // 英寸
    Foot         // 英尺
}

public enum AngleUnit
{
    Degree,      // 度
    Radian,      // 弧度
    Gradian      // 百分度
}

5.10 文档序列化

5.10.1 序列化框架

LightCAD的文档序列化支持将完整的文档模型保存到文件和从文件加载:

public class DocumentSerializer
{
    /// <summary>
    /// 保存文档到文件
    /// </summary>
    public void Save(LcDocument document, string filePath)
    {
        using var stream = File.Create(filePath);
        using var writer = new BinaryWriter(stream);

        // 写入文件头
        WriteHeader(writer, document);

        // 写入图层表
        WriteLayers(writer, document.Layers);

        // 写入实体
        WriteEntities(writer, document.Entities);

        // 写入块定义
        WriteBlocks(writer, document.Blocks);
    }

    /// <summary>
    /// 从文件加载文档
    /// </summary>
    public LcDocument Load(string filePath)
    {
        using var stream = File.OpenRead(filePath);
        using var reader = new BinaryReader(stream);

        var document = new LcDocument();

        // 读取文件头
        ReadHeader(reader, document);

        // 读取图层表
        ReadLayers(reader, document);

        // 读取实体
        ReadEntities(reader, document);

        // 读取块定义
        ReadBlocks(reader, document);

        return document;
    }
}

5.11 Core模块的扩展方式

5.11.1 创建自定义实体

要创建新的自定义实体,需要继承LcEntity并实现所有抽象方法:

public class LcCustomElement : LcEntity, IUpdateObject
{
    // 自定义几何数据
    public Point2d Position { get; set; }
    public double Width { get; set; }
    public double Height { get; set; }
    public double Rotation { get; set; }

    // 自定义属性
    public PropertyBag Properties { get; }

    public override string TypeName => "CustomElement";

    public override BoundingBox2d Bounds
    {
        get
        {
            // 计算旋转后的包围盒
            var corners = GetCorners();
            return BoundingBox2d.FromPoints(corners);
        }
    }

    public override void TransformBy(Matrix4d matrix)
    {
        var p3d = new Point3d(Position.X, Position.Y, 0);
        var transformed = matrix.Transform(p3d);
        Position = new Point2d(transformed.X, transformed.Y);
    }

    public override LcEntity Clone()
    {
        return new LcCustomElement
        {
            Position = this.Position,
            Width = this.Width,
            Height = this.Height,
            Rotation = this.Rotation,
            Color = this.Color,
            LayerName = this.LayerName
        };
    }

    public override double DistanceTo(Point2d point)
    {
        // 计算点到元素的最近距离
        return GeometryUtils.PointToRectDistance(
            point, Position, Width, Height, Rotation);
    }

    // IUpdateObject实现
    public bool NeedsUpdate { get; private set; }

    public void OnUpdate(UpdateContext context)
    {
        NeedsUpdate = false;
    }
}

5.11.2 注册自定义元素类型

// 在插件初始化时注册
public class MyPlugin
{
    public void Initialize()
    {
        var customType = new ElementType
        {
            Guid = new LcGuid("my-custom-element-type"),
            Name = "CustomElement",
            DisplayName = "自定义元素",
            Category = "自定义",
            Is3D = false,
            Creator = () => new LcCustomElement
            {
                Width = 100,
                Height = 50
            }
        };

        ElementTypeRegistry.Register(customType);
    }
}

5.12 本章小结

本章详细介绍了LightCAD.Core模块的核心数据模型,包括文档结构(LcDocument)、实体基类(LcEntity)、元素类型系统(ElementType)、属性系统、变更通知机制、颜色系统和坐标单位等。理解这些数据模型是后续学习二维图元、三维建模和渲染系统的基础。Core模块的设计体现了良好的面向对象原则,通过接口和抽象类提供了强大的扩展能力。


上一章第四章:数学库详解

下一章第六章:二维图元系统