核心架构解析

第十一章 核心架构解析

11.1 架构概述

11.1.1 整体架构

LibreCAD采用模块化的面向对象架构,基于Qt框架构建。其架构遵循类似MVC(Model-View-Controller)的设计模式。

┌──────────────────────────────────────────────────────────────┐
│                     用户界面层 (UI Layer)                     │
│  ┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐  │
│  │ QC_Application │ │  Dialogs    │ │   Dock Widgets      │  │
│  │    Window     │ │             │ │                      │  │
│  └──────────────┘ └──────────────┘ └──────────────────────┘  │
├──────────────────────────────────────────────────────────────┤
│                    动作层 (Action Layer)                      │
│  ┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐  │
│  │RS_ActionInterface│ │ Drawing  │ │   Modification      │  │
│  │              │ │  Actions    │ │   Actions            │  │
│  └──────────────┘ └──────────────┘ └──────────────────────┘  │
├──────────────────────────────────────────────────────────────┤
│                    核心库层 (Core Library)                    │
│  ┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐  │
│  │ RS_Entity    │ │ RS_Graphic  │ │   RS_GraphicView    │  │
│  │ System       │ │             │ │                      │  │
│  └──────────────┘ └──────────────┘ └──────────────────────┘  │
├──────────────────────────────────────────────────────────────┤
│                    数据层 (Data Layer)                        │
│  ┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐  │
│  │  libdxfrw    │ │ File I/O    │ │   Filters            │  │
│  └──────────────┘ └──────────────┘ └──────────────────────┘  │
└──────────────────────────────────────────────────────────────┘

11.1.2 主要模块

模块 路径 功能
main librecad/src/main 程序入口
lib/engine librecad/src/lib/engine 图形引擎核心
lib/gui librecad/src/lib/gui GUI组件
lib/actions librecad/src/lib/actions 动作基类
lib/creation librecad/src/lib/creation 图形创建
lib/modification librecad/src/lib/modification 图形修改
lib/information librecad/src/lib/information 信息查询
lib/math librecad/src/lib/math 数学计算
lib/filters librecad/src/lib/filters 文件过滤器
actions librecad/src/actions 具体动作实现
ui librecad/src/ui 用户界面
plugins librecad/src/plugins 插件接口

11.1.3 技术栈

技术栈
├── 编程语言:C++17
├── GUI框架:Qt 6.x
├── 构建系统:CMake / qmake
├── 数学库:Boost
├── 文件I/O:libdxfrw
├── 表达式解析:muParser
└── 字体渲染:FreeType

11.2 实体系统

11.2.1 RS_Entity基类

所有图形实体的基类:

class RS_Entity {
public:
    // 构造和析构
    RS_Entity(RS_EntityContainer* parent = nullptr);
    virtual ~RS_Entity();
    
    // 实体类型
    virtual RS2::EntityType rtti() const = 0;
    
    // 绘制
    virtual void draw(RS_Painter* painter, 
                     RS_GraphicView* view,
                     double& patternOffset) = 0;
    
    // 几何操作
    virtual RS_Vector getNearestPointOnEntity(
        const RS_Vector& coord,
        bool onEntity = true,
        double* dist = nullptr,
        RS_Entity** entity = nullptr
    ) const;
    
    virtual double getDistanceToPoint(
        const RS_Vector& coord,
        RS_Entity** entity = nullptr,
        RS2::ResolveLevel level = RS2::ResolveNone,
        double solidDist = RS_MAXDOUBLE
    ) const;
    
    // 边界
    virtual RS_Vector getMin() const;
    virtual RS_Vector getMax() const;
    
    // 变换
    virtual void move(const RS_Vector& offset);
    virtual void rotate(const RS_Vector& center, double angle);
    virtual void scale(const RS_Vector& center, const RS_Vector& factor);
    virtual void mirror(const RS_Vector& axisPoint1, 
                       const RS_Vector& axisPoint2);
    
    // 属性
    RS_Layer* getLayer() const;
    void setLayer(RS_Layer* layer);
    RS_Pen getPen() const;
    void setPen(const RS_Pen& pen);
    
protected:
    RS_EntityContainer* parent;
    RS_Pen pen;
    RS_Layer* layer;
    bool visible;
    bool selected;
};

11.2.2 实体类型枚举

namespace RS2 {
    enum EntityType {
        EntityUnknown,
        EntityContainer,
        EntityBlock,
        EntityFontChar,
        EntityInsert,
        EntityGraphic,
        EntityPoint,
        EntityLine,
        EntityPolyline,
        EntityVertex,
        EntityArc,
        EntityCircle,
        EntityEllipse,
        EntityHyperbola,
        EntitySolid,
        EntityImage,
        EntitySpline,
        EntitySplinePoints,
        EntityHatch,
        EntityText,
        EntityMText,
        EntityDimLinear,
        EntityDimAligned,
        EntityDimRadial,
        EntityDimDiametric,
        EntityDimAngular,
        EntityDimLeader,
        EntityOverlay
    };
}

11.2.3 实体继承层次

RS_Entity
├── RS_Point           # 点
├── RS_Line            # 直线
├── RS_Circle          # 圆
├── RS_Arc             # 圆弧
├── RS_Ellipse         # 椭圆
├── RS_Spline          # 样条曲线
├── RS_Text            # 单行文字
├── RS_MText           # 多行文字
├── RS_Hatch           # 填充
├── RS_Image           # 图像
├── RS_Dimension       # 尺寸标注基类
│   ├── RS_DimLinear   # 线性标注
│   ├── RS_DimAligned  # 对齐标注
│   ├── RS_DimRadial   # 半径标注
│   ├── RS_DimDiametric# 直径标注
│   ├── RS_DimAngular  # 角度标注
│   └── RS_DimLeader   # 引线标注
└── RS_EntityContainer # 实体容器
    ├── RS_Polyline    # 折线
    ├── RS_Block       # 块定义
    ├── RS_Insert      # 块引用
    └── RS_Graphic     # 图形文档

11.3 图形视图系统

11.3.1 RS_GraphicView

负责图形的渲染和用户交互:

class RS_GraphicView : public QWidget {
public:
    RS_GraphicView(QWidget* parent = nullptr);
    virtual ~RS_GraphicView();
    
    // 设置图形数据
    void setContainer(RS_EntityContainer* container);
    RS_EntityContainer* getContainer() const;
    
    // 视图变换
    void zoomIn(double f = 1.5, const RS_Vector& center = RS_Vector(false));
    void zoomOut(double f = 1.5, const RS_Vector& center = RS_Vector(false));
    void zoomWindow(const RS_Vector& v1, const RS_Vector& v2);
    void zoomAuto(bool axis = true, bool keepAspectRatio = true);
    void zoomPan(int dx, int dy);
    
    // 坐标转换
    RS_Vector toGui(const RS_Vector& v) const;
    RS_Vector toGraph(const RS_Vector& v) const;
    double toGuiX(double x) const;
    double toGuiY(double y) const;
    double toGraphX(double x) const;
    double toGraphY(double y) const;
    
    // 绘制
    virtual void drawEntity(RS_Entity* e);
    virtual void drawLayer(RS_Layer* layer);
    void redraw(RS2::RedrawMethod method = RS2::RedrawAll);
    
    // 事件处理器
    void setEventHandler(RS_EventHandler* handler);
    
protected:
    void paintEvent(QPaintEvent* e) override;
    void mousePressEvent(QMouseEvent* e) override;
    void mouseReleaseEvent(QMouseEvent* e) override;
    void mouseMoveEvent(QMouseEvent* e) override;
    void wheelEvent(QWheelEvent* e) override;
    void keyPressEvent(QKeyEvent* e) override;
    
private:
    RS_EntityContainer* container;
    RS_EventHandler* eventHandler;
    double factor;           // 缩放因子
    int offsetX, offsetY;    // 视图偏移
};

11.3.2 坐标系统

图形坐标系 (Graph Coordinates)
     ↑ Y+
     │
     │
─────┼─────→ X+
     │
     │
     
界面坐标系 (GUI Coordinates)
─────┬─────→ X+
     │
     │
     ↓ Y+

转换公式:
guiX = (graphX + offsetX) * factor
guiY = -(graphY + offsetY) * factor + height

11.3.3 视图变换矩阵

// 图形坐标到屏幕坐标
RS_Vector RS_GraphicView::toGui(const RS_Vector& v) const {
    return RS_Vector(
        toGuiX(v.x),
        toGuiY(v.y)
    );
}

double RS_GraphicView::toGuiX(double x) const {
    return (x + offsetX) * factor;
}

double RS_GraphicView::toGuiY(double y) const {
    return -(y + offsetY) * factor + getHeight();
}

// 屏幕坐标到图形坐标
RS_Vector RS_GraphicView::toGraph(const RS_Vector& v) const {
    return RS_Vector(
        toGraphX(v.x),
        toGraphY(v.y)
    );
}

11.4 动作系统

11.4.1 RS_ActionInterface

所有动作的基类:

class RS_ActionInterface : public QObject {
    Q_OBJECT
    
public:
    RS_ActionInterface(const char* name,
                      RS_EntityContainer& container,
                      RS_GraphicView& graphicView);
    virtual ~RS_ActionInterface();
    
    // 动作生命周期
    virtual void init(int status = 0);
    virtual void finish(bool updateTB = true);
    virtual void suspend();
    virtual void resume();
    
    // 事件处理
    virtual void mouseReleaseEvent(QMouseEvent* e);
    virtual void mouseMoveEvent(QMouseEvent* e);
    virtual void mousePressEvent(QMouseEvent* e);
    virtual void keyPressEvent(QKeyEvent* e);
    virtual void coordinateEvent(RS_CoordinateEvent* e);
    virtual void commandEvent(RS_CommandEvent* e);
    
    // 状态管理
    int getStatus() const;
    void setStatus(int status);
    
    // 工具提示
    virtual void updateMouseButtonHints();
    virtual void updateToolBar();
    
protected:
    RS_EntityContainer* container;
    RS_GraphicView* graphicView;
    RS_Document* document;
    int status;
};

11.4.2 动作状态机

动作使用状态机模式管理用户交互:

// 画线动作的状态定义
enum Status {
    SetStartPoint,    // 等待起点
    SetEndPoint,      // 等待终点
    SetNextPoint      // 等待下一点
};

// 状态转换示例
void RS_ActionDrawLine::mouseReleaseEvent(QMouseEvent* e) {
    switch (getStatus()) {
        case SetStartPoint:
            // 保存起点
            startPoint = snapPoint(e);
            setStatus(SetEndPoint);
            break;
            
        case SetEndPoint:
            // 创建线段
            endPoint = snapPoint(e);
            createLine();
            // 准备下一条线
            startPoint = endPoint;
            setStatus(SetNextPoint);
            break;
            
        case SetNextPoint:
            // 继续画线
            endPoint = snapPoint(e);
            createLine();
            startPoint = endPoint;
            break;
    }
}

11.4.3 动作分类

librecad/src/actions/
├── drawing/           # 绘图动作
│   ├── RS_ActionDrawLine
│   ├── RS_ActionDrawCircle
│   ├── RS_ActionDrawArc
│   ├── RS_ActionDrawEllipse
│   ├── RS_ActionDrawSpline
│   ├── RS_ActionDrawPolyline
│   ├── RS_ActionDrawText
│   └── RS_ActionDrawHatch
├── file/              # 文件动作
│   ├── RS_ActionFileNew
│   ├── RS_ActionFileOpen
│   └── RS_ActionFileSave
├── dock_widgets/      # 停靠窗口动作
├── options/           # 选项动作
└── print_preview/     # 打印预览动作

11.5 命令系统

11.5.1 RS_Commands

命令处理核心类:

class RS_Commands {
public:
    // 注册命令
    static void addCommand(const QString& cmd, RS2::ActionType action);
    
    // 查找命令
    static RS2::ActionType getAction(const QString& cmd);
    
    // 命令别名
    static void addAlias(const QString& alias, const QString& cmd);
    
    // 命令列表
    static QStringList getCommands();
    
private:
    static QHash<QString, RS2::ActionType> commands;
    static QHash<QString, QString> aliases;
};

11.5.2 命令注册

// 注册命令示例
void RS_Commands::initCommands() {
    // 绘图命令
    addCommand("line", RS2::ActionDrawLine);
    addCommand("circle", RS2::ActionDrawCircle);
    addCommand("arc", RS2::ActionDrawArc);
    addCommand("ellipse", RS2::ActionDrawEllipse);
    addCommand("polyline", RS2::ActionDrawPolyline);
    addCommand("text", RS2::ActionDrawText);
    
    // 修改命令
    addCommand("move", RS2::ActionModifyMove);
    addCommand("copy", RS2::ActionModifyCopy);
    addCommand("rotate", RS2::ActionModifyRotate);
    addCommand("scale", RS2::ActionModifyScale);
    addCommand("mirror", RS2::ActionModifyMirror);
    
    // 别名
    addAlias("l", "line");
    addAlias("c", "circle");
    addAlias("a", "arc");
    addAlias("pl", "polyline");
    addAlias("m", "move");
    addAlias("co", "copy");
}

11.6 事件处理系统

11.6.1 RS_EventHandler

事件分发器:

class RS_EventHandler {
public:
    RS_EventHandler();
    virtual ~RS_EventHandler();
    
    // 设置当前动作
    void setCurrentAction(RS_ActionInterface* action);
    RS_ActionInterface* getCurrentAction() const;
    
    // 默认动作
    void setDefaultAction(RS_ActionInterface* action);
    
    // 事件分发
    void mouseReleaseEvent(QMouseEvent* e);
    void mouseMoveEvent(QMouseEvent* e);
    void mousePressEvent(QMouseEvent* e);
    void keyPressEvent(QKeyEvent* e);
    void coordinateEvent(RS_CoordinateEvent* e);
    void commandEvent(RS_CommandEvent* e);
    
    // 动作栈管理
    void back();
    bool hasAction() const;
    
private:
    RS_ActionInterface* defaultAction;
    QStack<RS_ActionInterface*> actionStack;
};

11.6.2 自定义事件

// 坐标事件
class RS_CoordinateEvent : public QEvent {
public:
    RS_CoordinateEvent(const RS_Vector& pos);
    RS_Vector getCoordinate() const;
    
private:
    RS_Vector pos;
};

// 命令事件
class RS_CommandEvent : public QEvent {
public:
    RS_CommandEvent(const QString& cmd);
    QString getCommand() const;
    void accept();
    void ignore();
    bool isAccepted() const;
    
private:
    QString cmd;
    bool accepted;
};

11.7 对象捕捉系统

11.7.1 RS_Snapper

对象捕捉核心类:

class RS_Snapper {
public:
    RS_Snapper(RS_EntityContainer& container,
              RS_GraphicView& graphicView);
    
    // 捕捉点计算
    RS_Vector snapPoint(QMouseEvent* e);
    RS_Vector snapFree(QMouseEvent* e);
    RS_Vector snapGrid(const RS_Vector& coord);
    
    // 捕捉模式
    void setSnapMode(RS_SnapMode mode);
    RS_SnapMode getSnapMode() const;
    
    // 具体捕捉
    RS_Vector snapEndpoint(const RS_Vector& coord);
    RS_Vector snapMiddle(const RS_Vector& coord);
    RS_Vector snapCenter(const RS_Vector& coord);
    RS_Vector snapIntersection(const RS_Vector& coord);
    RS_Vector snapOnEntity(const RS_Vector& coord);
    
    // 捕捉范围
    void setSnapRange(int range);
    
protected:
    RS_EntityContainer* container;
    RS_GraphicView* graphicView;
    RS_SnapMode snapMode;
    int snapRange;
};

11.7.2 捕捉模式

class RS_SnapMode {
public:
    bool snapEndpoint;      // 端点
    bool snapMiddle;        // 中点
    bool snapCenter;        // 圆心
    bool snapIntersection;  // 交点
    bool snapOnEntity;      // 最近点
    bool snapDist;          // 距离
    bool snapGrid;          // 网格
    bool snapFree;          // 自由
    
    // 限制
    bool restriction;       // 启用限制
    RS2::SnapRestriction restrictionType;
};

11.8 图层系统

11.8.1 RS_Layer

图层类定义:

class RS_Layer {
public:
    RS_Layer(const QString& name);
    
    // 名称
    QString getName() const;
    void setName(const QString& name);
    
    // 可见性
    bool isFrozen() const;
    void freeze(bool on);
    
    // 锁定
    bool isLocked() const;
    void lock(bool on);
    
    // 打印
    bool isPrint() const;
    void setPrint(bool on);
    
    // 画笔(颜色、线型、线宽)
    RS_Pen getPen() const;
    void setPen(const RS_Pen& pen);
    
private:
    QString name;
    RS_Pen pen;
    bool frozen;
    bool locked;
    bool print;
};

11.8.2 RS_LayerList

图层列表管理:

class RS_LayerList {
public:
    RS_LayerList();
    ~RS_LayerList();
    
    // 图层操作
    void add(RS_Layer* layer);
    void remove(RS_Layer* layer);
    RS_Layer* find(const QString& name);
    
    // 迭代器
    int count() const;
    RS_Layer* at(int i) const;
    
    // 当前图层
    void activate(RS_Layer* layer);
    RS_Layer* getActive() const;
    
    // 信号
    void layerActivated(RS_Layer*);
    void layerAdded(RS_Layer*);
    void layerRemoved(RS_Layer*);
    
private:
    QList<RS_Layer*> layers;
    RS_Layer* activeLayer;
};

11.9 文件I/O系统

11.9.1 RS_FileIO

文件操作抽象类:

class RS_FileIO {
public:
    // 导入
    static bool fileImport(RS_Graphic& g, 
                          const QString& file,
                          RS2::FormatType type = RS2::FormatUnknown);
    
    // 导出
    static bool fileExport(RS_Graphic& g,
                          const QString& file,
                          RS2::FormatType type = RS2::FormatUnknown);
    
    // 格式检测
    static RS2::FormatType detectFormat(const QString& file);
};

11.9.2 RS_FilterDXFRW

DXF过滤器(使用libdxfrw):

class RS_FilterDXFRW : public RS_FilterInterface,
                       public DRW_Interface {
public:
    RS_FilterDXFRW();
    
    // 导入
    bool fileImport(RS_Graphic& g, const QString& file, 
                   RS2::FormatType type) override;
    
    // 导出
    bool fileExport(RS_Graphic& g, const QString& file,
                   RS2::FormatType type) override;
    
    // DXF回调(实现DRW_Interface)
    void addLine(const DRW_Line& data) override;
    void addCircle(const DRW_Circle& data) override;
    void addArc(const DRW_Arc& data) override;
    void addText(const DRW_Text& data) override;
    // ... 更多回调
    
private:
    RS_Graphic* graphic;
};

11.10 本章小结

本章介绍了LibreCAD的核心架构:

  1. 整体架构:分层设计、主要模块、技术栈
  2. 实体系统:RS_Entity基类、实体类型、继承层次
  3. 图形视图系统:RS_GraphicView、坐标转换、视图变换
  4. 动作系统:RS_ActionInterface、状态机模式、动作分类
  5. 命令系统:RS_Commands、命令注册、别名
  6. 事件处理:RS_EventHandler、事件分发、自定义事件
  7. 对象捕捉:RS_Snapper、捕捉模式
  8. 图层系统:RS_Layer、RS_LayerList
  9. 文件I/O:RS_FileIO、DXF过滤器

理解核心架构是进行LibreCAD二次开发的基础。


上一章:打印与输出 | 下一章:源码编译与开发环境搭建


posted @ 2026-01-10 13:13  我才是银古  阅读(27)  评论(0)    收藏  举报