第03章-核心架构解析
第三章:核心架构解析
3.1 架构概述
QCAD采用分层的模块化架构设计,将核心功能、用户界面和扩展系统清晰分离。这种设计使得QCAD既保持了高性能的核心运算能力,又提供了强大的可扩展性。
3.1.1 整体架构图
┌─────────────────────────────────────────────────────────────┐
│ 用户界面层 (UI Layer) │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ 菜单栏 │ │ 工具栏 │ │ 绘图区 │ │ 面板 │ │
│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │
├─────────────────────────────────────────────────────────────┤
│ 脚本层 (Script Layer) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ ECMAScript/JavaScript 引擎 (Qt Script) │ │
│ │ • 工具脚本 • UI组件 • 自动化脚本 • 插件脚本 │ │
│ └─────────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ 核心层 (Core Layer) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ RDocument │ │ REntity │ │ RStorage │ │ RExporter│ │
│ │ 文档管理 │ │ 实体系统 │ │ 存储接口 │ │ 导出系统 │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ RMath │ │ RVector │ │ RBox │ │ RArc │ │
│ │ 数学库 │ │ 向量类 │ │ 包围盒 │ │ 几何类 │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
├─────────────────────────────────────────────────────────────┤
│ 平台层 (Platform Layer) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Qt Framework 5.x / 6.x │ │
│ │ • QtCore • QtGui • QtWidgets • QtScript │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
3.1.2 设计原则
QCAD的架构遵循以下设计原则:
-
模块化设计:
- 功能分离为独立模块
- 模块间通过明确的接口通信
- 便于维护和扩展
-
分层架构:
- 核心层提供基础功能
- 脚本层实现业务逻辑
- UI层处理用户交互
-
开放扩展:
- 几乎所有API对脚本开放
- 支持C++和JavaScript两种扩展方式
- 插件系统设计完善
-
跨平台兼容:
- 基于Qt框架
- 抽象平台差异
- 统一的代码库
3.2 源码目录结构
3.2.1 主要目录
qcad/
├── src/ # C++源代码
│ ├── core/ # 核心模块
│ ├── entity/ # 实体定义
│ ├── gui/ # 图形界面
│ ├── grid/ # 网格系统
│ ├── snap/ # 捕捉系统
│ ├── operations/ # 操作命令
│ ├── spatialindex/ # 空间索引
│ └── stemmer/ # 文本处理
├── scripts/ # JavaScript脚本
│ ├── Draw/ # 绘图工具
│ ├── Edit/ # 编辑工具
│ ├── File/ # 文件操作
│ ├── Modify/ # 修改工具
│ ├── View/ # 视图控制
│ ├── Snap/ # 捕捉设置
│ ├── Layer/ # 图层管理
│ ├── Block/ # 块管理
│ ├── Dimension/ # 标注工具
│ ├── Misc/ # 其他工具
│ └── Pro/ # 专业版功能
├── plugins/ # 插件目录
├── fonts/ # 字体文件
├── libraries/ # 符号库
├── patterns/ # 填充图案
├── linetypes/ # 线型定义
├── themes/ # 主题文件
├── ts/ # 翻译文件
└── examples/ # 示例文件
3.2.2 核心源码模块
src/core/ - 核心模块:
core/
├── RDocument.cpp # 文档类
├── RDocumentInterface.cpp # 文档接口
├── REntity.cpp # 实体基类
├── RStorage.cpp # 存储抽象
├── RMemoryStorage.cpp # 内存存储
├── RSpatialIndex.cpp # 空间索引
├── RTransaction.cpp # 事务处理
├── RUcs.cpp # 用户坐标系
├── RLayer.cpp # 图层
├── RLinetype.cpp # 线型
├── RBlock.cpp # 块定义
├── RView.cpp # 视图
└── ...
src/entity/ - 实体模块:
entity/
├── RLineEntity.cpp # 直线
├── RArcEntity.cpp # 圆弧
├── RCircleEntity.cpp # 圆
├── REllipseEntity.cpp # 椭圆
├── RPolylineEntity.cpp # 多段线
├── RSplineEntity.cpp # 样条曲线
├── RTextEntity.cpp # 文本
├── RDimensionEntity.cpp # 标注
├── RHatchEntity.cpp # 图案填充
├── RImageEntity.cpp # 图像
├── RBlockReferenceEntity.cpp # 块参照
└── ...
3.2.3 脚本目录结构
scripts/Draw/ - 绘图工具:
Draw/
├── Line/ # 直线工具
│ ├── Line.js
│ ├── Line2P.js # 两点直线
│ ├── LineAngle.js # 角度直线
│ ├── LineHorizontal.js # 水平线
│ └── ...
├── Arc/ # 圆弧工具
├── Circle/ # 圆工具
├── Ellipse/ # 椭圆工具
├── Polyline/ # 多段线工具
├── Spline/ # 样条工具
├── Shape/ # 形状工具
├── Text/ # 文本工具
└── Hatch/ # 填充工具
3.3 文档模型
3.3.1 RDocument类
RDocument是QCAD的核心类,代表一个CAD文档(图纸)。它管理文档中的所有实体、图层、块等元素。
主要职责:
- 管理所有实体对象
- 维护图层、块、线型等定义
- 提供空间索引用于快速查询
- 处理事务和撤销/重做
- 存储文档属性和变量
类定义概览:
class RDocument : public RRequireHeap {
public:
// 构造和初始化
RDocument(RStorage& storage, RSpatialIndex& spatialIndex);
// 实体管理
void addEntity(REntity* entity);
void removeEntity(REntity::Id entityId);
QSet<REntity::Id> queryAllEntities() const;
REntity* queryEntity(REntity::Id entityId) const;
// 图层管理
void addLayer(RLayer* layer);
RLayer* queryLayer(RLayer::Id layerId) const;
RLayer* queryLayer(const QString& layerName) const;
// 块管理
void addBlock(RBlock* block);
RBlock* queryBlock(RBlock::Id blockId) const;
// 空间查询
QSet<REntity::Id> queryIntersectedEntities(const RBox& box) const;
QSet<REntity::Id> queryContainedEntities(const RBox& box) const;
// 文档属性
RBox getBoundingBox() const;
void setVariable(const QString& key, const QVariant& value);
QVariant getVariable(const QString& key) const;
// 事务
RTransaction startTransaction();
void endTransaction();
void undo();
void redo();
private:
RStorage* storage; // 存储后端
RSpatialIndex* spatialIndex; // 空间索引
RTransactionStack* transactionStack;
};
3.3.2 RDocumentInterface类
RDocumentInterface提供了文档与用户界面之间的高级接口,协调文档操作、视图更新和用户交互。
主要职责:
- 连接文档和视图
- 处理用户操作
- 管理选择集
- 协调命令执行
类定义概览:
class RDocumentInterface {
public:
RDocumentInterface(RDocument& document);
// 文档访问
RDocument& getDocument();
RStorage& getStorage();
// 视图管理
void addView(RGraphicsView* view);
void removeView(RGraphicsView* view);
void regenerateViews();
void regenerateScenes();
// 选择管理
void selectEntity(REntity::Id entityId);
void deselectEntity(REntity::Id entityId);
void selectAll();
void deselectAll();
QSet<REntity::Id> getSelectedEntities() const;
// 操作执行
void applyOperation(ROperation* operation);
// 坐标转换
RVector snap(const RVector& position);
// 属性
void setCurrentLayer(const QString& layerName);
void setCurrentColor(const RColor& color);
private:
RDocument& document;
QList<RGraphicsView*> views;
QSet<REntity::Id> selectedEntities;
};
3.3.3 存储系统
QCAD使用抽象的存储系统,支持不同的存储后端:
RStorage - 存储抽象基类:
class RStorage {
public:
virtual ~RStorage() {}
// 实体存储
virtual void saveEntity(REntity* entity) = 0;
virtual REntity* loadEntity(REntity::Id id) = 0;
virtual void deleteEntity(REntity::Id id) = 0;
// 图层存储
virtual void saveLayer(RLayer* layer) = 0;
virtual RLayer* loadLayer(RLayer::Id id) = 0;
// 查询
virtual QSet<REntity::Id> queryAllEntities() = 0;
virtual QSet<REntity::Id> queryLayerEntities(RLayer::Id layerId) = 0;
};
RMemoryStorage - 内存存储实现:
- 将所有数据存储在内存中
- 适用于小型文档
- 快速访问
RLinkedStorage - 链接存储实现:
- 支持文档链接
- 适用于外部参照
3.4 实体系统
3.4.1 实体类层次
QCAD中所有可绘制对象都继承自REntity基类:
RObject
└── REntity (实体基类)
├── RLineEntity (直线)
├── RArcEntity (圆弧)
├── RCircleEntity (圆)
├── REllipseEntity (椭圆)
├── RPolylineEntity (多段线)
├── RSplineEntity (样条曲线)
├── RPointEntity (点)
├── RTextEntity (文本)
│ └── RTextBasedEntity
│ ├── RAttributeEntity (属性)
│ └── RAttributeDefinitionEntity (属性定义)
├── RDimensionEntity (标注)
│ ├── RDimLinearEntity (线性标注)
│ ├── RDimAlignedEntity (对齐标注)
│ ├── RDimAngularEntity (角度标注)
│ ├── RDimRadialEntity (半径标注)
│ ├── RDimDiametricEntity (直径标注)
│ └── RDimOrdinateEntity (坐标标注)
├── RHatchEntity (填充)
├── RImageEntity (图像)
├── RBlockReferenceEntity (块参照)
├── RLeaderEntity (引线)
├── RSolidEntity (实体填充)
├── RTraceEntity (轨迹)
└── RViewportEntity (视口)
3.4.2 REntity基类
REntity是所有实体的基类,定义了实体的通用接口:
class REntity : public RObject {
public:
typedef int Id;
// 图层和块
RLayer::Id getLayerId() const;
void setLayerId(RLayer::Id layerId);
RBlock::Id getBlockId() const;
void setBlockId(RBlock::Id blockId);
// 几何属性
virtual RBox getBoundingBox() const = 0;
virtual double getLength() const;
virtual double getArea() const;
virtual RVector getClosestPointOnEntity(const RVector& point) const;
virtual double getDistanceTo(const RVector& point) const;
// 变换
virtual void move(const RVector& offset);
virtual void rotate(double angle, const RVector& center);
virtual void scale(double factor, const RVector& center);
virtual void mirror(const RLine& axis);
// 绘制
virtual void exportEntity(RExporter& exporter) const = 0;
// 属性
void setColor(const RColor& color);
RColor getColor() const;
void setLinetype(const RLinetype& linetype);
void setLineweight(double lineweight);
// 选择
bool isSelected() const;
void setSelected(bool on);
protected:
RLayer::Id layerId;
RBlock::Id blockId;
RColor color;
RLinetype linetype;
double lineweight;
bool selected;
};
3.4.3 实体数据类
每个实体都有对应的数据类,存储实体的几何信息:
RLineData - 直线数据:
class RLineData : public REntityData {
public:
RLineData();
RLineData(const RVector& startPoint, const RVector& endPoint);
RVector getStartPoint() const { return startPoint; }
RVector getEndPoint() const { return endPoint; }
void setStartPoint(const RVector& p) { startPoint = p; }
void setEndPoint(const RVector& p) { endPoint = p; }
double getLength() const;
double getAngle() const;
RVector getMiddlePoint() const;
private:
RVector startPoint;
RVector endPoint;
};
RArcData - 圆弧数据:
class RArcData : public REntityData {
public:
RArcData();
RArcData(const RVector& center, double radius,
double startAngle, double endAngle, bool reversed);
RVector getCenter() const { return center; }
double getRadius() const { return radius; }
double getStartAngle() const { return startAngle; }
double getEndAngle() const { return endAngle; }
bool isReversed() const { return reversed; }
double getLength() const;
RVector getStartPoint() const;
RVector getEndPoint() const;
RVector getMiddlePoint() const;
private:
RVector center;
double radius;
double startAngle;
double endAngle;
bool reversed;
};
3.4.4 实体工厂
QCAD使用工厂模式创建实体:
class REntityFactory {
public:
static REntity* create(const QString& entityType);
static void registerEntity(const QString& type,
REntity* (*creator)());
private:
static QMap<QString, REntity* (*)(void)> creators;
};
// 注册实体类型
REntityFactory::registerEntity("RLineEntity",
[]() -> REntity* { return new RLineEntity(); });
3.5 图形视图系统
3.5.1 RGraphicsView类
RGraphicsView负责文档的可视化呈现:
class RGraphicsView : public QWidget {
public:
RGraphicsView(RDocument* document);
// 视图控制
void zoomIn();
void zoomOut();
void zoomToFit();
void zoomToRect(const RBox& rect);
void pan(const RVector& offset);
// 坐标转换
RVector mapToModel(const QPoint& screenPoint) const;
QPoint mapToScreen(const RVector& modelPoint) const;
// 视图属性
void setFactor(double factor);
double getFactor() const;
void setOffset(const RVector& offset);
RVector getOffset() const;
// 网格
void setGridVisible(bool visible);
bool isGridVisible() const;
// 渲染
void repaintView();
void regenerate();
protected:
void paintEvent(QPaintEvent* event) override;
void wheelEvent(QWheelEvent* event) override;
void mousePressEvent(QMouseEvent* event) override;
void mouseMoveEvent(QMouseEvent* event) override;
void mouseReleaseEvent(QMouseEvent* event) override;
private:
RDocument* document;
RGraphicsScene* scene;
double factor; // 缩放因子
RVector offset; // 平移偏移
bool gridVisible;
};
3.5.2 RGraphicsScene类
RGraphicsScene管理图形场景中的所有图形项:
class RGraphicsScene : public QGraphicsScene {
public:
RGraphicsScene(RDocument* document);
// 重新生成
void regenerate();
void regenerateEntity(REntity::Id entityId);
// 实体项管理
void addEntityItem(REntity::Id entityId, QGraphicsItem* item);
void removeEntityItem(REntity::Id entityId);
QGraphicsItem* getEntityItem(REntity::Id entityId) const;
// 高亮
void highlightEntity(REntity::Id entityId);
void dehighlightEntity(REntity::Id entityId);
private:
RDocument* document;
QMap<REntity::Id, QGraphicsItem*> entityItems;
};
3.5.3 导出器系统
RExporter用于将实体转换为图形输出:
class RExporter {
public:
virtual ~RExporter() {}
// 开始/结束
virtual void startExport() {}
virtual void endExport() {}
// 图形元素输出
virtual void exportLine(const RLine& line) = 0;
virtual void exportArc(const RArc& arc) = 0;
virtual void exportCircle(const RCircle& circle) = 0;
virtual void exportEllipse(const REllipse& ellipse) = 0;
virtual void exportPolyline(const RPolyline& polyline) = 0;
virtual void exportSpline(const RSpline& spline) = 0;
virtual void exportText(const RTextData& text) = 0;
// 属性
virtual void setColor(const RColor& color) {}
virtual void setLinetype(const RLinetype& linetype) {}
virtual void setLineweight(double lineweight) {}
};
// 图形场景导出器
class RGraphicsSceneExporter : public RExporter {
public:
RGraphicsSceneExporter(QGraphicsScene* scene);
void exportLine(const RLine& line) override;
void exportArc(const RArc& arc) override;
// ...
private:
QGraphicsScene* scene;
};
// PDF导出器
class RPdfExporter : public RExporter {
public:
RPdfExporter(const QString& fileName);
// ...
};
// SVG导出器
class RSvgExporter : public RExporter {
public:
RSvgExporter(const QString& fileName);
// ...
};
3.6 事务与撤销系统
3.6.1 RTransaction类
RTransaction管理文档修改的原子操作:
class RTransaction {
public:
RTransaction(RDocument& document);
// 操作记录
void addEntity(REntity* entity);
void modifyEntity(REntity* entity);
void deleteEntity(REntity::Id entityId);
// 事务控制
void commit();
void rollback();
// 撤销/重做
void undo();
void redo();
// 状态
bool isEmpty() const;
bool isValid() const;
private:
RDocument& document;
QList<ROperation*> operations;
bool committed;
};
3.6.2 撤销/重做实现
class RTransactionStack {
public:
void push(RTransaction* transaction);
RTransaction* pop();
void undo();
void redo();
bool canUndo() const;
bool canRedo() const;
void clear();
private:
QStack<RTransaction*> undoStack;
QStack<RTransaction*> redoStack;
};
3.7 空间索引系统
3.7.1 RSpatialIndex类
RSpatialIndex提供高效的空间查询能力:
class RSpatialIndex {
public:
virtual ~RSpatialIndex() {}
// 添加/删除
virtual void addEntity(REntity* entity) = 0;
virtual void removeEntity(REntity::Id entityId) = 0;
virtual void updateEntity(REntity* entity) = 0;
// 空间查询
virtual QSet<REntity::Id> queryIntersected(const RBox& box) const = 0;
virtual QSet<REntity::Id> queryContained(const RBox& box) const = 0;
virtual QSet<REntity::Id> queryNearby(const RVector& point,
double radius) const = 0;
// 最近实体
virtual REntity::Id queryNearest(const RVector& point) const = 0;
virtual void clear() = 0;
};
// 基于R-Tree的实现
class RSpatialIndexRTree : public RSpatialIndex {
// 使用Boost.Geometry R-Tree实现
};
// 简单的网格实现
class RSpatialIndexGrid : public RSpatialIndex {
// 使用规则网格划分
};
3.7.2 空间查询示例
// 查询矩形区域内的实体
RBox selectionBox(RVector(0, 0), RVector(100, 100));
QSet<REntity::Id> entities = document.queryContainedEntities(selectionBox);
// 查询与给定点最近的实体
RVector clickPoint(50, 50);
REntity::Id nearestId = spatialIndex.queryNearest(clickPoint);
REntity* entity = document.queryEntity(nearestId);
// 查询与给定包围盒相交的实体
QSet<REntity::Id> intersected = document.queryIntersectedEntities(selectionBox);
3.8 模块系统
3.8.1 模块组织
QCAD的源码组织为多个模块:
| 模块 | 说明 |
|---|---|
| core | 核心类、文档模型、基础设施 |
| entity | 实体类定义 |
| gui | 图形用户界面 |
| grid | 网格系统 |
| snap | 捕捉系统 |
| operations | 操作和命令 |
| spatialindex | 空间索引 |
| io | 文件输入输出 |
| dxf | DXF格式处理 |
3.8.2 模块依赖关系
┌─────┐
│ gui │
└──┬──┘
│
┌─────────────┼─────────────┐
│ │ │
┌────▼───┐ ┌────▼────┐ ┌────▼────┐
│ snap │ │operations│ │ grid │
└────┬───┘ └────┬─────┘ └────┬────┘
│ │ │
└────────────┼──────────────┘
│
┌─────▼─────┐
│ entity │
└─────┬─────┘
│
┌─────▼─────┐
│ core │
└───────────┘
3.9 本章小结
本章深入分析了QCAD的核心架构:
-
整体架构:
- 分层设计(平台层、核心层、脚本层、UI层)
- 模块化组织
- 清晰的职责分离
-
文档模型:
- RDocument管理文档内容
- RDocumentInterface协调文档与界面
- 抽象存储系统
-
实体系统:
- 继承层次清晰
- 实体与数据分离
- 工厂模式创建
-
图形视图:
- RGraphicsView处理视图
- RGraphicsScene管理场景
- 导出器模式输出
-
事务系统:
- 事务保证原子操作
- 完整的撤销/重做支持
-
空间索引:
- 高效的空间查询
- 多种索引实现
理解这些核心概念对于深入使用QCAD和进行二次开发至关重要。
下一章预告:第四章将详细介绍QCAD的用户界面,包括各个界面组件的功能和使用方法。

浙公网安备 33010602011771号