Inside or outside
Contains tells whether a point lies in a face, for one point or for an array of points at once. Points on the boundary count as inside, unless boundary=False is given. All examples on this page use the link from Tangents, two bosses of radius 1.5 and 1 with their centers 6 apart, with a hole in each.
[1]:
import numpy as np
import planex as px
link = px.QuickSketch()
link.Circle(0, 0, 1.5, id="boss1", construction=True)
link.Circle(6, 0, 1.0, id="boss2", construction=True)
link.Line(tangent=("boss1", "boss2"), id="upper")
link.Line(tangent=("boss1", "boss2"), reverse=True, id="lower")
link.Arc("lower", "upper", congruent="boss2", id="end2")
link.Arc("upper", "lower", congruent="boss1", id="end1")
link.Circle(0, 0, 0.6, id="hole1").Circle(6, 0, 0.4, id="hole2")
face = link.Face()
Three points
The example tests three points (Figure 1). The center of the large hole is outside, and a point on the web between the bosses is inside. The far end of the small boss, at (7, 0), lies on the boundary, so it counts as inside by default and as outside with boundary=False.
[3]:
points = [(0, 0), (3, 0), (7, 0)]
print([face.Contains(p) for p in points], face.Contains((7, 0), boundary=False))
[False, True, True] False
Counting points
An array of points is tested in one call, which returns an array of booleans. The example covers the bounding box with a grid of 160 × 60 points, at the middles of its cells. The share of points inside, times the area of the box, estimates the area of the face.
[5]:
(h0, v0), (h1, v1) = face.bounding_box
h, v = np.meshgrid(np.linspace(h0, h1, 161)[:-1], np.linspace(v0, v1, 61)[:-1])
cells = np.column_stack([h.ravel() + (h1 - h0) / 320, v.ravel() + (v1 - v0) / 120])
inside = face.Contains(cells)
print("estimate", inside.mean() * (h1 - h0) * (v1 - v0), "area", face.mass)
estimate 18.519375 area 18.523573419356737