Measuring
The measuring methods compute the shape first (see
When geometry is computed) and answer
in millimetres: mm² for areas, mm³ for volumes, grams for masses. The B-Rep engine can’t measure
yet: every method here except a Path’s is a NotImplementedError for a B-Rep part (see
Engine settings).
| Method | Solid | Sketch | Path | Assembly | Returns |
|---|---|---|---|---|---|
bbox |
✓ | ✓ | ✓ | ✓ | BoundingBox |
volume |
✓ | Number | |||
surface_area |
✓ | Number | |||
area |
✓ | Number | |||
genus |
✓ | Number | |||
center_of_mass |
✓ | [x, y, z] |
|||
mass |
✓ | ✓ | Number | ||
intersects? |
✓ | Boolean | |||
min_gap |
✓ | Number | |||
contains? |
✓ | ✓ | Boolean | ||
ray_cast |
✓ | Array of Maps | |||
empty? |
✓ | ✓ | Boolean |
A Path’s length, start and end are on the Paths
page.
shape.bboxThe shape’s axis-aligned bounding box. A Sketch’s and a Path’s have z 0. An Assembly’s holds all its parts that have one.
An empty shape has no box: its bbox is nil, and so is an Assembly’s when none of its parts
has one.
Returns: BoundingBox, or nil.
box = cube(x: 50, y: 30, z: 20).bboxputs box.size.inspect # [50, 30, 20]puts box.center.inspect # [25, 15, 10]puts box.x_max # 50BoundingBox
Section titled “BoundingBox”A BoundingBox answers its corners, centre and size as [x, y, z] Arrays, and each axis’s
part of them as a Number.
| Method | Returns |
|---|---|
min, max |
The low and high corners, [x, y, z]. |
center |
The centre, [x, y, z]. |
size |
The extent along each axis, [x, y, z]; never negative. |
x_min, y_min, z_min |
One axis of min. |
x_max, y_max, z_max |
One axis of max. |
x_size, y_size, z_size |
One axis of size. |
to_s, inspect |
BoundingBox(min: [0, 0, 0], max: [50, 30, 20], size: [50, 30, 20]) |
volume
Section titled “volume”solid.volumeThe volume the solid encloses, in mm³.
Returns: Number.
puts cube(x: 50, y: 30, z: 20).volume # 30000surface_area
Section titled “surface_area”solid.surface_areaThe area of the solid’s surface, in mm².
Returns: Number.
puts cube(x: 50, y: 30, z: 20).surface_area # 6200sketch.areaHow much the sketch encloses, holes left out, in mm².
Returns: Number.
puts (square(10) - square(4).translate(3, 3)).area # 84solid.genusThe number of holes through the solid: 0 for a cube, 1 for a ring.
Returns: Number.
puts cube(10).genus # 0puts (cube(10) - cylinder(r: 2, h: 30).translate(5, 5, -1)).genus # 1center_of_mass
Section titled “center_of_mass”solid.center_of_massThe centroid of the solid’s volume, [x, y, z]: where it balances at a uniform density.
Returns: Array.
Raises: ValueError for an empty solid.
puts cube(x: 50, y: 30, z: 20).center_of_mass.inspect # [25, 15, 10]solid.massassembly.massThe mass in grams: the volume times the density: of the solid’s
material, in g/cm³. An Assembly’s mass is that of
every Solid in it, its sub-assemblies’ too. A union has no material of its own, so assemble
parts of different materials to weigh them.
Returns: Number.
Raises: ValueError naming the part when a Solid has no density.
steel = cube(10).material(density: 7.85)puts steel.mass # 7.85intersects?
Section titled “intersects?”solid.intersects?(other)Whether the two solids overlap by more than the tolerance cubed. Solids that only touch, face on face, don’t.
Returns: Boolean.
Raises: TypeError when other isn’t a Solid.
box = cube(10)puts box.intersects?(cube(5).translate(8, 0, 0)) # trueputs box.intersects?(cube(5).translate(10, 0, 0)) # falsemin_gap
Section titled “min_gap”solid.min_gap(other)solid.min_gap(other, search_length)The shortest distance between two solids, however far apart. With search_length, it looks only
that far, which costs less: a wider gap answers search_length. 0 when they touch or overlap,
Infinity when either is empty.
| Parameter | Type | Default | Description |
|---|---|---|---|
other |
Solid | — | The solid to measure to. |
search_length |
Number | — | The farthest to look, greater than 0. |
Returns: Number.
box = cube(10)puts box.min_gap(cube(5).translate(20, 0, 0)) # 10puts box.min_gap(cube(5).translate(50, 0, 0), 5) # 5contains?
Section titled “contains?”solid.contains?([x, y, z])sketch.contains?([x, y])Whether the point is inside the shape. A point within the
tolerance of the surface or outline counts as
inside. A Sketch’s holes don’t contain; it takes [x, y] or [x, y, z], and a point off the
z = 0 plane is never inside.
Returns: Boolean.
box = cube(10)puts box.contains?([5, 5, 5]) # trueputs box.contains?([0, 0, 0]) # true: on the surfaceputs box.contains?([15, 5, 5]) # falseputs square(10).contains?([5, 5]) # trueray_cast
Section titled “ray_cast”solid.ray_cast(origin, end)Where the segment from origin to end (each [x, y, z]) meets the solid’s surface, nearest
origin first. Each hit is a Map with String keys:
| Key | Value |
|---|---|
"distance" |
From origin, in mm. |
"position" |
Where it meets the surface, [x, y, z]. |
"normal" |
The face’s outward normal, [x, y, z]. |
"crossing" |
1 where the ray goes into the solid, -1 where it comes out. |
A ray that only grazes an edge or a corner meets it as a 1 and a -1 at the same distance,
which cancel. To measure how much material lies along a ray, sum by crossings rather than count
hits.
Returns: Array of Maps.
box = cube(x: 50, y: 30, z: 20)hits = box.ray_cast([10, 10, 100], [10, 10, -100])puts hits[0]["position"].inspect # [10, 10, 20]puts hits.map { |h| -h["crossing"] * h["distance"] }.sum # 20: the thickness along the rayempty?
Section titled “empty?”shape.empty?Whether a Solid has no volume, or a Sketch no area. See Empty shapes.
Returns: Boolean.