|
|
|
|
@ -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,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|