Expand description
Certified boundary distance and Hausdorff distance between bodies made of several exact solids (#229).
A body here is a slice of ExactBRep items, one per solid: how an IFC
body with several items arrives. A slice, not one B-rep holding several
solids, because the items are produced and placed one by one, a
witness has to say which item it lies on, and the layout check below
works item against item. (One ExactBRep with several solids is
measured by the single-B-rep queries as the union of all its faces,
with none of the checks made here.)
§Distance
body_boundary_distance is the least distance between a point on the
boundary of an item of a and a point on the boundary of an item of
b: the minimum over item pairs, found by ONE branch and bound over the
elements of every item (as crate::boundary_distance for one pair),
so a pair of items far apart gets a large lower bound at the root and is
never refined. The witnesses name the items they lie on.
Items may touch or overlap. The minimum over pairs is then still the distance between the boundaries of the two unions, except where part of one body lies wholly inside the other: a boundary point of an item that is not on the union’s boundary is interior to the union, and from a point outside the union the segment to it crosses the union’s boundary at a point no farther away. As for one pair, containment is a separate classification.
§In plan
body_plan_boundary_distance, body_plan_boundary_clearance and
body_plan_overlap measure between the bodies’ shadows on the XY
plane by the same shared search (#237, plan.rs). Items of one body may
overlap freely there, so nothing about their layout is checked.
§Hausdorff
body_boundary_hausdorff_distance and
one_sided_body_boundary_hausdorff measure the boundary of the UNION
of each body’s items. Every body is first checked, item pair by item
pair, for a layout under which that boundary can be formed exactly:
- Apart: shown by a plane with a certified positive gap between them – a direction along which the exact projection ranges of every face patch and edge span of the two are disjoint, tried along the axes and every planar face’s normal – or, failing that, by a positive certified lower bound on the distance between their boundaries together with a boundary point of each outside an enclosing box of the other. The second test needs each item to be one solid (one outer shell, voids allowed): two such solids whose boundaries do not meet are disjoint unless the outer shell of one lies inside the other, and then its box lies in the other’s box. However small the gap – an exporter’s 0.3 mm between parts – both facing faces are on the union’s boundary and are measured as such: a gap is never glued.
- Touching without a shared patch: a plane separates them to within
rounding (
1e-9relative to their size), and one of the two has no face that can hold a patch of that plane – no planar face lying in it and no B-spline face reaching it (no other family holds an open patch of a plane). Interiors are then disjoint, and a boundary point of one that is not on the union’s boundary would have a ball round it covered by the two, cut by the plane into halves, one in each: a disc of the plane on both boundaries, which one of them cannot hold. So contact along edges or at points leaves the union boundary the union of the boundaries. Planes are tried along the axes, every planar face’s normal, and the sum of any two touching ones (two blocks meeting at an edge are separated by the diagonal plane, where neither has a face). - Exact face contact: they touch on a plane where both have faces,
every such face planar and lying, in the B-rep’s own numbers, on one
plane normal to a coordinate axis (its plane, vertices, lines and
circles all at the very same coordinate along it; a placement turning
about that axis keeps this), and bounded by lines and circles. Each
face in contact is then cut down to its free region, what is left of
it once the faces of other items lying against it are cut away, by an
exact arrangement of their boundaries on the plane (
contact).
Why cutting is right: interiors are disjoint, so a point p of an
item’s face F is off the union’s boundary only if a ball round it is
covered by items. By the argument above, the half of the ball across
F’s plane is covered by other items whose faces then hold a disc of
that plane round p – faces lying against F. So the union’s boundary
is the closure of the free regions of all faces: those in no contact as
they are, and those in contact cut. Its edges are the edges of those
regions; an edge between two faces both cut away (the foot of a wall
shared by two blocks on a footing) is not on it and is dropped.
Anything else is refused by name, never glued or snapped:
BodyMeasureError::ContactPlaneNotAxisNormal when two items touch, to
within rounding, on a plane no coordinate axis is normal to (a tilted
assembly, walls turned in plan: whether they meet, clear or overlap is
below rounding there); BodyMeasureError::ItemsNearlyShareFace with
the gap when they interpenetrate by no more than the caller’s tolerance,
or their faces are on axis planes at coordinates that differ below
rounding; BodyMeasureError::ItemsShareFace
when such faces cannot be cut (a B-spline face, an elliptical edge);
and BodyMeasureError::ItemsOverlap when they were not shown apart or
touching: boundaries that cross or come closer than the search resolves
with no plane between them, one item possibly inside another, or curved
items touching (no planar face to separate them by).
Gluing near contact and widening the result by the gap is not sound: lifted 0.3 mm off its footing, a column’s base disc and the disc of the footing’s top under it are both on the union’s boundary, and their centres are a whole radius from the boundary of the body glued shut. So a gap is measured as a gap, and an interpenetration is refused.
The one-sided distance is then measured by the search of
crate::one_sided_boundary_hausdorff on the union’s boundary of each
body. Faces are matched across every pair of items, so a body moved by
a translation closes as fast as one solid does: every face patch is
held at |t| by its own translate, and the support point of each item
against t seeds the lower bound. A free region is bounded through the
face it was cut from, so an exact cut that falls out differently in the
last bit for a translated copy (a sliver along a wall turned in plan)
still closes at once (exact_hausdorff/cut.rs).
§Placed bodies
Every query takes each side as a PlacedBody: the items in the
body’s own frame and one rigid placement. An IFC body’s extruded items
stand on axis-normal planes in the body’s frame however the body is
placed in the world, so contact is found and cut there, and the
placement then moves the cut boundary (and the items it was cut from)
before anything is measured: witnesses are in the world. A placement
cannot change what is measured, a rigid motion carrying the union’s
boundary onto the placed union’s. Items turned against each other in
the body’s own frame still touch on planes no axis is normal to and are
refused as BodyMeasureError::ContactPlaneNotAxisNormal; a slice of
items converts to a placed body with the identity placement.
Structs§
- Body
Distance - A certified distance between two bodies and the items its witnesses lie on.
- Body
Hausdorff - The two-sided Hausdorff distance between the boundaries of two bodies and both one-sided ones.
- Body
Hausdorff Bounds - A certified one-sided Hausdorff distance between two bodies and the items its witnesses lie on.
- Placed
Body - A body: its items in the body’s own frame, and one rigid placement that puts them in the world (#229).
Enums§
- Body
Measure Error - Why two bodies of exact solids could not be measured.
- Body
Plan Overlap - Whether the plan projections of two bodies overlap, and which items show it.
- Body
Side - Which argument of a body query a refusal is about.
Functions§
- body_
boundary_ clearance body_boundary_distancerefined only until it clearslimit.- body_
boundary_ distance - Distance between the boundaries of two bodies of exact solids, to within
accuracy(#229): the least over item pairs, by one shared search. - body_
boundary_ hausdorff_ distance - Two-sided Hausdorff distance between the boundaries of the unions of two
bodies’ items, to within
accuracy(#229). - body_
plan_ boundary_ clearance body_plan_boundary_distancerefined only until it clearslimit.- body_
plan_ boundary_ distance - Plan distance between two bodies of exact solids – between their
shadows on the XY plane – to within
accuracy(#237): the least over item pairs, by one shared search. - body_
plan_ overlap - Whether the plan projections of two bodies overlap over a patch of positive area – an item of one over an item of the other – are certainly apart, or neither could be shown (#237).
- one_
sided_ body_ boundary_ hausdorff - One-sided Hausdorff distance from the boundary of the union of
from’s items to that ofto’s, to withinaccuracy(#229). - one_
sided_ body_ boundary_ hausdorff_ with_ budget one_sided_body_boundary_hausdorffwith the caller’s cap on the splits, ascrate::one_sided_boundary_hausdorff_with_budget.