mirror of
https://github.com/storytold/cadcraft.git
synced 2026-10-14 14:26:45 -04:00
Squash of PR #601 by @MarekSpodBiedry. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
5cb54c3969
commit
41c3c83fb9
4 files changed
+26
-2
No files matched your search
@@ -212,6 +212,10 @@ fn object_area(s: &Session, h: Handle) -> Result<(f64, f64)> {
|
||||
(g.area().abs(), g.len())
|
||||
}
|
||||
EntityKind::Ellipse(el) => {
|
||||
let arc = cadcraft_geom::Ellipse { center: el.center.xy(), major: el.major.xy(), ratio: el.ratio, start: el.start, end: el.end };
|
||||
if !arc.is_full() {
|
||||
return Err(bad("area", "object has no area"));
|
||||
}
|
||||
let a = el.major.xy().len();
|
||||
let b = a * el.ratio;
|
||||
(cadcraft_geom::PI * a * b, cadcraft_geom::PI * (3.0 * (a + b) - ((3.0 * a + b) * (a + 3.0 * b)).sqrt()))
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
//! AREA's Object / Add area / Subtract area and DIST's Multiple points, typed as at the command line.
|
||||
|
||||
use cadcraft_engine::Session;
|
||||
use serde_json::json;
|
||||
|
||||
fn run(lines: &[&str]) -> (Session, Vec<String>) {
|
||||
let mut s = Session::new();
|
||||
@@ -48,3 +49,20 @@ fn dist_multiple_points_sums_the_segments() {
|
||||
assert!(has(&log, "Distance = 11.0000"), "{log:?}");
|
||||
assert!(s.running.is_none(), "{}", s.prompt_text());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn area_of_an_open_elliptical_arc_is_refused_and_a_full_ellipse_is_measured() {
|
||||
for end in [90, 45] {
|
||||
let mut s = Session::new();
|
||||
let r = s.execute("ellipse", &json!({"center": [0, 0], "major": [4, 0], "ratio": 0.5, "start": 0, "end": end})).unwrap();
|
||||
assert!(s.execute("area", &json!({"handle": r["handle"]})).is_err());
|
||||
}
|
||||
let mut s = Session::new();
|
||||
let r = s.execute("ellipse", &json!({"center": [0, 0], "major": [4, 0], "ratio": 0.5})).unwrap();
|
||||
let a = s.execute("area", &json!({"handle": r["handle"]})).unwrap();
|
||||
assert!((a["area"].as_f64().unwrap() - 8.0 * std::f64::consts::PI).abs() < 1e-9, "{a}");
|
||||
// Object selection of the quarter ellipse says it has no area.
|
||||
let (_, log) = run(&["ellipse a c 0,0 4,0 2 0 90", "area", "o", "4,0"]);
|
||||
assert!(has(&log, "no area"), "{log:?}");
|
||||
assert!(!has(&log, "Area = "), "{log:?}");
|
||||
}
|
||||
@@ -20,10 +20,12 @@ fn frame(app: &mut CadApp, ctx: &egui::Context) {
|
||||
let mut raw = egui::RawInput { screen_rect: Some(egui::Rect::from_min_size(egui::Pos2::ZERO, egui::vec2(1280.0, 800.0))), ..Default::default() };
|
||||
app.raw_input_hook(&mut raw);
|
||||
cadcraft_ui_egui::cmdline::capture_tab(ctx, &mut raw);
|
||||
let _ = ctx.run_ui(raw, |ui| {
|
||||
let mut out = ctx.run_ui(raw, |ui| {
|
||||
app.logic(ui.ctx());
|
||||
app.ui(ui);
|
||||
});
|
||||
// No renderer here: drop the texture updates deliberately.
|
||||
out.textures_delta.clear();
|
||||
assert!(!ctx.egui_wants_keyboard_input(), "a text field must not hold focus");
|
||||
}
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ Where line and arc are supported the results are exact.
|
||||
| Closest point: line, arc, circle, polyline | exact | exact |
|
||||
| Closest point: ellipse, spline | exact to tolerance | **sampled** (`curve.rs:264`, `curves.rs:637`) |
|
||||
| Tangent points, common tangents | every curve | circles and arcs only (`curve.rs:170-183`) |
|
||||
| AREA: circle, ellipse | exact | exact area (ellipse perimeter by Ramanujan, not exact) |
|
||||
| AREA: circle, ellipse | exact | exact area (ellipse perimeter by Ramanujan, not exact); an open elliptical arc has no area, like an arc |
|
||||
| AREA: polyline with arcs | exact (bulge segments) | **tessellated at 1e-4** (`curve.rs:491`) |
|
||||
| MASSPROP (regions: area, perimeter, centroid, moments) | exact on regions and solids | shoelace over a tessellated circle, polyline or first hatch loop (`utility.rs:310-352`); no regions |
|
||||
| LIST/DIST/ID precision | full double | full double |
|
||||
|
||||
Reference in new issue
Block a user