实体系统详解

第十三章 实体系统详解

13.1 实体系统概述

13.1.1 实体的概念

在LibreCAD中,实体(Entity)是图形对象的基本单元。所有可以绘制、编辑和显示的图形元素都是实体的子类。

实体的特征

  • 具有几何属性(位置、尺寸)
  • 具有显示属性(颜色、线型、线宽)
  • 可以被选择和操作
  • 属于某个图层
  • 可以包含在容器中

13.1.2 实体分类

实体类型
├── 基本实体
│   ├── 点 (RS_Point)
│   ├── 直线 (RS_Line)
│   ├── 圆 (RS_Circle)
│   ├── 圆弧 (RS_Arc)
│   ├── 椭圆 (RS_Ellipse)
│   └── 样条曲线 (RS_Spline)
├── 复合实体
│   ├── 折线 (RS_Polyline)
│   ├── 填充 (RS_Hatch)
│   └── 尺寸标注 (RS_Dimension)
├── 注释实体
│   ├── 单行文字 (RS_Text)
│   └── 多行文字 (RS_MText)
├── 特殊实体
│   ├── 图像 (RS_Image)
│   └── 块引用 (RS_Insert)
└── 容器实体
    ├── 块定义 (RS_Block)
    └── 图形 (RS_Graphic)

13.2 RS_Entity基类详解

13.2.1 类定义

class RS_Entity {
public:
    // 构造函数
    RS_Entity(RS_EntityContainer* parent = nullptr);
    virtual ~RS_Entity();
    
    // 实体类型识别
    virtual RS2::EntityType rtti() const = 0;
    virtual QString typeName() const;
    virtual bool isOfType(RS2::EntityType type) const;
    
    // 克隆
    virtual RS_Entity* clone() const = 0;
    
    // 父容器
    RS_EntityContainer* getParent() const;
    void setParent(RS_EntityContainer* parent);
    
    // 图层
    RS_Layer* getLayer() const;
    void setLayer(RS_Layer* layer);
    void setLayer(const QString& name);
    
    // 画笔属性
    RS_Pen getPen(bool resolve = true) const;
    void setPen(const RS_Pen& pen);
    RS_Color getColor(bool resolve = true) const;
    RS2::LineType getLineType(bool resolve = true) const;
    RS2::LineWidth getLineWidth(bool resolve = true) const;
    
    // 可见性
    bool isVisible() const;
    void setVisible(bool v);
    
    // 选择状态
    bool isSelected() const;
    void setSelected(bool s);
    virtual void selectWindow(RS_Vector v1, RS_Vector v2, bool select);
    
    // 几何属性(纯虚函数,子类实现)
    virtual RS_Vector getCenter() const;
    virtual RS_Vector getStartpoint() const;
    virtual RS_Vector getEndpoint() const;
    virtual RS_Vector getMiddlePoint() const;
    virtual double getLength() const;
    
    // 边界盒
    virtual RS_Vector getMin() const;
    virtual RS_Vector getMax() const;
    RS_Vector getSize() const;
    
    // 变换操作
    virtual void move(const RS_Vector& offset);
    virtual void rotate(const RS_Vector& center, double angle);
    virtual void rotate(const RS_Vector& center, const RS_Vector& angleVector);
    virtual void scale(const RS_Vector& center, const RS_Vector& factor);
    virtual void mirror(const RS_Vector& axisPoint1, 
                       const RS_Vector& axisPoint2);
    virtual void stretch(const RS_Vector& firstCorner,
                        const RS_Vector& secondCorner,
                        const RS_Vector& offset);
    
    // 绘制
    virtual void draw(RS_Painter* painter,
                     RS_GraphicView* view,
                     double& patternOffset) = 0;
    
    // 距离计算
    virtual double getDistanceToPoint(
        const RS_Vector& coord,
        RS_Entity** entity = nullptr,
        RS2::ResolveLevel level = RS2::ResolveNone,
        double solidDist = RS_MAXDOUBLE) const;
    
    virtual RS_Vector getNearestPointOnEntity(
        const RS_Vector& coord,
        bool onEntity = true,
        double* dist = nullptr,
        RS_Entity** entity = nullptr) const;
    
    // 捕捉点
    virtual RS_Vector getNearestEndpoint(const RS_Vector& coord,
                                        double* dist = nullptr) const;
    virtual RS_Vector getNearestCenter(const RS_Vector& coord,
                                      double* dist = nullptr) const;
    virtual RS_Vector getNearestMiddle(const RS_Vector& coord,
                                      double* dist = nullptr,
                                      int middlePoints = 1) const;
    
protected:
    RS_EntityContainer* parent;
    RS_Layer* layer;
    RS_Pen pen;
    bool visible;
    bool selected;
    unsigned long id;
};

13.2.2 实体ID系统

每个实体都有唯一的ID:

class RS_Entity {
public:
    unsigned long getId() const { return id; }
    static unsigned long getNextId();
    
private:
    unsigned long id;
    static unsigned long nextId;
};

// ID生成
unsigned long RS_Entity::nextId = 0;

unsigned long RS_Entity::getNextId() {
    return ++nextId;
}

13.3 基本实体实现

13.3.1 RS_Point - 点

class RS_Point : public RS_AtomicEntity {
public:
    RS_Point(RS_EntityContainer* parent,
            const RS_PointData& d);
    
    RS2::EntityType rtti() const override {
        return RS2::EntityPoint;
    }
    
    RS_Entity* clone() const override;
    
    RS_Vector getPos() const { return data.pos; }
    void setPos(const RS_Vector& pos) { data.pos = pos; }
    
    RS_Vector getCenter() const override { return data.pos; }
    RS_Vector getStartpoint() const override { return data.pos; }
    RS_Vector getEndpoint() const override { return data.pos; }
    
    void move(const RS_Vector& offset) override {
        data.pos += offset;
    }
    
    void rotate(const RS_Vector& center, double angle) override {
        data.pos.rotate(center, angle);
    }
    
    void scale(const RS_Vector& center, const RS_Vector& factor) override {
        data.pos.scale(center, factor);
    }
    
    void draw(RS_Painter* painter, RS_GraphicView* view,
              double& patternOffset) override;
    
private:
    RS_PointData data;
};

// 点数据结构
struct RS_PointData {
    RS_Vector pos;
    
    RS_PointData() : pos(0.0, 0.0) {}
    RS_PointData(const RS_Vector& pos) : pos(pos) {}
};

13.3.2 RS_Line - 直线

class RS_Line : public RS_AtomicEntity {
public:
    RS_Line(RS_EntityContainer* parent,
           const RS_LineData& d);
    
    RS2::EntityType rtti() const override {
        return RS2::EntityLine;
    }
    
    RS_Entity* clone() const override;
    
    // 几何属性
    RS_Vector getStartpoint() const override { return data.startpoint; }
    RS_Vector getEndpoint() const override { return data.endpoint; }
    
    void setStartpoint(const RS_Vector& s) { 
        data.startpoint = s;
        calculateBorders();
    }
    
    void setEndpoint(const RS_Vector& e) {
        data.endpoint = e;
        calculateBorders();
    }
    
    RS_Vector getMiddlePoint() const override {
        return (data.startpoint + data.endpoint) / 2.0;
    }
    
    double getLength() const override {
        return data.startpoint.distanceTo(data.endpoint);
    }
    
    double getAngle1() const {
        return data.startpoint.angleTo(data.endpoint);
    }
    
    double getAngle2() const {
        return data.endpoint.angleTo(data.startpoint);
    }
    
    // 变换
    void move(const RS_Vector& offset) override {
        data.startpoint += offset;
        data.endpoint += offset;
        calculateBorders();
    }
    
    void rotate(const RS_Vector& center, double angle) override {
        data.startpoint.rotate(center, angle);
        data.endpoint.rotate(center, angle);
        calculateBorders();
    }
    
    void scale(const RS_Vector& center, const RS_Vector& factor) override {
        data.startpoint.scale(center, factor);
        data.endpoint.scale(center, factor);
        calculateBorders();
    }
    
    void mirror(const RS_Vector& axisPoint1,
               const RS_Vector& axisPoint2) override {
        data.startpoint.mirror(axisPoint1, axisPoint2);
        data.endpoint.mirror(axisPoint1, axisPoint2);
        calculateBorders();
    }
    
    // 计算与点的距离
    double getDistanceToPoint(const RS_Vector& coord,
                             RS_Entity** entity = nullptr,
                             RS2::ResolveLevel level = RS2::ResolveNone,
                             double solidDist = RS_MAXDOUBLE) const override;
    
    RS_Vector getNearestPointOnEntity(const RS_Vector& coord,
                                     bool onEntity = true,
                                     double* dist = nullptr,
                                     RS_Entity** entity = nullptr) const override;
    
    void draw(RS_Painter* painter, RS_GraphicView* view,
              double& patternOffset) override;
    
private:
    RS_LineData data;
    
    void calculateBorders();
};

// 直线数据结构
struct RS_LineData {
    RS_Vector startpoint;
    RS_Vector endpoint;
    
    RS_LineData() {}
    RS_LineData(const RS_Vector& startpoint, const RS_Vector& endpoint)
        : startpoint(startpoint), endpoint(endpoint) {}
};

13.3.3 RS_Circle - 圆

class RS_Circle : public RS_AtomicEntity {
public:
    RS_Circle(RS_EntityContainer* parent,
             const RS_CircleData& d);
    
    RS2::EntityType rtti() const override {
        return RS2::EntityCircle;
    }
    
    RS_Entity* clone() const override;
    
    // 几何属性
    RS_Vector getCenter() const override { return data.center; }
    double getRadius() const { return data.radius; }
    
    void setCenter(const RS_Vector& c) { data.center = c; }
    void setRadius(double r) { data.radius = r; }
    
    double getLength() const override {
        return 2.0 * M_PI * data.radius;
    }
    
    double getArea() const {
        return M_PI * data.radius * data.radius;
    }
    
    // 边界
    RS_Vector getMin() const override {
        return RS_Vector(data.center.x - data.radius,
                        data.center.y - data.radius);
    }
    
    RS_Vector getMax() const override {
        return RS_Vector(data.center.x + data.radius,
                        data.center.y + data.radius);
    }
    
    // 变换
    void move(const RS_Vector& offset) override {
        data.center += offset;
    }
    
    void rotate(const RS_Vector& center, double angle) override {
        data.center.rotate(center, angle);
    }
    
    void scale(const RS_Vector& center, const RS_Vector& factor) override {
        data.center.scale(center, factor);
        data.radius *= (factor.x + factor.y) / 2.0;
    }
    
    // 创建方法
    static RS_Circle* createFrom2Points(RS_EntityContainer* container,
                                        const RS_Vector& p1,
                                        const RS_Vector& p2);
    
    static RS_Circle* createFrom3Points(RS_EntityContainer* container,
                                        const RS_Vector& p1,
                                        const RS_Vector& p2,
                                        const RS_Vector& p3);
    
    void draw(RS_Painter* painter, RS_GraphicView* view,
              double& patternOffset) override;
    
private:
    RS_CircleData data;
};

// 圆数据结构
struct RS_CircleData {
    RS_Vector center;
    double radius;
    
    RS_CircleData() : radius(0.0) {}
    RS_CircleData(const RS_Vector& center, double radius)
        : center(center), radius(radius) {}
};

13.3.4 RS_Arc - 圆弧

class RS_Arc : public RS_AtomicEntity {
public:
    RS_Arc(RS_EntityContainer* parent,
          const RS_ArcData& d);
    
    RS2::EntityType rtti() const override {
        return RS2::EntityArc;
    }
    
    RS_Entity* clone() const override;
    
    // 几何属性
    RS_Vector getCenter() const override { return data.center; }
    double getRadius() const { return data.radius; }
    double getAngle1() const { return data.angle1; }  // 起始角度
    double getAngle2() const { return data.angle2; }  // 终止角度
    bool isReversed() const { return data.reversed; }
    
    RS_Vector getStartpoint() const override {
        return data.center + RS_Vector(data.angle1) * data.radius;
    }
    
    RS_Vector getEndpoint() const override {
        return data.center + RS_Vector(data.angle2) * data.radius;
    }
    
    RS_Vector getMiddlePoint() const override {
        double a = (data.angle1 + data.angle2) / 2.0;
        if (data.reversed) {
            a = RS_Math::correctAngle(a + M_PI);
        }
        return data.center + RS_Vector(a) * data.radius;
    }
    
    double getLength() const override {
        return fabs(getAngleLength()) * data.radius;
    }
    
    double getAngleLength() const {
        double ret = data.angle2 - data.angle1;
        if (data.reversed) {
            ret = -(2.0 * M_PI - ret);
        }
        return ret;
    }
    
    double getBulge() const;  // 弧度系数
    
    void draw(RS_Painter* painter, RS_GraphicView* view,
              double& patternOffset) override;
    
private:
    RS_ArcData data;
};

// 圆弧数据结构
struct RS_ArcData {
    RS_Vector center;
    double radius;
    double angle1;     // 起始角度(弧度)
    double angle2;     // 终止角度(弧度)
    bool reversed;     // 是否反向
    
    RS_ArcData() : radius(0.0), angle1(0.0), angle2(0.0), reversed(false) {}
    RS_ArcData(const RS_Vector& center, double radius,
               double angle1, double angle2, bool reversed = false)
        : center(center), radius(radius),
          angle1(angle1), angle2(angle2), reversed(reversed) {}
};

13.4 复合实体

13.4.1 RS_Polyline - 折线

class RS_Polyline : public RS_EntityContainer {
public:
    RS_Polyline(RS_EntityContainer* parent,
               const RS_PolylineData& d);
    
    RS2::EntityType rtti() const override {
        return RS2::EntityPolyline;
    }
    
    RS_Entity* clone() const override;
    
    // 闭合状态
    bool isClosed() const { return data.closed; }
    void setClosed(bool cl);
    
    // 添加顶点
    RS_Entity* addVertex(const RS_Vector& v,
                        double bulge = 0.0,
                        bool prepend = false);
    
    // 获取顶点
    RS_Vector getStartpoint() const override;
    RS_Vector getEndpoint() const override;
    
    // 遍历顶点
    int countVertices() const;
    RS_Vector getVertex(int index) const;
    
    // 长度
    double getLength() const override;
    
    // 面积(闭合折线)
    double getArea() const;
    
    void draw(RS_Painter* painter, RS_GraphicView* view,
              double& patternOffset) override;
    
private:
    RS_PolylineData data;
};

// 折线数据结构
struct RS_PolylineData {
    RS_Vector startpoint;
    RS_Vector endpoint;
    bool closed;
    
    RS_PolylineData() : closed(false) {}
    RS_PolylineData(const RS_Vector& startpoint,
                   const RS_Vector& endpoint,
                   bool closed)
        : startpoint(startpoint), endpoint(endpoint), closed(closed) {}
};

13.4.2 RS_Hatch - 填充

class RS_Hatch : public RS_EntityContainer {
public:
    RS_Hatch(RS_EntityContainer* parent,
            const RS_HatchData& d);
    
    RS2::EntityType rtti() const override {
        return RS2::EntityHatch;
    }
    
    // 填充图案
    bool isSolid() const { return data.solid; }
    QString getPattern() const { return data.pattern; }
    double getScale() const { return data.scale; }
    double getAngle() const { return data.angle; }
    
    // 更新填充
    void update();
    
    void draw(RS_Painter* painter, RS_GraphicView* view,
              double& patternOffset) override;
    
private:
    RS_HatchData data;
    
    void calculateBorders();
};

// 填充数据结构
struct RS_HatchData {
    bool solid;        // 是否实心填充
    double scale;      // 图案比例
    double angle;      // 图案角度
    QString pattern;   // 图案名称
    
    RS_HatchData() : solid(false), scale(1.0), angle(0.0) {}
    RS_HatchData(bool solid, double scale, double angle, const QString& pattern)
        : solid(solid), scale(scale), angle(angle), pattern(pattern) {}
};

13.5 实体容器

13.5.1 RS_EntityContainer

class RS_EntityContainer : public RS_Entity {
public:
    RS_EntityContainer(RS_EntityContainer* parent = nullptr,
                      bool owner = true);
    virtual ~RS_EntityContainer();
    
    RS2::EntityType rtti() const override {
        return RS2::EntityContainer;
    }
    
    // 实体管理
    void addEntity(RS_Entity* entity);
    void insertEntity(int index, RS_Entity* entity);
    void removeEntity(RS_Entity* entity);
    void clear();
    
    // 查询
    unsigned count() const { return entities.size(); }
    RS_Entity* entityAt(unsigned index) const;
    RS_Entity* first() const;
    RS_Entity* last() const;
    RS_Entity* next() const;
    RS_Entity* prev() const;
    
    // 查找
    RS_Entity* findEntity(unsigned long id) const;
    RS_Entity* findEntity(const RS_Vector& coord) const;
    
    // 迭代器
    typedef QList<RS_Entity*>::iterator iterator;
    typedef QList<RS_Entity*>::const_iterator const_iterator;
    
    iterator begin() { return entities.begin(); }
    iterator end() { return entities.end(); }
    const_iterator begin() const { return entities.begin(); }
    const_iterator end() const { return entities.end(); }
    
    // 边界计算
    void calculateBorders();
    RS_Vector getMin() const override;
    RS_Vector getMax() const override;
    
    // 变换
    void move(const RS_Vector& offset) override;
    void rotate(const RS_Vector& center, double angle) override;
    void scale(const RS_Vector& center, const RS_Vector& factor) override;
    void mirror(const RS_Vector& axisPoint1,
               const RS_Vector& axisPoint2) override;
    
    // 选择
    void selectAll(bool select = true);
    void selectWindow(RS_Vector v1, RS_Vector v2, bool select);
    QList<RS_Entity*> getSelectedEntities() const;
    
    void draw(RS_Painter* painter, RS_GraphicView* view,
              double& patternOffset) override;
    
protected:
    QList<RS_Entity*> entities;
    bool autoDelete;
    RS_Vector minV, maxV;
    
    mutable int entityIteratorIndex;
};

13.5.2 RS_Graphic - 图形文档

class RS_Graphic : public RS_EntityContainer {
public:
    RS_Graphic();
    virtual ~RS_Graphic();
    
    RS2::EntityType rtti() const override {
        return RS2::EntityGraphic;
    }
    
    // 图层管理
    RS_LayerList* getLayerList() { return &layerList; }
    void addLayer(RS_Layer* layer);
    RS_Layer* findLayer(const QString& name);
    RS_Layer* getActiveLayer() { return layerList.getActive(); }
    void activateLayer(RS_Layer* layer);
    
    // 块管理
    RS_BlockList* getBlockList() { return &blockList; }
    void addBlock(RS_Block* block);
    RS_Block* findBlock(const QString& name);
    
    // 变量
    void addVariable(const QString& key, const QString& value);
    QString getVariableString(const QString& key) const;
    int getVariableInt(const QString& key) const;
    double getVariableDouble(const QString& key) const;
    
    // 文件操作
    bool save(const QString& filename = QString());
    bool open(const QString& filename);
    QString getFilename() const { return filename; }
    
    // 修改标志
    bool isModified() const { return modified; }
    void setModified(bool m);
    
    // 单位
    RS2::Unit getUnit() const;
    void setUnit(RS2::Unit u);
    
    // 纸张
    RS_Vector getPaperSize() const;
    void setPaperSize(const RS_Vector& s);
    
private:
    RS_LayerList layerList;
    RS_BlockList blockList;
    QHash<QString, RS_Variable> variables;
    QString filename;
    bool modified;
};

13.6 创建实体

13.6.1 使用RS_Creation

class RS_Creation {
public:
    RS_Creation(RS_EntityContainer* container,
               RS_GraphicView* graphicView = nullptr);
    
    // 创建直线
    RS_Line* createLine(const RS_Vector& p1, const RS_Vector& p2);
    RS_Line* createParallelLine(RS_Entity* ref, double distance);
    RS_Line* createBisector(const RS_Vector& p1,
                           const RS_Vector& p2,
                           const RS_Vector& p3);
    
    // 创建圆
    RS_Circle* createCircle(const RS_Vector& center, double radius);
    RS_Circle* createCircle2Points(const RS_Vector& p1, const RS_Vector& p2);
    RS_Circle* createCircle3Points(const RS_Vector& p1,
                                   const RS_Vector& p2,
                                   const RS_Vector& p3);
    
    // 创建圆弧
    RS_Arc* createArc(const RS_Vector& center,
                     double radius,
                     double angle1,
                     double angle2,
                     bool reversed = false);
    RS_Arc* createArc3Points(const RS_Vector& p1,
                            const RS_Vector& p2,
                            const RS_Vector& p3);
    
    // 创建椭圆
    RS_Ellipse* createEllipse(const RS_Vector& center,
                             const RS_Vector& majorP,
                             double ratio);
    
private:
    RS_EntityContainer* container;
    RS_GraphicView* graphicView;
    RS_Document* document;
};

// 使用示例
void createEntities(RS_Graphic* graphic) {
    RS_Creation creation(graphic);
    
    // 创建直线
    RS_Line* line = creation.createLine(
        RS_Vector(0, 0),
        RS_Vector(100, 100)
    );
    
    // 创建圆
    RS_Circle* circle = creation.createCircle(
        RS_Vector(50, 50),
        25.0
    );
    
    // 创建三点圆弧
    RS_Arc* arc = creation.createArc3Points(
        RS_Vector(0, 0),
        RS_Vector(50, 25),
        RS_Vector(100, 0)
    );
}

13.6.2 直接创建

// 直接创建实体
void createEntityDirectly(RS_EntityContainer* container) {
    // 创建直线
    RS_Line* line = new RS_Line(container,
        RS_LineData(RS_Vector(0, 0), RS_Vector(100, 100)));
    container->addEntity(line);
    
    // 创建圆
    RS_Circle* circle = new RS_Circle(container,
        RS_CircleData(RS_Vector(50, 50), 25.0));
    container->addEntity(circle);
}

13.7 修改实体

13.7.1 使用RS_Modification

class RS_Modification {
public:
    RS_Modification(RS_EntityContainer& container,
                   RS_GraphicView* graphicView = nullptr);
    
    // 移动
    bool move(RS_MoveData& data);
    
    // 复制
    bool copy(RS_CopyData& data);
    
    // 旋转
    bool rotate(RS_RotateData& data);
    
    // 缩放
    bool scale(RS_ScaleData& data);
    
    // 镜像
    bool mirror(RS_MirrorData& data);
    
    // 修剪
    bool trim(const RS_Vector& trimPoint,
             RS_Entity* limitEntity,
             bool trimBoth = false);
    
    // 延伸
    bool extend(const RS_Vector& trimPoint,
               RS_Entity* limitEntity);
    
    // 偏移
    bool offset(RS_Entity* entity, double distance, bool copy);
    
    // 圆角
    bool fillet(RS_Entity* entity1, RS_Entity* entity2, double radius);
    
    // 倒角
    bool chamfer(RS_Entity* entity1, RS_Entity* entity2,
                double distance1, double distance2);
    
    // 炸开
    bool explode(RS_Entity* entity);
    
private:
    RS_EntityContainer* container;
    RS_GraphicView* graphicView;
    RS_Document* document;
};

13.7.2 数据结构

// 移动数据
struct RS_MoveData {
    int number;           // 复制数量(0=移动)
    bool useCurrentAttr;  // 使用当前属性
    bool useCurrentLayer; // 使用当前图层
    RS_Vector offset;     // 偏移量
};

// 旋转数据
struct RS_RotateData {
    int number;
    bool useCurrentAttr;
    bool useCurrentLayer;
    RS_Vector center;     // 旋转中心
    double angle;         // 旋转角度
};

// 缩放数据
struct RS_ScaleData {
    int number;
    bool useCurrentAttr;
    bool useCurrentLayer;
    RS_Vector referencePoint;  // 缩放中心
    RS_Vector factor;          // 缩放因子
};

// 镜像数据
struct RS_MirrorData {
    bool copy;            // 是否保留原对象
    bool useCurrentAttr;
    bool useCurrentLayer;
    RS_Vector axisPoint1; // 镜像轴点1
    RS_Vector axisPoint2; // 镜像轴点2
};

13.8 本章小结

本章详细介绍了LibreCAD的实体系统:

  1. 实体概述:概念、分类、层次结构
  2. RS_Entity基类:属性、方法、ID系统
  3. 基本实体:点、线、圆、弧、椭圆
  4. 复合实体:折线、填充
  5. 实体容器:RS_EntityContainer、RS_Graphic
  6. 创建实体:RS_Creation类、直接创建
  7. 修改实体:RS_Modification类

理解实体系统是进行LibreCAD二次开发的核心。


上一章:源码编译与开发环境搭建 | 下一章:Action系统与命令开发


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