feat: 实现椭圆功能

This commit is contained in:
2026-02-28 18:44:50 +08:00
parent 9337f15da1
commit d7f4571217
2 changed files with 92 additions and 0 deletions

View File

@@ -653,6 +653,73 @@ impl MSCanvas {
self.bezier(points); self.bezier(points);
} }
pub fn ellipse(&mut self, center: Point, rx: f32, ry: f32) {
let mut x = 0.0;
let mut y = ry; // 初始时将y设置为半高
// 计算初始决策参数
let mut decision = ry * ry - rx * rx * ry + rx * rx / 4.0;
while ry * ry * x < rx * rx * y {
// 在每个阶段,根据对称性绘制四个方向上的点
self.draw_pixel_at(Point::new(center.x + x, center.y + y));
self.draw_pixel_at(Point::new(center.x - x, center.y + y));
self.draw_pixel_at(Point::new(center.x + x, center.y - y));
self.draw_pixel_at(Point::new(center.x - x, center.y - y));
if decision < 0.0 {
x += 1.0;
decision += 2.0 * ry * ry * x + ry * ry;
} else {
x += 1.0;
y -= 1.0;
decision += 2.0 * ry * ry * x - 2.0 * rx * rx * y + ry * ry;
}
}
decision =
ry * ry * (x + 0.5) * (x + 0.5) + rx * rx * (y - 1.0) * (y - 1.0) - rx * rx * ry * ry;
while y > 0.0 {
// 同样地,根据对称性绘制四个方向上的点
self.draw_pixel_at(Point::new(center.x + x, center.y + y));
self.draw_pixel_at(Point::new(center.x - x, center.y + y));
self.draw_pixel_at(Point::new(center.x + x, center.y - y));
self.draw_pixel_at(Point::new(center.x - x, center.y - y));
if decision > 0.0 {
y -= 1.0;
decision += rx * rx - 2.0 * rx * rx * y;
} else {
x += 1.0;
y -= 1.0;
decision += 2.0 * ry * ry * x - 2.0 * rx * rx * y + rx * rx;
}
}
}
pub fn ellipse1(&mut self, p1: Point, p2: Point) {
let mut rx = (p2.x - p1.x) / 2.0;
let mut ry = (p2.y - p1.y) / 2.0;
if rx > 0.0 && ry > 0.0 {
let center = Point::new(p1.x + rx, p1.y + ry);
self.ellipse(center, rx, ry);
} else if rx < 0.0 && ry < 0.0 {
rx = -rx;
ry = -ry;
let center = Point::new(p1.x - rx, p1.y - ry);
self.ellipse(center, rx, ry);
} else if ry < 0.0 {
ry = -ry;
let center = Point::new(p1.x + rx, p1.y - ry);
self.ellipse(center, rx, ry);
} else {
rx = -rx;
let center = Point::new(p1.x - rx, p1.y + ry);
self.ellipse(center, rx, ry);
}
}
pub fn begin_path(&mut self) { pub fn begin_path(&mut self) {
self.path2d = Path2D::new(); self.path2d = Path2D::new();
} }

View File

@@ -447,6 +447,9 @@ impl PaintApp {
Tool::Polygon => { Tool::Polygon => {
self.update_with_polygon(message); self.update_with_polygon(message);
} }
Tool::Ellipse => {
self.update_with_ellipse(message);
}
_ => {} _ => {}
} }
@@ -794,6 +797,28 @@ impl PaintApp {
} }
} }
pub fn update_with_ellipse(&mut self, message: Message) {
match message {
Message::MousePressed(pos) => {
self.is_drawing = true;
self.canvas.save_pixels();
self.begin_point = pos;
}
Message::MouseReleased(pos) => {
self.is_drawing = false;
self.begin_point = pos;
}
Message::MouseMoved(pos) => {
if self.is_drawing {
self.canvas.restore_pixels();
self.canvas.ellipse1(self.begin_point, pos);
self.dirty = true;
}
}
_ => {}
}
}
// endregion // endregion
pub fn update_tool_states(&mut self, tool: Tool) { pub fn update_tool_states(&mut self, tool: Tool) {