|
|
|
@ -289,3 +289,168 @@ impl ScaleEntity for Polygon {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// 判断LwPolyline是否为带圆角的四边形
|
|
|
|
|
|
|
|
/// 条件:恰好8个顶点,闭合,每个顶点的bulge值要么为0(直线段)要么非0(圆弧段)
|
|
|
|
|
|
|
|
pub fn is_rounded_rectangle(lwpolyline: &LwPolyline) -> bool {
|
|
|
|
|
|
|
|
// 检查顶点数量
|
|
|
|
|
|
|
|
if lwpolyline.vertices.len() != 8 {
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 检查每个顶点的bulge值,确保形成合理的圆角四边形
|
|
|
|
|
|
|
|
// 圆角四边形应该有交替的直线段和圆弧段,或者4个圆角
|
|
|
|
|
|
|
|
let bulge_count = lwpolyline.vertices.iter()
|
|
|
|
|
|
|
|
.filter(|v| v.bulge.abs() > 0.0)
|
|
|
|
|
|
|
|
.count();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 4个圆角
|
|
|
|
|
|
|
|
bulge_count == 4
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// 将带圆角的四边形拆分为圆弧和直线段
|
|
|
|
|
|
|
|
pub fn decompose_rounded_rectangle(lwpolyline: &LwPolyline) -> Vec<super::Objects> {
|
|
|
|
|
|
|
|
let mut objects = Vec::new();
|
|
|
|
|
|
|
|
let vertices = &lwpolyline.vertices;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for i in 0..vertices.len() {
|
|
|
|
|
|
|
|
let current = &vertices[i];
|
|
|
|
|
|
|
|
let next = &vertices[(i + 1) % vertices.len()];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if current.bulge.abs() > 1e-10 {
|
|
|
|
|
|
|
|
// 创建圆弧段
|
|
|
|
|
|
|
|
if let Some(arc) = create_arc_from_bulge(current.x, current.y, next.x, next.y, current.bulge) {
|
|
|
|
|
|
|
|
objects.push(super::Objects::Arc(arc));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
// 创建直线段
|
|
|
|
|
|
|
|
let style = if lwpolyline.thickness > 0.5 {
|
|
|
|
|
|
|
|
"line-style:normal;line-weight:normal;filling:none;color:black"
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
"line-style:normal;line-weight:thin;filling:none;color:black"
|
|
|
|
|
|
|
|
}.to_string();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let line = super::Line::new(
|
|
|
|
|
|
|
|
current.x,
|
|
|
|
|
|
|
|
-current.y, // Y轴翻转
|
|
|
|
|
|
|
|
next.x,
|
|
|
|
|
|
|
|
-next.y, // Y轴翻转
|
|
|
|
|
|
|
|
style,
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
objects.push(super::Objects::Line(line));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
objects
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// 根据bulge值创建圆弧
|
|
|
|
|
|
|
|
fn create_arc_from_bulge(start_x: f64, start_y: f64, end_x: f64, end_y: f64, bulge: f64) -> Option<super::Arc> {
|
|
|
|
|
|
|
|
if bulge.abs() <= 1e-10 {
|
|
|
|
|
|
|
|
return None;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 计算弦长和中点
|
|
|
|
|
|
|
|
let chord_length = ((end_x - start_x).powi(2) + (end_y - start_y).powi(2)).sqrt();
|
|
|
|
|
|
|
|
let mid_x = (start_x + end_x) / 2.0;
|
|
|
|
|
|
|
|
let mid_y = (start_y + end_y) / 2.0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 根据bulge值计算圆弧参数
|
|
|
|
|
|
|
|
// bulge = tan(angle/4),其中angle是圆弧的包含角
|
|
|
|
|
|
|
|
let included_angle = 4.0 * bulge.atan(); // 圆弧包含角(弧度)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 计算半径
|
|
|
|
|
|
|
|
let radius: f64 = chord_length / (2.0 * (included_angle / 2.0).sin());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 计算圆心位置
|
|
|
|
|
|
|
|
// 弦的方向向量
|
|
|
|
|
|
|
|
let chord_dx = end_x - start_x;
|
|
|
|
|
|
|
|
let chord_dy = end_y - start_y;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 弦的垂直方向(向左旋转90度)
|
|
|
|
|
|
|
|
let perp_dx = -chord_dy;
|
|
|
|
|
|
|
|
let perp_dy = chord_dx;
|
|
|
|
|
|
|
|
let perp_length: f64 = (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: f64 = 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 = (start_y - center_y).atan2(start_x - center_x);
|
|
|
|
|
|
|
|
let end_angle = (end_y - center_y).atan2(end_x - center_x);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 将弧度转换为度数
|
|
|
|
|
|
|
|
let mut start_angle_deg: f64 = start_angle.to_degrees();
|
|
|
|
|
|
|
|
let mut end_angle_deg: f64 = 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: f64 = included_angle.to_degrees().abs();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// // 计算圆弧参数
|
|
|
|
|
|
|
|
// let start_x = start_vertex.x;
|
|
|
|
|
|
|
|
// let start_y = -start_vertex.y; // Y轴翻转
|
|
|
|
|
|
|
|
// let end_x = end_vertex.x;
|
|
|
|
|
|
|
|
// let end_y = -end_vertex.y; // Y轴翻转
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// // 弦长
|
|
|
|
|
|
|
|
// let chord_length = ((end_x - start_x).powi(2) + (end_y - start_y).powi(2)).sqrt();
|
|
|
|
|
|
|
|
// if chord_length < 1e-10 {
|
|
|
|
|
|
|
|
// return None;
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// // 根据bulge计算圆弧的角度
|
|
|
|
|
|
|
|
// let angle = 4.0 * bulge.atan();
|
|
|
|
|
|
|
|
// // 计算圆弧的半径
|
|
|
|
|
|
|
|
// let radius = chord_length / (2.0 * (angle / 2.0).sin());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// // 计算中点
|
|
|
|
|
|
|
|
// let mid_x = (start_x + end_x) / 2.0;
|
|
|
|
|
|
|
|
// let mid_y = (start_y + end_y) / 2.0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// // 计算弦角
|
|
|
|
|
|
|
|
// let chord_angle = (end_y - start_y).atan2(end_x - start_x);
|
|
|
|
|
|
|
|
// let center_offset = radius * (angle / 2.0).cos();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// let center_x = mid_x - center_offset * (chord_angle + std::f64::consts::PI / 2.0).sin();
|
|
|
|
|
|
|
|
// let center_y = mid_y + center_offset * (chord_angle + std::f64::consts::PI / 2.0).cos();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// // 计算起始角度和角度跨度
|
|
|
|
|
|
|
|
// 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();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Some(super::Arc::new(
|
|
|
|
|
|
|
|
center_x-radius,
|
|
|
|
|
|
|
|
-center_y-radius,
|
|
|
|
|
|
|
|
radius.abs() * 2.0,
|
|
|
|
|
|
|
|
radius.abs() * 2.0,
|
|
|
|
|
|
|
|
start_angle_deg,
|
|
|
|
|
|
|
|
arc_angle,
|
|
|
|
|
|
|
|
style,
|
|
|
|
|
|
|
|
))
|
|
|
|
|
|
|
|
}
|