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

基于 Rust 的 CAD 工具demo示例

以下是一个基于 Rust 的 CAD 工具框架基础实现,聚焦几何建模、坐标系管理和 DXF 文件交互(CAD 最常用的交换格式)。代码设计强调模块化、可扩展性和 Rust 语言特性(如所有权、错误处理、泛型)。


AUTOCAD

一、框架整体架构

cad-framework/
├── src/
│   ├── geometry/          # 几何核心(点、线、圆、多边形等)
│   ├── coordinate_system/ # 坐标系管理(WCS/UCS 转换)
│   ├── drawing/           # 绘图上下文与渲染接口
│   ├── io/                # 文件 IO(DXF 读写)
│   └── main.rs            # 示例用法
└── Cargo.toml

在这里插入图片描述

二、核心模块实现

在这里插入图片描述

1. 几何模型(Geometry)

定义基础几何对象(点、线、圆)及其操作(平移、旋转、相交检测等)。

// src/geometry/mod.rs
use std::ops::{Add, Sub, Mul, Div};
use std::fmt;/// 二维点(浮点精度)
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Point2D {pub x: f64,pub y: f64,
}impl Point2D {pub fn new(x: f64, y: f64) -> Self {Self { x, y }}/// 平移点pub fn translate(&self, dx: f64, dy: f64) -> Self {Self::new(self.x + dx, self.y + dy)}/// 绕原点旋转(弧度)pub fn rotate(&self, angle: f64) -> Self {let cos = angle.cos();let sin = angle.sin();Self::new(self.x * cos - self.y * sin,self.x * sin + self.y * cos,)}
}impl Add for Point2D {type Output = Self;fn add(self, other: Self) -> Self {Self::new(self.x + other.x, self.y + other.y)}
}impl Sub for Point2D {type Output = Self;fn sub(self, other: Self) -> Self {Self::new(self.x - other.x, self.y - other.y)}
}/// 二维线段(两点确定)
#[derive(Debug, Clone, PartialEq)]
pub struct Line2D {pub start: Point2D,pub end: Point2D,
}impl Line2D {pub fn new(start: Point2D, end: Point2D) -> Self {Self { start, end }}/// 计算线段长度pub fn length(&self) -> f64 {(self.end - self.start).x.hypot((self.end - self.start).y)}/// 判断线段是否与另一线段相交(快速排斥 + 跨立实验)pub fn intersects(&self, other: &Line2D) -> bool {let a = self.start;let b = self.end;let c = other.start;let d = other.end;// 快速排斥实验let max_x = [a.x, b.x, c.x, d.x].iter().fold(f64::MIN, |a, &b| a.max(b));let min_x = [a.x, b.x, c.x, d.x].iter().fold(f64::MAX, |a, &b| a.min(b));let max_y = [a.y, b.y, c.y, d.y].iter().fold(f64::MIN, |a, &b| a.max(b));let min_y = [a.y, b.y, c.y, d.y].iter().fold(f64::MAX, |a, &b| a.min(b));if (self.start.x < min_x && self.end.x < min_x) || (self.start.x > max_x && self.end.x > max_x) {return false;}if (self.start.y < min_y && self.end.y < min_y) || (self.start.y > max_y && self.end.y > max_y) {return false;}// 跨立实验let cross = |p: Point2D, a: Point2D, b: Point2D| -> f64 {(a.x - p.x) * (b.y - p.y) - (a.y - p.y) * (b.x - p.x)};let c1 = cross(a, b, c);let c2 = cross(a, b, d);let c3 = cross(c, d, a);let c4 = cross(c, d, b);(c1 * c2 <= 1e-8) && (c3 * c4 <= 1e-8) // 允许微小误差}
}/// 二维圆(圆心 + 半径)
#[derive(Debug, Clone, PartialEq)]
pub struct Circle2D {pub center: Point2D,pub radius: f64,
}impl Circle2D {pub fn new(center: Point2D, radius: f64) -> Self {assert!(radius > 0.0, "Radius must be positive");Self { center, radius }}/// 判断圆与线段是否相交pub fn intersects_line(&self, line: &Line2D) -> bool {let d = line.start.distance_to(&line.end); // 线段长度let a = (line.end.x - line.start.x).powi(2) + (line.end.y - line.start.y).powi(2);let b = 2.0 * ((line.start.x - self.center.x) * (line.end.x - line.start.x) +(line.start.y - self.center.y) * (line.end.y - line.start.y));let c = (line.start.x - self.center.x).powi(2) +(line.start.y - self.center.y).powi(2) - self.radius.powi(2);let delta = b.powi(2) - 4.0 * a * c;if delta < 0.0 {return false; // 无交点}let t1 = (-b - delta.sqrt()) / (2.0 * a);let t2 = (-b + delta.sqrt()) / (2.0 * a);// 交点在线段范围内(t ∈ [0,1])(t1 >= 0.0 && t1 <= 1.0) || (t2 >= 0.0 && t2 <= 1.0)}
}// 为 Point2D 实现距离计算
trait Distance {fn distance_to(&self, other: &Self) -> f64;
}impl Distance for Point2D {fn distance_to(&self, other: &Self) -> f64 {(self.x - other.x).hypot(self.y - other.y)}
}

2. 坐标系管理(Coordinate System)

支持世界坐标系(WCS)和用户坐标系(UCS)的转换。

// src/coordinate_system/mod.rs
use super::geometry::Point2D;/// 坐标系类型(世界坐标系 WCS 或用户坐标系 UCS)
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CoordinateSystem {WCS, // 世界坐标系(全局固定)UCS, // 用户坐标系(可自定义原点、旋转)
}/// 坐标系变换参数(原点偏移 + 旋转角度)
#[derive(Debug, Clone)]
pub struct Transform {pub origin: Point2D, // UCS 原点相对于 WCS 的偏移pub rotation: f64,   // UCS 相对于 WCS 的旋转角度(弧度)
}impl Transform {pub fn new(origin: Point2D, rotation: f64) -> Self {Self { origin, rotation }}/// 将 UCS 坐标转换为 WCS 坐标pub fn ucs_to_wcs(&self, point: Point2D) -> Point2D {// 1. 平移(抵消 UCS 原点偏移)let translated = point.translate(-self.origin.x, -self.origin.y);// 2. 旋转(反向旋转抵消 UCS 旋转)translated.rotate(-self.rotation)}/// 将 WCS 坐标转换为 UCS 坐标pub fn wcs_to_ucs(&self, point: Point2D) -> Point2D {// 1. 旋转(应用 UCS 旋转)let rotated = point.rotate(self.rotation);// 2. 平移(添加 UCS 原点偏移)rotated.translate(self.origin.x, self.origin.y)}
}

3. 绘图上下文(Drawing Context)

抽象绘图操作接口,支持不同渲染目标(如屏幕、SVG、DXF)。

// src/drawing/mod.rs
use super::geometry::{Line2D, Circle2D, Point2D};
use std::error::Error;/// 绘图操作 trait(抽象渲染接口)
pub trait Drawer {/// 设置当前颜色(RGB 0-255)fn set_color(&mut self, r: u8, g: u8, b: u8);/// 设置线宽(单位:毫米)fn set_line_width(&mut self, width: f64);/// 绘制线段fn draw_line(&mut self, line: &Line2D) -> Result<(), Box<dyn Error>>;/// 绘制圆fn draw_circle(&mut self, circle: &Circle2D) -> Result<(), Box<dyn Error>>;/// 绘制点(可选,用于调试)fn draw_point(&mut self, point: &Point2D) -> Result<(), Box<dyn Error>>;
}/// 基于文本的简单绘图器(用于调试)
pub struct TextDrawer {current_color: (u8, u8, u8),current_line_width: f64,
}impl TextDrawer {pub fn new() -> Self {Self {current_color: (0, 0, 0), // 默认黑色current_line_width: 0.5,}}
}impl Drawer for TextDrawer {fn set_color(&mut self, r: u8, g: u8, b: u8) {self.current_color = (r, g, b);}fn set_line_width(&mut self, width: f64) {self.current_line_width = width;}fn draw_line(&mut self, line: &Line2D) -> Result<(), Box<dyn Error>> {println!("Draw Line (Color: RGB{}, Width: {}): ({:.2}, {:.2}) -> ({:.2}, {:.2})",self.current_color.0,self.current_color.1,self.current_color.2,self.current_line_width,line.start.x,line.start.y,line.end.x,line.end.y);Ok(())}fn draw_circle(&mut self, circle: &Circle2D) -> Result<(), Box<dyn Error>> {println!("Draw Circle (Color: RGB{}, Width: {}): Center ({:.2}, {:.2}), Radius: {:.2}",self.current_color.0,self.current_color.1,self.current_color.2,self.current_line_width,circle.center.x,circle.center.y,circle.radius);Ok(())}fn draw_point(&mut self, point: &Point2D) -> Result<(), Box<dyn Error>> {println!("Draw Point (Color: RGB{}): ({:.2}, {:.2})",self.current_color.0, self.current_color.1, self.current_color.2, point.x, point.y);Ok(())}
}

4. DXF 文件 IO(关键交换格式)

实现 DXF 文件的读取和写入(支持线段、圆等基础实体)。

// src/io/dxf/mod.rs
use super::geometry::{Line2D, Circle2D, Point2D};
use std::fs::File;
use std::io::{BufWriter, Write};
use std::error::Error;/// DXF 实体类型
#[derive(Debug, Clone, PartialEq)]
pub enum DxfEntity {Line(Line2D),Circle(Circle2D),
}/// DXF 图层(可选,用于组织实体)
#[derive(Debug, Clone)]
pub struct DxfLayer {pub name: String,pub color: (u8, u8, u8), // RGB 颜色
}/// DXF 文件写入器
pub struct DxfWriter {writer: BufWriter<File>,layers: Vec<DxfLayer>,current_layer: usize, // 当前使用的图层索引
}impl DxfWriter {pub fn new(path: &str) -> Result<Self, Box<dyn Error>> {let file = File::create(path)?;Ok(Self {writer: BufWriter::new(file),layers: vec![DxfLayer {name: "0".to_string(), // DXF 默认图层color: (0, 0, 0),      // 默认黑色}],current_layer: 0,})}/// 添加新图层pub fn add_layer(&mut self, name: &str, color: (u8, u8, u8)) {self.layers.push(DxfLayer { name: name.to_string(), color });}/// 切换当前图层pub fn switch_layer(&mut self, index: usize) -> Result<(), Box<dyn Error>> {if index < self.layers.len() {self.current_layer = index;Ok(())} else {Err(format!("Layer index {} not found", index).into())}}/// 写入 DXF 文件头fn write_header(&mut self) -> Result<(), Box<dyn Error>> {writeln!(self.writer, "0\nSECTION\n2\nENTITIES")?;Ok(())}/// 写入 DXF 实体(线段/圆)fn write_entity(&mut self, entity: &DxfEntity) -> Result<(), Box<dyn Error>> {let layer = &self.layers[self.current_layer];match entity {DxfEntity::Line(line) => {writeln!(self.writer,"0\nLINE\n8\n{}\n62\n{:02x}{:02x}{:02x}\n10\n{:.3}\n20\n{:.3}\n11\n{:.3}\n21\n{:.3}",layer.name,layer.color.0, layer.color.1, layer.color.2,line.start.x, line.start.y,line.end.x, line.end.y)?;}DxfEntity::Circle(circle) => {writeln!(self.writer,"0\nCIRCLE\n8\n{}\n62\n{:02x}{:02x}{:02x}\n10\n{:.3}\n40\n{:.3}",layer.name,layer.color.0, layer.color.1, layer.color.2,circle.center.x, circle.radius)?;}}Ok(())}/// 完成写入并关闭文件fn write_footer(&mut self) -> Result<(), Box<dyn Error>> {writeln!(self.writer, "0\nENDSEC\n0\nEOF")?;self.writer.flush()?;Ok(())}/// 保存所有实体到 DXF 文件pub fn save(&mut self, entities: &[DxfEntity]) -> Result<(), Box<dyn Error>> {self.write_header()?;for entity in entities {self.write_entity(entity)?;}self.write_footer()}
}/// DXF 文件读取器(简化版,仅解析线段和圆)
pub struct DxfReader;impl DxfReader {/// 从 DXF 文件读取实体(仅支持 LINE 和 CIRCLE)pub fn read(path: &str) -> Result<Vec<DxfEntity>, Box<dyn Error>> {let content = std::fs::read_to_string(path)?;let mut entities = Vec::new();let mut current_entity: Option<DxfEntity> = None;let mut current_code: Option<u32> = None;let mut current_value: Option<String> = None;for line in content.lines() {let parts: Vec<&str> = line.trim().split_whitespace().collect();if parts.is_empty() {continue;}match parts[0] {"0" => {// 新实体开始if let Some(ent) = current_entity.take() {entities.push(ent);}current_entity = match parts[1] {"LINE" => Some(DxfEntity::Line(Line2D {start: Point2D::new(0.0, 0.0),end: Point2D::new(0.0, 0.0),})),"CIRCLE" => Some(DxfEntity::Circle(Circle2D {center: Point2D::new(0.0, 0.0),radius: 0.0,})),_ => None, // 忽略不支持的实体};current_code = None;current_value = None;}"8" => {// 图层名称if let Some(ent) = ¤t_entity {if let DxfEntity::Line(_) | DxfEntity::Circle(_) = ent {current_code = Some(parts[1].parse()?);}}}"10" | "20" => {// 线段的起点(10=x, 20=y)if let Some(DxfEntity::Line(line)) = ¤t_entity {let coord = parts[1].parse::<f64>()?;if parts[0] == "10" {line.start.x = coord;} else {line.start.y = coord;}}}"11" | "21" => {// 线段的终点(11=x, 21=y)if let Some(DxfEntity::Line(line)) = ¤t_entity {let coord = parts[1].parse::<f64>()?;if parts[0] == "11" {line.end.x = coord;} else {line.end.y = coord;}}}"100" => {// 圆的半径(假设 40 码对应半径)if let Some(DxfEntity::Circle(circle)) = ¤t_entity {if parts[0] == "40" {circle.radius = parts[1].parse()?;}}}_ => {}}}// 处理最后一个实体if let Some(ent) = current_entity.take() {entities.push(ent);}Ok(entities)}
}

在这里插入图片描述

三、示例用法

// src/main.rs
use cad_framework::{geometry::{Line2D, Circle2D, Point2D},coordinate_system::Transform,drawing::TextDrawer,io::dxf::{DxfWriter, DxfEntity},
};fn main() -> Result<(), Box<dyn std::error::Error>> {// 1. 创建几何对象let line = Line2D::new(Point2D::new(0.0, 0.0), Point2D::new(100.0, 100.0));let circle = Circle2D::new(Point2D::new(200.0, 200.0), 50.0);// 2. 坐标系变换(示例:将 UCS 原点偏移到 (50,50),旋转 30 度)let ucs_transform = Transform::new(Point2D::new(50.0, 50.0), 30.0_f64.to_radians());let wcs_line = line.translate(ucs_transform.origin.x, ucs_transform.origin.y).rotate(ucs_transform.rotation);let wcs_circle = Circle2D::new(Point2D::new(200.0 - 50.0, 200.0 - 50.0).rotate(ucs_transform.rotation),50.0,);// 3. 使用文本绘图器可视化let mut text_drawer = TextDrawer::new();text_drawer.set_color(255, 0, 0); // 红色text_drawer.set_line_width(1.0);text_drawer.draw_line(&wcs_line)?;text_drawer.draw_circle(&wcs_circle)?;// 4. 导出为 DXF 文件let dxf_entities = vec![DxfEntity::Line(wcs_line),DxfEntity::Circle(wcs_circle),];let mut dxf_writer = DxfWriter::new("output.dxf")?;dxf_writer.add_layer("MyLayer", (0, 255, 0)); // 添加绿色图层dxf_writer.switch_layer(1)?; // 切换到新图层dxf_writer.save(&dxf_entities)?;println!("DXF 文件已生成:output.dxf");Ok(())
}

四、扩展方向

  1. 三维支持:扩展 Point3DLine3DPlane 等几何类型,添加三维变换(平移、旋转、缩放矩阵)。
  2. 约束求解:实现几何约束(如平行、垂直、共点)的求解器(参考 drakegeometric-constraints 库)。
  3. 更复杂的 DXF 支持:解析图层、线型、块(Block)、尺寸标注(Dimension)等高级特性。
  4. GUI 集成:使用 eguirelm4 开发图形界面,支持可视化绘图和交互操作。
  5. 性能优化:使用空间分区数据结构(如四叉树、R-tree)加速几何查询(如碰撞检测)。

五、依赖配置(Cargo.toml)

[package]
name = "cad-framework"
version = "0.1.0"
edition = "2021"[dependencies]
thiserror = "1.0"   # 错误处理
num-traits = "0.2"  # 数值特性(可选,用于泛型计算)

该框架实现了 CAD 的核心基础功能(几何建模、坐标系转换、文件交互),并通过模块化设计支持后续扩展。Rust 的内存安全和零成本抽象特性使其适合高性能 CAD 工具开发。


文章转载自:

http://h5g1uWVs.xpfwr.cn
http://BDRxNYyJ.xpfwr.cn
http://ABWmEeil.xpfwr.cn
http://XqcTjUpI.xpfwr.cn
http://7l5fIatg.xpfwr.cn
http://WcezWRgp.xpfwr.cn
http://s3BVzyo7.xpfwr.cn
http://Lcrp9W4q.xpfwr.cn
http://LqkWwzfh.xpfwr.cn
http://TMgPxzTW.xpfwr.cn
http://IxsovhfV.xpfwr.cn
http://4IlsgiNW.xpfwr.cn
http://e9Ro4qOv.xpfwr.cn
http://HxphGTXk.xpfwr.cn
http://Sw7dMjiN.xpfwr.cn
http://U2TvQT7L.xpfwr.cn
http://ZRVK2aSi.xpfwr.cn
http://6vNRuAu8.xpfwr.cn
http://Oa57NOm4.xpfwr.cn
http://WCmndT1Z.xpfwr.cn
http://nbC1GXys.xpfwr.cn
http://3RHcXKt4.xpfwr.cn
http://sRLOoCc9.xpfwr.cn
http://ENMSpk1c.xpfwr.cn
http://84RMuEe1.xpfwr.cn
http://kxvpTCHH.xpfwr.cn
http://E1Mrlt19.xpfwr.cn
http://zl9JNJS5.xpfwr.cn
http://G9ZzUlF1.xpfwr.cn
http://6VrH32C4.xpfwr.cn
http://www.dtcms.com/a/388551.html

相关文章:

  • 多模态大模型研究每日简报【2025-09-17】
  • 2D平台动作游戏《Haneda Girl》推出免费体验版
  • 《艾尔登法环:黑夜君临》DLC泄露:更多角色和Boss!
  • 向量化执行引擎是啥?
  • LeetCode 刷题【81. 搜索旋转排序数组 II、82. 删除排序链表中的重复元素 II、83. 删除排序链表中的重复元素】
  • 关于二叉树的OJ练习
  • STM32H743-ARM例程1-GPIO点亮LED
  • 25.9.16幂等性总结
  • 27、Transformer架构详解-序列建模的革命性突破
  • [从青铜到王者] Spring Boot+Redis+Kafka电商场景面试全解析
  • 基于el-upload和vue-cropper实现图片上传裁剪组件
  • Kettle时间戳转换为日期格式处理方式
  • go.js Panel中文API
  • 加密货币中的MEV是什么
  • 【Linux学习笔记】线程概念与控制(一)
  • Linux笔记---非阻塞IO与多路复用
  • 生物信息学中的 AI Agent: Codex 初探
  • 贪心算法应用:埃及分数问题详解
  • 力扣hot100刷题day1
  • 什么是跨站脚本攻击
  • 团队对 DevOps 理解不统一会带来哪些问题
  • I²C 总线通信原理与时序
  • C#关键字record介绍
  • 试验台铁地板的设计与应用
  • 原子操作:多线程编程
  • 项目:寻虫记日志系统(三)
  • 在Arduino上模拟和电子I/O工作
  • Windows 命令行:相对路径
  • 线程、进程、协程
  • Java/注解Annotation/反射/元数据