sketchingpy.bezier_util
Utility to build bezier curves.
License:
BSD
1"""Utility to build bezier curves. 2 3License: 4 BSD 5""" 6import typing 7 8 9class BezierMaker: 10 """Builds points along a bezier curve of arbitrary degree.""" 11 12 def __init__(self): 13 """Create a new curve with no points.""" 14 self._points: typing.List[typing.Tuple[float, float]] = [] 15 16 def add_point(self, x: float, y: float): 17 """Add a point to this curve. 18 19 Add a point to this curve. If it is the first or last point, it is start and destination 20 respectively. Otherwise, it is a control point. 21 22 Args: 23 x: The x position of the point. 24 y: The y position of the point. 25 """ 26 self._points.append((x, y)) 27 28 def get_points(self, num_points: int) -> typing.List[typing.Tuple[float, float]]: 29 """Get a series of points within the curve. 30 31 Args: 32 num_points: The number of points to return. 33 34 Returns: 35 List of coordinates along curve. 36 """ 37 if len(self._points) == 0: 38 raise RuntimeError('Curve without points.') 39 40 input_point_ids = range(0, num_points) 41 input_fracs = map(lambda x: x / (num_points - 1.0), input_point_ids) 42 return [self._evaluate(frac) for frac in input_fracs] 43 44 def _evaluate(self, t: float) -> typing.Tuple[float, float]: 45 """Evaluate the bezier curve at a single parameter value. 46 47 Uses the De Casteljau algorithm, repeatedly interpolating between 48 neighboring points until a single point remains. Works for a curve of 49 any degree (any number of control points). 50 51 Args: 52 t: Parameter along the curve from 0 (start) to 1 (destination). 53 54 Returns: 55 The (x, y) coordinate on the curve at t. 56 """ 57 current = self._points 58 while len(current) > 1: 59 current = [ 60 ( 61 (1 - t) * current[i][0] + t * current[i + 1][0], 62 (1 - t) * current[i][1] + t * current[i + 1][1] 63 ) 64 for i in range(len(current) - 1) 65 ] 66 67 return (float(current[0][0]), float(current[0][1]))
class
BezierMaker:
10class BezierMaker: 11 """Builds points along a bezier curve of arbitrary degree.""" 12 13 def __init__(self): 14 """Create a new curve with no points.""" 15 self._points: typing.List[typing.Tuple[float, float]] = [] 16 17 def add_point(self, x: float, y: float): 18 """Add a point to this curve. 19 20 Add a point to this curve. If it is the first or last point, it is start and destination 21 respectively. Otherwise, it is a control point. 22 23 Args: 24 x: The x position of the point. 25 y: The y position of the point. 26 """ 27 self._points.append((x, y)) 28 29 def get_points(self, num_points: int) -> typing.List[typing.Tuple[float, float]]: 30 """Get a series of points within the curve. 31 32 Args: 33 num_points: The number of points to return. 34 35 Returns: 36 List of coordinates along curve. 37 """ 38 if len(self._points) == 0: 39 raise RuntimeError('Curve without points.') 40 41 input_point_ids = range(0, num_points) 42 input_fracs = map(lambda x: x / (num_points - 1.0), input_point_ids) 43 return [self._evaluate(frac) for frac in input_fracs] 44 45 def _evaluate(self, t: float) -> typing.Tuple[float, float]: 46 """Evaluate the bezier curve at a single parameter value. 47 48 Uses the De Casteljau algorithm, repeatedly interpolating between 49 neighboring points until a single point remains. Works for a curve of 50 any degree (any number of control points). 51 52 Args: 53 t: Parameter along the curve from 0 (start) to 1 (destination). 54 55 Returns: 56 The (x, y) coordinate on the curve at t. 57 """ 58 current = self._points 59 while len(current) > 1: 60 current = [ 61 ( 62 (1 - t) * current[i][0] + t * current[i + 1][0], 63 (1 - t) * current[i][1] + t * current[i + 1][1] 64 ) 65 for i in range(len(current) - 1) 66 ] 67 68 return (float(current[0][0]), float(current[0][1]))
Builds points along a bezier curve of arbitrary degree.
BezierMaker()
13 def __init__(self): 14 """Create a new curve with no points.""" 15 self._points: typing.List[typing.Tuple[float, float]] = []
Create a new curve with no points.
def
add_point(self, x: float, y: float):
17 def add_point(self, x: float, y: float): 18 """Add a point to this curve. 19 20 Add a point to this curve. If it is the first or last point, it is start and destination 21 respectively. Otherwise, it is a control point. 22 23 Args: 24 x: The x position of the point. 25 y: The y position of the point. 26 """ 27 self._points.append((x, y))
Add a point to this curve.
Add a point to this curve. If it is the first or last point, it is start and destination respectively. Otherwise, it is a control point.
Arguments:
- x: The x position of the point.
- y: The y position of the point.
def
get_points(self, num_points: int) -> List[Tuple[float, float]]:
29 def get_points(self, num_points: int) -> typing.List[typing.Tuple[float, float]]: 30 """Get a series of points within the curve. 31 32 Args: 33 num_points: The number of points to return. 34 35 Returns: 36 List of coordinates along curve. 37 """ 38 if len(self._points) == 0: 39 raise RuntimeError('Curve without points.') 40 41 input_point_ids = range(0, num_points) 42 input_fracs = map(lambda x: x / (num_points - 1.0), input_point_ids) 43 return [self._evaluate(frac) for frac in input_fracs]
Get a series of points within the curve.
Arguments:
- num_points: The number of points to return.
Returns:
List of coordinates along curve.