当前位置: 首页 > news >正文

【学写LibreCAD】1 创建核心模块库

从核心模块开始重写 LibreCAD 的 Rust 实现,需要从基础数据结构、数学工具和关键接口入手。以下是具体的代码起步步骤:

  1. 创建 Rust 核心模块项目
    (1) 初始化项目
cargo new cad_core --lib
cd cad_core

(2) 添加 cxx-qt 依赖(用于与 C++/Qt 交互)
在 Cargo.toml 中添加:

[lib]
crate-type = ["staticlib", "cdylib"]  # 生成静态库和动态库

[dependencies]
cxx = "1.0"
cxx-qt = "0.7"
cxx-qt-lib = "0.7"
  1. 定义核心数据结构
    (1) 几何对象(geometry.rs)
// src/geometry.rs
#[derive(Debug, Clone, Copy)]
pub struct Point2D {
    pub x: f64,
    pub y: f64,
}

#[derive(Debug, Clone)]
pub enum Shape {
    Line(Point2D, Point2D),
    Circle(Point2D, f64),       // 圆心 + 半径
    Arc(Point2D, f64, f64, f64), // 圆心、半径、起始角、终止角(弧度)
}

(2) 数学工具(math.rs)

// src/math.rs
use crate::geometry::Point2D;

// 计算两点距离
pub fn distance(p1: &Point2D, p2: &Point2D) -> f64 {
    ((p1.x - p2.x).powi(2) + (p1.y - p2.y).powi(2)).sqrt()
}

// 判断点是否在线上(简化版)
pub fn is_point_on_line(point: &Point2D, line_start: &Point2D, line_end: &Point2D) -> bool {
    // 实现具体的几何判断逻辑
    // 示例:简单阈值判断
    distance(point, line_start) + distance(point, line_end) - distance(line_start, line_end) < 1e-6
}
  1. 文档管理模块(document.rs)
// src/document.rs
use std::collections::HashMap;
use crate::geometry::Shape;

pub struct Layer {
    pub name: String,
    pub visible: bool,
}

pub struct Document {
    pub layers: HashMap<String, Layer>,
    pub shapes: Vec<Shape>,
}

impl Document {
    pub fn new() -> Self {
        Document {
            layers: HashMap::new(),
            shapes: Vec::new(),
        }
    }

    pub fn add_shape(&mut self, shape: Shape) {
        self.shapes.push(shape);
    }

    pub fn create_layer(&mut self, name: &str) {
        self.layers.insert(
            name.to_string(),
            Layer {
                name: name.to_string(),
                visible: true,
            },
        );
    }
}
  1. 通过 CXX-QT 暴露接口给 C++
    (1) 创建桥接文件(src/cxx_qt.rs)
// src/cxx_qt.rs
#[cxx_qt::bridge]
mod ffi {
    use super::*;
    use crate::geometry::{Point2D, Shape};
    use crate::document::Document;

    // 暴露 Point2D 到 C++
    #[derive(Debug, Clone, Copy)]
    #[namespace = "rust::core"]
    struct Point2D {
        x: f64,
        y: f64,
    }

    // 暴露 Document 的接口
    #[namespace = "rust::core"]
    extern "Rust" {
        type Document;

        fn new_document() -> UniquePtr<Document>;
        fn add_shape(self: Pin<&mut Document>, shape: Shape);
        fn create_layer(self: Pin<&mut Document>, name: &str);
    }
}

(2) 实现 CXX-QT 绑定(src/lib.rs)

// src/lib.rs
mod geometry;
mod math;
mod document;

use cxx_qt::CxxQtType;
use std::pin::Pin;

// 实现 CXX-QT 的 Document 类型
impl document::Document {
    fn new_document() -> cxx::UniquePtr<Self> {
        cxx::UniquePtr::new(document::Document::new())
    }

    fn add_shape(self: Pin<&mut Self>, shape: geometry::Shape) {
        self.get_mut().add_shape(shape);
    }

    fn create_layer(self: Pin<&mut Self>, name: &str) {
        self.get_mut().create_layer(name);
    }
}
  1. 单元测试
// tests/core_tests.rs
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_distance() {
        let p1 = geometry::Point2D { x: 0.0, y: 0.0 };
        let p2 = geometry::Point2D { x: 3.0, y: 4.0 };
        assert_eq!(math::distance(&p1, &p2), 5.0);
    }

    #[test]
    fn test_add_shape() {
        let mut doc = document::Document::new();
        let line = geometry::Shape::Line(
            geometry::Point2D { x: 0.0, y: 0.0 },
            geometry::Point2D { x: 1.0, y: 1.0 },
        );
        doc.add_shape(line);
        assert_eq!(doc.shapes.len(), 1);
    }
}
  1. 集成到现有 C++ 项目
    (1) C++ 调用示例
// main.cpp
#include "rust/core.h"

int main() {
    auto doc = rust::core::new_document();
    doc->create_layer("Default");

    rust::core::Point2D p1{0.0, 0.0};
    rust::core::Point2D p2{10.0, 10.0};
    doc->add_shape(rust::core::Shape::Line(p1, p2));

    return 0;
}

(2) 构建配置(CMakeLists.txt)

cmake_minimum_required(VERSION 3.15)
project(LibreCAD_Core)

# 添加 Rust 库
add_subdirectory(libre_cad_core)

add_executable(libre_cad_core_test main.cpp)
target_link_libraries(libre_cad_core_test PRIVATE libre_cad_core)
  1. 关键注意事项
  2. 内存管理:
  • 使用 UniquePtr 确保 Rust 对象在 C++ 中安全传递。
  • 避免跨 FFI 边界传递复杂生命周期对象。
  1. 性能优化:
  • 对高频调用的数学函数(如 distance)添加 #[inline]。
  • 使用 Arc<Mutex> 实现多线程安全(如果涉及并发)。
  1. 逐步替换策略:
  • 先替换无 UI 依赖的模块(如几何计算)。
  • 通过 CXX-QT 逐步将 Rust 实现的模块接入 Qt 界面。

下一步行动

  1. 运行测试:
cargo test
  1. 构建并链接到 C++:
mkdir build
cd build
cmake ..
make
  1. 扩展功能:
  • 实现更多几何类型(如圆弧、多段线)。
  • 添加文件 I/O 支持(如 DXF 解析)。
    通过这种方式,可以逐步将 LibreCAD 的核心模块迁移到 Rust,同时保持与现有 C++/Qt 代码的互操作性。

相关文章:

  • 数据解析与处理
  • 我的AI工具箱Tauri版-InteriorDecorationDesignDrawing平面设计图生成房屋所有室内的效果图
  • SGMII(Serial Gigabit Media Independent Interface)详解
  • C++ 二叉搜索树与双向链表_牛客题霸_牛客网
  • Docker Desktop 社区版安装配置全流程指南(Windows平台)
  • Docker快速使用指南
  • Spring Boot @Component注解介绍
  • 清华大学DeepSeek赋能职场教程下载,清华大学DeepSeek文档下载(完成版下载)
  • 在VSCode中安装jupyter跑.ipynb格式文件
  • 【备赛】按键消抖+长短按键区分
  • AI工具箱最新使用教程
  • 【有啥问啥】All-to-All 通信:原理、实现与应用
  • YOLOv8架构中的SAConv空洞卷积机制:性能优化与未来发展方向
  • C++ 线程库使用详解
  • 局部适应的分子标记筛选
  • 京准电钟:NTP精密时钟服务器在自动化系统中的作用
  • 2025年2月最新一区SCI-海市蜃楼搜索优化算法Mirage search optimization-附Matlab免费代码
  • 5、进程间有哪些通信方式【高频】
  • 蓝桥杯之日期问题2
  • 前端如何进行性能优化
  • 韩国执政党总统候选人更换方案被否决,金文洙候选人资格即刻恢复
  • 贵州省总工会党组成员、副主席梁伟接受审查调查
  • 被取消总统候选人资格,金文洙:将采取政治法律措施讨回公道
  • 会计江湖|年报披露关注什么:独董给出的“信号”
  • 央行设立服务消费与养老再贷款,额度5000亿元
  • 江西省直机关工委副书记熊亮华履新宜春市委常委、宣传部部长