Skip to main content

Module exact_bodies

Module exact_bodies 

Source
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-9 relative 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§

BodyDistance
A certified distance between two bodies and the items its witnesses lie on.
BodyHausdorff
The two-sided Hausdorff distance between the boundaries of two bodies and both one-sided ones.
BodyHausdorffBounds
A certified one-sided Hausdorff distance between two bodies and the items its witnesses lie on.
PlacedBody
A body: its items in the body’s own frame, and one rigid placement that puts them in the world (#229).

Enums§

BodyMeasureError
Why two bodies of exact solids could not be measured.
BodyPlanOverlap
Whether the plan projections of two bodies overlap, and which items show it.
BodySide
Which argument of a body query a refusal is about.

Functions§

body_boundary_clearance
body_boundary_distance refined only until it clears limit.
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_distance refined only until it clears limit.
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 of to’s, to within accuracy (#229).
one_sided_body_boundary_hausdorff_with_budget
one_sided_body_boundary_hausdorff with the caller’s cap on the splits, as crate::one_sided_boundary_hausdorff_with_budget.