Several loops
Move lifts the pen, so one sketch can hold many loops. Face() takes all drawn edges together and decides what is material by nesting: a loop inside another loop is a hole, and a loop inside a hole is material again. The same rule applies where separately drawn loops overlap: a region inside two loops counts as a hole. Parts that overlap and should become one region are therefore drawn as separate faces and united.
[1]:
import math
import planex as px
A pipe flange gasket
The example is a gasket with an outer diameter of 150, an inner diameter of 90 and eight holes of 14 on a bolt circle of 120 (Figure 1). The first hole is drawn at 22.5°, and CircularPattern repeats it eight times around the origin. These are ten circles in one sketch, and the nesting makes nine of them holes.
[3]:
s = px.QuickSketch().Circle(75).Circle(45)
a = math.radians(22.5)
s.Circle(60 * math.cos(a), 60 * math.sin(a), 7, id="hole")
s.CircularPattern("hole", "origin", 8)
gasket = s.Face()
[5]:
print("area", gasket.mass, "exact", math.pi / 4 * (150**2 - 90**2 - 8 * 14**2))
area 10078.229232716058 exact 10078.229232716056
A dog bone
The example is a dog bone: two discs of radius 10, 40 apart, and a bar 8 wide between their centers (Figure 2a). Drawn into one sketch, the parts of the bar inside the discs lie inside two loops and become holes. The outline then falls apart into three regions, so Face() raises an error, and Shape() keeps all three (Figure 2b). As separate faces, px.Unify joins the three parts into one dog bone (Figure 2c).
[6]:
one_sketch = px.QuickSketch().Circle(10).Circle(40, 0, 10).Move((0, -4)).Rectangle(40, 8)
try:
one_sketch.Face()
except ValueError as err:
print(err)
discs = [px.Circle((0, 0), 10).Face(), px.Circle((40, 0), 10).Face()]
bar = px.QuickSketch((0, -4)).Rectangle(40, 8).Face()
bone = px.Unify([*discs, bar])
Face(): the edges bound 3 regions; Shape() keeps them all
(a) Two discs and a bar
(b) In one sketch: the overlaps are holes
(c) United
The united area is the two discs and the bar, less the two pieces of the bar inside the discs:
[8]:
inside = 4 * math.sqrt(10**2 - 4**2) + 10**2 * math.asin(8 / 20)
print("area", bone.mass, "exact", 2 * math.pi * 10**2 + 40 * 8 - 2 * inside)
area 792.6939503851675 exact 792.6939503851676
See Faces, shapes and compounds for faces of several regions, and Boolean operations for unions and differences.