--- jupyter: description: 'Places along an edge in planex2d: Measure(at=...) gives the point, tangent, normal and curvature at an arc length or nearest a point, on the exact curves. The leading edge of a NACA 0012, marks every 50 along a heater track, and the place on it nearest a sensor.' --- # 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 | |---|---| | `Measure(at=s)` | At the arc length $s$ from the start | | `Measure(at=(h, v))` | Nearest the point; of places equally near, the one with the smallest arc length | The result is a dict: - `point` and `point_hv`, the place in 3D and in the plane; - `tangent` and `tangent_hv`, the unit tangent along the direction of the chain; - `normal` and `normal_hv`, the unit normal to its left; - `curvature`, positive where the chain turns left; - `arc_length` from the start, and `distance` from 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. ```python import math import planex as px ``` ```python nbsphinx="hidden" from docs_figures import Row ``` ## 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): ```python 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) ``` ```python nbsphinx="hide-input" close = naca * px.QuickSketch((-1, -2.5)).Rectangle(6, 5).Face() Row((naca, "A NACA 0012", {"marks": [(0, 0)]}), (close, "The nose and the circle of radius r", {"dashed": [px.Circle((r, 0), r)], "marks": [(0, 0)]}), caption="The curvature at the leading edge of a NACA 0012") ``` ## 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](../sketch/offsets.md), 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: ```python 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) ``` ## 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: ```python 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"]) ``` ```python nbsphinx="hide-input" Row((track, "A mark every 50 along the track", {"fill": False, "marks": [m["point_hv"] for m in marks]}), (track, "The place nearest the sensor at (60, 12)", {"fill": False, "marks": [(60, 12), near["point_hv"]], "dashed": [px.Line((60, 12), near["point_hv"])]}), caption="Places along a heater track") ``` See [Distances and clearances](distances.md) for distances between objects, and [Parametric curves](../basics/curves.md) for curves drawn from their formula.