ModGeom/parametric_curves_2.ipynb

894 lines
124 KiB
Plaintext
Raw Permalink Normal View History

2023-10-27 18:08:21 +02:00
{
"cells": [
{
"cell_type": "markdown",
"id": "1b1c1dc2",
"metadata": {},
"source": [
"\\textbf{Copyright:} Wojciech Kowalewski WMiI UAM\n",
"\n",
"\\textbf{Kurs}: Modelowanie geometryczne 2021/22\n",
"\n",
"---\n",
"---\n",
"# Modelowanie geometryczne\n",
"---\n",
"---\n",
"# I. Modelowanie parametryczne"
]
},
{
"cell_type": "code",
"execution_count": 24,
"id": "e2b5e255",
"metadata": {
"deletable": false,
"editable": false
},
"outputs": [],
"source": [
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"import math\n",
"import ipywidgets as widgets"
]
},
{
"cell_type": "markdown",
"id": "8a6112da",
"metadata": {},
"source": [
"## 3. Wymierne krzywe Beziera stopnia 3\n",
"================================================="
]
},
{
"cell_type": "markdown",
"id": "b727c642",
"metadata": {},
"source": [
"### 3.1. Macierz funkcji bazowych"
]
},
{
"cell_type": "code",
"execution_count": 25,
"id": "d1d7fad9",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[[-1.0, 3.0, -3.0, 1.0],\n",
" [3.0, -6.0, 3.0, 0.0],\n",
" [-3.0, 3.0, 0.0, 0.0],\n",
" [1.0, 0.0, 0.0, 0.0]]"
]
},
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"bezier_basis_matrix_2D = [\n",
" [-1.0,3.0,-3.0,1.0],\n",
" [3.0,-6.0,3.0,0.0],\n",
" [-3.0,3.0,.0,0.0],\n",
" [1.0,0.0,0.0,0.0]\n",
"]\n",
"bezier_basis_matrix_2D"
]
},
{
"cell_type": "code",
"execution_count": 26,
"id": "c999b172",
"metadata": {},
"outputs": [],
"source": [
"bezier_basis_function_2D = []\n",
"bezier_basis_function_2D.append(\n",
" lambda t: bezier_basis_matrix_2D[0][0]*t**3 + bezier_basis_matrix_2D[0][1]*t**2 + bezier_basis_matrix_2D[0][2]*t + bezier_basis_matrix_2D[0][3],\n",
") \n",
"bezier_basis_function_2D.append(\n",
"lambda t: bezier_basis_matrix_2D[1][0]*t**3 + bezier_basis_matrix_2D[1][1]*t**2 + bezier_basis_matrix_2D[1][2]*t + bezier_basis_matrix_2D[1][3]\n",
")\n",
"bezier_basis_function_2D.append(\n",
" lambda t: bezier_basis_matrix_2D[2][0]*t**3 + bezier_basis_matrix_2D[2][1]*t**2 + bezier_basis_matrix_2D[2][2]*t + bezier_basis_matrix_2D[2][3]\n",
")\n",
"bezier_basis_function_2D.append(\n",
"lambda t: bezier_basis_matrix_2D[3][0]*t**3 + bezier_basis_matrix_2D[3][1]*t**2 + bezier_basis_matrix_2D[3][2]*t + bezier_basis_matrix_2D[3][3]\n",
")\n"
]
},
{
"cell_type": "markdown",
"id": "f69f1721",
"metadata": {},
"source": [
"### 3.2. Wykresy funkcji bazowych"
]
},
{
"cell_type": "code",
"execution_count": 27,
"id": "ee8f907c",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 720x720 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"%matplotlib inline\n",
"\n",
"t = np.arange(0.0, 1.01, 0.01)\n",
"\n",
"\n",
"fig, ax = plt.subplots()\n",
"#ustawienie rozmiaru obrazka na 10x10 cali\n",
"fig.set_size_inches(25.4/2.54, 25.4/2.54, forward=True)\n",
"plt.title(\"Funkcje bazowe Beziera stopnia 3\")\n",
"\n",
"for n in range(4):\n",
" ax.plot(t,bezier_basis_function_2D[n](t) , label=\"b_\"+str(n)+\"(t)\")\n",
"\n",
"leg = ax.legend(loc='upper center', ncol=2, shadow='True')\n",
"leg.get_frame().set_alpha(0.5)\n",
"plt.grid();\n",
"\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": 28,
"id": "14de6217",
"metadata": {},
"outputs": [],
"source": [
"def find_ext(x,y, lp, lk):\n",
" t = np.arange(lp, lk, 0.001)\n",
" xmin = xmax = x(lp)\n",
" ymin = ymax = y(lp)\n",
" for p in t:\n",
" if x(p) < xmin:\n",
" xmin = x(p)\n",
" else:\n",
" if x(p) > xmax:\n",
" xmax = x(p)\n",
" if y(p) < ymin:\n",
" ymin = y(p)\n",
" else:\n",
" if y(p) > ymax:\n",
" ymax = y(p)\n",
" return [[xmin,xmax],[ymin,ymax]]"
]
},
{
"cell_type": "markdown",
"id": "373fa553",
"metadata": {},
"source": [
"### 3.3. Przykłady"
]
},
{
"cell_type": "markdown",
"id": "69663125",
"metadata": {},
"source": [
"#### 3.3.1. Przykład 1"
]
},
{
"cell_type": "code",
"execution_count": 29,
"id": "acd666f8",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 720x720 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"### %matplotlib inline\n",
"\n",
"t = np.arange(0.0, 1.01, 0.01)\n",
"\n",
"P0 = [0.0,0.0]\n",
"P1 = [0.25,1.0]\n",
"P2 = [0.75,1.0]\n",
"P3 = [1.0,0.0]\n",
"w = [0.5,5.0,10.0,1.0]\n",
"\n",
"Tp= [3.0*(P1[0]-P0[0]),3.0*(P1[1]-P0[1])]\n",
"Tk= [3.0*(P3[0]-P2[0]),3.0*(P3[1]-P2[1])]\n",
"\n",
"lenTp = math.sqrt(Tp[0]**2+Tp[1]**2)/2.54\n",
"lenTk = math.sqrt(Tk[0]**2+Tk[1]**2)/2.54 \n",
"\n",
"\n",
"fig, ax = plt.subplots()\n",
"#ustawienie rozmiaru obrazka na 10x10 cali\n",
"fig.set_size_inches(25.4/2.54, 25.4/2.54, forward=True)\n",
"plt.title(\"Segment wymiernej krzywej Beziera\")\n",
"\n",
"\n",
"\n",
"def X(t):\n",
" denominator = 1.0/(w[0]*bezier_basis_function_2D[0](t) + \n",
" w[1]*bezier_basis_function_2D[1](t) + \n",
" w[2]*bezier_basis_function_2D[2](t) + \n",
" w[3]*bezier_basis_function_2D[3](t)\n",
" )\n",
" return denominator*(w[0]*P0[0]*bezier_basis_function_2D[0](t) + w[1]*P1[0]*bezier_basis_function_2D[1](t) + w[2]*P2[0]*bezier_basis_function_2D[2](t) + w[3]*P3[0]*bezier_basis_function_2D[3](t))\n",
"\n",
"def Y(t):\n",
" denominator = 1.0/(w[0]*bezier_basis_function_2D[0](t) + \n",
" w[1]*bezier_basis_function_2D[1](t) + \n",
" w[2]*bezier_basis_function_2D[2](t) + \n",
" w[3]*bezier_basis_function_2D[3](t)\n",
" )\n",
" return denominator*(w[0]*P0[1]*bezier_basis_function_2D[0](t) + w[1]*P1[1]*bezier_basis_function_2D[1](t) + w[2]*P2[1]*bezier_basis_function_2D[2](t) + w[3]*P3[1]*bezier_basis_function_2D[3](t))\n",
"\n",
"\n",
"extr = find_ext(X,Y,0.0,1.01)\n",
"\n",
"borderXp = min(extr[0][0],P0[0]+Tp[0],P3[0]+Tk[0],P0[0],P1[0],P2[0],P3[0])-0.1\n",
"borderXk = max(extr[0][1],P0[0]+Tp[0],P3[0]+Tk[0],P0[0],P1[0],P2[0],P3[0])+0.1\n",
"\n",
"borderYp = min(extr[1][0],P0[1]+Tp[1],P3[1]+Tk[1],P0[1],P1[1],P2[1],P3[1])-0.1\n",
"borderYk = max(extr[1][1],P0[1]+Tp[1],P3[1]+Tk[1],P0[1],P1[1],P2[1],P3[1])+0.1\n",
"\n",
"\n",
"plt.xlim(borderXp, borderXk)\n",
"plt.ylim(borderYp, borderYk)\n",
"\n",
"x = X(t)\n",
"y = Y(t)\n",
"\n",
"ax.set_aspect('equal')\n",
"\n",
"ax.plot(x,y, color='red')\n",
"\n",
"ax.plot(P0[0], P0[1], color='blue', marker=\".\", markersize=20)\n",
"ax.plot(P1[0], P1[1], color='blue', marker=\".\", markersize=20)\n",
"ax.plot(P2[0], P2[1], color='blue', marker=\".\", markersize=20)\n",
"ax.plot(P3[0], P3[1], color='blue', marker=\".\", markersize=20)\n",
"\n",
"\n",
"\n",
"plt.quiver(P0[0],P0[1], Tp[0] , Tp[1],color='green', angles='xy', scale_units='xy', scale=1)\n",
"plt.quiver(P3[0],P3[1], Tk[0] , Tk[1],color='green', angles='xy', scale_units='xy', scale=1)\n",
"\n",
"\n",
"#eg = ax.legend(loc='upper center', ncol=2, shadow='True')\n",
"leg.get_frame().set_alpha(0.5)\n",
"plt.grid();\n",
"\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"id": "635f22cd",
"metadata": {},
"source": [
"#### 3.3.2. Przykład 2"
]
},
{
"cell_type": "code",
"execution_count": 30,
"id": "5cbd0130",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 720x720 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"### %matplotlib inline\n",
"\n",
"t = np.arange(0.0, 1.01, 0.01)\n",
"\n",
"P0 = [0.0,0.0]\n",
"P1 = [0.25,1.0]\n",
"P2 = [1.0,0.0]\n",
"P3 = [0.75,1.0]\n",
"w = [1.0,5.0,10.0,1.0]\n",
"\n",
"Tp= [3.0*(P1[0]-P0[0]),3.0*(P1[1]-P0[1])]\n",
"Tk= [3.0*(P3[0]-P2[0]),3.0*(P3[1]-P2[1])]\n",
"\n",
"lenTp = math.sqrt(Tp[0]**2+Tp[1]**2)/2.54\n",
"lenTk = math.sqrt(Tk[0]**2+Tk[1]**2)/2.54 \n",
"\n",
"\n",
"fig, ax = plt.subplots()\n",
"#ustawienie rozmiaru obrazka na 10x10 cali\n",
"fig.set_size_inches(25.4/2.54, 25.4/2.54, forward=True)\n",
"plt.title(\"Segment wymiernej krzywej Beziera\")\n",
"\n",
"\n",
"\n",
"def X(t):\n",
" denominator = 1.0/(w[0]*bezier_basis_function_2D[0](t) + \n",
" w[1]*bezier_basis_function_2D[1](t) + \n",
" w[2]*bezier_basis_function_2D[2](t) + \n",
" w[3]*bezier_basis_function_2D[3](t)\n",
" )\n",
" return denominator*(w[0]*P0[0]*bezier_basis_function_2D[0](t) + w[1]*P1[0]*bezier_basis_function_2D[1](t) + w[2]*P2[0]*bezier_basis_function_2D[2](t) + w[3]*P3[0]*bezier_basis_function_2D[3](t))\n",
"\n",
"def Y(t):\n",
" denominator = 1.0/(w[0]*bezier_basis_function_2D[0](t) + \n",
" w[1]*bezier_basis_function_2D[1](t) + \n",
" w[2]*bezier_basis_function_2D[2](t) + \n",
" w[3]*bezier_basis_function_2D[3](t)\n",
" )\n",
" return denominator*(w[0]*P0[1]*bezier_basis_function_2D[0](t) + w[1]*P1[1]*bezier_basis_function_2D[1](t) + w[2]*P2[1]*bezier_basis_function_2D[2](t) + w[3]*P3[1]*bezier_basis_function_2D[3](t))\n",
"\n",
"\n",
"extr = find_ext(X,Y,0.0,1.01)\n",
"\n",
"borderXp = min(extr[0][0],P0[0]+Tp[0],P3[0]+Tk[0],P0[0],P1[0],P2[0],P3[0])-0.1\n",
"borderXk = max(extr[0][1],P0[0]+Tp[0],P3[0]+Tk[0],P0[0],P1[0],P2[0],P3[0])+0.1\n",
"\n",
"borderYp = min(extr[1][0],P0[1]+Tp[1],P3[1]+Tk[1],P0[1],P1[1],P2[1],P3[1])-0.1\n",
"borderYk = max(extr[1][1],P0[1]+Tp[1],P3[1]+Tk[1],P0[1],P1[1],P2[1],P3[1])+0.1\n",
"\n",
"\n",
"plt.xlim(borderXp, borderXk)\n",
"plt.ylim(borderYp, borderYk)\n",
"\n",
"x = X(t)\n",
"y = Y(t)\n",
"\n",
"ax.set_aspect('equal')\n",
"\n",
"ax.plot(x,y, color='red')\n",
"\n",
"ax.plot(P0[0], P0[1], color='blue', marker=\".\", markersize=20)\n",
"ax.plot(P1[0], P1[1], color='blue', marker=\".\", markersize=20)\n",
"ax.plot(P2[0], P2[1], color='blue', marker=\".\", markersize=20)\n",
"ax.plot(P3[0], P3[1], color='blue', marker=\".\", markersize=20)\n",
"\n",
"\n",
"\n",
"plt.quiver(P0[0],P0[1], Tp[0] , Tp[1],color='green', angles='xy', scale_units='xy', scale=1)\n",
"plt.quiver(P3[0],P3[1], Tk[0] , Tk[1],color='green', angles='xy', scale_units='xy', scale=1)\n",
"\n",
"\n",
"#eg = ax.legend(loc='upper center', ncol=2, shadow='True')\n",
"leg.get_frame().set_alpha(0.5)\n",
"plt.grid();\n",
"\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"id": "bbbf7f42",
"metadata": {},
"source": [
"#### 3.3.3. Wersja interaktywna"
]
},
{
"cell_type": "code",
"execution_count": 31,
"id": "de29aa49",
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "a5a3cc4df7194feda51131cd6bb5daac",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"HBox(children=(VBox(children=(FloatSlider(value=0.0, description='P0X', layout=Layout(grid_area='widget001'), …"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "58b872bec9cb40678924b267416a8a0d",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"Output()"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"%matplotlib inline\n",
"\n",
"\n",
"def draw_rational_Bezier_segment(P0X,P0Y,P1X,P1Y,P2X,P2Y,P3X,P3Y,w0,w1,w2,w3):\n",
" t = np.arange(0.0, 1.01, 0.01)\n",
" \n",
" ### %matplotlib inline\n",
"\n",
" t = np.arange(0.0, 1.01, 0.01)\n",
"\n",
" Tp= [3.0*(P1X-P0X),3.0*(P1Y-P0Y)]\n",
" Tk= [3.0*(P3X-P2X),3.0*(P3Y-P2Y)]\n",
"\n",
" lenTp = math.sqrt(Tp[0]**2+Tp[1]**2)/2.54\n",
" lenTk = math.sqrt(Tk[0]**2+Tk[1]**2)/2.54 \n",
"\n",
"\n",
" fig, ax = plt.subplots()\n",
" #ustawienie rozmiaru obrazka na 10x10 cali\n",
" fig.set_size_inches(25.4/2.54, 25.4/2.54, forward=True)\n",
" plt.title(\"Segment wymiernej krzywej Beziera\")\n",
"\n",
"\n",
" def X(t):\n",
" denominator = 1.0/(w0*bezier_basis_function_2D[0](t) + w1*bezier_basis_function_2D[1](t) + w2*bezier_basis_function_2D[2](t) + w3*bezier_basis_function_2D[3](t))\n",
" return denominator*(w0*P0X*bezier_basis_function_2D[0](t) + w1*P1X*bezier_basis_function_2D[1](t) + w2*P2X*bezier_basis_function_2D[2](t) + w3*P3X*bezier_basis_function_2D[3](t))\n",
"\n",
" def Y(t):\n",
" denominator = 1.0/(w0*bezier_basis_function_2D[0](t) + w1*bezier_basis_function_2D[1](t) + w2*bezier_basis_function_2D[2](t) + w3*bezier_basis_function_2D[3](t))\n",
" return denominator*(w0*P0Y*bezier_basis_function_2D[0](t) + w1*P1Y*bezier_basis_function_2D[1](t) + w2*P2Y*bezier_basis_function_2D[2](t) + w3*P3Y*bezier_basis_function_2D[3](t))\n",
"\n",
"\n",
"\n",
" extr = find_ext(X,Y,0.0,1.01)\n",
"\n",
" borderXp = min(extr[0][0],P0X+Tp[0],P3X+Tk[0],P0X,P1X,P2X,P3X)-0.2\n",
" borderXk = max(extr[0][1],P0X+Tp[0],P3X+Tk[0],P0X,P1X,P2X,P3X)+0.2\n",
"\n",
" borderYp = min(extr[1][0],P0Y+Tp[1],P3Y+Tk[1],P0Y,P1Y,P2Y,P3Y)-0.2\n",
" borderYk = max(extr[1][1],P0Y+Tp[1],P3Y+Tk[1],P0Y,P1Y,P2Y,P3Y)+0.2\n",
"\n",
" plt.xlim(borderXp, borderXk)\n",
" plt.ylim(borderYp, borderYk)\n",
"\n",
" x = X(t)\n",
" y = Y(t)\n",
"\n",
" ax.set_aspect('equal')\n",
"\n",
" ax.plot(x,y, color='red')\n",
"\n",
" ax.plot(P0X, P0Y, color='blue', marker=\".\", markersize=20)\n",
" ax.plot(P1X, P1Y, color='blue', marker=\".\", markersize=20)\n",
" ax.plot(P2X, P2Y, color='blue', marker=\".\", markersize=20)\n",
" ax.plot(P3X, P3Y, color='blue', marker=\".\", markersize=20)\n",
"\n",
"\n",
"\n",
" plt.quiver(P0X,P0Y, Tp[0] , Tp[1],color='green', angles='xy', scale_units='xy', scale=1)\n",
" plt.quiver(P3X,P3Y, Tk[0] , Tk[1],color='green', angles='xy', scale_units='xy', scale=1)\n",
"\n",
"\n",
" #eg = ax.legend(loc='upper center', ncol=2, shadow='True')\n",
" leg.get_frame().set_alpha(0.5)\n",
" plt.grid();\n",
"\n",
" plt.show()\n",
"\n",
"p0 = [0.0,0.0]\n",
"p1 = [0.25,1]\n",
"p2 = [0.75,1]\n",
"p3 = [1.0,0.0]\n",
"w = [1.0,2.0,0.5,1.0]\n",
" \n",
"#draw_Hermite_segment(Pp1[0],Pp1[1],Pk1[0],Pk1[1],Tp1[0],Tp1[1],Tk1[0],Tk1[1])\n",
"grid = widgets.GridspecLayout(4, 3)\n",
"grid[0, 0] = widgets.FloatSlider(min=-5, max=5, step=0.1,value=p0[0],description='P0X')\n",
"grid[0, 1] = widgets.FloatSlider(min=-5, max=5, step=0.1,value=p0[1],description='P0Y')\n",
"grid[0, 2] = widgets.FloatSlider(min=-5, max=20, step=0.05,value=w[0],description='w0')\n",
"\n",
"grid[1, 0] = widgets.FloatSlider(min=-5, max=5, step=0.1,value=p1[0],description='P1X')\n",
"grid[1, 1] = widgets.FloatSlider(min=-5, max=5, step=0.1,value=p1[1],description='P1Y')\n",
"grid[1, 2] = widgets.FloatSlider(min=-5, max=20, step=0.05,value=w[1],description='w1')\n",
"\n",
"grid[2, 0] = widgets.FloatSlider(min=-5, max=5, step=0.1,value=p2[0],description='P2X')\n",
"grid[2, 1] = widgets.FloatSlider(min=-5, max=5, step=0.1,value=p2[1],description='P2Y')\n",
"grid[2, 2] = widgets.FloatSlider(min=-5, max=20, step=0.05,value=w[2],description='w2')\n",
"\n",
"grid[3, 0] = widgets.FloatSlider(min=-5, max=5, step=0.1,value=p3[0],description='P3X')\n",
"grid[3, 1] = widgets.FloatSlider(min=-5, max=5, step=0.1,value=p3[1],description='P3Y')\n",
"grid[3, 2] = widgets.FloatSlider(min=-5, max=20, step=0.05,value=w[3],description='w3')\n",
"\n",
"k1 = widgets.VBox([grid[0,0],grid[1,0],grid[2,0],grid[3,0]])\n",
"k2 = widgets.VBox([grid[0,1],grid[1,1],grid[2,1],grid[3,1]])\n",
"k3 = widgets.VBox([grid[0,2],grid[1,2],grid[2,2],grid[3,2]])\n",
"ui = widgets.HBox([k1,k2,k3])\n",
"\n",
"out = widgets.interactive_output(draw_rational_Bezier_segment, {'P0X': grid[0,0], 'P0Y': grid[0,1], 'w0': grid[0,2],\n",
" 'P1X': grid[1,0], 'P1Y': grid[1,1],'w1': grid[1,2],\n",
" 'P2X': grid[2,0], 'P2Y': grid[2,1], 'w2': grid[2,2],\n",
" 'P3X': grid[3,0], 'P3Y': grid[3,1], 'w3': grid[3,2]\n",
" })\n",
"\n",
"display(ui, out)\n",
"\n"
]
},
{
"cell_type": "markdown",
"id": "0520f4fe",
"metadata": {},
"source": [
"## 4. Krzywe B-spline\n",
"========================"
]
},
{
"cell_type": "markdown",
"id": "70ff9eba",
"metadata": {},
"source": [
"### 4.1. Funkcje bazowe"
]
},
{
"cell_type": "code",
"execution_count": 39,
"id": "cb73f70f",
"metadata": {},
"outputs": [],
"source": [
"def N(t_,i_,p_,u_):\n",
" \"\"\"\n",
" t - wartość obliczeniowa parametru\n",
" i - indeks segmentu parametru\n",
" u - wektor węzłów\n",
" \"\"\"\n",
" \n",
" if p_ == 0:\n",
" if u_[i_+1] > u_[i_] or i_ == 0: \n",
" if u_[i_] <= t_ and t_ < u_[i_+1]: \n",
" return 1.0\n",
" else:\n",
" return 0.0\n",
" if abs(u_[i_+1]- u_[i_])<eps: \n",
" if abs(t_ - u_[i_+1])<eps: \n",
" return 1.0\n",
" else:\n",
" return 0.0 \n",
" else:\n",
" \n",
" if u_[i_+p_] == u_[i_]:\n",
" c1 = 0.0\n",
" else:\n",
" c11 = (t_ - u_[i_])/(u_[i_+p_] - u_[i_])\n",
" c12 =N(t_, i_,p_-1, u_)\n",
" c1 = c11 * c12 \n",
" \n",
" if u_[i_+p_+1] == u_[i_+1]:\n",
" c2 = 0.0\n",
" else:\n",
" c21 = (u_[i_+p_+1] - t_)/(u_[i_+p_+1] - u_[i_+1])\n",
" c22 = N(t_,i_+1, p_-1, u_)\n",
" c2 = c21 * c22 \n",
" return c1 + c2"
]
},
{
"cell_type": "markdown",
"id": "0cee63e8",
"metadata": {},
"source": [
"### 4.2. Wykresy funkcji bazowych"
]
},
{
"cell_type": "code",
"execution_count": 41,
"id": "059ea3ca",
"metadata": {
"scrolled": true
},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "6a314a78238f4ac88efc4b7937924040",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"GridspecLayout(children=(HBox(children=(Label(value='Wektor węzłów (przecinek jako separator)', layout=Layout(…"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "b1e77d8685a24e3fb25e06fd628683b0",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"Output()"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"%matplotlib inline\n",
"\n",
"from IPython.display import clear_output\n",
"from scipy.spatial import ConvexHull, convex_hull_plot_2d\n",
"from ipywidgets import Button, Layout\n",
"\n",
"out = widgets.Output()\n",
" \n",
"def draw_Bspline_basis(out):\n",
" \n",
" %matplotlib inline\n",
"\n",
" if knots_input.value == \"\":\n",
" return\n",
" \n",
" \n",
" \n",
" knots_txt = knots_input.value.split(',')\n",
" p = fun_level.value\n",
" i = fun_idx.value\n",
" m = len(knots_txt) - 1\n",
" \n",
" \n",
" if (m < 1):\n",
" print(\"Wektor węzłów musi być listą dlugości co najmniej 2\")\n",
" return\n",
" if (p>=(m+1)):\n",
" print(\"Stopień funkcji musi być mniejszy od ilości węzłów \")\n",
" return\n",
" if (i>=m):\n",
" print(\"Indeks funkcji musi być mniejszy od ilości przedziałów wektora węzłów \")\n",
" return\n",
" \n",
" knots = []\n",
" for e in knots_txt:\n",
" knots.append(float(e))\n",
" \n",
" t = np.arange(knots[0], knots[len(knots)-1], 0.001)\n",
" with out:\n",
" fig, ax = plt.subplots()\n",
" #ustawienie rozmiaru obrazka na 10x10 cali\n",
" fig.set_size_inches(25.4/2.54, 25.4/2.54, forward=True)\n",
" plt.title(\"Funkcje bazowe B-spline \")\n",
"\n",
" \n",
" \n",
" def Npi(t):\n",
" return N(t,i,p,knots)\n",
" \n",
" with out:\n",
" clear_output(True)\n",
" \n",
" y = list(map(Npi,t))\n",
" ax.plot(t,y , label=\"N_\"+str(fun_idx.value)+\",\"+str(fun_level.value)+\"(t)\")\n",
"\n",
" leg = ax.legend(loc='upper center', ncol=2, shadow='True')\n",
" leg.get_frame().set_alpha(0.5)\n",
" plt.grid();\n",
"\n",
" plt.show()\n",
" \n",
"\n",
"knots_input = widgets.Text(\n",
" value=\"\",\n",
" description='',\n",
" disabled=False,\n",
" layout=Layout(width='400px')\n",
")\n",
"\n",
"par_val = widgets.FloatText(\n",
" value=0.0,\n",
" description='',\n",
" disabled=False,\n",
" layout=Layout(width='150px')\n",
")\n",
"\n",
"fun_level = widgets.IntText(\n",
" value=0,\n",
" description='',\n",
" disabled=False,\n",
" layout=Layout(width='150px')\n",
")\n",
"\n",
"fun_idx = widgets.IntText(\n",
" value=0,\n",
" description='',\n",
" disabled=False,\n",
" layout=Layout(width='150px')\n",
")\n",
"\n",
"\n",
"show_hull = widgets.Checkbox(\n",
" value=False,\n",
" description='Show convex hull',\n",
" disabled=False,\n",
" indent=False\n",
")\n",
"\n",
"\n",
"def update_plot(b):\n",
" if knots_input.value != \"\":\n",
" draw_Bspline_basis(out)\n",
" \n",
"draw_button = widgets.Button(description='Draw Bspline Basis',layout=Layout(width='400px'),merge=False)\n",
"draw_button.on_click(update_plot)\n",
"label1 = widgets.Label(value=\"Wektor węzłów (przecinek jako separator)\", layout={'width': \"400px\"})\n",
"label2 = widgets.Label(value=\"Stopień funkcji bazowej(pusty == wszystkie)\", layout={'width': \"400px\"})\n",
"label3 = widgets.Label(value=\"Indeks funkcji bazowej\", layout={'width': \"400px\"})\n",
"\n",
"grid = widgets.GridspecLayout(4, 2)\n",
"grid[0,0] = widgets.HBox([label1,knots_input])\n",
"grid[0,1] = draw_button\n",
"#grid[1, 0] = widgets.HBox([label2,par_val])\n",
"grid[1, 0] = widgets.HBox([label2,fun_level])\n",
"grid[2, 0] = widgets.HBox([label3,fun_idx])\n",
"\n",
"display(grid,out)\n",
"#draw_Bspline(out\n"
]
},
{
"cell_type": "markdown",
"id": "4d014983",
"metadata": {},
"source": [
"## Zadania "
]
},
{
"cell_type": "markdown",
"id": "a2ba0722",
"metadata": {},
"source": [
"\n",
"\n",
"\n",
"<ol>\n",
"<li> <b>Wymierne krzywe Beziera</b> \n",
" <ol> \n",
" <li> W skrypcie 3.3.3. dodaj możliwość wystąpienia wag ujemnych oraz zabezpiecz się na wagi powodujące dzielenie przez zero. Przetestuj konstrukcje krzywych z niektórymi wagami równymi zero oraz (niezależnie) wagami ujemnymi\n",
"\n",
" <li> Napisać wesję skryptu z punktu 2.4. dla wymiernych krzywych Beziera (<b>nieobowiązkowe</b>)\n",
"\n",
" <li> Napisać program implementujący i wizualizujący krzywe Hermite'a oraz krzywe Beziera w 3D (w obu przypadkach 3 stopnia) (zob. <a href=\"https://matplotlib.org/2.0.2/examples/mplot3d/lines3d_demo.html\">matplotlib demo</a>) \n",
" oraz (nieobowiązkowo) ich łączenie.\n",
"\n",
" \n",
" <li> Napisać program implementujący i wizualizujący wymierne krzywe Beziera stopnia 3 w 3D oraz (nieobowiązkowo) ich łączenie. Przetestować rysowanie krzywych stożkowych.\n",
"\n",
"</ol>\n",
" \n",
"<li> <b>Krzywe B-spline</b>\n",
" \n",
" <ol> \n",
" <li> W skrypcie 4.2 wykonać następujące doświadzenia\n",
" \n",
" <ol>\n",
"\n",
" <li> Ustalić wektor węzłów na 0,1,2,3, stopień funkcji bazowej na 2, indeks funkcji bazowej na 0.\n",
"\n",
" Zaobserwować, że nośnik funkcji bazowej, to 0-3 oraz że najbardziej wpływa ona w centrum tego zakresu, tzn. pomiędzy węzłami 1,2 \n",
"\n",
" <li> Zmienić wektor węzłów na 0,1,1,3 - zwiększenie krotności węzła drugiego do 2,\n",
"\n",
" Zaobserwować, że nośnik funkcji bazowej pozostaje bez zmian, ale istotna wartość funkcji kumuluje się w otoczeniu węzła drugiego\n",
"\n",
" <li> Zmienić wektor węzłów na 0,1,1,1,3 - zwiększenie krotności węzła drugiego do 3\n",
"\n",
" Zaobserwować, że nośnik funkcji bazowej, to 0-1 (na prawo od drugiego węzła wpływ funkcji jest zerowy ) oraz, że funkcja najbardziej wpływa w węźle o krotności 3.\n",
"\n",
"<li> Zmienić wektor węzłów na 0,1,3,3 - zwiększenie krotności węzła trzeciego do 2\n",
"\n",
" Zaobserwować, że nośnik funkcji bazowej, to nadal 0-3, ale nastąpiło przesunięcie maksymalnego wpływu funkcji w kierunku węzła 3\n",
"\n",
" <li> Zmienić wektor węzłów na 0,3,3,3 - zwiększenie krotności węzła drugiego do 3\n",
"\n",
" Zaobserwować, że nośnik funkcji bazowej, to nadal 0-3, ale nastąpiło kolejne przesunięcie maksymalnego wpływu funkcji w kierunku węzła 3 (teraz maksimum jest w tym węźle)\n",
"\n",
"<li> Zmienić wektor węzłów na 0,1,3,3,3 \n",
"\n",
" Zaobserwować, że nośnik funkcji bazowej, to nadal 0-3, ale ostatni węzeł nie ma wpływu na kształt funkcji. Następnie zmienić indeks funkcji na 1 i zaobserwowować, że tym razem węzeł o wartości 0 nie ma wpływu na wartość funkcji - wynika to z faktu, że dziedziną funkcji $N_{1,2}(t)$ jest przedział $[1,4)$ (natomiast funkcji $N_{0,2}(t)$ przedział $[0,3)$) \n",
"\n",
" </ol>\n",
" <li> Wykonać analogiczne doświadczenia dla funkcji bazowej stopnia 3 \n",
" </ol> \n",
" \n",
"</ol>\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ce32b4f7",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.5"
},
"latex_envs": {
"LaTeX_envs_menu_present": true,
"autoclose": false,
"autocomplete": true,
"bibliofile": "biblio.bib",
"cite_by": "apalike",
"current_citInitial": 1,
"eqLabelWithNumbers": true,
"eqNumInitial": 1,
"hotkeys": {
"equation": "Ctrl-E",
"itemize": "Ctrl-I"
},
"labels_anchors": false,
"latex_user_defs": false,
"report_style_numbering": false,
"user_envs_cfg": false
}
},
"nbformat": 4,
"nbformat_minor": 5
}