geom2d.bezier¶
Cubic bezier curve.
Includes biarc approximation.
- class geom2d.bezier.CubicBezier(p1: TPoint, c1: TPoint, c2: TPoint, p2: TPoint)¶
Two dimensional immutable cubic bezier curve.
For information about Bezier curves see: https://pomax.github.io/bezierinfo
- Parameters:
p1 – Start point as 2-tuple (x, y).
c1 – First control point as 2-tuple (x, y).
c2 – Second control point as 2-tuple (x, y).
p2 – End point as 2-tuple (x, y).
- biarc_approximation(tolerance: float = 0.001, max_depth: float = 4, line_flatness: float = 0.001, _recurs_depth: float = 0) list[Arc | Line] ¶
Approximate this curve using biarcs.
This will recursively subdivide the curve into a series of G1 (tangential continuity) connected arcs or lines until the Hausdorff distance between the approximation and this bezier curve is within the specified tolerance.
- Parameters:
tolerance – Approximation tolerance. A lower value increases accuracy at the cost of time and number of generated biarc segments.
max_depth – Maximum recursion depth. This limits how many times the Bezier curve can be subdivided.
line_flatness – Segments flatter than this value will be converted to straight line segments instead of arcs with huge radii. Generally this should be a small value (say <= 0.01) to avoid path distortions.
- Returns:
A list of Arc and/or Line objects. The list will be empty if the curve is degenerate (i.e. if the end points are coincident).
- controlpoints_at(t: float) tuple[P, P, P, P, P] ¶
Get the point on this curve at t plus control points.
Useful for subdividing the curve at t.
- Parameters:
t – location on curve. A value between 0.0 and 1.0
- Returns:
A tuple of the form (C0, C1, P, C2, C3) where C1 and C2 are the control points tangent to P and C0 and C3 would be the new control points of the endpoints where this curve to be subdivided at P.
- curvature_at(t: float) float ¶
Calculate the curvature at t.
See http://www.spaceroots.org/documents/ellipse/node6.html
- Returns:
A scalar value K representing the curvature at t. Negative if curving to the right or positive if curving to the left when t increases.
- derivative1(t: float) P ¶
Calculate the 1st derivative of this curve at t.
- Returns:
The first derivative at t as 2-tuple (dx, dy).
- derivative2(t: float) P ¶
Calculate the 2nd derivative of this curve at t.
- Returns:
The second derivative at t as 2-tuple (dx, dy).
- derivative3() P ¶
Calculate the 3rd derivative of this curve.
- Returns:
The third derivative as 2-tuple (dx, dy).
- end_tangent_angle() float ¶
Return the end tangent direction of this curve.
From the end (second) point. Angle in radians: -PI < angle < PI.
- find_extrema() list[float] ¶
Find the extremities of this curve.
- See:
https://pomax.github.io/bezierinfo/#extremities https://github.polettix.it/ETOOBUSY/2020/07/09/bezier-extremes/
- Returns:
A list of zero to four parametric (t) values.
- find_extrema_align(calc_bbox: bool = True) tuple[tuple, tuple | None] ¶
Find the extremities of the curve.
As if a chord connecting the end points is parallel to the X axis.
This can be used to find the height of the curve if the curve has no inflections..
This also returns the bounding box since it needs to be rotated to match the curve alignment.
- Parameters:
calc_bbox – Calculate an aligned bounding box. This can be performed slightly more efficiently here since the alignment rotation is known.
- Returns:
A tuple where the first item is a list of zero to four points and the second is the bounding box (as a list of four points) or None if no extrema can be found.
- find_extrema_points() list[P] ¶
Find the extremities of this curve.
- Returns:
A list of zero to four points.
- flatness() float ¶
Return the flatness of this curve.
The maximum distance between the control points and the line segment defined by the start and end points of the curve. This is known as convex hull flatness and is robust regarding degenerate curves.
- static from_quadratic(qp1: Sequence[float], qp2: Sequence[float], qp3: Sequence[float]) CubicBezier ¶
Create a CubicBezier from a quadratic Bazier curve.
- Parameters:
qp1 – Start point as 2-tuple (x, y).
qp2 – Control point as 2-tuple (x, y).
qp3 – End point as 2-tuple (x, y).
- hausdorff_distance(arc: Arc, t1: float = 0, t2: float = 1, ndiv: int = 9) float ¶
Calculate Hausdorff distance to arc.
The approximation accuracy depends on the number of steps specified by ndiv.
This curve should have no inflections and the arc should have the same convexity (ie “bulge” in the same direction).
- Parameters:
arc (
Arc
) – The arc to testt1 (float) – Start location of curve
t2 (float) – End location of curve
ndiv (int) – Number of steps
- Returns:
Maximum distance along curve.
- length(tolerance: float | None = None) float ¶
Approximate arc length of this curve.
Calculate the approximate arc length of this curve within the specified tolerance. The resulting computed arc length will be cached so that subsequent calls are not expensive.
Uses a simple and clever numerical algorithm described/invented by Jens Gravesen.
- Parameters:
tolerance – The approximation tolerance. Default is const.EPSILON.
- Returns:
The approximate arc length of this curve.
- line_intersection(line: Sequence[Sequence[float]]) list[P] ¶
Find intersection points of a line segment and this curve.
- Returns:
A list of zero to three points where the line intersects this curve.
- path_reversed() CubicBezier ¶
Return a CubicBezier with control points (direction) reversed.
- point_at(t: float) P ¶
A point on the curve corresponding to <t>.
This is the parametric function Bezier(t), where 0 < t < 1.0.
- Returns:
A point as 2-tuple (x, y).
- roots() tuple[float, float] ¶
Find roots of this curve.
The roots are inflection points are where the curve changes direction, has a cusp, or a loop. There may be none, one, or two inflections on the curve. A loop will have two inflections.
These inflection points can be used to subdivide the curve.
- Parameters:
imaginary – If True find imaginary inflection points. These are useful for subdividing curves with loops. Default is False.
- Returns:
A tuple containing the roots (t1, t2). The root values will be 0 < t < 1 or -1 if no root. If there is only one root it will always be the first value of the tuple. The roots will be ordered by ascending value if there is more than one.
- start_tangent_angle() float ¶
The tangent direction of this curve at the first point.
This would normally be the same as the angle of the first control point vector, unless the control point is coincident with the first point. Angle in radians: -PI < angle < PI.
- subdivide(t: float) tuple[CubicBezier, CubicBezier] ¶
Subdivide this curve at the point on the curve at t.
Split curve into two cubic bezier curves, where 0<t<1. Uses De Casteljaus’s algorithm.
- Returns:
A tuple of one or two CubicBezier objects.
- subdivide_inflections() tuple[CubicBezier, ...] ¶
Subdivide this curve at the inflection points, if any.
- Returns:
A list containing one to three curves depending on whether there are no inflections, one inflection, or two inflections.
- tangent(t: float) P ¶
The tangent unit vector at the point on the curve at t.
t is the unit distance from first point where 0 <= t <= 1.
- to_svg_path(scale: float = 1, add_prefix: bool = True, add_move: bool = False) str ¶
CubicBezier to SVG path string.
- Parameters:
scale – Scale factor. Default is 1.
add_prefix – Prefix with the command prefix if True.
add_move – Prefix with M command if True.
- Returns:
A string with the SVG path ‘d’ attribute value that corresponds with this curve.
- transform(matrix: TMatrix) CubicBezier ¶
Apply transform to this curve and return a copy.
- geom2d.bezier.arc_bezier_h(angle: float) float ¶
Find best h for angle, for converting circular arc to cubic Bezier.
- geom2d.bezier.bezier_circle(center: Sequence[float] = (0, 0), radius: float = 1.0) tuple[CubicBezier, CubicBezier, CubicBezier, CubicBezier] ¶
Create an approximation of a circle with a cubic Bezier curve.
- Parameters:
center (tuple) – The center point of the circle. Default is (0,0).
radius (float) – The radius of the circle. Default is 1.
- Returns:
A tuple with four bezier curves for each circle quadrant. Circle will be clockwise from the positive x axis relative to the center point.
- Return type:
tuple
- geom2d.bezier.bezier_circle_2(center: Sequence[float] = (0, 0), radius: float = 1.0) tuple[CubicBezier, CubicBezier, CubicBezier, CubicBezier] ¶
Create an approximation of a circle with a cubic Bezier curve.
This is a better approximation than
bezier_circle()
, except that the curves are not strictly G1 continuous.- Parameters:
center (tuple) – The center point of the circle. Default is (0,0).
radius (float) – The radius of the circle. Default is 1.
- Returns:
A tuple with four bezier curves for each circle quadrant. Circle will be clockwise from the positive x axis relative to the center point.
- Return type:
tuple
- geom2d.bezier.bezier_circular_arc(arc: Arc) CubicBezier ¶
Create a cubic Bezier approximation of a circular arc.
The central arc must be less than PI/2 radians (90deg).
- Parameters:
arc (
Arc
) – A circular arc.- Returns:
A bezier curve.
- Return type:
- geom2d.bezier.bezier_ellipse(ellipse: Ellipse | EllipticalArc) list[CubicBezier] ¶
Approximate an elliptical arc segment with Bezier curves.
If the sweep angle is greater than PI/2 the arc will be subdivided so that no segment has a sweep angle larger than PI/2.
- Parameters:
ellipse – An Ellipse or EllipticalArc
- Returns:
A list containing one to four BezierCurves.
- geom2d.bezier.bezier_elliptical_arc(ellipse: Ellipse | EllipticalArc, t1: float, t2: float) CubicBezier ¶
Approximate elliptical arc with Bezier curve.
Compute a BezierCurve that can approximate the elliptical arc between t1 and t2.
This does not subdivide the arc to reduce errors so if t2-t1 > PI/2 then the results may be less than ideal.
- Parameters:
ellipse – An Ellipse
t1 – Parametric angle from semi-major axis to first location.
t2 – Parametric angle from semi-major axis to second location.
- Returns:
A cubic bezier curve (as CubicBezier).
- geom2d.bezier.bezier_sine_wave(amplitude: float = 1, wavelength: float = 1, cycles: int = 1, origin: Sequence[float] = (0.0, 0.0), angle: float = 0) list[CubicBezier] ¶
Create an approximation of a sine wave using a cubic Bezier curve.
- Parameters:
amplitude – The amplitude (vertical scale) of the sine wave. This is one half the vertical distance from the trough to the peak.
wavelength – The horizontal length of one complete cycle.
cycles – The number of cycles. Default is one.
origin – Location of start point as a tuple (x,y). Default is (0, 0).
angle – Rotation angle of sine wave.
- Returns:
A list of BezierCurve instances that describe the sine wave. Each curve will be one quarter of a sine wave, so one cycle will return a list four BezierCurves, two cycle will be eight, etc…
- Return type:
list
- geom2d.bezier.draw_bezier(curve: CubicBezier | Sequence[TPoint], color: str = '#ff0000', width: str | float = '1px', opacity: float = 1, verbose: bool = False, svg_context: SVGContext | None = None) None ¶
Draw an SVG version of this curve for debugging/testing.
Draws control points, inflection points, and tangent lines.
- geom2d.bezier.path_biarc_approximation(path: Iterable[Line | Arc | CubicBezier], tolerance: float = 0.001, max_depth: float = 4, line_flatness: float = 0.001) list[Line | Arc] ¶
Convert cubic bezier curves in path to biarcs.
Biarcs are tangentially connected circular arcs.
- Parameters:
path – An iterable collection of bezier.CubicBezier, geom2d.Line, or geom2d.Arc objects.
tolerance – Approximation tolerance. A lower value increases accuracy at the cost of time and number of generated biarc segments.
max_depth – Maximum recursion depth. This limits how many times the Bezier curve can be subdivided.
line_flatness – Segments flatter than this value will be converted to straight line segments instead of arcs with huge radii. Generally this should be a small value (say <= 0.01) to avoid path distortions.
- geom2d.bezier.smooth_path(path: Sequence[Line | Arc | CubicBezier], smoothness: float = 0.5) list[CubicBezier] ¶
Create a smooth approximation of the path using Bezier curves.
- Parameters:
path (list) – A list of connected Line/Arc/CubicBezier segments.
smoothness (float) – Smoothness value (usually between 0 and 1). .5 is a reasonable default.
- Returns:
A list of CubicBezier segments.
- Return type:
list
Note
Support for Bezier segments is currently zilch.
- geom2d.bezier.smoothing_curve(seg1: Line | Arc | CubicBezier, seg2: Line | Arc | CubicBezier | None, cp1: Sequence[float] | None = None, smoothness: float = 0.5, match_arcs: bool = True) tuple[CubicBezier, P] ¶
Create a smoothing Bezier curve between two segments.
The segments are not currently G1 continuous. The resulting Bezier curve will connect the two endpoints of the first segment.
- Parameters:
seg1 – First path segment containing first and second points. Can be a Line or Arc.
seg2 – Second path segment containing second and third points. Can be a Line or Arc.
cp1 (tuple) – First control point computed from previous invocation. If cp1 is None then the first endpoint of the first segment will be used as the initial control point. Default is None.
smoothness (float) – Affects the magnitude of the smoothing curve control points. A value between 0 and 1. Default is 0.5
match_arcs (bool) – Try to better match arc connections.
- Returns:
A tuple containing CubicBezier and the control point for the next curve.