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