├── .gitignore ├── LICENSE ├── README.md ├── b-spline-curve-evaluation.png ├── b-spline-curve-interpolation.png ├── b-spline-evaluation.py └── b-spline-interpolation.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | # C extensions 6 | *.so 7 | 8 | # Distribution / packaging 9 | .Python 10 | env/ 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | *.egg-info/ 23 | .installed.cfg 24 | *.egg 25 | 26 | # PyInstaller 27 | # Usually these files are written by a python script from a template 28 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 29 | *.manifest 30 | *.spec 31 | 32 | # Installer logs 33 | pip-log.txt 34 | pip-delete-this-directory.txt 35 | 36 | # Unit test / coverage reports 37 | htmlcov/ 38 | .tox/ 39 | .coverage 40 | .coverage.* 41 | .cache 42 | nosetests.xml 43 | coverage.xml 44 | *,cover 45 | 46 | # Translations 47 | *.mo 48 | *.pot 49 | 50 | # Django stuff: 51 | *.log 52 | 53 | # Sphinx documentation 54 | docs/_build/ 55 | 56 | # PyBuilder 57 | target/ 58 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Kaoua Cherif 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Python-B-spline-examples 2 | 3 | Examples in Python about evaluating and interpolating a B-spline curve and their comparaison using Numpy, Scipy and Matplotlib. 4 | 5 | ### **Requirements** 6 | 7 | 8 | * Python 2.7.x or 3.x.x, 9 | * Numpy 10 | * Scipy 11 | * Matplotlib 12 | 13 | 14 | ## Getting hands dirty 15 | 16 | Assuming you already know a little about B-spline curves, otherwise google it or [check this out](http://web.mit.edu/hyperbook/Patrikalakis-Maekawa-Cho/node17.html). 17 | 18 | Let consider a 9 points list named __plist__ : 19 | 20 | ```python 21 | plist = [(3 , 1), (2.5, 4), (0, 1), (-2.5, 4),(-3, 0), (-2.5, -4), (0, -1), (2.5, -4), (3, -1),] 22 | ``` 23 | 24 | We will do two things : 25 | 26 | * A. Drawing a cubic B-Spline curve where __plist__ is the control polygon. 27 | 28 | * B. Find(interpolate) and draw the B-spline curve that go trough __plist__ points and or in other words __a curve fitting__ using a cubic B-spline curve. 29 | 30 | As we will work with Numpy , let's create a numpy array named __ctr__ from __plist__ ,and then split it into __x__ and __y__ arrays. 31 | ```python 32 | ctr =np.array(plist) 33 | 34 | x=ctr[:,0] 35 | y=ctr[:,1] 36 | 37 | ``` 38 | ## **A. Drawing the B-spline Curve** 39 | 40 | We will draw a cubic B-spline which degree __k__=3 as it's the most used one. 41 | We need now to define the __knots vector__, with __k__ ending equal knots: 42 | 43 | ```python 44 | l=len(x) 45 | t=np.linspace(0,1,l-2,endpoint=True) 46 | t=np.append([0,0,0],t) 47 | t=np.append(t,[1,1,1]) 48 | ``` 49 | Now we have defined all requirement to draw it. we can construct a sequence of length 3 containing the knots, coefficients, and degree of the spline to pass it as the __tck__ argument to [scipy.interpolate.splev](http://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.splev.html#scipy.interpolate.splev) , the function that will evaluate our curve: 50 | 51 | ```python 52 | tck=[t,[x,y],3] 53 | ``` 54 | And as we will evaluate the B-spline curve, we need a second parameter__u__ , an array of points : 55 | ```python 56 | u3=np.linspace(0,1,(max(l*2,70)),endpoint=True) 57 | ``` 58 | 59 | And we evaluate it : 60 | ```python 61 | out = interpolate.splev(u3,tck) 62 | ``` 63 | 64 | Drawing it using matplotlib : 65 | 66 | ![Cubic B-spline curve drawing](b-spline-curve-evaluation.png "Cubic B-spline curve drawing") 67 | 68 | With this code : 69 | 70 | ```python 71 | plt.plot(x,y,'k--',label='Control polygon',marker='o',markerfacecolor='red') 72 | plt.plot(out[0],out[1],'b',linewidth=2.0,label='B-spline curve') 73 | plt.legend(loc='best') 74 | plt.axis([min(x)-1, max(x)+1, min(y)-1, max(y)+1]) 75 | plt.title('Cubic B-spline curve evaluation') 76 | plt.show() 77 | ``` 78 | 79 | 80 | ## **B. interpolate the B-spline Curve** 81 | 82 | We will interpolate now the B-spline cruve that should go through n points. 83 | As we done before, a numpy array must be created using __plist__ and split into x and y arrays : 84 | 85 | ```python 86 | plist = [(3 , 1), (2.5, 4), (0, 1), (-2.5, 4),(-3, 0), (-2.5, -4), (0, -1), (2.5, -4), (3, -1),] 87 | 88 | ctr =np.array(plist) 89 | 90 | x=ctr[:,0] 91 | y=ctr[:,1] 92 | 93 | ``` 94 | To interpolate the B-spline that go through this points. To do so, we will be using __scipy.interpolate.splprep__, to get the interpolated S-pline parameters : 95 | ```python 96 | tck,_=interpolate.splprep([x,y],k=3,s=0) 97 | ``` 98 | And we use them to evaluate it using __scipy.interpolate.splev__, we still have a to redefine __u__ variable to get a clear plot : 99 | ```python 100 | u=np.linspace(0,1,num=50,endpoint=True) 101 | out = interpolate.splev(u,tck) 102 | ``` 103 | 104 | and we finaly draw it : 105 | ![Cubic B-spline curve interplation](b-spline-curve-interpolation.png "Cubic B-spline curve interpolation") 106 | 107 | With this code : 108 | ```python 109 | plt.figure() 110 | plt.plot(x, y, 'ro', out[0], out[1], 'b') 111 | plt.legend(['Points', 'Interpolated B-spline', 'True'],loc='best') 112 | plt.axis([min(x)-1, max(x)+1, min(y)-1, max(y)+1]) 113 | plt.title('B-Spline interpolation') 114 | plt.show() 115 | ``` 116 | 117 | ## **Full code :** 118 | 119 | ### B-Spline evalutation 120 | 121 | ```python 122 | 123 | import numpy as np 124 | from scipy import interpolate 125 | 126 | import matplotlib.pyplot as plt 127 | 128 | 129 | ctr =np.array( [(3 , 1), (2.5, 4), (0, 1), (-2.5, 4), 130 | (-3, 0), (-2.5, -4), (0, -1), (2.5, -4), (3, -1),]) 131 | x=ctr[:,0] 132 | y=ctr[:,1] 133 | 134 | # uncomment both lines for a closed curve 135 | #x=np.append(x,[x[0]]) 136 | #y=np.append(y,[y[0]]) 137 | 138 | l=len(x) 139 | 140 | t=np.linspace(0,1,l-2,endpoint=True) 141 | t=np.append([0,0,0],t) 142 | t=np.append(t,[1,1,1]) 143 | 144 | tck=[t,[x,y],3] 145 | u3=np.linspace(0,1,(max(l*2,70)),endpoint=True) 146 | out = interpolate.splev(u3,tck) 147 | 148 | plt.plot(x,y,'k--',label='Control polygon',marker='o',markerfacecolor='red') 149 | #plt.plot(x,y,'ro',label='Control points only') 150 | plt.plot(out[0],out[1],'b',linewidth=2.0,label='B-spline curve') 151 | plt.legend(loc='best') 152 | plt.axis([min(x)-1, max(x)+1, min(y)-1, max(y)+1]) 153 | plt.title('Cubic B-spline curve evaluation') 154 | plt.show() 155 | ``` 156 | 157 | ### B-Spline interpolation 158 | 159 | ```python 160 | import numpy as np 161 | from scipy import interpolate 162 | 163 | import matplotlib.pyplot as plt 164 | 165 | #x = np.arange(0, 2*np.pi+np.pi/4, 2*np.pi/8) 166 | #y = np.sin(x) 167 | 168 | ctr =np.array( [(3 , 1), (2.5, 4), (0, 1), (-2.5, 4), 169 | (-3, 0), (-2.5, -4), (0, -1), (2.5, -4), (3, -1)]) 170 | 171 | x=ctr[:,0] 172 | y=ctr[:,1] 173 | 174 | #x=np.append(x,x[0]) 175 | #y=np.append(y,y[0]) 176 | 177 | tck,u = interpolate.splprep([x,y],k=3,s=0) 178 | u=np.linspace(0,1,num=50,endpoint=True) 179 | out = interpolate.splev(u,tck) 180 | 181 | plt.figure() 182 | plt.plot(x, y, 'ro', out[0], out[1], 'b') 183 | plt.legend(['Points', 'Interpolated B-spline', 'True'],loc='best') 184 | plt.axis([min(x)-1, max(x)+1, min(y)-1, max(y)+1]) 185 | plt.title('B-Spline interpolation') 186 | plt.show() 187 | ``` 188 | 189 | You can comment about it [here](http://kaoua.ch/how-to-draw-and-interpolate-a-b-spline-curve-on-python.html) 190 | 191 | 192 | **Please help improving this code.** 193 | -------------------------------------------------------------------------------- /b-spline-curve-evaluation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawache/Python-B-spline-examples/0557daee013e2c913a30bc7d3fc1b17ac1878cda/b-spline-curve-evaluation.png -------------------------------------------------------------------------------- /b-spline-curve-interpolation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawache/Python-B-spline-examples/0557daee013e2c913a30bc7d3fc1b17ac1878cda/b-spline-curve-interpolation.png -------------------------------------------------------------------------------- /b-spline-evaluation.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from scipy import interpolate 3 | 4 | import matplotlib.pyplot as plt 5 | 6 | 7 | ctr =np.array( [(3 , 1), (2.5, 4), (0, 1), (-2.5, 4), 8 | (-3, 0), (-2.5, -4), (0, -1), (2.5, -4), (3, -1),]) 9 | x=ctr[:,0] 10 | y=ctr[:,1] 11 | 12 | # uncomment both lines for a closed curve 13 | #x=np.append(x,[x[0]]) 14 | #y=np.append(y,[y[0]]) 15 | 16 | l=len(x) 17 | 18 | t=np.linspace(0,1,l-2,endpoint=True) 19 | t=np.append([0,0,0],t) 20 | t=np.append(t,[1,1,1]) 21 | 22 | tck=[t,[x,y],3] 23 | u3=np.linspace(0,1,(max(l*2,70)),endpoint=True) 24 | out = interpolate.splev(u3,tck) 25 | 26 | plt.plot(x,y,'k--',label='Control polygon',marker='o',markerfacecolor='red') 27 | #plt.plot(x,y,'ro',label='Control points only') 28 | plt.plot(out[0],out[1],'b',linewidth=2.0,label='B-spline curve') 29 | plt.legend(loc='best') 30 | plt.axis([min(x)-1, max(x)+1, min(y)-1, max(y)+1]) 31 | plt.title('Cubic B-spline curve evaluation') 32 | plt.show() 33 | 34 | -------------------------------------------------------------------------------- /b-spline-interpolation.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from scipy import interpolate 3 | 4 | import matplotlib.pyplot as plt 5 | 6 | #x = np.arange(0, 2*np.pi+np.pi/4, 2*np.pi/8) 7 | #y = np.sin(x) 8 | 9 | ctr =np.array( [(3 , 1), (2.5, 4), (0, 1), (-2.5, 4), 10 | (-3, 0), (-2.5, -4), (0, -1), (2.5, -4), (3, -1)]) 11 | 12 | x=ctr[:,0] 13 | y=ctr[:,1] 14 | 15 | #x=np.append(x,x[0]) 16 | #y=np.append(y,y[0]) 17 | 18 | tck,u = interpolate.splprep([x,y],k=3,s=0) 19 | u=np.linspace(0,1,num=50,endpoint=True) 20 | out = interpolate.splev(u,tck) 21 | 22 | plt.figure() 23 | plt.plot(x, y, 'ro', out[0], out[1], 'b') 24 | plt.legend(['Points', 'Interpolated B-spline', 'True'],loc='best') 25 | plt.axis([min(x)-1, max(x)+1, min(y)-1, max(y)+1]) 26 | plt.title('B-Spline interpolation') 27 | plt.show() 28 | --------------------------------------------------------------------------------