Cavity
Sometimes it is useful for the holes to be 1st class objects, instead of only modelling the solid parts. For example, we could define a pipe by modelling just the solid part (an extruded ring), or we could define it as a solid cylinder with a cylindrical cavity through it.
The difference in these two approaches is important when we combine two or more shapes. If we join two pipes at right angles to form a T shape, could this be used a plumbing T joint? When we only model the solids, the answer is no, because there is nothing to say that the hole in the middle must remain when the two shapes overlap.
This is where Cavities comes into play. By making the cavities part of the models definition, then we can join the two pipes together, whilst keeping the holes, to form a working T joint.
There are examples of pipes using cavities in the Help->Examples menu of the FooCAD application.
Cavities use remove instead of Shape3d.difference (or the minus operator), and and instead of Shape3d.union (or the plus operator). For example :
val tube = Cylinder(30,10).center() remove ( Cylinder(32,9).center() )
val xJoint = tube and (tube.rotateY(90))
instead of
val tube = Cylinder(30,10).center() - Cylinder(32,9).center()
val fails = tube + tube.rotateY(90)
Note that many operations perform Shape3d.union behind the scenes (such as Transformation3d.also, as well as the functions in the Layout extension). In this case, you can use Union3d.withCavities to ensure the cavities are correctly applied. e.g.
val xJoint = tube.rotateY(90).also().withCavities()
So if cavities remain as cavities when two or more shapes are combined, how do we insert something into the cavity? Use the insert method.