From bbab20d48fd7a3b4d02e84230edfc593b7f25ba7 Mon Sep 17 00:00:00 2001 From: liaoxianglian Date: Fri, 19 Sep 2025 16:41:13 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A4=84=E7=90=86=E5=A4=9A=E7=BA=BF=E6=AE=B5?= =?UTF-8?q?=E3=80=81=E7=9F=A9=E5=BD=A2=E7=9A=84=E9=A2=9C=E8=89=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/qelmt/arc.rs | 13 +++- src/qelmt/ellipse.rs | 25 +++++++- src/qelmt/line.rs | 16 +++-- src/qelmt/mod.rs | 150 +++++++++++++++++++++++-------------------- src/qelmt/polygon.rs | 33 +++++++--- 5 files changed, 149 insertions(+), 88 deletions(-) diff --git a/src/qelmt/arc.rs b/src/qelmt/arc.rs index e2cb1c6..586f795 100644 --- a/src/qelmt/arc.rs +++ b/src/qelmt/arc.rs @@ -156,6 +156,13 @@ impl TryFrom<&LwPolyline> for Arc { type Error = String; fn try_from(lwpolyline: &LwPolyline) -> Result { + Self::try_from_lwpolyline_with_color(lwpolyline, HexColor::BLACK) + } +} + +impl Arc { + /// 从DXF LwPolyline实体创建Arc,支持自定义颜色 + pub fn try_from_lwpolyline_with_color(lwpolyline: &LwPolyline, color: HexColor) -> Result { // 检查顶点数量,必须是2个顶点才能形成圆弧 if lwpolyline.vertices.len() != 2 { return Err(format!("Arc conversion requires exactly 2 vertices, got {}", lwpolyline.vertices.len())); @@ -239,10 +246,10 @@ impl TryFrom<&LwPolyline> for Arc { start: start_angle_deg, // 起始角度(度) angle: arc_angle, // 圆弧角度跨度(度) style: if lwpolyline.thickness > 0.1 { - "line-style:normal;line-weight:normal;filling:none;color:black" + format!("line-style:normal;line-weight:normal;filling:none;color:{}", color.display_rgb()) } else { - "line-style:normal;line-weight:thin;filling:none;color:black" - }.into(), + format!("line-style:normal;line-weight:thin;filling:none;color:{}", color.display_rgb()) + }, antialias: false, }) } diff --git a/src/qelmt/ellipse.rs b/src/qelmt/ellipse.rs index ca130ca..e1fe5bb 100644 --- a/src/qelmt/ellipse.rs +++ b/src/qelmt/ellipse.rs @@ -1,5 +1,6 @@ use super::{two_dec, Circularity, ScaleEntity}; use dxf::entities::{self, Circle, LwPolyline, Polyline}; +use hex_color::HexColor; use simple_xml_builder::XMLElement; #[derive(Debug)] @@ -7,6 +8,7 @@ pub struct Ellipse { height: f64, width: f64, style: String, + color: HexColor, //need to brush up on my Rust scoping rules, isn't there a way to make this pub to just the module? pub x: f64, @@ -22,6 +24,7 @@ impl From<&Circle> for Ellipse { y: -circ.center.y - circ.radius, height: circ.radius * 2.0, width: circ.radius * 2.0, + color: HexColor::BLACK, //in the original code antialias is always set to false...I'm guessing for performance //reasons...I'm trying to think if there is a time we might want to turn it on? @@ -43,6 +46,7 @@ impl From<&entities::Ellipse> for Ellipse { y: -ellipse.center.y - ellipse.major_axis.x * ellipse.minor_axis_ratio, width: ellipse.major_axis.x * 2.0, height: ellipse.major_axis.x * 2.0 * ellipse.minor_axis_ratio, + color: HexColor::BLACK, //in the original code antialias is always set to false...I'm guessing for performance //reasons...I'm trying to think if there is a time we might want to turn it on? @@ -87,6 +91,7 @@ impl TryFrom<&Polyline> for Ellipse { y: -max_y, height: max_y - y, width: max_x - x, + color: HexColor::BLACK, //in the original code antialias is always set to false...I'm guessing for performance //reasons...I'm trying to think if there is a time we might want to turn it on? @@ -100,6 +105,12 @@ impl TryFrom<&LwPolyline> for Ellipse { type Error = &'static str; //add better error later fn try_from(poly: &LwPolyline) -> Result { + Self::try_from_lwpolyline_with_color(poly, HexColor::BLACK) + } +} + +impl Ellipse { + pub fn try_from_lwpolyline_with_color(poly: &LwPolyline, color: HexColor) -> Result { let is_bugle_circle = poly.is_circular_with_bulge(); if !is_bugle_circle&&!poly.is_circular() { @@ -126,6 +137,8 @@ impl TryFrom<&LwPolyline> for Ellipse { .iter() .fold(f64::MIN, |max_y, vtx| max_y.max(vtx.y)); + let style = format!("line-style:normal;line-weight:thin;filling:none;color:rgb({},{},{})", color.r, color.g, color.b); + Ok(Ellipse { x, y: if is_bugle_circle {-max_y-(max_x - x)/2.0} else {-max_y}, @@ -135,11 +148,12 @@ impl TryFrom<&LwPolyline> for Ellipse { max_y - y }, width: max_x - x, + color, //in the original code antialias is always set to false...I'm guessing for performance //reasons...I'm trying to think if there is a time we might want to turn it on? antialias: false, - style: "line-style:normal;line-weight:thin;filling:none;color:black".into(), + style, }) } } @@ -153,6 +167,7 @@ impl From<&Ellipse> for XMLElement { ell_xml.add_attribute("height", two_dec(ell.height)); ell_xml.add_attribute("antialias", ell.antialias); ell_xml.add_attribute("style", &ell.style); + ell_xml.add_attribute("color", ell.color.display_rgb().to_string()); ell_xml } } @@ -168,6 +183,14 @@ impl Ellipse { { update_fn(&mut self.style); } + + pub fn set_color(&mut self, color: HexColor) { + self.color = color; + } + + pub fn get_color(&self) -> HexColor { + self.color + } } impl ScaleEntity for Ellipse { diff --git a/src/qelmt/line.rs b/src/qelmt/line.rs index bd4bfdb..b632aa5 100644 --- a/src/qelmt/line.rs +++ b/src/qelmt/line.rs @@ -65,6 +65,13 @@ impl TryFrom<&LwPolyline> for Line { type Error = &'static str; //add better error later fn try_from(poly: &LwPolyline) -> Result { + Self::try_from_lwpolyline_with_color(poly, HexColor::BLACK) + } +} + +impl Line { + /// 从DXF LwPolyline实体创建Line,支持自定义颜色 + pub fn try_from_lwpolyline_with_color(poly: &LwPolyline, color: HexColor) -> Result { if poly.vertices.len() != 2 { return Err("Error can't convert polyline with more than 2 points into a Line"); } @@ -83,13 +90,12 @@ impl TryFrom<&LwPolyline> for Line { //reasons...I'm trying to think if there is a time we might want to turn it on? antialias: false, style: if poly.thickness > 0.1 { - "line-style:normal;line-weight:normal;filling:none;color:black" + format!("line-style:normal;line-weight:normal;filling:none;color:{}", color.display_rgb()) } else if poly.constant_width > 1.0{ - "line-style:normal;line-weight:hight;filling:none;color:black" + format!("line-style:normal;line-weight:hight;filling:none;color:{}", color.display_rgb()) } else { - "line-style:normal;line-weight:thin;filling:none;color:black" - } - .into(), + format!("line-style:normal;line-weight:thin;filling:none;color:{}", color.display_rgb()) + }, }) } } diff --git a/src/qelmt/mod.rs b/src/qelmt/mod.rs index 46dd709..0708d6d 100644 --- a/src/qelmt/mod.rs +++ b/src/qelmt/mod.rs @@ -201,15 +201,16 @@ impl Circularity for LwPolyline { } // 实现Definition的方法 +// 最后返回文本的definition标签了 impl Definition { - // 创建新的 Definition 实例 + // 创建新的 Definition 实例,对应elmt的标签 传入参数:文件名, 步长, dxf图纸 pub fn new(name: impl Into, spline_step: u32, drw: &Drawing) -> Self { /*for st in drw.styles() { dbg!(st); }*/ - // 缩放处理 + // 根据制图系统的类型缩放处理 let scale_factor = Self::scale_factor(drw.header.default_drawing_units); - // 创建description + // 创建description,对应elmt的标签,里面就是实际的画图元素标签 let description = { let mut description: Description = (drw, spline_step).into(); description.scale(scale_factor, scale_factor); @@ -847,87 +848,96 @@ impl<'a> ObjectsBuilder<'a> { } } }, - EntityType::LwPolyline(lwpolyline) => match lwpolyline.vertices.len() { - 0 | 1 => Err("Error empty LwPolyline"), - 2 => { - if lwpolyline.vertices[0].bulge != 0.0 { - match Arc::try_from(lwpolyline) { - Ok(mut arc) => { - arc.update_line_style(&update_line_style); - arc.scale(self.scale_fact.x, self.scale_fact.y); - arc.x += self.offset.x; - arc.y -= self.offset.y; - return Ok(Objects::Arc(arc)); - } - Err(_) => { - // Arc转换失败,继续执行下面的Line转换 + EntityType::LwPolyline(lwpolyline) => { + // 获取颜色 + let color = if let Some(aci_index) = self.ent.common.color.index() { + aci_to_hex_color(aci_index) + } else { + HexColor::from_u32(self.ent.common.color_24_bit as u32) + }; + + match lwpolyline.vertices.len() { + 0 | 1 => Err("Error empty LwPolyline"), + 2 => { + if lwpolyline.vertices[0].bulge != 0.0 { + match Arc::try_from_lwpolyline_with_color(lwpolyline, color) { + Ok(mut arc) => { + arc.update_line_style(&update_line_style); + arc.scale(self.scale_fact.x, self.scale_fact.y); + arc.x += self.offset.x; + arc.y -= self.offset.y; + return Ok(Objects::Arc(arc)); + } + Err(_) => { + // Arc转换失败,继续执行下面的Line转换 + } } } - } - - let mut line = Line::try_from(lwpolyline)?; - - // 根据line_type_name更新线型样式 - line.update_line_style(&update_line_style); - line.scale(self.scale_fact.x, self.scale_fact.y); - - line.x1 += self.offset.x; - line.y1 -= self.offset.y; - - line.x2 += self.offset.x; - line.y2 -= self.offset.y; + let mut line = Line::try_from_lwpolyline_with_color(lwpolyline, color)?; - Ok(Objects::Line(line)) - } - _ => { - if let Ok(mut ellipse) = Ellipse::try_from(lwpolyline) { // 根据line_type_name更新线型样式 - ellipse.update_line_style(&update_line_style); + line.update_line_style(&update_line_style); - ellipse.scale(self.scale_fact.x, self.scale_fact.y); + line.scale(self.scale_fact.x, self.scale_fact.y); - ellipse.x += self.offset.x; - ellipse.y -= self.offset.y; + line.x1 += self.offset.x; + line.y1 -= self.offset.y; - Ok(Objects::Ellipse(ellipse)) - } else if polygon::is_rounded_rectangle(lwpolyline) { - // 拆分圆角四边形为圆弧和直线段 - let mut decomposed_objects = polygon::decompose_rounded_rectangle(lwpolyline); - - // 对每个对象应用缩放和偏移 - for obj in &mut decomposed_objects { - obj.scale(self.scale_fact.x, self.scale_fact.y); - match obj { - Objects::Arc(ref mut arc) => { - arc.x += self.offset.x; - arc.y -= self.offset.y; - } - Objects::Line(ref mut line) => { - line.x1 += self.offset.x; - line.y1 -= self.offset.y; - line.x2 += self.offset.x; - line.y2 -= self.offset.y; + line.x2 += self.offset.x; + line.y2 -= self.offset.y; + + Ok(Objects::Line(line)) + } + _ => { + if let Ok(mut ellipse) = Ellipse::try_from_lwpolyline_with_color(lwpolyline, color) { + // 根据line_type_name更新线型样式 + ellipse.update_line_style(&update_line_style); + + ellipse.scale(self.scale_fact.x, self.scale_fact.y); + + ellipse.x += self.offset.x; + ellipse.y -= self.offset.y; + + Ok(Objects::Ellipse(ellipse)) + } else if polygon::is_rounded_rectangle(lwpolyline) { + // 拆分圆角四边形为圆弧和直线段 + let mut decomposed_objects = polygon::decompose_rounded_rectangle_with_color(lwpolyline, color); + + // 对每个对象应用缩放和偏移 + for obj in &mut decomposed_objects { + obj.scale(self.scale_fact.x, self.scale_fact.y); + match obj { + Objects::Arc(ref mut arc) => { + arc.x += self.offset.x; + arc.y -= self.offset.y; + } + Objects::Line(ref mut line) => { + line.x1 += self.offset.x; + line.y1 -= self.offset.y; + line.x2 += self.offset.x; + line.y2 -= self.offset.y; + } + _ => {} } - _ => {} } - } - - Ok(Objects::Group(decomposed_objects)) - } else { - let mut poly: Polygon = lwpolyline.into(); + + Ok(Objects::Group(decomposed_objects)) + } else { + let mut poly: Polygon = Polygon::from_lwpolyline_with_color(lwpolyline, color); - // 根据line_type_name更新线型样式 - poly.update_line_style(&update_line_style); + // 根据line_type_name更新线型样式 + poly.update_line_style(&update_line_style); - poly.scale(self.scale_fact.x, self.scale_fact.y); + poly.scale(self.scale_fact.x, self.scale_fact.y); - for cord in &mut poly.coordinates { - cord.x += self.offset.x; - cord.y -= self.offset.y; - } + for cord in &mut poly.coordinates { + cord.x += self.offset.x; + cord.y -= self.offset.y; + } - Ok(Objects::Polygon(poly)) + Ok(Objects::Polygon(poly)) + } } } }, diff --git a/src/qelmt/polygon.rs b/src/qelmt/polygon.rs index 989e174..2ececcc 100644 --- a/src/qelmt/polygon.rs +++ b/src/qelmt/polygon.rs @@ -1,5 +1,6 @@ use super::{two_dec, ScaleEntity}; use dxf::entities::{LwPolyline, Polyline, Solid, Spline}; +use hex_color::HexColor; use simple_xml_builder::XMLElement; use std::ops::{Add, Mul}; @@ -79,6 +80,13 @@ impl From<&Polyline> for Polygon { impl From<&LwPolyline> for Polygon { fn from(poly: &LwPolyline) -> Self { + Self::from_lwpolyline_with_color(poly, HexColor::BLACK) + } +} + +impl Polygon { + /// 从DXF LwPolyline实体创建Polygon,支持自定义颜色 + pub fn from_lwpolyline_with_color(poly: &LwPolyline, color: HexColor) -> Self { Polygon { coordinates: poly .vertices @@ -93,11 +101,10 @@ impl From<&LwPolyline> for Polygon { //reasons...I'm trying to think if there is a time we might want to turn it on? antialias: false, style: if poly.thickness > 0.1 { - "line-style:normal;line-weight:normal;filling:none;color:black" + format!("line-style:normal;line-weight:normal;filling:none;color:{}", color.display_rgb()) } else { - "line-style:normal;line-weight:thin;filling:none;color:black" - } - .into(), + format!("line-style:normal;line-weight:thin;filling:none;color:{}", color.display_rgb()) + }, } } } @@ -311,6 +318,10 @@ pub fn is_rounded_rectangle(lwpolyline: &LwPolyline) -> bool { /// 将带圆角的四边形拆分为圆弧和直线段 pub fn decompose_rounded_rectangle(lwpolyline: &LwPolyline) -> Vec { + decompose_rounded_rectangle_with_color(lwpolyline, HexColor::BLACK) +} + +pub fn decompose_rounded_rectangle_with_color(lwpolyline: &LwPolyline, color: HexColor) -> Vec { let mut objects = Vec::new(); let vertices = &lwpolyline.vertices; @@ -320,16 +331,16 @@ pub fn decompose_rounded_rectangle(lwpolyline: &LwPolyline) -> Vec 1e-10 { // 创建圆弧段 - if let Some(arc) = create_arc_from_bulge(current.x, current.y, next.x, next.y, current.bulge) { + if let Some(arc) = create_arc_from_bulge_with_color(current.x, current.y, next.x, next.y, current.bulge, color) { objects.push(super::Objects::Arc(arc)); } } else { // 创建直线段 let style = if lwpolyline.thickness > 0.5 { - "line-style:normal;line-weight:normal;filling:none;color:black" + format!("line-style:normal;line-weight:normal;filling:none;color:color:{}", color.display_rgb()) } else { - "line-style:normal;line-weight:thin;filling:none;color:black" - }.to_string(); + format!("line-style:normal;line-weight:thin;filling:none;color:color:{}", color.display_rgb()) + }; let line = super::Line::new( current.x, @@ -346,6 +357,10 @@ pub fn decompose_rounded_rectangle(lwpolyline: &LwPolyline) -> Vec Option { + create_arc_from_bulge_with_color(start_x, start_y, end_x, end_y, bulge, HexColor::BLACK) +} + +fn create_arc_from_bulge_with_color(start_x: f64, start_y: f64, end_x: f64, end_y: f64, bulge: f64, color: HexColor) -> Option { if bulge.abs() <= 1e-10 { return None; } @@ -442,7 +457,7 @@ fn create_arc_from_bulge(start_x: f64, start_y: f64, end_x: f64, end_y: f64, bul // let start_angle = (start_y - center_y).atan2(start_x - center_x).to_degrees(); // let angle_span = angle.to_degrees().abs(); - let style = "line-style:normal;line-weight:thin;filling:none;color:black".to_string(); + let style = format!("line-style:normal;line-weight:thin;filling:none;color:{}", color.display_rgb()); Some(super::Arc::new( center_x-radius,