diff --git a/crates/doc/src/eval.rs b/crates/doc/src/eval.rs index 4d2009f6..857ac64a 100644 --- a/crates/doc/src/eval.rs +++ b/crates/doc/src/eval.rs @@ -28,8 +28,8 @@ pub struct ModelBody { // Timeline snapshots are cloned before meshes are requested. Share the cell itself so // meshing any snapshot also warms every unchanged copy of this body. mesh: Arc>>, - /// The display plan the mesh is evaluated from (none when the body has no plan: a mesh - /// body, or one the planner refuses), shared like the mesh. A GPU viewport draws it. + /// The display plan (none when the body has no plan: a mesh body, or one the planner + /// refuses), shared like the mesh. A GPU viewport draws it. plan: Arc>>>, /// Identity of this body's content for the evaluation cache: the key of the evaluation /// that produced it (kept while later features pass it through unchanged). @@ -75,19 +75,17 @@ impl ModelBody { /// curved face or edge turning more than [`kernel::DISPLAY_ANGLE`], so that a bend or a /// hole that is small beside the body is still drawn round. pub fn mesh(&self) -> Arc { + // From the reference mesher, not the display plan: the model reads this mesh (holes + // finding their surface, picks naming their face, sketch planes), and a different + // triangulation moved those and changed what designs build. A GPU viewport draws the + // plan ([`ModelBody::display_plan`]). self.mesh - .get_or_init(|| { - let mesh = match self.display_plan() { - Some(plan) => self.body.display_mesh_of(&plan), - None => self.body.reference_display_mesh_angular(self.display_tol(), kernel::DISPLAY_ANGLE), - }; - Arc::new(mesh.unwrap_or_default()) - }) + .get_or_init(|| Arc::new(self.body.reference_display_mesh_angular(self.display_tol(), kernel::DISPLAY_ANGLE).unwrap_or_default())) .clone() } - /// The display plan behind [`ModelBody::mesh`] (same tolerance and angle), made once; `None` - /// when the body has no plan and its mesh comes from the reference mesher. + /// The display plan of this body (the same tolerance and angle as [`ModelBody::mesh`]), made + /// once; `None` when the body has no plan (a mesh body, or one the planner refuses). pub fn display_plan(&self) -> Option> { self.plan .get_or_init(|| match self.body.display_plan_angular(self.display_tol(), kernel::DISPLAY_ANGLE) { diff --git a/tests/robustness/goldens.json b/tests/robustness/goldens.json index b5444c59..41c57226 100644 --- a/tests/robustness/goldens.json +++ b/tests/robustness/goldens.json @@ -1,9 +1,9 @@ { "about": "What each robustness seed builds (crates/engine/src/tests/robustness_goldens.rs, docs/robustness.md). Record changes with ROBUSTNESS_GOLDENS_BLESS=\"why\".", "seeds": { - "0": {"area":4785.573769,"bodies":1,"edges":78,"error":null,"faces":29,"outcome":"ok","rejected":0,"shells":1,"steps":["extruded profile","hole","circular pattern","circular pattern","cut sphere","join cylinder","cut cylinder","fillet"],"unsupported":1,"volume":13461.708575}, + "0": {"area":4795.764399,"bodies":1,"edges":79,"error":null,"faces":29,"outcome":"ok","rejected":0,"shells":1,"steps":["extruded profile","hole","circular pattern","circular pattern","cut sphere","join cylinder","cut cylinder","fillet"],"unsupported":1,"volume":13466.472104}, "1": {"area":2642.476675,"bodies":1,"edges":37,"error":null,"faces":15,"outcome":"ok","rejected":0,"shells":1,"steps":["revolved section","cut cylinder","join cylinder"],"unsupported":0,"volume":6991.559474}, - "2": {"area":2493.96451,"bodies":1,"edges":59,"error":null,"faces":22,"outcome":"ok","rejected":0,"shells":1,"steps":["box","cut cylinder","fillet","cut sphere","rectangular pattern","cut sphere"],"unsupported":3,"volume":5020.250734}, + "2": {"area":2493.96451,"bodies":1,"edges":59,"error":null,"faces":22,"outcome":"ok","rejected":0,"shells":1,"steps":["box","cut cylinder","fillet","cut sphere","rectangular pattern","cut sphere"],"unsupported":3,"volume":5020.244288}, "3": {"area":6336.456108,"bodies":1,"edges":33,"error":null,"faces":13,"outcome":"ok","rejected":0,"shells":1,"steps":["box","cut box","hole","fillet","hole"],"unsupported":0,"volume":28037.146872}, "4": {"area":5813.939544,"bodies":1,"edges":27,"error":null,"faces":11,"outcome":"ok","rejected":0,"shells":1,"steps":["box","cut cylinder","fillet"],"unsupported":0,"volume":28462.605133}, "5": {"area":1696.077144,"bodies":1,"edges":24,"error":"boolean Cut: the operation failed: no result; the operation ","faces":12,"outcome":"failed","rejected":1,"shells":1,"steps":["box","cut cylinder","hole","cut cylinder"],"unsupported":0,"volume":3520.994026}, @@ -15,15 +15,15 @@ "11": {"area":7858.300481,"bodies":1,"edges":33,"error":null,"faces":13,"outcome":"ok","rejected":0,"shells":1,"steps":["extruded profile","hole","rectangular pattern","fillet"],"unsupported":0,"volume":34605.048259}, "12": {"area":4668.664174,"bodies":2,"edges":62,"error":null,"faces":25,"outcome":"ok","rejected":0,"shells":2,"steps":["extruded profile","chamfer","join cylinder","join box","cut cylinder","circular pattern"],"unsupported":3,"volume":11874.471611}, "13": {"area":1857.434659,"bodies":4,"edges":78,"error":null,"faces":34,"outcome":"ok","rejected":1,"shells":4,"steps":["revolved section","cut cylinder","join box","rectangular pattern","cut cylinder","cut box","fillet","hole"],"unsupported":0,"volume":2300.910644}, - "14": {"area":6276.769189,"bodies":1,"edges":24,"error":"offset: a corner whose faces don't meet the same way after t","faces":10,"outcome":"failed","rejected":0,"shells":1,"steps":["extruded profile","cut cylinder","shell"],"unsupported":0,"volume":26373.506605}, + "14": {"area":10553.267699,"bodies":1,"edges":43,"error":null,"faces":20,"outcome":"ok","rejected":0,"shells":1,"steps":["extruded profile","cut cylinder","shell","fillet"],"unsupported":0,"volume":10369.009812}, "15": {"area":1974.784048,"bodies":1,"edges":40,"error":"boolean Cut: the operation failed: no result; the operation ","faces":18,"outcome":"failed","rejected":0,"shells":2,"steps":["revolved section","fillet","cut box","rectangular pattern","cut sphere","cut cylinder","cut sphere"],"unsupported":1,"volume":4781.224576}, "16": {"area":8872.873884,"bodies":3,"edges":49,"error":null,"faces":23,"outcome":"ok","rejected":0,"shells":3,"steps":["box","join cylinder","circular pattern","hole"],"unsupported":0,"volume":44953.403148}, "17": {"area":6048.425784,"bodies":1,"edges":56,"error":null,"faces":19,"outcome":"ok","rejected":0,"shells":1,"steps":["revolved section","cut box","shell","cut cylinder"],"unsupported":0,"volume":2968.531542}, "18": {"area":5524.583818,"bodies":4,"edges":98,"error":"boolean Cut: the operation failed: no result; the operation ","faces":44,"outcome":"failed","rejected":0,"shells":4,"steps":["extruded profile","join cylinder","circular pattern","cut cylinder","hole","cut cylinder","hole","circular pattern"],"unsupported":0,"volume":21568.016708}, "19": {"area":5938.978965,"bodies":1,"edges":74,"error":null,"faces":25,"outcome":"ok","rejected":0,"shells":1,"steps":["revolved section","cut sphere","shell"],"unsupported":1,"volume":2942.886331}, - "20": {"area":5727.101213,"bodies":1,"edges":116,"error":null,"faces":45,"outcome":"ok","rejected":0,"shells":1,"steps":["extruded profile","fillet","cut box","cut cylinder","hole","circular pattern","cut box"],"unsupported":1,"volume":17142.726126}, + "20": {"area":5727.101254,"bodies":1,"edges":116,"error":null,"faces":45,"outcome":"ok","rejected":0,"shells":1,"steps":["extruded profile","fillet","cut box","cut cylinder","hole","circular pattern","cut box"],"unsupported":1,"volume":17142.729272}, "21": {"area":5968.473044,"bodies":2,"edges":54,"error":null,"faces":21,"outcome":"ok","rejected":0,"shells":2,"steps":["revolved section","join box","hole","fillet","hole","cut box"],"unsupported":1,"volume":18926.835174}, - "22": {"area":4634.478462,"bodies":2,"edges":108,"error":null,"faces":40,"outcome":"ok","rejected":0,"shells":2,"steps":["revolved section","join box","join box","join box","rectangular pattern","cut cylinder"],"unsupported":0,"volume":7855.54666}, + "22": {"area":4634.478462,"bodies":2,"edges":108,"error":null,"faces":40,"outcome":"ok","rejected":0,"shells":2,"steps":["revolved section","join box","join box","join box","rectangular pattern","cut cylinder"],"unsupported":0,"volume":7855.549403}, "23": {"area":1795.696192,"bodies":1,"edges":16,"error":null,"faces":7,"outcome":"ok","rejected":0,"shells":1,"steps":["revolved section","cut sphere"],"unsupported":0,"volume":3198.694598}, "24": {"area":13432.401544,"bodies":1,"edges":86,"error":null,"faces":35,"outcome":"ok","rejected":0,"shells":1,"steps":["revolved section","chamfer","hole","cut box","cut sphere","cut sphere","shell"],"unsupported":0,"volume":9985.175049}, "25": {"area":6134.243434,"bodies":1,"edges":56,"error":null,"faces":19,"outcome":"ok","rejected":0,"shells":1,"steps":["revolved section","shell"],"unsupported":0,"volume":5828.585616}, @@ -33,18 +33,18 @@ "29": {"area":6965.599057,"bodies":1,"edges":74,"error":null,"faces":30,"outcome":"ok","rejected":0,"shells":1,"steps":["extruded profile","shell","join cylinder"],"unsupported":0,"volume":3977.885339}, "30": {"area":853.525389,"bodies":1,"edges":23,"error":null,"faces":10,"outcome":"ok","rejected":0,"shells":1,"steps":["revolved section","chamfer"],"unsupported":0,"volume":1337.14821}, "31": {"area":10195.468258,"bodies":3,"edges":75,"error":null,"faces":31,"outcome":"ok","rejected":1,"shells":3,"steps":["box","cut box","fillet","join box","circular pattern","cut box","circular pattern","hole"],"unsupported":1,"volume":56416.134415}, - "32": {"area":3220.802419,"bodies":1,"edges":51,"error":null,"faces":19,"outcome":"ok","rejected":0,"shells":1,"steps":["revolved section","cut sphere","cut box","cut box","join box"],"unsupported":0,"volume":7565.955759}, + "32": {"area":3220.802776,"bodies":1,"edges":51,"error":null,"faces":19,"outcome":"ok","rejected":0,"shells":1,"steps":["revolved section","cut sphere","cut box","cut box","join box"],"unsupported":0,"volume":7565.955387}, "33": {"area":5269.06481,"bodies":2,"edges":64,"error":null,"faces":29,"outcome":"ok","rejected":0,"shells":3,"steps":["revolved section","fillet","join box","cut cylinder","join box","chamfer","fillet","fillet"],"unsupported":2,"volume":13840.242661}, "34": {"area":1086.303472,"bodies":1,"edges":30,"error":null,"faces":14,"outcome":"ok","rejected":0,"shells":1,"steps":["revolved section","cut sphere","hole"],"unsupported":0,"volume":2134.365275}, "35": {"area":4605.630216,"bodies":1,"edges":26,"error":null,"faces":11,"outcome":"ok","rejected":0,"shells":1,"steps":["box","fillet","join box"],"unsupported":0,"volume":13965.526982}, - "36": {"area":10407.941641,"bodies":1,"edges":60,"error":null,"faces":26,"outcome":"ok","rejected":0,"shells":2,"steps":["revolved section","cut cylinder","join box","fillet","join cylinder"],"unsupported":0,"volume":55728.210954}, + "36": {"area":10408.82575,"bodies":1,"edges":60,"error":null,"faces":26,"outcome":"ok","rejected":0,"shells":2,"steps":["revolved section","cut cylinder","join box","fillet","join cylinder"],"unsupported":0,"volume":55729.313461}, "37": {"area":11714.822253,"bodies":1,"edges":44,"error":null,"faces":18,"outcome":"ok","rejected":0,"shells":1,"steps":["box","cut cylinder","join cylinder","cut sphere","circular pattern","fillet","circular pattern","rectangular pattern"],"unsupported":3,"volume":75556.602064}, "38": {"area":11769.375817,"bodies":1,"edges":44,"error":"offset: a corner whose faces don't meet the same way after t","faces":12,"outcome":"failed","rejected":1,"shells":1,"steps":["box","hole","cut cylinder","shell"],"unsupported":0,"volume":78261.020973}, "39": {"area":1892.050815,"bodies":1,"edges":27,"error":null,"faces":11,"outcome":"ok","rejected":0,"shells":1,"steps":["extruded profile","chamfer","cut sphere","rectangular pattern"],"unsupported":1,"volume":4040.62787}, "40": {"area":15548.516183,"bodies":1,"edges":49,"error":"offset: a corner whose faces don't meet the same way after t","faces":22,"outcome":"failed","rejected":0,"shells":1,"steps":["extruded profile","cut cylinder","shell","cut cylinder","join cylinder","shell"],"unsupported":0,"volume":16543.777645}, "41": {"area":7611.393446,"bodies":1,"edges":99,"error":null,"faces":35,"outcome":"ok","rejected":0,"shells":1,"steps":["box","cut sphere","shell","fillet","cut cylinder","rectangular pattern","cut sphere","join cylinder"],"unsupported":2,"volume":5973.93328}, "42": {"area":5486.881252,"bodies":1,"edges":45,"error":null,"faces":17,"outcome":"ok","rejected":0,"shells":1,"steps":["extruded profile","cut box","cut cylinder","rectangular pattern"],"unsupported":0,"volume":19095.110963}, - "43": {"area":2619.198567,"bodies":1,"edges":66,"error":"offset: a corner whose faces don't meet the same way after t","faces":24,"outcome":"failed","rejected":0,"shells":1,"steps":["extruded profile","cut cylinder","rectangular pattern","fillet","hole","rectangular pattern","shell"],"unsupported":2,"volume":4213.337621}, + "43": {"area":2623.031137,"bodies":1,"edges":72,"error":"boolean Union: the operation failed: no result; the operatio","faces":26,"outcome":"failed","rejected":0,"shells":1,"steps":["extruded profile","cut cylinder","rectangular pattern","fillet","hole","rectangular pattern","join cylinder"],"unsupported":3,"volume":4325.21806}, "44": {"area":7972.435565,"bodies":1,"edges":36,"error":null,"faces":15,"outcome":"ok","rejected":0,"shells":1,"steps":["extruded profile","shell","cut sphere"],"unsupported":0,"volume":7622.184369}, "45": {"area":14416.876392,"bodies":2,"edges":62,"error":"boolean Union: implausible result volume ","faces":29,"outcome":"failed","rejected":0,"shells":3,"steps":["revolved section","join cylinder","fillet","shell","cut box","join box"],"unsupported":1,"volume":14286.791174}, "46": {"area":3445.160599,"bodies":1,"edges":99,"error":null,"faces":31,"outcome":"ok","rejected":0,"shells":1,"steps":["extruded profile","join cylinder","hole","cut cylinder","rectangular pattern","cut box","cut cylinder"],"unsupported":0,"volume":6232.317431}, @@ -72,7 +72,7 @@ "68": {"area":7338.675126,"bodies":1,"edges":36,"error":null,"faces":14,"outcome":"ok","rejected":0,"shells":1,"steps":["extruded profile","hole","hole","rectangular pattern","rectangular pattern","fillet","circular pattern"],"unsupported":2,"volume":29780.742221}, "69": {"area":6451.122768,"bodies":1,"edges":132,"error":"offset: a corner whose faces don't meet the same way after t","faces":27,"outcome":"failed","rejected":0,"shells":3,"steps":["revolved section","join box","shell","shell"],"unsupported":0,"volume":4761.477514}, "70": {"area":3682.669157,"bodies":1,"edges":24,"error":"lumps: shell boundaries intersect or touch; cavity ownership","faces":12,"outcome":"failed","rejected":0,"shells":2,"steps":["extruded profile","join box","hole"],"unsupported":1,"volume":9155.027162}, - "71": {"area":3980.38113,"bodies":1,"edges":50,"error":null,"faces":19,"outcome":"ok","rejected":0,"shells":1,"steps":["revolved section","cut box","cut cylinder","hole","join cylinder"],"unsupported":0,"volume":15750.655245}, + "71": {"area":3389.533577,"bodies":1,"edges":34,"error":"boolean Union: the operation failed: no result; the operatio","faces":14,"outcome":"failed","rejected":0,"shells":1,"steps":["revolved section","cut box","cut cylinder","hole","join cylinder"],"unsupported":0,"volume":14306.661547}, "72": {"area":5770.270336,"bodies":2,"edges":46,"error":null,"faces":20,"outcome":"ok","rejected":1,"shells":2,"steps":["box","join cylinder","hole","join box","join box","cut box","cut cylinder","cut cylinder"],"unsupported":0,"volume":16081.801492}, "73": {"area":6868.162117,"bodies":1,"edges":40,"error":"offset: a corner whose faces don't meet the same way after t","faces":18,"outcome":"failed","rejected":0,"shells":1,"steps":["extruded profile","join box","shell"],"unsupported":1,"volume":36461.939381}, "74": {"area":9294.57311,"bodies":1,"edges":22,"error":null,"faces":9,"outcome":"ok","rejected":0,"shells":1,"steps":["box","hole"],"unsupported":0,"volume":55866.183074}, @@ -95,13 +95,14 @@ "91": {"area":4061.429312,"bodies":1,"edges":36,"error":null,"faces":14,"outcome":"ok","rejected":1,"shells":1,"steps":["revolved section","cut cylinder","chamfer"],"unsupported":2,"volume":9885.654049}, "92": {"area":2855.139226,"bodies":1,"edges":30,"error":null,"faces":12,"outcome":"ok","rejected":0,"shells":1,"steps":["revolved section","chamfer","cut sphere"],"unsupported":0,"volume":9814.303984}, "93": {"area":7266.404017,"bodies":7,"edges":115,"error":null,"faces":51,"outcome":"ok","rejected":0,"shells":7,"steps":["extruded profile","fillet","chamfer","join box","circular pattern","rectangular pattern","cut cylinder"],"unsupported":0,"volume":12734.393171}, - "94": {"area":3504.501724,"bodies":1,"edges":75,"error":null,"faces":28,"outcome":"ok","rejected":0,"shells":1,"steps":["revolved section","cut cylinder","hole","rectangular pattern","cut box","cut box","join box"],"unsupported":2,"volume":5900.747919}, + "94": {"area":3504.024629,"bodies":1,"edges":73,"error":null,"faces":27,"outcome":"ok","rejected":0,"shells":1,"steps":["revolved section","cut cylinder","hole","rectangular pattern","cut box","cut box","join box"],"unsupported":2,"volume":5899.987584}, "95": {"area":2339.366789,"bodies":1,"edges":27,"error":null,"faces":11,"outcome":"ok","rejected":0,"shells":1,"steps":["revolved section","hole","cut cylinder","cut sphere","chamfer","circular pattern"],"unsupported":1,"volume":6587.694591} }, "notes": [ {"reason":"First record: what each seed builds on main at 1a0100cd","seeds":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95]}, {"reason":"seed 0 meshes differently since display tessellation plans (#805), which landed alongside these goldens (#826)","seeds":[0]}, {"reason":"the kernel fixes merged together on 13 October (#838, #839, #841, #855, #856) change what these seeds build: several joins that used to fail now succeed, small volume and area shifts, and shell now refuses seeds 6, 14, 43 and 73 with an offset corner error (seed 14 built before: #897)","seeds":[2,6,14,22,36,43,50,63,71,73,94]}, - {"reason":"#936: a fillet or chamfer of a smooth seam is refused as an invalid pick (no corner to round) instead of as unsupported","seeds":[72]} + {"reason":"#936: a fillet or chamfer of a smooth seam is refused as an invalid pick (no corner to round) instead of as unsupported","seeds":[72]}, + {"reason":"the model's body mesh is the reference mesher's again (the display plan's since #805, which moved these seeds rather than the kernel fixes above): they build as they did before #805, and seed 14 builds again (#897)","seeds":[0,2,14,36,43,71,94]} ] }