核心架构与模块设计

第三章:核心架构与模块设计

3.1 LightCAD框架架构

3.1.1 整体架构

LightCAD采用分层架构设计,从底层到上层依次为:

┌─────────────────────────────────────────────────────────────┐
│                      UI Layer (用户界面层)                    │
│   WinForms | Avalonia | Ribbon | DockPanel | PropertyGrid   │
├─────────────────────────────────────────────────────────────┤
│                   Runtime Layer (运行时层)                    │
│     AppRuntime | DocumentRuntime | CommandSystem | Plugin   │
├─────────────────────────────────────────────────────────────┤
│                  Drawing Layer (绘图层)                       │
│     Canvas2d | Canvas3d | SkiaSharp | ThreeJs4Net          │
├─────────────────────────────────────────────────────────────┤
│                   Model Layer (模型层)                        │
│     Component | Parameter | Provider | Definition           │
├─────────────────────────────────────────────────────────────┤
│                    Core Layer (核心层)                        │
│     Document | Element | Transaction | Layer | Style        │
├─────────────────────────────────────────────────────────────┤
│                    Math Layer (数学层)                        │
│     Vector | Matrix | Geometry | CSG | Intersect           │
└─────────────────────────────────────────────────────────────┘

3.1.2 核心概念

概念 类名 说明
文档 LcDocument CAD文档,包含所有元素和设置
元素 LcElement 图形元素基类
图层 LcLayer 图层管理
事务 Transaction 撤销/重做支持
运行时 DocumentRuntime 文档运行时环境
视口 Viewport 视图管理

3.1.3 命名空间结构

LightCAD
├── Core                    # 核心模块
│   ├── LcDocument         # 文档类
│   ├── LcElement          # 元素基类
│   ├── ElementType        # 元素类型定义
│   ├── LcLayer            # 图层类
│   ├── LcGuid             # GUID类型
│   └── Elements/          # 内置元素类型
├── MathLib                 # 数学库
│   ├── Vector2/Vector3    # 向量
│   ├── Matrix3/Matrix4    # 矩阵
│   ├── Box2/Box3          # 包围盒
│   ├── Curve2d/Curve3d    # 曲线
│   ├── Polyline2d         # 多段线
│   ├── Color              # 颜色
│   └── Csg/               # CSG运算
├── Drawing                 # 绘图模块
│   ├── LcCanvas2d         # 2D画布
│   ├── LcPaint            # 画笔
│   └── LcTextPaint        # 文字画笔
├── Drawing.Actions         # 操作模块
│   ├── ElementAction      # 元素操作基类
│   ├── DirectComponentAction # 直接组件操作
│   ├── PointInputer       # 点输入器
│   └── Action/            # 内置操作
├── Model                   # 模型模块
│   ├── DirectComponent    # 直接组件
│   ├── LcComponentDefinition # 组件定义
│   └── LcParameterSet     # 参数集
└── Runtime                 # 运行时
    ├── AppRuntime         # 应用运行时
    ├── DocumentRuntime    # 文档运行时
    ├── ILcPlugin          # 插件接口
    └── CommandClass       # 命令特性

3.2 FY_Layout模块架构

3.2.1 模块总览

FY_Layout包含两个主要项目:

FY_Layout
├── QdLayout                # 主插件项目
│   ├── 插件入口(LayoutPlugin)
│   ├── 命令系统(LayoutCmds)
│   ├── 元素类型(LayoutElementType)
│   └── 场布模块(各功能模块)
└── QdLayoutProvider        # Provider项目
    └── 三维模型生成器

3.2.2 QdLayout项目结构

QdLayout/
├── LayoutPlugin.cs         # 插件入口,实现ILcPlugin
├── LayoutCmds.cs           # 命令定义类
├── LayoutElementType.cs    # 元素类型静态定义
├── LcCurveChangeLoop.cs    # 曲线闭合工具类
├── GlobalUsing.cs          # 全局using声明
│
├── Barrier/                # 防护栏杆模块
│   ├── QdBarrier.cs       # 元素类
│   ├── BarrierAction.cs   # 二维操作类
│   └── Barrier3dAction.cs # 三维操作类
│
├── Berm/                   # 出土道路模块
│   ├── QdBerm.cs
│   ├── QdBermDef.cs       # 定义类
│   ├── BermAction.cs
│   └── Berm3dAction.cs
│
├── Earthwork/              # 土方回填模块
├── Equipment/              # 设备模块
├── Fence/                  # 围栏模块
├── FoundationPit/          # 基坑模块
├── Ground/                 # 硬化地面模块
├── Harden/                 # 路面硬化模块
├── Lawn/                   # 草坪模块
├── OpenLine/               # 开门边线模块
├── PlanBuild/              # 拟建建筑模块
├── PlateHouse/             # 板房模块
├── PropertyLine/           # 用地红线模块
├── Road/                   # 道路模块
├── Site/                   # 场地模块
├── TemplateArrange/        # 模板排布模块
│
├── Properties/             # 项目属性
│   ├── Resources.resx     # 资源文件
│   └── Resources.Designer.cs
└── Resources/              # 资源文件(图标等)

3.2.3 单个功能模块结构

以草坪(Lawn)模块为例,展示标准的模块结构:

Lawn/
├── QdLawn.cs           # 元素类,继承DirectComponent
├── QdLawnDef.cs        # 定义类,继承组件定义
├── LawnAction.cs       # 二维操作类,继承DirectComponentAction
└── Lawn3dAction.cs     # 三维操作类,处理三维渲染

类职责说明:

类名 基类 职责
QdLawn DirectComponent 数据模型,存储元素属性和几何数据
QdLawnDef LcComponentDefinition 元素定义,提供默认参数和配置
LawnAction DirectComponentAction 二维操作,处理绘制、编辑、夹点等
Lawn3dAction IElement3dAction 三维操作,生成三维模型

3.3 插件入口类详解

3.3.1 ILcPlugin接口

public interface ILcPlugin
{
    void InitUI();                              // UI初始化
    void Loaded();                              // 插件加载
    void Completed();                           // 完成加载
    void OnInitializeDocRt(DocumentRuntime docRt); // 文档初始化
    void OnDisposeDocRt(DocumentRuntime docRt);    // 文档销毁
}

3.3.2 LayoutPlugin实现分析

namespace QdLayout
{
    public class LayoutPlugin : ILcPlugin
    {
        // 静态TabItem定义:创建"场布"选项卡的UI结构
        public static TabItem LayoutItem = new TabItem
        {
            Name = "LayoutMajor",
            Text = "场布",
            ShortcutKey = "ALT-L",
            ButtonGroups = new List<TabButtonGroup>
            {
                new TabButtonGroup 
                {
                    Buttons = new List<TabButton>
                    {
                        // 创建项目按钮
                        new TabButton
                        {
                            Name = "CreateProject",
                            Text = "创建项目",
                            Icon = Properties.Resources.创建项目,
                            IsCommand = true,
                        },
                        // 草坪按钮(带下拉菜单)
                        new TabButton
                        {
                            Name = "Lawn",
                            Text = "草坪",
                            Icon = Properties.Resources.草地,
                            IsCommand = true,
                            DropDowns = new List<TabButton>
                            {
                                new TabButton { Name = "Lawn", Text = "任意绘制", ... },
                                new TabButton { Name = "LawnRec", Text = "矩形绘制", ... },
                                new TabButton { Name = "LawnChange", Text = "转换多段线", ... },
                            }
                        },
                        // 其他按钮...
                    }
                }
            }   
        };

        public void InitUI()
        {
            // UI初始化阶段(在Loaded之后调用)
        }

        public void Loaded()
        {
            // 1. 注册元素类型
            LcDocument.RegistElementTypes(LayoutElementType.All);
            
            // 2. 注册程序集
            LcRuntime.RegistAssemblies.Add("QdLayout");
            
            // 3. 注册元素操作类(二维)
            LcDocument.ElementActions.Add(LayoutElementType.Lawn, new LawnAction());
            LcDocument.ElementActions.Add(LayoutElementType.Fence, new FenceAction());
            LcDocument.ElementActions.Add(LayoutElementType.FoundationPit, new FoundationPitAction());
            // ... 更多元素操作注册
            
            // 4. 注册三维操作类
            LcDocument.Element3dActions.Add(LayoutElementType.Lawn, new Lawn3dAction());
            LcDocument.Element3dActions.Add(LayoutElementType.Fence, new Fence3dAction());
            // ... 更多三维操作注册
            
            // 5. 初始化其他配置
            PlateRoomConfigManager.Init();
        }

        public void Completed()
        {
            // 将TabItem添加到主界面
            AppRuntime.UISystem.AddInitTabItems([LayoutItem]);
        }

        public void OnInitializeDocRt(DocumentRuntime docRt)
        {
            // 每个文档初始化时调用
        }

        public void OnDisposeDocRt(DocumentRuntime docRt)
        {
            // 每个文档关闭时调用
        }
    }
}

3.3.3 插件生命周期

应用程序启动
     │
     ▼
扫描并加载插件DLL
     │
     ▼
创建ILcPlugin实例
     │
     ▼
调用 Loaded()           ← 注册元素类型、操作类
     │
     ▼
调用 InitUI()           ← UI初始化
     │
     ▼
调用 Completed()        ← 添加UI元素
     │
     ▼
┌────────────────────────┐
│    应用程序运行中       │
│         │              │
│         ▼              │
│   用户打开新文档        │
│         │              │
│         ▼              │
│ OnInitializeDocRt()    │
│         │              │
│         ▼              │
│   用户关闭文档          │
│         │              │
│         ▼              │
│ OnDisposeDocRt()       │
└────────────────────────┘
     │
     ▼
应用程序关闭

3.4 元素类型系统

3.4.1 ElementType定义

// LayoutElementType.cs
public static class LayoutElementType
{
    // 草坪元素类型
    public static ElementType Lawn = new ElementType
    {
        Guid = Guid.ParseExact("{63A566EA-3702-A98C-7A6B-8DBEA6B3F41A}", "B").ToLcGuid(),
        Name = "Lawn",
        DispalyName = "草坪",
        ClassType = typeof(QdLawn)
    };
    
    // 基坑元素类型
    public static ElementType FoundationPit = new ElementType
    {
        Guid = Guid.ParseExact("{C082E6EA-E099-94AB-50FA-50DF72D286D4}", "B").ToLcGuid(),
        Name = "FoundationPit",
        DispalyName = "基坑",
        ClassType = typeof(QdFoundationPit)
    };
    
    // 围栏元素类型
    public static ElementType Fence = new ElementType
    {
        Guid = Guid.ParseExact("{5A9EC5E6-09BF-4DB3-9AD2-DD0DA74F099A}", "B").ToLcGuid(),
        Name = "Fence",
        DispalyName = "围墙",
        ClassType = typeof(QdFence)
    };
    
    // ... 其他元素类型定义
    
    // 所有元素类型数组(用于批量注册)
    public static ElementType[] All = new ElementType[]
    {
        Lawn, FoundationPit, Road, Earthwork, Berm, 
        Harden, Site, PropertyLine, Fence, PlateBuilding, 
        PlateBuildGroup, OpenLine
    };
}

3.4.2 ElementType属性说明

属性 类型 说明
Guid LcGuid 唯一标识符,全局唯一
Name string 内部名称,用于代码引用
DispalyName string 显示名称,用于UI显示
ClassType Type 元素类的类型信息

3.4.3 GUID格式说明

// "B"格式:带大括号和连字符
Guid.ParseExact("{63A566EA-3702-A98C-7A6B-8DBEA6B3F41A}", "B")

// 其他格式:
// "D":带连字符,无大括号 63A566EA-3702-A98C-7A6B-8DBEA6B3F41A
// "N":32位数字 63A566EA3702A98C7A6B8DBEA6B3F41A
// "P":带括号 (63A566EA-3702-A98C-7A6B-8DBEA6B3F41A)

3.5 命令系统

3.5.1 CommandClass特性

[CommandClass]
public class LayoutCmds
{
    // 命令方法定义
}

3.5.2 CommandMethod特性

[CommandMethod(Name = "Lawn", ShortCuts = "LW")]
public CommandResult DrawLawn(IDocumentEditor docEditor, string[] args)
{
    var lawnAction = new LawnAction(docEditor);
    lawnAction.ExecCreatePoly(args);
    return CommandResult.Succ();
}

特性参数说明:

参数 类型 说明
Name string 命令名称,用于命令行调用
ShortCuts string 快捷键或简写

3.5.3 命令方法签名

public CommandResult MethodName(IDocumentEditor docEditor, string[] args)
  • 返回值CommandResult,表示命令执行结果
  • 参数
    • IDocumentEditor docEditor:文档编辑器接口
    • string[] args:命令参数数组

3.5.4 LayoutCmds完整分析

[CommandClass]
public class LayoutCmds
{
    // 围栏命令
    [CommandMethod(Name = "Fence", ShortCuts = "W")]
    public CommandResult DrawFence(IDocumentEditor docEditor, string[] args)
    {
        var fenceAction = new FenceAction(docEditor);
        fenceAction.ExecCreate(args);
        return CommandResult.Succ();
    }
    
    // 草坪命令 - 任意绘制
    [CommandMethod(Name = "Lawn", ShortCuts = "LW")]
    public CommandResult DrawLawn(IDocumentEditor docEditor, string[] args)
    {
        var lawnAction = new LawnAction(docEditor);
        lawnAction.ExecCreatePoly(args);  // 任意多边形绘制
        return CommandResult.Succ();
    }
    
    // 草坪命令 - 矩形绘制
    [CommandMethod(Name = "LawnRec", ShortCuts = "LWRC")]
    public CommandResult DrawLawnRec(IDocumentEditor docEditor, string[] args)
    {
        var lawnAction = new LawnAction(docEditor);
        lawnAction.ExecCreateRec(args);   // 矩形绘制
        return CommandResult.Succ();
    }
    
    // 草坪命令 - 转换多段线
    [CommandMethod(Name = "LawnChange", ShortCuts = "LWCH")]
    public CommandResult DrawLawnChange(IDocumentEditor docEditor, string[] args)
    {
        var lawnAction = new LawnAction(docEditor);
        lawnAction.ExecCreate(args);      // 从现有线段转换
        return CommandResult.Succ();
    }
    
    // 基坑命令
    [CommandMethod(Name = "FoundationPit", ShortCuts = "FDP")]
    public CommandResult DrawFoundationPit(IDocumentEditor docEditor, string[] args)
    {
        var fdpAction = new FoundationPitAction(docEditor);
        fdpAction.ExecCreatePoly(args);
        return CommandResult.Succ();
    }
    
    // 道路命令
    [CommandMethod(Name = "Road", ShortCuts = "ROD")]
    public CommandResult DrawRoad(IDocumentEditor docEditor, string[] args)
    {
        var roadAction = new RoadAction(docEditor);
        roadAction.ExecCreate(args);
        return CommandResult.Succ();
    }
    
    // ... 更多命令
}

3.6 配置与设置

3.6.1 QdLayoutCategorySettings

public static class QdLayoutCategorySettings
{
    // 命名空间键,用于组件分类
    public static string NamespaceKey = "场布施工设计";
    
    // 使用类型
    public static string UseType = "设计";
    
    // FromType转换方法
    public static void CnovertFromtype(ref FromType fromtype, out string convertLabel)
    {
        if (fromtype == FromType.Library)
        {
            fromtype = FromType.Document;
            convertLabel = "转到文档中";
        }
        else
        {
            fromtype = FromType.Library;
            convertLabel = "转到构件库中";
        }
    }
    
    public static string FromTypeMessage(FromType fromtype)
    {
        return fromtype == FromType.Library ? "转到文档中" : "转到构件库中";
    }
}

3.6.2 全局配置使用

在GlobalUsing.cs中使用静态导入:

global using static QdLayout.QdLayoutCategorySettings;

这样可以在代码中直接使用NamespaceKey等静态成员:

// 获取组件定义
var lawnDef = docRt.GetUseComDef($"{NamespaceKey}.绿色文明", "草坪", null);

3.7 模块间关系

3.7.1 依赖关系图

                    ┌─────────────────┐
                    │  LayoutPlugin   │
                    │   (插件入口)     │
                    └────────┬────────┘
                             │
         ┌───────────────────┼───────────────────┐
         ▼                   ▼                   ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│  LayoutCmds     │ │LayoutElementType│ │ 场布功能模块    │
│   (命令系统)    │ │  (类型定义)     │ │  (Lawn等)      │
└────────┬────────┘ └────────┬────────┘ └────────┬────────┘
         │                   │                   │
         └───────────────────┼───────────────────┘
                             ▼
                    ┌─────────────────┐
                    │   LightCAD      │
                    │   核心框架       │
                    └─────────────────┘

3.7.2 数据流向

用户操作(命令/鼠标)
         │
         ▼
    LayoutCmds          命令入口
         │
         ▼
    XxxAction           操作类(如LawnAction)
         │
    ┌────┴────┐
    ▼         ▼
创建/编辑   绘制
    │         │
    ▼         ▼
QdXxx      LcCanvas2d   元素类/画布
    │
    ▼
LcDocument              文档存储

3.8 扩展机制

3.8.1 添加新元素类型

  1. 定义ElementType

    public static ElementType NewElement = new ElementType
    {
        Guid = Guid.NewGuid().ToLcGuid(),
        Name = "NewElement",
        DispalyName = "新元素",
        ClassType = typeof(QdNewElement)
    };
    
  2. 创建元素类

    public class QdNewElement : DirectComponent
    {
        // 属性和方法...
    }
    
  3. 创建操作类

    public class NewElementAction : DirectComponentAction
    {
        // 绘制、编辑逻辑...
    }
    
  4. 注册元素和操作

    // 在Loaded()中
    LcDocument.ElementActions.Add(LayoutElementType.NewElement, new NewElementAction());
    

3.8.2 添加新命令

// 在LayoutCmds中添加
[CommandMethod(Name = "NewCommand", ShortCuts = "NC")]
public CommandResult NewCommand(IDocumentEditor docEditor, string[] args)
{
    // 命令逻辑
    return CommandResult.Succ();
}

3.8.3 添加新UI元素

// 在TabItem定义中添加按钮
new TabButton
{
    Name = "NewCommand",
    Text = "新功能",
    Icon = Properties.Resources.新图标,
    IsCommand = true,
}

3.9 本章小结

本章详细介绍了FY_Layout的核心架构与模块设计:

  1. LightCAD框架架构:分层设计,各层职责清晰
  2. FY_Layout模块结构:QdLayout和QdLayoutProvider两个项目
  3. 插件入口类:ILcPlugin接口实现和生命周期
  4. 元素类型系统:ElementType的定义和注册
  5. 命令系统:CommandClass和CommandMethod特性的使用
  6. 配置管理:全局设置和命名空间管理
  7. 扩展机制:如何添加新元素、命令和UI

理解了核心架构后,下一章我们将深入学习插件开发的基础知识。


posted @ 2026-01-31 16:02  我才是银古  阅读(2)  评论(0)    收藏  举报