解决缺少弧线和实心长方形的问题:处理线的宽度constant_width,增加lwpolyline转圆弧的代码

master
liaoxianglian 5 months ago
parent aca0c7803c
commit ae54a27dca

@ -1,5 +1,6 @@
use super::{two_dec, ScaleEntity};
use dxf::entities;
use dxf::entities::LwPolyline;
use simple_xml_builder::XMLElement;
#[derive(Debug)]
@ -130,3 +131,100 @@ impl ScaleEntity for Arc {
self.y + self.height
}
}
// 在 mod.rs 中添加从 LwPolyline 转换为 Arc 的方法
impl TryFrom<&LwPolyline> for Arc {
type Error = String;
fn try_from(lwpolyline: &LwPolyline) -> Result<Self, Self::Error> {
// 检查顶点数量必须是2个顶点才能形成圆弧
if lwpolyline.vertices.len() != 2 {
return Err(format!("Arc conversion requires exactly 2 vertices, got {}", lwpolyline.vertices.len()));
}
let v1 = &lwpolyline.vertices[0];
let v2 = &lwpolyline.vertices[1];
// 检查第一个顶点是否有bulge值
if v1.bulge == 0.0 {
return Err("No bulge value found for arc conversion".to_string());
}
// 计算弦长和中点
let chord_length = ((v2.x - v1.x).powi(2) + (v2.y - v1.y).powi(2)).sqrt();
let mid_x = (v1.x + v2.x) / 2.0;
let mid_y = (v1.y + v2.y) / 2.0;
// 根据bulge值计算圆弧参数
// bulge = tan(angle/4)其中angle是圆弧的包含角
let bulge = v1.bulge;
let included_angle = 4.0 * bulge.atan(); // 圆弧包含角(弧度)
// 计算半径
let radius = chord_length / (2.0 * (included_angle / 2.0).sin());
// 计算圆心位置
// 弦的方向向量
let chord_dx = v2.x - v1.x;
let chord_dy = v2.y - v1.y;
// 弦的垂直方向向左旋转90度
let perp_dx = -chord_dy;
let perp_dy = chord_dx;
let perp_length = (perp_dx * perp_dx + perp_dy * perp_dy).sqrt();
// 标准化垂直向量
let unit_perp_x = perp_dx / perp_length;
let unit_perp_y = perp_dy / perp_length;
// 计算圆心到弦中点的距离
let center_distance = radius * (included_angle / 2.0).cos();
// 根据bulge的符号确定圆心位置
let center_x = if bulge > 0.0 {
mid_x + center_distance * unit_perp_x
} else {
mid_x - center_distance * unit_perp_x
};
let center_y = if bulge > 0.0 {
mid_y + center_distance * unit_perp_y
} else {
mid_y - center_distance * unit_perp_y
};
// 计算起始角度和结束角度
let start_angle = (v1.y - center_y).atan2(v1.x - center_x);
let end_angle = (v2.y - center_y).atan2(v2.x - center_x);
// 将弧度转换为度数
let mut start_angle_deg = start_angle.to_degrees();
let mut end_angle_deg = end_angle.to_degrees();
// 标准化角度到0-360度范围
if start_angle_deg < 0.0 {
start_angle_deg += 360.0;
}
if end_angle_deg < 0.0 {
end_angle_deg += 360.0;
}
// 计算角度跨度
let arc_angle = included_angle.to_degrees().abs();
// 创建Arc对象
Ok(Arc {
x: center_x - radius, // 边界框左上角x坐标
y: -center_y - radius, // 边界框左上角y坐标y轴翻转
width: radius * 2.0, // 边界框宽度
height: radius * 2.0, // 边界框高度
start: start_angle_deg, // 起始角度(度)
angle: arc_angle, // 圆弧角度跨度(度)
style: if lwpolyline.thickness > 0.1 {
"line-style:normal;line-weight:normal;filling:none;color:black"
} else {
"line-style:normal;line-weight:thin;filling:none;color:black"
}.into(),
antialias: false,
})
}
}

@ -819,6 +819,21 @@ 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转换
}
}
}
let mut line = Line::try_from(lwpolyline)?;
// 根据line_type_name更新线型样式

Loading…
Cancel
Save