Skip to main content

model_scale

Function model_scale 

Source
pub fn model_scale(points: impl IntoIterator<Item = Vec3>) -> f64
Expand description

The kernel’s single definition of a model’s characteristic length: the bounding-box diagonal of a point set.

Two properties define it, and both are load-bearing:

  • Size-based. It answers “how big is this geometry?”, which is the only question a size-relative tolerance may ask. Note what “this” means: the answer is the extent of the point set handed in, so the caller chooses the scope by choosing the points. A local solve should pass its own local geometry (see curve_model_scale) rather than the whole solid’s vertices, or a 2 mm feature inherits a 2 m frame’s band.
  • Translation-invariant. Moving the geometry rigidly does not change it, so the identical feature solves to the identical tolerance wherever the modeller happened to place it.

§Why the origin-distance form is wrong

The tempting one-liner points.map(|p| p.length()).fold(1.0, f64::max) — the maximum distance from the world origin — satisfies neither property:

  • It grows with placement. A 10 mm part at the origin gets scale ≈ 10; the same part translated to (5000, 0, 0) gets scale ≈ 5000. Every tolerance derived from it loosens by 500× for a part that did not change shape, so coincidence, weld and convergence bands silently absorb real geometric error the moment a part is placed away from the origin.
  • It ignores size. Two parts whose bounding boxes differ by three orders of magnitude get the same scale if they sit the same distance out.
  • It is translation-VARIANT, so results are not reproducible under a rigid move: the same fillet at the origin and translated far away produced different volumes, and eventually a broken result. [merge_scale] records that exact failure for the imprint vertex-merge band, which was fixed the same way.

§Degenerate input

An empty set, a single point, coincident points, or non-finite coordinates all return 1.0: there is no meaningful extent to scale by, and a zero (or NaN, or infinite) scale would collapse or explode every derived band.

§Floors are the caller’s business

model_scale returns the RAW diagonal for any well-formed input — it is not floored at 1.0. Sub-unit parts are real (see KernelTolerances::pcurve_acceptance’s ABC 00000041 case) and flooring would hand a 0.3 mm part a band larger than itself. Sites that want the historical >= 1.0 floor take solid_scale, which applies it explicitly.