Geometry¶
sewpat.geometry
¶
2D geometry primitives for sewing pattern generation.
This package re-exports everything from the sub-modules so that all existing
imports like from sewpat.geometry import Point continue to work unchanged.
Point(x: float, y: float, name: str | None = None)
dataclass
¶
An immutable 2-D point (and displacement vector).
Internally the coordinates are stored as a length-2 NumPy array so that
vector arithmetic (+, -, scalar *) works naturally between
:class:Point instances.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
float
|
X coordinate in mm. |
required |
y
|
float
|
Y coordinate in mm. |
required |
name
|
str | None
|
Optional label, used in string representations and debugging. |
None
|
Example
a = Point(3, 0) b = Point(0, 4) (a - b).distance_to(Point(0, 0)) 5.0
Initialise with coordinates x, y and optional name.
x: float
property
¶
X coordinate in mm.
y: float
property
¶
Y coordinate in mm.
__add__(other: Point) -> Point
¶
Return self + other as a new :class:Point (vector addition).
__eq__(other: object) -> bool
¶
Return True when both coordinates and name match exactly.
Note
For approximate spatial equality use :meth:distance_to with a
tolerance instead.
__hash__() -> int
¶
Hash based on coordinates rounded to 9 decimal places and name.
__mul__(scalar: float) -> Point
¶
Return self * scalar (uniform scaling of the position vector).
__neg__() -> Point
¶
Return the negated point (-x, -y).
__rmul__(scalar: float) -> Point
¶
Return scalar * self (reflected scalar multiplication).
__str__() -> str
¶
Return a human-readable string representation.
__sub__(other: Point) -> Point
¶
Return self - other as a new :class:Point (vector subtraction).
distance_to(other: Point | np.ndarray) -> float
¶
Return the Euclidean distance to other.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
other
|
Point | ndarray
|
Another :class: |
required |
Returns:
| Type | Description |
|---|---|
float
|
Distance in mm as a :class: |
distance_to_segment(seg: Segment) -> float
¶
Return the shortest distance from this point to seg.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
seg
|
Segment
|
The segment to measure against. |
required |
Returns:
| Type | Description |
|---|---|
float
|
Distance in mm; zero when the point lies exactly on the segment. |
rotate(center: Point, angle_rad: float) -> Point
¶
Return a copy rotated counter-clockwise by angle_rad around center.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
center
|
Point
|
The pivot point. |
required |
angle_rad
|
float
|
Rotation angle in radians (positive = counter-clockwise). |
required |
Returns:
| Type | Description |
|---|---|
Point
|
A new :class: |
Segment(p1: Point, p2: Point, name: str | None = None)
¶
Bases: _LinearGeom
A line segment from p1 to p2.
Initialise from endpoints p1 and p2 with optional name.
direction_unnormalized: np.ndarray
property
¶
Direction vector (not normalised).
end: Point
property
¶
End point of the segment (alias for p2).
length: float
property
¶
Euclidean length.
midpoint: Point
property
¶
Midpoint of the segment.
start: Point
property
¶
Start point of the segment (alias for p1).
unit_direction: np.ndarray
property
¶
Normalised direction vector.
__repr__() -> str
¶
Return the same as __str__.
__str__() -> str
¶
Return a human-readable string representation.
bounding_box() -> tuple[Point, Point]
¶
Return the axis-aligned bounding box as (min_point, max_point).
contains_point(point: Point, tolerance: float = 1e-09) -> bool
¶
Return True if point lies on the segment within tolerance mm.
from_direction(start: Point, through: Point, length: float, name: str | None = None) -> Segment
classmethod
¶
Create a segment starting at start, pointing towards through, with given length.
offset(distance: float, center: Point | None = None) -> Segment
¶
Return a new Segment offset perpendicularly by distance mm.
point_along_from(point: Point, arc_length: float) -> Point
¶
Return the point arc_length mm further along this segment from point.
Raises ValueError if the result falls outside the segment bounds.
point_at_length(arc_length: float) -> Point
¶
Return the point at arc_length mm from p1; raises ValueError if out of range.
point_at_t(t: float) -> Point
¶
Return the point at parameter t ∈ [0, 1] (0 = p1, 1 = p2).
point_perpendicular(distance: float, arc_length: float | None = None, t: float | None = None) -> Point
¶
Return a point offset perpendicularly from the segment.
set_name(name: str) -> Segment
¶
Set the name of this segment and return self for fluent chaining.
split(t: float) -> tuple[Segment, Segment]
¶
Split at parameter t ∈ (0, 1) and return (left, right).
split_at_points(points: list[Point], tolerance: float = 0.5) -> list[Segment]
¶
Split at a list of points that lie on this segment.
translate(dx: float, dy: float) -> Segment
¶
Return a copy translated by (dx, dy).
Ray(origin: Point, direction: tuple[float, float] | list[float] | np.ndarray, name: str | None = None)
¶
Bases: _LinearGeom
A ray starting from a point and going in a specific direction.
Initialize a ray with an origin point and direction vector.
__str__() -> str
¶
Return a human-readable string representation.
contains_point(point: Point, tolerance: float = 1e-09) -> bool
¶
Return True if point lies on the ray within tolerance mm.
A point behind the origin (negative projection) is never on the ray.
translate(dx: float, dy: float) -> Ray
¶
Return a copy translated by (dx, dy).
Line(point: Point, direction: tuple[float, float] | list[float] | np.ndarray, name: str | None = None)
¶
Bases: _LinearGeom
An infinite line going in a specific direction.
Initialize a line with a point and direction vector.
Circle(center: Point, radius: float, name: str | None = None)
¶
A circle defined by a center point and radius.
Initialize a circle with center point and radius.
area: float
property
¶
Area of the circle.
circumference: float
property
¶
Circumference of the circle.
diameter: float
property
¶
Diameter of the circle.
length: float
property
¶
Circumference of the circle: 2 * π * radius.
Alias for :attr:circumference so that :class:Circle participates
uniformly in :meth:~sewpat.pattern.PatternPart.seam_length.
__str__() -> str
¶
Return a human-readable string representation.
contains_point(point: Point, tolerance: float = 1e-14) -> bool
¶
Return True if point lies on the circle boundary within tolerance.
contains_point_inside(point: Point, include_boundary: bool = True) -> bool
¶
Return True if point is inside (or on) the circle.
point_along_from(point: Point, arc_length: float) -> Point
¶
Return the point arc_length mm further along this circle from point (CCW).
point_at_angle(angle_rad: float) -> Point
¶
Return the point on the circle at the given angle (radians, CCW from +x).
set_name(name: str) -> Circle
¶
Set the name of this circle and return self for fluent chaining.
translate(dx: float, dy: float) -> Circle
¶
Return a copy translated by (dx, dy).
Rect(origin: Point, width: float, height: float, name: str | None = None)
¶
An axis-aligned rectangle defined by its top-left corner, width and height.
Initialise from top-left origin, width, height, and optional name.
length: float
property
¶
Perimeter of the rectangle: 2 * (width + height).
__repr__() -> str
¶
Return an unambiguous string representation.
__str__() -> str
¶
Return a human-readable string representation.
set_name(name: str) -> Rect
¶
Set the name of this rectangle and return self for fluent chaining.
translate(dx: float, dy: float) -> Rect
¶
Return a copy translated by (dx, dy).
Triangle(p1: Point, p2: Point, p3: Point, name: str | None = None)
¶
A triangle defined by three points.
Initialise from three vertices p1, p2, p3 and optional name.
base_midpoint: Point
property
¶
Midpoint of the base edge (p1 ↔ p2).
length: float
property
¶
Perimeter of the triangle: sum of the three side lengths.
__repr__() -> str
¶
Return the same as __str__.
__str__() -> str
¶
Return a human-readable string representation.
set_name(name: str) -> Triangle
¶
Set the name of this triangle and return self for fluent chaining.
translate(dx: float, dy: float) -> Triangle
¶
Return a copy translated by (dx, dy).
CubicBezier(p0: Point, p1: Point, p2: Point, p3: Point, name: str | None = None)
¶
A 2-D cubic Bézier curve defined by four control points.
The curve is parameterised by t ∈ [0, 1] using the standard cubic Bernstein basis::
B(t) = (1-t)³·p0 + 3(1-t)²t·p1 + 3(1-t)t²·p2 + t³·p3
p0 and p3 are the on-curve endpoints; p1 and p2 are the
off-curve control points that pull the curve without lying on it.
Attributes:
| Name | Type | Description |
|---|---|---|
p0 |
Start point (on-curve, |
|
p1 |
First control point (off-curve). |
|
p2 |
Second control point (off-curve). |
|
p3 |
End point (on-curve, |
|
name |
Optional human-readable label. Preserved through |
Initialise a cubic Bézier from four control points.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
p0
|
Point
|
Start point of the curve ( |
required |
p1
|
Point
|
First off-curve control point. |
required |
p2
|
Point
|
Second off-curve control point. |
required |
p3
|
Point
|
End point of the curve ( |
required |
name
|
str | None
|
Optional label used in string representations and debugging. |
None
|
end: Point
property
¶
On-curve end point; alias for :attr:p3.
length: float
property
¶
Arc length in mm, computed via Gauss-Legendre quadrature (svgpathtools).
start: Point
property
¶
On-curve start point; alias for :attr:p0.
__repr__() -> str
¶
Return the same string as :meth:__str__.
__str__() -> str
¶
Return a human-readable representation including all four control points.
bounding_box() -> tuple[Point, Point]
¶
Return the tight axis-aligned bounding box of the curve.
Delegates to svgpathtools.CubicBezier.bbox(), which finds the
exact extrema by solving B'(t) = 0 analytically. The result reflects
the actual curve extent, not the convex hull of the control points.
Returns:
| Type | Description |
|---|---|
Point
|
|
Point
|
|
contains_point(point: Point, tolerance: float = 0.01) -> bool
¶
Return True if point is within tolerance mm of the curve.
The check is approximate: the curve is discretised into 64 segments and the Shapely distance to the resulting polyline is tested. Points very close to the true curve but between sample locations may read as outside when tolerance is very tight.
normal_at_t(t: float) -> np.ndarray
¶
Return the unit normal vector at parameter t.
The normal is rotated 90° counter-clockwise from the tangent, i.e. it points left of the direction of travel.
Falls back gracefully when the tangent is degenerate (zero-length derivative):
- Try
svg.normal(t)directly. - If that raises
ValueError, nudge t by ±1e-4 toward the nearer interior and retry. - If still degenerate, use a finite-difference approximation over a ±1e-4 window.
Returns:
| Type | Description |
|---|---|
ndarray
|
A length-2 NumPy array |
offset(distance: float, center: Point | None = None, hausdorff_limit: float = 1.5) -> CubicBezier
¶
Return a single-Bézier approximation of the parallel offset curve.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
distance
|
float
|
Signed offset in mm. Positive moves left of travel. |
required |
center
|
Point | None
|
When given, the sign of distance is overridden so the offset moves away from center. |
None
|
hausdorff_limit
|
float
|
Quality threshold as a multiple of
|
1.5
|
Delegates to :func:~sewpat.geometry._bezier_offset.bezier_offset.
offset_adaptive(distance: float, center: Point | None = None, eps: float = 0.1, _depth: int = 0, _max_depth: int = 8) -> list[CubicBezier]
¶
Return the offset as a list of Béziers with Hausdorff error < eps mm.
The curve is recursively bisected at t=0.5 until every segment's
hodograph approximation is within eps mm of the true parallel offset,
or the recursion reaches _max_depth levels (default 8, giving at most
256 output segments).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
distance
|
float
|
Signed offset in mm. Positive moves left of travel. |
required |
center
|
Point | None
|
When given, determines the sign of distance (see
:meth: |
None
|
eps
|
float
|
Maximum allowed Hausdorff error per segment in mm. |
0.1
|
_depth
|
int
|
Current recursion depth — do not set manually. |
0
|
_max_depth
|
int
|
Hard recursion cap — do not set manually. |
8
|
Returns:
| Type | Description |
|---|---|
list[CubicBezier]
|
An ordered list of :class: |
list[CubicBezier]
|
approximates the true parallel offset within eps mm. |
Delegates to :func:~sewpat.geometry._bezier_offset.bezier_offset_adaptive.
offset_error(distance: float, center: Point | None = None) -> float
¶
Return the Hausdorff error (mm) between the hodograph approximation and the true offset.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
distance
|
float
|
Signed offset in mm. |
required |
center
|
Point | None
|
When given, determines the sign of distance (see
:meth: |
None
|
Returns:
| Type | Description |
|---|---|
float
|
Non-negative Hausdorff error in mm. |
Delegates to :func:~sewpat.geometry._bezier_offset.bezier_offset_error.
point_along_from(point: Point, arc_length: float) -> Point
¶
Return the point arc_length mm further along the curve from point.
point is snapped to the nearest location on the curve via
:func:_bezier_closest_t, so it need not lie exactly on the curve.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
point
|
Point
|
Reference location on (or near) the curve. |
required |
arc_length
|
float
|
Additional distance to travel in mm. May be negative to travel backwards. |
required |
point_at_length(arc_length: float) -> Point
¶
Return the point at arc_length mm from :attr:p0 along the curve.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
arc_length
|
float
|
Distance in mm, measured along the curve. Must satisfy
|
required |
Returns:
| Name | Type | Description |
|---|---|---|
The |
Point
|
class: |
Raises:
| Type | Description |
|---|---|
ValueError
|
If arc_length is negative or exceeds the total curve length (a 1 nm tolerance is allowed for floating-point noise). |
point_at_t(t: float) -> Point
¶
Evaluate the curve at parameter t ∈ [0, 1].
Computed directly from the Bernstein basis — no library call.
t=0 returns :attr:p0; t=1 returns :attr:p3.
point_perpendicular(distance: float, t: float) -> Point
¶
Return a point offset perpendicularly from the curve at parameter t.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
distance
|
float
|
Offset in mm. Positive moves left of travel (the counter-clockwise normal direction); negative moves right. |
required |
t
|
float
|
Curve parameter ∈ [0, 1] at which to apply the offset. |
required |
set_name(name: str) -> CubicBezier
¶
Set :attr:name and return self for fluent chaining.
split(t: float) -> tuple[CubicBezier, CubicBezier]
¶
Split the curve at t ∈ (0, 1) and return (left, right).
Uses de Casteljau subdivision (delegated to svgpathtools). Both
sub-curves inherit :attr:name from this curve.
split_at_points(points: list[Point], tolerance: float = 0.5) -> list[CubicBezier]
¶
Split the curve at each point in points and return the sub-curves in order.
Each point is projected onto the curve via :func:_bezier_closest_t.
Points that project within tolerance mm of either endpoint are treated
as outside the curve interior and ignored. Duplicate projections (two
points mapping to the same t) are deduplicated by the sort; only one
split is performed at each unique t.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
points
|
list[Point]
|
Points that lie on (or very near) the curve. |
required |
tolerance
|
float
|
Points whose projected t falls within
|
0.5
|
Returns:
| Type | Description |
|---|---|
list[CubicBezier]
|
An ordered list of sub-curves. Returns |
list[CubicBezier]
|
points is empty or all points fall outside the interior. |
tangent_at_t(t: float) -> np.ndarray
¶
Return the (unnormalised) tangent vector B'(t) at parameter t.
The vector points in the direction of travel and has magnitude
proportional to the curve speed at t. Use :meth:normal_at_t for
the perpendicular unit vector.
Returns:
| Type | Description |
|---|---|
ndarray
|
A length-2 NumPy array |
translate(dx: float, dy: float) -> CubicBezier
¶
Return a copy of this curve shifted by (dx, dy) mm.
All four control points are translated; :attr:name is preserved.
Dart(leg_a: Point, leg_b: Point, center: Point, tip: Point, dart_type: DartType | str = DartType.TRIANGLE, name: str | None = None, second_tip: Point | None = None, stitch_curve_a: Segment | CubicBezier | None = None, stitch_curve_b: Segment | CubicBezier | None = None, _edge_element: object | None = None)
¶
Immutable dart (Abnäher) geometry.
Defined by four key points: leg_a, leg_b (mouth endpoints), center (mouth midpoint, base of the fold line) and tip (apex). All secondary geometry is derived as properties.
For rhombus darts a second_tip may be supplied explicitly; when omitted
it defaults to mirror_tip (reflection of tip across the mouth line).
Curved stitching legs (stitch_curve_a, stitch_curve_b) replace the straight stitch lines when set. Both run tip → leg so direction is always consistent with straight legs.
Use the factory class methods (or the equivalent module-level
dart_from_* functions) for the common construction cases rather than
supplying all four points by hand.
Initialise a dart from its four key points and optional metadata.
depth: float
property
¶
Depth in mm (mouth center → tip).
effective_second_tip: Point
property
¶
Second apex for rhombus darts: second_tip if set, else mirror_tip.
fold_line: Segment
property
¶
Full fold/crease line.
-
Triangle dart — runs
center → tip(from the mouth base to the apex).fold_line.unit_directionpoints towards the tip and is used as the reference direction for dart transfer and rotation. -
Rhombus dart — runs
tip → effective_second_tip, spanning the full axis of the diamond from one apex to the other.
Note: :attr:roof (triangle only) is a derived point on the
infinite extension of the center → tip segment.
intake_angle: float
property
¶
Full intake angle in radians (leg_a–tip–leg_b).
Computed as twice the arctangent of half-width over depth::
intake_angle = 2 * atan2(width / 2, depth)
Handles depth = 0 (flat dart) gracefully — returns π rather
than raising :exc:ZeroDivisionError.
intake_angle_deg: float
property
¶
Full intake angle in degrees (leg_a–tip–leg_b).
Equivalent to math.degrees(self.intake_angle).
is_triangle: bool
property
¶
True for a seam-edge triangle dart.
mirror_tip: Point
property
¶
Tip reflected across the mouth line — default second apex for rhombus darts.
roof: Point
property
¶
Abnäherdach peak — corrected seam point on the fold line.
The roof accounts for the fabric tuck: when the dart is folded and
stitched, the seam at center must be shifted outward (away from
the tip) by roof_height so that the finished edge lies flat.
It is computed as::
roof_height = tan(intake_angle) * (width / 2)
roof = center - fold_direction * roof_height
where fold_direction points from center toward tip, so
subtracting it moves the roof past center in the outward direction.
The roof therefore lies on the infinite extension of the fold line on
the far side of center from tip for typical darts, but its
exact position depends on the dart's proportions and edge curvature:
- For typical darts it lies beyond
center(outward past the seam). - For very wide or shallow darts
roof_heightcan become very large. - On curved edges the normal may not point directly away from the mouth,
so
tipitself can be offset, shifting whererooffalls.
stitch_line_a: Segment | CubicBezier
property
¶
Stitch line from tip to leg_a.
Returns :attr:stitch_curve_a if set, otherwise a straight
:class:Segment from tip to leg_a.
stitch_line_b: Segment | CubicBezier
property
¶
Stitch line from tip to leg_b.
Returns :attr:stitch_curve_b if set, otherwise a straight
:class:Segment from tip to leg_b.
width: float
property
¶
Mouth opening width in mm (leg_a → leg_b).
__eq__(other: object) -> bool
¶
Value-based equality on all seven defining fields.
Fields compared: leg_a, leg_b, center, tip,
dart_type, name, second_tip.
__hash__() -> int
¶
Hash based on tip coordinates, width and depth.
__repr__() -> str
¶
Return an unambiguous string representation.
from_edge_at_legs(edge: object, leg_a: Point, leg_b: Point, tip: Point, dart_type: DartType | str = DartType.TRIANGLE, name: str | None = None) -> Dart
classmethod
¶
Place a dart on edge with explicit leg points.
Delegates to :func:dart_from_edge_at_legs.
from_edge_at_point(edge: object, point: Point, width: float, depth: float, dart_type: DartType | str = DartType.TRIANGLE, name: str | None = None) -> Dart
classmethod
¶
Place a dart orthogonally on edge nearest to point.
Delegates to :func:dart_from_edge_at_point.
from_edge_at_t(edge: object, t: float, width: float, depth: float, dart_type: DartType | str = DartType.TRIANGLE, name: str | None = None) -> Dart
classmethod
¶
Place a dart orthogonally on edge at parameter t.
Delegates to :func:dart_from_edge_at_t.
from_edge_free_tip(edge: object, t: float, width: float, reference_point: Point, tip_shortfall: float = 20.0, dart_type: DartType | str = DartType.TRIANGLE, name: str | None = None) -> Dart
classmethod
¶
Place a dart on edge at t aimed at reference_point.
Delegates to :func:dart_from_edge_free_tip.
from_tip_and_legs(tip: Point, leg_a: Point, leg_b: Point, dart_type: DartType | str = DartType.TRIANGLE, name: str | None = None, second_tip: Point | None = None) -> Dart
classmethod
¶
Construct a dart from tip and the two mouth endpoints.
Delegates to :func:dart_from_tip_and_legs.
from_tip_center_width(tip: Point, center: Point, width: float, dart_type: DartType | str = DartType.TRIANGLE, name: str | None = None, second_tip: Point | None = None) -> Dart
classmethod
¶
Construct a dart from tip, mouth center and width.
Delegates to :func:dart_from_tip_center_width.
rotate(pivot: Point, angle_rad: float) -> Dart
¶
Return a rotated copy (CCW around pivot).
set_name(name: str) -> Dart
¶
Return a copy of this dart with name set.
All other fields are unchanged. Returns a new :class:Dart rather
than mutating self, consistent with :meth:translate and
:meth:rotate.
split(ratio: float = 0.5) -> tuple[Dart, Dart]
¶
Split into two sub-darts sharing the same tip.
translate(dx: float, dy: float) -> Dart
¶
Return a translated copy.
DartType
¶
Bases: StrEnum
Shape variant of a :class:Dart.
str mixin allows comparing with plain strings for backward compatibility
(e.g. dart.dart_type == "triangle" still works).
Attributes:
| Name | Type | Description |
|---|---|---|
TRIANGLE |
Seam-edge dart — rendered as two stitch lines + fold line. |
|
RHOMBUS |
Inner-panel dart — rendered as a closed four-point diamond. |
InfoBox(position: Point, header: str, notes: list[str] | None = None)
¶
A text info box displayed at a given position.
Initialise with display position, bold header, and optional notes.
dart_from_tip_center_width(tip: Point, center: Point, width: float, dart_type: DartType | str = 'triangle', name: str | None = None, second_tip: Point | None = None) -> Dart
¶
Construct a dart from tip, mouth center and width.
This is the free-function form of :meth:Dart.from_tip_center_width.
dart_from_edge_at_legs(edge: object, leg_a: Point, leg_b: Point, tip: Point, dart_type: DartType | str = 'triangle', name: str | None = None) -> Dart
¶
Place a dart on edge with explicitly supplied leg points.
This is the free-function form of :meth:Dart.from_edge_at_legs.
dart_from_tip_and_legs(tip: Point, leg_a: Point, leg_b: Point, dart_type: DartType | str = 'triangle', name: str | None = None, second_tip: Point | None = None) -> Dart
¶
Construct a dart from tip and the two explicit mouth endpoints.
This is the free-function form of :meth:Dart.from_tip_and_legs.
dart_from_edge_at_t(edge: object, t: float, width: float, depth: float, dart_type: DartType | str = 'triangle', name: str | None = None) -> Dart
¶
Place a dart orthogonally on edge at parameter t.
This is the free-function form of :meth:Dart.from_edge_at_t.
dart_from_edge_at_point(edge: object, point: Point, width: float, depth: float, dart_type: DartType | str = 'triangle', name: str | None = None) -> Dart
¶
Place a dart orthogonally on edge nearest to point.
This is the free-function form of :meth:Dart.from_edge_at_point.
dart_from_edge_free_tip(edge: object, t: float, width: float, reference_point: Point, tip_shortfall: float = 20.0, dart_type: DartType | str = 'triangle', name: str | None = None) -> Dart
¶
Place a dart on edge at t with the tip aimed at reference_point.
This is the free-function form of :meth:Dart.from_edge_free_tip.
edge_tangent(g: _LinearGeom | CubicBezier, at_end: bool) -> np.ndarray
¶
Return the unit tangent of g in the direction of travel.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
g
|
_LinearGeom | CubicBezier
|
A linear geometry or :class: |
required |
at_end
|
bool
|
If |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
A unit-length |
ndarray
|
direction of travel. |
Note
For a :class:CubicBezier with a cusp (zero-length tangent), the raw
(un-normalised) derivative is returned as a fallback to avoid division
by zero. For linear geometry the tangent is constant along the whole
edge and at_end has no effect.
intersect(a: GEOMETRIC_TYPE, b: GEOMETRIC_TYPE) -> list[Point]
¶
Find intersections between two geometric objects.
Linear objects (Segment, Ray, Line) and circles are handled via Shapely's GEOS backend. Bézier–Bézier intersections use svgpathtools (Bézier-clipping). Bézier–linear and Bézier–circle intersections discretise the curve and use Shapely.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
a
|
GEOMETRIC_TYPE
|
First geometric object. Must be one of :data: |
required |
b
|
GEOMETRIC_TYPE
|
Second geometric object. Must be one of :data: |
required |
Returns:
| Type | Description |
|---|---|
list[Point]
|
A list of :class: |
list[Point]
|
empty list when there are no intersections or the objects are parallel / |
list[Point]
|
coincident. |
Raises:
| Type | Description |
|---|---|
TypeError
|
If the combination of types |
Note
- Accuracy differs by backend: GEOS (linear/circle) is exact; Bézier intersections are approximated via polyline discretisation.
- The order of points in the returned list is not guaranteed.
Example
seg = Segment(Point(0, 0), Point(10, 0)) ray = Ray(Point(5, -5), np.array([0.0, 1.0])) intersect(seg, ray) [Point(5.0, 0.0)]
seam_length(geoms: list[Segment | CubicBezier | Circle | Rect | Triangle]) -> float
¶
Return the total arc length in mm of a list of measurable geometry objects.
Supported types and what length means for each:
- :class:
Segment— Euclidean distance between endpoints. - :class:
CubicBezier— arc length via numerical integration. - :class:
Circle— full circumference (2 * π * radius). - :class:
Rect— full perimeter (2 * (width + height)). - :class:
Triangle— full perimeter (sum of the three side lengths).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
geoms
|
list[Segment | CubicBezier | Circle | Rect | Triangle]
|
A list of measurable geometry objects. May be empty. |
required |
Returns:
| Type | Description |
|---|---|
float
|
Total arc length in mm as a :class: |
float
|
empty list. |