1.. include:: ../spline-links.inc 2 3.. _tut_spline: 4 5Tutorial for Spline 6=================== 7 8Background information about `B-spline`_ at Wikipedia. 9 10Splines from fit points 11----------------------- 12 13Splines can be defined by fit points only, this means the curve goes through all given fit points. 14AutoCAD and BricsCAD generates required control points and knot values by itself, if only fit points 15are present. 16 17Create a simple spline: 18 19.. code-block:: python 20 21 doc = ezdxf.new('R2000') 22 23 fit_points = [(0, 0, 0), (750, 500, 0), (1750, 500, 0), (2250, 1250, 0)] 24 msp = doc.modelspace() 25 spline = msp.add_spline(fit_points) 26 27.. image:: gfx/spline1.png 28 29Append a fit point to a spline: 30 31.. code-block:: python 32 33 # fit_points, control_points, knots and weights are list-like containers: 34 spline.fit_points.append((2250, 2500, 0)) 35 36.. image:: gfx/spline2.png 37 38You can set additional `control points`, but if they do not fit the auto-generated AutoCAD values, they will be ignored 39and don't mess around with `knot`_ values. 40 41Solve problems of incorrect values after editing a spline generated by AutoCAD: 42 43.. code-block:: python 44 45 doc = ezdxf.readfile("AutoCAD_generated.dxf") 46 47 msp = doc.modelspace() 48 spline = msp.query('SPLINE').first 49 50 # fit_points, control_points, knots and weights are list-like objects: 51 spline.fit_points.append((2250, 2500, 0)) 52 53As far as I have tested, this approach works without complaints from AutoCAD, but for the case of problems 54remove invalid data: 55 56.. code-block:: python 57 58 # current control points do not match spline defined by fit points 59 spline.control_points = [] 60 61 # count of knots is not correct: 62 # count of knots = count of control points + degree + 1 63 spline.knots = [] 64 65 # same for weights, count of weights == count of control points 66 spline.weights = [] 67 68 69Splines by control points 70------------------------- 71 72To create splines from fit points is the easiest way to create splines, but this method is also the least accurate, 73because a spline is defined by control points and knot values, which are generated for the case of a definition by 74fit points, and the worst fact is that for every given set of fit points exist an infinite number of possible 75splines as solution. 76 77AutoCAD (and BricsCAD also) uses an proprietary algorithm to generate control points and knot values from fit points, 78which differs from the well documented `Global Curve Interpolation`_. Therefore splines generated from fit points 79by `ezdxf` do not match splines generated by AutoCAD (BricsCAD). 80 81To ensure the same spline geometry for all CAD applications, the spline has to be defined by control points. The method 82:meth:`~ezdxf.layouts.BaseLayout.add_spline_control_frame` adds a spline trough fit points by calculating the control 83points by the `Global Curve Interpolation`_ algorithm. There is also a low level function 84:func:`ezdxf.math.global_bspline_interpolation` which calculates the control points from fit points. 85 86.. code-block:: python 87 88 msp.add_spline_control_frame(fit_points, method='uniform', dxfattribs={'color': 1}) 89 msp.add_spline_control_frame(fit_points, method='chord', dxfattribs={'color': 3}) 90 msp.add_spline_control_frame(fit_points, method='centripetal', dxfattribs={'color': 5}) 91 92- black curve: AutoCAD/BricsCAD spline generated from fit points 93- red curve: spline curve interpolation, "uniform" method 94- green curve: spline curve interpolation, "chord" method 95- blue curve: spline curve interpolation, "centripetal" method 96 97.. image:: gfx/spline3.png 98 99Open Spline 100~~~~~~~~~~~ 101 102Add and open (clamped) spline defined by control points with the method 103:meth:`~ezdxf.layouts.BaseLayout.add_open_spline`. If no `knot`_ values are given, an open uniform knot vector will be 104generated. A clamped B-spline starts at the first control point and ends at the last control point. 105 106.. code-block:: python 107 108 control_points = [(0, 0, 0), (1250, 1560, 0), (3130, 610, 0), (2250, 1250, 0)] 109 msp.add_open_spline(control_points) 110 111.. image:: gfx/spline4.png 112 113Rational Spline 114~~~~~~~~~~~~~~~ 115 116`Rational B-splines`_ have a weight for every control point, which can raise or lower the influence of the control point, 117default weight = ``1``, to lower the influence set a weight < ``1`` to raise the influence set a weight > ``1``. 118The count of weights has to be always equal to the count of control points. 119 120Example to raise the influence of the first control point: 121 122.. code-block:: python 123 124 msp.add_closed_rational_spline(control_points, weights=[3, 1, 1, 1]) 125 126.. image:: gfx/spline6.png 127 128Spline properties 129----------------- 130 131Check if spline is a `closed curve`_ or close/open spline, for a closed spline the last point is connected to the 132first point: 133 134.. code-block:: python 135 136 if spline.closed: 137 # this spline is closed 138 pass 139 140 # close spline 141 spline.closed = True 142 143 # open spline 144 spline.closed = False 145 146 147Set start- and end tangent for splines defined by fit points: 148 149.. code-block:: python 150 151 spline.dxf.start_tangent = (0, 1, 0) # in y-axis 152 spline.dxf.end_tangent = (1, 0, 0) # in x-axis 153 154Get data count as stored in DXF file: 155 156.. code-block:: python 157 158 count = spline.dxf.n_fit_points 159 count = spline.dxf.n_control_points 160 count = spline.dxf.n_knots 161 162Get data count of real existing data: 163 164.. code-block:: python 165 166 count = spline.fit_point_count 167 count = spline.control_point_count 168 count = spline.knot_count 169