解决圆角问题

master
liaoxianglian 5 months ago
parent ae54a27dca
commit dc7edc3de0

@ -99,6 +99,19 @@ impl From<&Arc> for XMLElement {
}
impl Arc {
pub fn new(x: f64, y: f64, width: f64, height: f64, start: f64, angle: f64, style: String) -> Self {
Arc {
x,
y,
width,
height,
start,
angle,
style,
antialias: false,
}
}
pub fn update_line_style<F>(&mut self, update_fn: F)
where
F: FnOnce(&mut String),

@ -174,6 +174,21 @@ impl From<&Line> for XMLElement {
}
impl Line {
pub fn new(x1: f64, y1: f64, x2: f64, y2: f64, style: String) -> Self {
Line {
length2: 1.5,
end2: LineEnd::None,
length1: 1.5,
x1,
y1,
x2,
y2,
style,
end1: LineEnd::None,
antialias: false,
}
}
pub fn update_line_style<F>(&mut self, update_fn: F)
where
F: FnOnce(&mut String),

@ -860,6 +860,29 @@ impl<'a> ObjectsBuilder<'a> {
ellipse.y -= 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;
}
_ => {}
}
}
Ok(Objects::Group(decomposed_objects))
} else {
let mut poly: Polygon = lwpolyline.into();
@ -1638,3 +1661,4 @@ enum TextEntity<'a> {
MText(&'a dxf::entities::MText),
Attrib(&'a AttributeDefinition),
}

@ -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,
))
}
Loading…
Cancel
Save