Along an edge
Measure(at=...) finds a place along an edge, a wire, a selection of edges, or a sketch element or chain, and returns what the geometry is like there. The place is given in one of two ways:
Call |
The place |
|---|---|
|
At the arc length \(s\) from the start |
|
Nearest the point; of places equally near, the one with the smallest arc length |
The result is a dict:
pointandpoint_hv, the place in 3D and in the plane;tangentandtangent_hv, the unit tangent along the direction of the chain;normalandnormal_hv, the unit normal to its left;curvature, positive where the chain turns left;arc_lengthfrom the start, anddistancefrom the point given, 0 for an arc length;edge, the edge the place lies on.
Everything is taken on the exact curves, splines included. wire.Reverse() runs a wire the other way, in place, and wire.Reversed() returns a reversed copy, so the arc length can count from either end.
[1]:
import math
import planex as px
The leading edge of an airfoil
The leading edge of a NACA four-digit airfoil is round. Near the nose, the half thickness grows as \(5t \cdot 0.2969\,\sqrt{x c}\) for a thickness \(t\) as a fraction of the chord \(c\), so the nose is a circle of radius \(r = (5t \cdot 0.2969)^2\,c/2\). The example is a NACA 0012 with a chord of 100. FromNACA draws its profile from the formula, and the curvature measured at the nose is \(1/r\) (Figure 1):
[3]:
naca = px.FromNACA("0012", chord=100)
nose = naca.outer.Measure(at=(0, 0))
r = (5 * 0.12 * 0.2969) ** 2 * 100 / 2
print("nose", nose["point_hv"], "tangent", nose["tangent_hv"])
print("curvature", nose["curvature"], "1/r", 1 / r)
nose (0.0, 0.0) tangent (0.0, -1.0)
curvature 0.6302416488916462 1/r 0.6302416488916464
(a) A NACA 0012
(b) The nose and the circle of radius r
Marks along a path
A place at a given arc length puts marks along a path. The example is the meander heater track from Offsets, six runs of 40 joined by half circles of radius 3, with a mark every 50 along its center line for a row of temperature sensors (Figure 2a). Each mark lies on the path, at the arc length asked for:
[5]:
s = px.QuickSketch()
for k in range(5):
s.Line(40).Arc(3, 180 if k % 2 == 0 else -180)
s.Line(40)
track = s.Wire()
marks = [track.Measure(at=d) for d in range(0, 288, 50)]
for mark in marks:
print("at", mark["arc_length"], "point", mark["point_hv"], "off the path", track.Distance(mark["point_hv"]))
print("length", track.mass, "exact", 6 * 40 + 5 * math.pi * 3)
at 0.0 point (0.0, 0.0) off the path 0.0
at 50.0 point (39.424777960769376, 6.0) off the path 0.0
at 100.0 point (1.1504440784612484, 12.0) off the path 0.0
at 150.0 point (38.27433388230813, 18.0) off the path 0.0
at 200.0 point (2.300888156922497, 24.0) off the path 0.0
at 250.0 point (37.12388980384688, 30.0) off the path 0.0
length 287.12388980384685 exact 287.1238898038469
The place nearest a point
A point gives the place nearest it. The example is a sensor at (60, 12), beside the track. The nearest place lies as far away as Distance measures, and its arc length says how far along the track it is (Figure 2b). On the reversed track, the arc length counts from the other end:
[6]:
near = track.Measure(at=(60, 12))
print("nearest", near["point_hv"], "distance", near["distance"], "Distance", track.Distance((60, 12)))
print("arc length", near["arc_length"], "normal", near["normal_hv"])
back = track.Reversed().Measure(at=(60, 12))
print("from the other end", back["arc_length"], "exact", track.mass - near["arc_length"])
nearest (42.966809058604895, 14.554978641209265) distance 17.22374841615668 Distance 17.22374841615668
arc length 143.11527505909496 normal (-0.9889363528682975, 0.14834045293024475)
from the other end 144.00861474475192 exact 144.0086147447519
(a) A mark every 50 along the track
(b) The place nearest the sensor at (60, 12)
See Distances and clearances for distances between objects, and Parametric curves for curves drawn from their formula.