1980 lines
233 KiB
Plaintext
1980 lines
233 KiB
Plaintext
|
{
|
||
|
"cells": [
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"# Przygotowanie innowacyjnych materiałów szkoleniowych i dokumentacji wewnętrznych w obszarze IT\n",
|
||
|
"\n",
|
||
|
"## 4. Jupyter - kalkulator symboliczny: zadanie \"Pudełko Pad Thai\"\n",
|
||
|
"### <i>Bartosz Naskręcki</i>\n",
|
||
|
"\n",
|
||
|
"W tym pliku rozważymy zadanie z geometrii, którego rozwiązanie może być w całości wykonane z wykorzystaniem możliwości symbolicznych pakietu SymPy. Wszystkie obliczenia będą wykonane w rachunku symbolicznym, co powoduje, że nasze wyniki nie są przybliżeniami i wszelkie uzyskane formuły są udowodnione w sposób algebraiczny."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"## Zadanie:\n",
|
||
|
"\n",
|
||
|
"Rozważamy pudełko, którego ściany są pięciokątami foremnymi o długości boku 1. Podstawa pudełka jest kwadratem o boku 1. Zakładając, że ściany pudełka stykają się, oblicz jaka jest odległość pomiędzy górnymi wierzchołkami ścian pudełka leżących naprzeciw siebie."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"<img src=\"pad_thai.png\"></img>"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Wykonujemy import z biblioteki SymPy. W przypadku komunikatu o błędzie importu, należy zainstalować bibliotekę w lokalnej instancji Pythona."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 93,
|
||
|
"metadata": {},
|
||
|
"outputs": [],
|
||
|
"source": [
|
||
|
"from sympy import *"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Biblioteka [SymPy](https://www.sympy.org) posiada wbudowane możliwości rachunków symbolicznych na zmiennych oraz obsługę funkcji matematycznych wraz z relacjami pomiędzy nimi. Konstruując rozwiązanie naszego zadania zapoznamy się z szeregiem standardowych funkcjonalności. Rozszerzone możliwości tej biblioteki są wbudowane w pakiet matematyczny [SageMath](https://www.sagemath.org)."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"## Strategia rozwiązania zadania:\n",
|
||
|
"\n",
|
||
|
"Aby obliczyć pożądaną odległość spróbujemy \"wyobrazić\" sobie całą sytuację. Powstanie pudełka polega na obróceniu w przestrzeni 3D czterech pięciokątnych ścian o pewien kąt $\\alpha$. Wybór tego kąta jest jednoznacznie ustalony przez warunek stykania się ścian wzdłuż zewnętrznych krawędzi. Nasza strategia wygląda więc następująco:\n",
|
||
|
"\n",
|
||
|
"1. Generujemy mechanizm, który wyznacza symbolicznie współrzędne wierzchołków pięciokąta foremnego.\n",
|
||
|
"2. Pozycjonujemy cztery kopie takiego pięciokąta na płaszczyźnie.\n",
|
||
|
"3. Korzystając z transformacji obrotu o zadany kąt względem prostej obracamy wybrane ściany o pewien nieznany kąt $\\alpha$. \n",
|
||
|
"4. Formułujemy warunek stykania ścian (warunek ten jest równaniem).\n",
|
||
|
"5. Wyznaczamy kąt z równania (jako wyrażenie symboliczne).\n",
|
||
|
"6. Obliczamy odległość zadanych punktów korzystając z wbudowanych w SymPy tożsamości trygonometrycznych."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"## Macierz obrotu o zadany kąt\n",
|
||
|
"\n",
|
||
|
"Macierze w SymPy są inicjalizowane komendą <b>Matrix</b>. Jako argument funkcja ta pobiera listę składającą z się z list tej samej długości (reprezentujących wiersze)."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 5,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/latex": [
|
||
|
"$\\displaystyle \\left[\\begin{matrix}1 & 2\\\\3 & 4\\end{matrix}\\right]$"
|
||
|
],
|
||
|
"text/plain": [
|
||
|
"Matrix([\n",
|
||
|
"[1, 2],\n",
|
||
|
"[3, 4]])"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 5,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"M1=Matrix([[1,2],[3,4]])\n",
|
||
|
"M1"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Na macierzach możemy wykonywać standardowe operacje dodawania i mnożenia, operację obliczania śladu, wyznacznika i wiele innych. Użytkownik może sprawdzić aktualną listę zaimplementowanych funkcji za pomocą nazwy obiektu i kropki oraz przez wciśnięcie tabulatora"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": null,
|
||
|
"metadata": {},
|
||
|
"outputs": [],
|
||
|
"source": [
|
||
|
"M1. #<+tabulator>"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Macierz obrotu wokół punktu $(0,0)$ o zadany kąt $t$ (przeciwnie do ruchu wskazówek zegara) jest macierzą postaci"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 14,
|
||
|
"metadata": {},
|
||
|
"outputs": [],
|
||
|
"source": [
|
||
|
"def obrot(t):\n",
|
||
|
" m=Matrix([[cos(t),-sin(t)],[sin(t),cos(t)]])\n",
|
||
|
" return m"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 16,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/latex": [
|
||
|
"$\\displaystyle \\left[\\begin{matrix}0 & -1\\\\1 & 0\\end{matrix}\\right]$"
|
||
|
],
|
||
|
"text/plain": [
|
||
|
"Matrix([\n",
|
||
|
"[0, -1],\n",
|
||
|
"[1, 0]])"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 16,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"obrot(pi/2) #obrót o 90 stopni przeciwnie do ruchu wskazówek zegara"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Działanie macierzy obrotu możemy przetestować na wektorach (macierzach o wymiarach $1\\times n$). Wykorzystamy zmienne symboliczne, aby wyrazić działanie w ogólnym przypadku"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 20,
|
||
|
"metadata": {},
|
||
|
"outputs": [],
|
||
|
"source": [
|
||
|
"x,y=symbols('x,y') #za pomocą komendy symbols możemy inicjalizować listę abstrakcyjnych zmiennych symbolicznych"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Na zmiennych symbolicznych $x,y$ możemy wykonywać operacje podstawiania, elementarne operacje oraz wykorzystywać je jako argumenty w funkcjach, a także podstawiać pod nie wartości."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 24,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/latex": [
|
||
|
"$\\displaystyle x + y$"
|
||
|
],
|
||
|
"text/plain": [
|
||
|
"x + y"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 24,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"#dodawanie zmiennych\n",
|
||
|
"x+y"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 25,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/latex": [
|
||
|
"$\\displaystyle x y$"
|
||
|
],
|
||
|
"text/plain": [
|
||
|
"x*y"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 25,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"#mnożenie zmiennych\n",
|
||
|
"x*y"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 26,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/latex": [
|
||
|
"$\\displaystyle x^{y}$"
|
||
|
],
|
||
|
"text/plain": [
|
||
|
"x**y"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 26,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"#potęgowanie zmiennych\n",
|
||
|
"x**y"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"<b>UWAGA!</b>\n",
|
||
|
"\n",
|
||
|
"W standardowym Pythonie symbol ^ oznacza operację dodawania bitowego XOR. Do oznaczenia potęgowania używamy symbolu **"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 27,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/latex": [
|
||
|
"$\\displaystyle \\sin{\\left(y \\right)} + \\cos{\\left(x \\right)}$"
|
||
|
],
|
||
|
"text/plain": [
|
||
|
"sin(y) + cos(x)"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 27,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"#funkcja z abstrakcyjnym argumentem\n",
|
||
|
"cos(x)+sin(y)"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 29,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/latex": [
|
||
|
"$\\displaystyle \\sin{\\left(y^{2} + 1 \\right)}$"
|
||
|
],
|
||
|
"text/plain": [
|
||
|
"sin(y**2 + 1)"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 29,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"#podstawienie argumentu\n",
|
||
|
"#w celu podstawienie wykorzystujemy strukturę słownika dict, której kluczami są podstawiane zmienne, a wartościami kluczy\n",
|
||
|
"#są wartości podstawiane\n",
|
||
|
"sin(x).subs({x:y**2+1})"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 30,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/latex": [
|
||
|
"$\\displaystyle 0.900968867902419$"
|
||
|
],
|
||
|
"text/plain": [
|
||
|
"0.900968867902419"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 30,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"#wartości symboliczne można przybliżać numerycznie\n",
|
||
|
"cos(pi/7).n()"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 31,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/plain": [
|
||
|
"0.9009688679024191"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 31,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"#możemy konwertować wartości numeryczne do standardowego typu danych float\n",
|
||
|
"float(cos(pi/7))"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Ciekawostka:\n",
|
||
|
"Niektóre stałe matematyczne, np. $\\pi$ są wbudowane w SymPy i traktowane jako pewne zmienne symboliczne, które posiadają szczególne własności, np. wartości $\\cos(\\pi/n)$ można podać algebraicznie i numerycznie. To bardzo wygodny sposób operowania podstawowymi stałymi matematyki."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Zbadajmy działanie operacji obrotu o kąt $t$ na wektorze o zmiennych symbolicznych $(x,y)$ "
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 42,
|
||
|
"metadata": {},
|
||
|
"outputs": [],
|
||
|
"source": [
|
||
|
"t,x,y=symbols('t,x,y') #UWAGA: nie musimy ponownie deklarować zmiennych symbolicznych, robimy to tylko dla zachowania\n",
|
||
|
" #przejrzystości kodu"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 43,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/latex": [
|
||
|
"$\\displaystyle \\left[\\begin{matrix}x\\\\y\\end{matrix}\\right]$"
|
||
|
],
|
||
|
"text/plain": [
|
||
|
"Matrix([\n",
|
||
|
"[x],\n",
|
||
|
"[y]])"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 43,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"v=Matrix([[x],[y]])\n",
|
||
|
"v"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 44,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/latex": [
|
||
|
"$\\displaystyle \\left[\\begin{matrix}\\cos{\\left(t \\right)} & - \\sin{\\left(t \\right)}\\\\\\sin{\\left(t \\right)} & \\cos{\\left(t \\right)}\\end{matrix}\\right]$"
|
||
|
],
|
||
|
"text/plain": [
|
||
|
"Matrix([\n",
|
||
|
"[cos(t), -sin(t)],\n",
|
||
|
"[sin(t), cos(t)]])"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 44,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"obrot_o_t=obrot(t)\n",
|
||
|
"obrot_o_t"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 45,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/latex": [
|
||
|
"$\\displaystyle \\left[\\begin{matrix}x \\cos{\\left(t \\right)} - y \\sin{\\left(t \\right)}\\\\x \\sin{\\left(t \\right)} + y \\cos{\\left(t \\right)}\\end{matrix}\\right]$"
|
||
|
],
|
||
|
"text/plain": [
|
||
|
"Matrix([\n",
|
||
|
"[x*cos(t) - y*sin(t)],\n",
|
||
|
"[x*sin(t) + y*cos(t)]])"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 45,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"#obrót wektora (x,y) o kąt t\n",
|
||
|
"obrot_o_t*v"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Zadanie: jakie są współrzędne wektora $(1,3)$ po obrocie o kąt $\\pi/4$ ?"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 50,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/latex": [
|
||
|
"$\\displaystyle \\left[\\begin{matrix}- \\sqrt{2}\\\\2 \\sqrt{2}\\end{matrix}\\right]$"
|
||
|
],
|
||
|
"text/plain": [
|
||
|
"Matrix([\n",
|
||
|
"[ -sqrt(2)],\n",
|
||
|
"[2*sqrt(2)]])"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 50,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"(obrot_o_t*v).subs({x:1,y:3,t:pi/4})"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Zadanie: Korzystając z wektorów i macierzy obrotów wyznacz współrzędne wierzchołków wielokata foremnego (mającego $n$ boków) na płaszczyźnie, którego boki mają długość 1\n",
|
||
|
"\n",
|
||
|
"Rozwiązanie metodą \"żółwia\":\n",
|
||
|
"\n",
|
||
|
"1. Wystartuj w punkcie $(0,0)$.\n",
|
||
|
"2. Przesuń się o jednostkę w prawo za pomocą wektora $k=(1,0)$. Jesteś w punkcie $P_0=(1,0)$.\n",
|
||
|
"3. Obróć głowę żółwia o kąt $2\\cdot \\pi/n$.\n",
|
||
|
"4. Przesuń żółwia o jednostkę \"do przodu\". Jesteś w punkcie $P_1=P_0+\\theta(t)(k)$\n",
|
||
|
"5. Powtarzaj punkty (3)-(5) $n-1$ razy.\n",
|
||
|
"\n",
|
||
|
"Zwróć listę wierzchołków: $P_0,\\ldots, P_{n-1}$.\n",
|
||
|
"\n",
|
||
|
"Uwaga: Operacja $\\theta(t)$ to obrót wektora o zadany kąt $t$. W naszym przypadku mnożymy wektor kolumnowy z lewej przez macierz obrotu o kąt $t$."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 127,
|
||
|
"metadata": {},
|
||
|
"outputs": [],
|
||
|
"source": [
|
||
|
"def NkatForemny(n):\n",
|
||
|
" p0=Matrix([[0],[0]])\n",
|
||
|
" k=Matrix([[1],[0]])\n",
|
||
|
" ob=obrot(2*pi/n)\n",
|
||
|
" nkat=[]\n",
|
||
|
" w=p0+k\n",
|
||
|
" for i in range(0,n):\n",
|
||
|
" nkat.append(w)\n",
|
||
|
" k=ob*k #obróć żółwia\n",
|
||
|
" w+=k #przesuń o jednostkę w nowym kierunku\n",
|
||
|
" return nkat"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 131,
|
||
|
"metadata": {
|
||
|
"scrolled": true
|
||
|
},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"name": "stdout",
|
||
|
"output_type": "stream",
|
||
|
"text": [
|
||
|
"⎡ ⎡1/2⎤ ⎤\n",
|
||
|
"⎢⎡1⎤ ⎢ ⎥ ⎡0⎤⎥\n",
|
||
|
"⎢⎢ ⎥, ⎢√3 ⎥, ⎢ ⎥⎥\n",
|
||
|
"⎢⎣0⎦ ⎢── ⎥ ⎣0⎦⎥\n",
|
||
|
"⎣ ⎣2 ⎦ ⎦\n"
|
||
|
]
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"pretty_print(NkatForemny(3)) #współrzędne trójkąta foremnego"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"## Rysowanie z biblioteką matplotlib\n",
|
||
|
"\n",
|
||
|
"Do rysowania wykorzystamy uniwersalną bibliotekę matplotlib. Na potrzeby prawidłowego rysowania korzystamy z dodatkowej \"magicznej komendy\"\n",
|
||
|
"\n",
|
||
|
"%matplotlib inline"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 132,
|
||
|
"metadata": {},
|
||
|
"outputs": [],
|
||
|
"source": [
|
||
|
"%matplotlib inline\n",
|
||
|
"import matplotlib.pyplot as plt"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"### Rysowanie wielokątów\n",
|
||
|
"\n",
|
||
|
"Wielokąt w bibliotece matplotlib możemy narysować korzystając z komendy `fill`. Do narysowania wielokąta przekazujemy osobno jako argumenty wartości współrzędnych $x$-owych i $y$-owych. Do rozbicia listy wierzcholków na współrzędne używamy komendy \n",
|
||
|
"\n",
|
||
|
"`zip(*lista_wierzcholkow)`\n",
|
||
|
"\n",
|
||
|
"Uwaga: aby figury nie nachodziły na siebie przesuwamy macierzowo zbiory wierzchołków o odpowiedni wektor $(3i,0)$ dla każdej $i$-tej figury."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 134,
|
||
|
"metadata": {
|
||
|
"scrolled": true
|
||
|
},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"image/png": "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
|
||
|
"text/plain": [
|
||
|
"<Figure size 432x288 with 1 Axes>"
|
||
|
]
|
||
|
},
|
||
|
"metadata": {
|
||
|
"needs_background": "light"
|
||
|
},
|
||
|
"output_type": "display_data"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"fig = plt.figure()\n",
|
||
|
"for i in range(0,5):\n",
|
||
|
" wielokatli=(list(tuple(wierzcholek+Matrix([[3*i],[0]])) for wierzcholek in NkatForemny(i+3)));\n",
|
||
|
" wielokatli.append(wielokatli[0]) #dla domknięcia dodajemy ostatni wierzchołek równy pierwszemu\n",
|
||
|
" xli,yli=zip(*wielokatli)\n",
|
||
|
" plt.axis('equal') #proporcjonalne osie\n",
|
||
|
" #axis('off')\n",
|
||
|
" plt.fill(xli,yli)\n",
|
||
|
"plt.show() #rysowanie skonfigurowanej ilustracji"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Teraz jesteśmy już gotowi do wygenerowania naszego modelowego pięciokąta foremnego. Pamiętamy o dodaniu na końcu listy dodatkowego wierzchołka, który jest równy $P_0$. Jest to potrzebne dla prawidłowego rysowania wielokątów."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 173,
|
||
|
"metadata": {},
|
||
|
"outputs": [],
|
||
|
"source": [
|
||
|
"pieciokat0=NkatForemny(5)\n",
|
||
|
"pieciokat0.append(pieciokat0[0])\n",
|
||
|
"pieciokat=[Matrix([[list(y)[0].simplify()],[list(y)[1].simplify()]]) for y in pieciokat0] #upraszczamy formuły"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"W kodzie powyżej użyliśmy potężnej funkcjonalności \n",
|
||
|
"\n",
|
||
|
"`<wyrazenie>.simplify()`\n",
|
||
|
"\n",
|
||
|
"która upraszcza w znany SymPy sposób wyrażenia symboliczne. Do uproszczeń stosuje się znane zależności między funkcjami oraz tożsamości. Efekt działania tej komendy zależy w istotny sposób od wyrażenia i jest zawsze taki sam dla tego samego wyrażenia."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 140,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"image/png": "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
|
||
|
"text/plain": [
|
||
|
"<Figure size 360x360 with 1 Axes>"
|
||
|
]
|
||
|
},
|
||
|
"metadata": {
|
||
|
"needs_background": "light"
|
||
|
},
|
||
|
"output_type": "display_data"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"wielokatli=list(tuple(wierzcholek) for wierzcholek in NkatForemny(5));\n",
|
||
|
"wielokatli.append(wielokatli[0])\n",
|
||
|
"xli,yli=zip(*wielokatli)\n",
|
||
|
"fig=plt.figure(figsize=[5,5]) #wielkość figury w kierunku x i y\n",
|
||
|
"plt.axis('equal')\n",
|
||
|
"plt.axis('off') #wyłączenie wyświetlania osi\n",
|
||
|
"plt.fill(xli,yli,color='red')\n",
|
||
|
"plt.show()"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Wielokąty możemy na siebie nakładać i kolorować. Poniższy przykład polega na obracaniu pięciokątów o zadany kąt i ustawianiu ich jeden na drugim, ze zmieniającym się kolorem. Kolor jest zadany jako `color=(R,G,B)`, gdzie parametry $R$, $G$, $B$ są liczbami rzeczywistymi w przedziale $0$ do $1$."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 243,
|
||
|
"metadata": {
|
||
|
"scrolled": true
|
||
|
},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"image/png": "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
|
||
|
"text/plain": [
|
||
|
"<Figure size 360x360 with 1 Axes>"
|
||
|
]
|
||
|
},
|
||
|
"metadata": {
|
||
|
"needs_background": "light"
|
||
|
},
|
||
|
"output_type": "display_data"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"#wyznaczanie środka ciężkości\n",
|
||
|
"def sumM(li): \n",
|
||
|
" sum0=li[0]\n",
|
||
|
" for el in li[1:]:\n",
|
||
|
" sum0+=el\n",
|
||
|
" return sum0*Rational(1,len(li))\n",
|
||
|
"\n",
|
||
|
"#obrót wielokąta po przesunięcia środka ciężkości do (0,0) i przesunięcie go z powrotem + zastosowanie skali\n",
|
||
|
"def obrotSkalaWielokat(wiel,t,skala): #wiel[:-1]==wiel[0]\n",
|
||
|
" s=sumM(wiel[:-1])\n",
|
||
|
" rot=[obrot(t)*((el-s)*skala)+s for el in wiel[:-1]]\n",
|
||
|
" return rot+[rot[0]]\n",
|
||
|
"\n",
|
||
|
"\n",
|
||
|
"#inicjalizacja figury\n",
|
||
|
"fig=plt.figure(figsize=[5,5]) #wielkość figury w kierunku x i y\n",
|
||
|
"plt.axis('equal')\n",
|
||
|
"#plt.axis('off') #wyłączenie wyświetlania osi\n",
|
||
|
"\n",
|
||
|
"#trzydzieści iteracji rysowania pięciokąta\n",
|
||
|
"iteracje=30\n",
|
||
|
"for i in range(0,iteracje):\n",
|
||
|
" wielokatli=obrotSkalaWielokat(pieciokat,2*i*pi/(5*iteracje),Rational(iteracje-i,40*iteracje))\n",
|
||
|
" xli,yli=zip(*wielokatli)\n",
|
||
|
" plt.fill(xli,yli,color=(1-(i/iteracje)**(1/2),(i/iteracje)**2,(iteracje-i)/iteracje))\n",
|
||
|
"plt.show()"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Wracając do naszego głównego zadania, pozycjonujemy cztery pięciokącie na płaszczyźnie, aby stworzyły makietę ścian naszego pudełka. Ponieważ dno pudełka nie będzie nam potrzebne, więc je ignorujemy.\n",
|
||
|
"\n",
|
||
|
"Pozycjonowanie odbywa się za pomocą obrotów o kąty $0,90,180$ i $270$ stopni, wraz z odpowiednimi przesunięciami o wektory na płaszczyźnie. Do szybkiego przetransformowania odpowiednich wektorów stosujemy komendę `map` wraz z argumentem, którym jest funkcja transformująca i lista (w tym przypadku `pieciokat`)."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 245,
|
||
|
"metadata": {},
|
||
|
"outputs": [],
|
||
|
"source": [
|
||
|
"pi1=list(map(lambda x: x+Matrix([[0],[1]]),pieciokat))\n",
|
||
|
"pi2=list(map(lambda x: obrot(-pi/2)*x+Matrix([[1],[1]]),pieciokat))\n",
|
||
|
"pi3=list(map(lambda x: obrot(-pi)*x+Matrix([[1],[0]]),pieciokat))\n",
|
||
|
"pi4=list(map(lambda x: obrot(-3/2*pi)*x+Matrix([[0],[0]]),pieciokat))"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 249,
|
||
|
"metadata": {
|
||
|
"scrolled": true
|
||
|
},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAUQAAAEvCAYAAAA92bhfAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/Il7ecAAAACXBIWXMAAAsTAAALEwEAmpwYAAAtPklEQVR4nO3dd5wU9f3H8deHAw4woCAHIu0wwYIoAhcEpSgKgkGKh5GzgYUiYIkkSkwUf8bEaNQoaIJYiAUhEQRBURQpFhQ4zB0qTUQNnQOV3g4+vz9m1ROu78x+Z3c/z8djHuztzs33M7vs+6Z9vyOqijHGGKjgugBjjAkLC0RjjImwQDTGmAgLRGOMibBANMaYCAtEY4yJqOi6gOLUrl1b09PTXZdhjEkwS5Ys2aqqaUc+H+pATE9PJzs723UZxpgEIyJfF/a87TIbY0yEBaIxxkRYIBpjTIQFojHGRFggGmNMhAWiMcZERB2IItJQROaKyDIR+UxEbilknvNEZLuI5ESmu6Nt1xhj/ObHdYj5wAhV/VhEqgNLRORtVV12xHzvqWoPH9oz5keHDsG998LGjfDoo1CtmuuKTByLOhBVdSOwMfJ4p4gsB+oDRwaiMf763//gyivh/fe9n997DyZNghYt3NZl4pavxxBFJB1oCSws5OV2IpIrIm+IyOnFLGOQiGSLSHZeXp6f5ZlEMmUKnHXWj2EIsGIFnH02jB7trCwT33wLRBH5GTAFuFVVdxzx8sdAY1VtAYwBphW1HFUdp6oZqpqRlnZUV0OT7PbuhcGDoW9f+Pbbo1/fvx9uuQUuuQS2bo19fSau+RKIIlIJLwwnqOorR76uqjtUdVfk8UygkojU9qNtk0Q++QQyMmDcuJLnfe01b9d57tzg6zIJw4+zzAI8AyxX1UeKmOeEyHyISJtIu9uibdskkSeegDZtYFkZDk1v2AAXXgh33gn5+cHVZhKGH2eZzwWuBj4RkZzIc3cCjQBUdSzQF7hRRPKBvUA/tdv9mdL45hu47jp49dXy/f7hw3D//d6W4sSJYMPJmWJImHMpIyNDbfivJDZ/Plx1Faxb58/yjj0WnnwSLr/cn+WZuCUiS1Q148jnraeKCZ9Dh+Cuu6BzZ//CEGD7dujXz9vi3L3bv+WahGGBaMLl66+hY0e47z5vdzcI48dD69aQkxPM8k3cskA04TF5sndt4YIFwbe1ciW0bev1bjEmwgLRuLdnDwwcCJddBt99F7t29++H3/wGevQA6wRgsEA0ri1d6l1b+PTT7mp4/XXvmsV33nFXgwkFC0Tjzpgx3rWFy5e7rsQbHKJrVxg50q5ZTGIWiCb2tm2DXr3g5pu93dawOHwYHngA2reHNWtcV2McsEA0sTV3Lpx5Jkyf7rqSoi1cCC1behdym6RigWhiIz8f/vAHryvdhg2uqynZjh1wxRUwYADs2uW6GhMjFogmeF995V1b+Je/BHdtYVCee867ZvHjj11XYmLAAtEE6z//8a4t/PBD15WU36pV0K4dPPIIhLirq4meBaIJxp49cP31Xr/h7dtdVxO9AwdgxAj41a9gyxbX1ZiAWCAa/+XmeruZzz7ruhL/vfGGd83i22+7rsQEwALR+Ouxx7xh/FescF1JcDZtgosugttvh4MHXVdjfGSBaPyxdas3bP+tt4br2sKgqMLf/gbnngtffOG6GuMTC0QTvTlzvN3I115zXUnsLV7sXbM4YYLrSowPLBBN+eXne8Pzd+kSH9cWBmXnTm8g22uusWsW45wFoimfL7/0urjdf3/8XVsYlBdegFatYMkS15WYcrJANGU3aZJ3beHCwm6/neQ+/9y7ZvGhh+yaxThkgWhKb/dub/j9rCyva5sp3MGD8LvfQffusHmz62pMGVggmtL573+93cHx411XEj9mzfJONs2a5boSU0oWiKZkjz7qDbe/apXrSuLP5s3eluJvf2vXLMYBP25U31BE5orIMhH5TERuKWQeEZHRIrJaRJaKSKto2zUxkJfndVX7zW+8rmumfFTh4YfhnHNg9WrX1Zhi+LGFmA+MUNVmQFtgmIg0O2Ke7kDTyDQI+KcP7ZogzZ7tjVs4c6brShJHdrZ3zeLzz7uuxBQh6kBU1Y2q+nHk8U5gOVD/iNl6Ac+r5yPgOBGpF23bJgD5+d4w+l27el3UjL927YL+/eHqq73rF02o+HoMUUTSgZbAkddj1AfWFvh5HUeHpnFtzRqvK9oDD9glI0F78UVva3HxYteVmAJ8C0QR+RkwBbhVVct9TYaIDBKRbBHJzrNbQ8bOSy95X9BFi1xXkjy++ML7A/Tgg/YHKCR8CUQRqYQXhhNU9ZVCZlkPNCzwc4PIc0dR1XGqmqGqGWlpaX6UZ4qza5c3TP6VV9q1hS4cPAh33OGNnmOHKJzz4yyzAM8Ay1X1kSJmmw5cEznb3BbYrqobo23bRGnLFm/cwueec12Jeftt75rFTz5xXUlSq+jDMs4FrgY+EZGcyHN3Ao0AVHUsMBO4GFgN7AGu9aFdE63jjrOtkjDZsgVq1HBdRVKLOhBV9X1ASphHgWHRtmV8Vrky9OjhHT807mVkQOPGrqtIatZTJdllZrquwHzPPgvnLBCTXffucMwxrqswAH37uq4g6VkgJruqVb1QNG6deSb84heuq0h6FojGdtXCwD6DULBANN4ADqmprqtIbhaIoWCBaKB6da/vsnHj1FPh9NNdV2GwQDTfsy0Ud+y9Dw0LROPp1QsqVXJdRXKyQAwNC0TjOe446NzZdRXJp0kTb1ANEwoWiOZHtqUSe/aeh4oFovlR796QkuK6iuRigRgqFojmR2lp0KGD6yqSR4MGcPbZrqswBVggmp+yLZbYufRSkGLHRTExZoFofsq+pLFjf3xCxwLR/NSJJ0K7dq6rSHx160L79q6rMEewQDRHsy2X4PXuDRXs6xc29omYo116qesKEp/90QklC0RztPR0714rJhi1asH557uuwhTCAtEUzrZggtOrF1T043ZGxm8WiKZwNnpzcOyPTWhZIJrCNW0KZ5zhuorEU6MGdOniugpTBAtEUzTbkvFfjx7e3Q5NKPkSiCLyrIhsEZFPi3j9PBHZLiI5keluP9o1AbNA9J8digg1v7YQ/wV0K2Ge91T1rMh0r0/tmiA1bw4nn+y6isRxzDHQraSviXHJl0BU1XeBb/xYlgkZ20r0T/fu3l0OTWjF8hhiOxHJFZE3RMRuIBEvbBfPP/bHJfRiFYgfA41VtQUwBphW1IwiMkhEskUkOy8vL0blmSK1auWN6myik5rq3d3QhFpMAlFVd6jqrsjjmUAlEaldxLzjVDVDVTPS0tJiUZ4piXXli17Xrt7dDU2oxSQQReQEEW9MKRFpE2l3WyzaNj6wXb3o2aGHuOBL/yERmQicB9QWkXXAKKASgKqOBfoCN4pIPrAX6Keq6kfbJgbatoX69WH9eteVxKdKlaBnT9dVmFLwJRBVNauE1x8HHvejLeOACPTpA4/bR1gunTt7dzU0oWc9VUzp2C5f+dkhh7hhgWhKp0MHqFPHdRXxJyXFGwzWxAULRFM6FSrYF7s8Onb07mZo4oIFoik92/UrO3vP4ooFoim9zp290Z5N6Xx/MsrEDQtEU3oVK9rlI2XRrp13F0MTNywQA/TFF1+wZMkS12X4y3YBSy/B3quVKyE313UVwbJADMi+ffvo06cPGRkZNGnShBEjRrBgwQLi/nr0Ll2sC1ppJUAgLl0Ko0Z5I8GdeipcdBFs3uy6qgCpamin1q1ba7waOnSoAkdN9evX1+HDh+vcuXM1Pz/fdZnlk5WlCjYVN2VkuP6Uym3xYtWRI1WbNi181S66SPXwYddVRgfI1kIyx3noFTfFayBOmzat0DA8ckpLS9OBAwfqrFmz9ODBg67LLr3Jk90HTtin++93/SmV2uHDqh98oPqb36g2bly61fvb31xXHZ2iAlG818IpIyNDs7OzXZdRJuvWraNFixZ8803ZxsutWbMmPXv2JDMzk65du5KamhpQhT7Ys8e7tm7PHteVhNeqVd6NukLq0CF4912YMgWmToUNG8r2+5UqwYI
|
||
|
"text/plain": [
|
||
|
"<Figure size 360x360 with 1 Axes>"
|
||
|
]
|
||
|
},
|
||
|
"metadata": {
|
||
|
"needs_background": "light"
|
||
|
},
|
||
|
"output_type": "display_data"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"#definiujemy pomocniczą funkcję rysującą pojedynczy wielokąt\n",
|
||
|
"def polygon_draw(li,color):\n",
|
||
|
" wielokatli=list(tuple(wierzcholek) for wierzcholek in li);\n",
|
||
|
" wielokatli.append(wielokatli[0])\n",
|
||
|
" xli,yli=zip(*wielokatli)\n",
|
||
|
" plt.fill(xli,yli,color)\n",
|
||
|
"\n",
|
||
|
"fig=plt.figure(figsize=[5,5])\n",
|
||
|
"plt.axis('equal')\n",
|
||
|
"polygon_draw(pi1,color='red')\n",
|
||
|
"polygon_draw(pi2,color='blue')\n",
|
||
|
"polygon_draw(pi3,color='green')\n",
|
||
|
"polygon_draw(pi4,color='black')\n",
|
||
|
"plt.show()"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Teraz czeka nas trudniejsze zadanie. Musimy opracować wzory na obracanie naszych pięciokątów w trzech wymiarach, wokół krawędzi, która styka się z białym kwadratem. \n",
|
||
|
"\n",
|
||
|
"Nasze pięciokąty zyskają dodatkową, trzecią współrzędną, równą 0. Po obrocie ich współrzędne będą zazwyczaj niezerowe."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Obrót wokół osi $X$ odbywa się w ten sposób, że wektor $(x,y,z)$ zachowuje współrzędną $y$. Współrzędne $(x,z)$ obracamy za pomocą macierzy obrotu $\\theta(t)$ o zadany kąt $t$."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 258,
|
||
|
"metadata": {
|
||
|
"scrolled": true
|
||
|
},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/latex": [
|
||
|
"$\\displaystyle \\left[\\begin{matrix}x \\cos{\\left(t \\right)} - z \\sin{\\left(t \\right)}\\\\y\\\\x \\sin{\\left(t \\right)} + z \\cos{\\left(t \\right)}\\end{matrix}\\right]$"
|
||
|
],
|
||
|
"text/plain": [
|
||
|
"Matrix([\n",
|
||
|
"[x*cos(t) - z*sin(t)],\n",
|
||
|
"[ y],\n",
|
||
|
"[x*sin(t) + z*cos(t)]])"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 258,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"x,y,z,t=symbols('x,y,z,t')\n",
|
||
|
"v=Matrix([[x],[y],[z]]) #wektor poddany transformacji\n",
|
||
|
"vtmp=obrot(t)*Matrix([v[0],v[2]]) #obrót tylko na 0 i 2 współrzędnej\n",
|
||
|
"vobr=Matrix([[vtmp[0]],[v[1]],[vtmp[1]]]) #złączenie ponowne w wektor 3D\n",
|
||
|
"vobr"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Bazując na powyższych kalkulacjach definiujemy zatem funkcję"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 256,
|
||
|
"metadata": {},
|
||
|
"outputs": [],
|
||
|
"source": [
|
||
|
"def ObrotWX0(v,t):\n",
|
||
|
" x,y,z=list(v)\n",
|
||
|
" return Matrix([[x*cos(t) - z*sin(t), y, x*sin(t)+z*cos(t)]])"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Podobnie wyznaczamy obrót wokół osi Y"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 257,
|
||
|
"metadata": {},
|
||
|
"outputs": [],
|
||
|
"source": [
|
||
|
"def ObrotWY0(v,t):\n",
|
||
|
" x,y,z=list(v)\n",
|
||
|
" return Matrix([[x, y*cos(t) - z*sin(t), y*sin(t)+z*cos(t)]])"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Teraz chcemy obrócić wokół osi zadanej równaniem $x=1$. W związku z tym, najpierw przesuwamy nasze punktu o $1$ jednostkę w lewo, obracamy, a następnie wracamy o jedną jednostkę w prawo. Tak uzyskana transformacja będzie obrotem o zadany kąt wokół osi przechodzącej przez $x=1$."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 259,
|
||
|
"metadata": {
|
||
|
"scrolled": true
|
||
|
},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/latex": [
|
||
|
"$\\displaystyle \\left[\\begin{matrix}- z \\sin{\\left(t \\right)} + \\left(x - 1\\right) \\cos{\\left(t \\right)} + 1\\\\y\\\\z \\cos{\\left(t \\right)} + \\left(x - 1\\right) \\sin{\\left(t \\right)}\\end{matrix}\\right]$"
|
||
|
],
|
||
|
"text/plain": [
|
||
|
"Matrix([\n",
|
||
|
"[-z*sin(t) + (x - 1)*cos(t) + 1],\n",
|
||
|
"[ y],\n",
|
||
|
"[ z*cos(t) + (x - 1)*sin(t)]])"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 259,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"x,y,z,t=symbols('x,y,z,t')\n",
|
||
|
"v=Matrix([[x],[y],[z]]) #wektor poddany transformacji\n",
|
||
|
"vtmp=obrot(t)*Matrix([v[0]-1,v[2]]) #obrót tylko na 0 i 2 współrzędnej\n",
|
||
|
"vobr=Matrix([[vtmp[0]+1],[v[1]],[vtmp[1]]]) #złączenie ponowne w wektor 3D\n",
|
||
|
"vobr"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Przedstawiamy rezultat w formie stosownej funkcji"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 260,
|
||
|
"metadata": {},
|
||
|
"outputs": [],
|
||
|
"source": [
|
||
|
"def ObrotWX1(v,t):\n",
|
||
|
" x,y,z=list(v)\n",
|
||
|
" return Matrix([[-z*sin(t)+(x-1)*cos(t) +1 , y, z*cos(t) + (x-1)*sin(t)]])"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Analogiczny rachunek pozwala nam skonstruować funkcję obrotu wokół osi zadanej równaniem $y=1$"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 261,
|
||
|
"metadata": {},
|
||
|
"outputs": [],
|
||
|
"source": [
|
||
|
"def ObrotWY1(v,t):\n",
|
||
|
" x,y,z=list(v)\n",
|
||
|
" return Matrix([[x, 1 - cos(t) + y*cos(t) - z*sin(t), z*cos(t) - sin(t) + y*sin(t)]])"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Teraz mając zadany wektor oraz kąt obrotu, możemy śledzić zmiany konkretnych wektorów pod wpływem obrotów. Przykładowo"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 262,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/latex": [
|
||
|
"$\\displaystyle \\left[\\begin{matrix}\\cos{\\left(t \\right)} & 1 & \\sin{\\left(t \\right)}\\end{matrix}\\right]$"
|
||
|
],
|
||
|
"text/plain": [
|
||
|
"Matrix([[cos(t), 1, sin(t)]])"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 262,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"t=Symbol('t')\n",
|
||
|
"ObrotWX0([1,1,0],t)"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 263,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/latex": [
|
||
|
"$\\displaystyle \\left[\\begin{matrix}1 & \\cos{\\left(t \\right)} & \\sin{\\left(t \\right)}\\end{matrix}\\right]$"
|
||
|
],
|
||
|
"text/plain": [
|
||
|
"Matrix([[1, cos(t), sin(t)]])"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 263,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"ObrotWY0([1,1,0],t)"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 264,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/latex": [
|
||
|
"$\\displaystyle \\left[\\begin{matrix}\\cos{\\left(t \\right)} + 1 & 0 & \\sin{\\left(t \\right)}\\end{matrix}\\right]$"
|
||
|
],
|
||
|
"text/plain": [
|
||
|
"Matrix([[cos(t) + 1, 0, sin(t)]])"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 264,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"ObrotWX1([2,0,0],t)"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 265,
|
||
|
"metadata": {
|
||
|
"scrolled": true
|
||
|
},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/latex": [
|
||
|
"$\\displaystyle \\left[\\begin{matrix}0 & \\cos{\\left(t \\right)} + 1 & \\sin{\\left(t \\right)}\\end{matrix}\\right]$"
|
||
|
],
|
||
|
"text/plain": [
|
||
|
"Matrix([[0, cos(t) + 1, sin(t)]])"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 265,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"ObrotWY1([0,2,0],t)"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Potrzebujemy teraz biblioteki do rysowania kształtów w 3D"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 266,
|
||
|
"metadata": {},
|
||
|
"outputs": [],
|
||
|
"source": [
|
||
|
"from mpl_toolkits.mplot3d import Axes3D"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Wyrysujmy w 3D trajektorie ruchu czterech wierzchołków pod wpływem obrotu o zadany kąt. Funkcja `arange` pozwala nam wybrać częstotliwość próbkowania liczb z zadanego przedziału."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 270,
|
||
|
"metadata": {
|
||
|
"scrolled": true
|
||
|
},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"image/png": "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
|
||
|
"text/plain": [
|
||
|
"<Figure size 432x288 with 1 Axes>"
|
||
|
]
|
||
|
},
|
||
|
"metadata": {
|
||
|
"needs_background": "light"
|
||
|
},
|
||
|
"output_type": "display_data"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"fig = plt.figure()\n",
|
||
|
"ax = fig.gca(projection='3d')\n",
|
||
|
"\n",
|
||
|
"x,y,z=list(ObrotWX0([1,1,0],t))\n",
|
||
|
"xli=list(map(lambda v:x.subs({t:v}),arange(-pi/2,0,0.1)))\n",
|
||
|
"yli=list(map(lambda v:y.subs({t:v}),arange(-pi/2,0,0.1)))\n",
|
||
|
"zli=list(map(lambda v:z.subs({t:v}),arange(-pi/2,0,0.1)))\n",
|
||
|
"ax.plot(xli, yli, zli)\n",
|
||
|
"\n",
|
||
|
"x,y,z=list(ObrotWY0([1,1,0],t))\n",
|
||
|
"xli=list(map(lambda v:x.subs({t:v}),arange(0,pi/2,0.1)))\n",
|
||
|
"yli=list(map(lambda v:y.subs({t:v}),arange(0,pi/2,0.1)))\n",
|
||
|
"zli=list(map(lambda v:z.subs({t:v}),arange(0,pi/2,0.1)))\n",
|
||
|
"ax.plot(xli, yli, zli)\n",
|
||
|
"\n",
|
||
|
"x,y,z=list(ObrotWX1([2,0,0],t))\n",
|
||
|
"xli=list(map(lambda v:x.subs({t:v}),arange(0,pi/2,0.1)))\n",
|
||
|
"yli=list(map(lambda v:y.subs({t:v}),arange(0,pi/2,0.1)))\n",
|
||
|
"zli=list(map(lambda v:z.subs({t:v}),arange(0,pi/2,0.1)))\n",
|
||
|
"ax.plot(xli, yli, zli)\n",
|
||
|
"\n",
|
||
|
"x,y,z=list(ObrotWY1([0,2,0],t))\n",
|
||
|
"xli=list(map(lambda v:x.subs({t:v}),arange(0,pi/2,0.1)))\n",
|
||
|
"yli=list(map(lambda v:y.subs({t:v}),arange(0,pi/2,0.1)))\n",
|
||
|
"zli=list(map(lambda v:z.subs({t:v}),arange(0,pi/2,0.1)))\n",
|
||
|
"ax.plot(xli, yli, zli)\n",
|
||
|
"\n",
|
||
|
"plt.show()"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Wprowadźmy teraz cztery pięciokąty jako trójwymiarowe figury. Będziemy na nich wykonywać operacje obrotu (na ich wierzchołkach), wokół wybranych wcześniej osi."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 272,
|
||
|
"metadata": {},
|
||
|
"outputs": [],
|
||
|
"source": [
|
||
|
"pi1_3d=list(map(lambda x: Matrix(list(x)+[0]),pi1))\n",
|
||
|
"pi2_3d=list(map(lambda x: Matrix(list(x)+[0]),pi2))\n",
|
||
|
"pi3_3d=list(map(lambda x: Matrix(list(x)+[0]),pi3))\n",
|
||
|
"pi4_3d=list(map(lambda x: Matrix(list(x)+[0]),pi4))"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Funkcjonalność SymPy pozwala nam obrócić dany pięciokąt o abstrakcyjny kąt $t$."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 315,
|
||
|
"metadata": {},
|
||
|
"outputs": [],
|
||
|
"source": [
|
||
|
"t=symbols('t')\n",
|
||
|
"pol1_3d=list(map(lambda x: ObrotWY1(x,t),pi1_3d)) #obrót przeciwny do ruchu wskazówek zegara\n",
|
||
|
"pol2_3d=list(map(lambda x: ObrotWX1(x,t),pi2_3d)) #obrót przeciwny do ruchu wskazówek zegara\n",
|
||
|
"pol3_3d=list(map(lambda x: ObrotWY0(x,-t),pi3_3d)) #obrót zgodny z ruchem wskazówek zegara\n",
|
||
|
"pol4_3d=list(map(lambda x: ObrotWX0(x,-t),pi4_3d)) #obrót zgodny z ruchem wskazówek zegara"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Efekt takiej operacji jest skomplikowanym wyrażeniem wierzchołków jako funkcji zależnych od $t$.\n",
|
||
|
"\n",
|
||
|
"Uwaga: rezygnujemy z wektorów kolumnowych, od teraz będziemy posługiwać się tylko wektorami wierszowymi"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 277,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/plain": [
|
||
|
"[Matrix([[1, 1, 0]]),\n",
|
||
|
" Matrix([[sqrt(5)/4 + 3/4, -cos(t) + (sqrt(2*sqrt(5) + 10)/4 + 1)*cos(t) + 1, -sin(t) + (sqrt(2*sqrt(5) + 10)/4 + 1)*sin(t)]]),\n",
|
||
|
" Matrix([[1/2, -cos(t) + (1 + (sqrt(2) + sqrt(10))*sqrt(sqrt(5) + 5)/8)*cos(t) + 1, -sin(t) + (1 + (sqrt(2) + sqrt(10))*sqrt(sqrt(5) + 5)/8)*sin(t)]]),\n",
|
||
|
" Matrix([[1/4 - sqrt(5)/4, -cos(t) + (sqrt(2*sqrt(5) + 10)/4 + 1)*cos(t) + 1, -sin(t) + (sqrt(2*sqrt(5) + 10)/4 + 1)*sin(t)]]),\n",
|
||
|
" Matrix([[0, 1, 0]]),\n",
|
||
|
" Matrix([[1, 1, 0]])]"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 277,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"pol1_3d"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Wreszcie jesteśmy gotowi rozwiązać nasze zadanie. Mając dane dwa sąsiednie pięciokąty pod wpływem obrotu, czekamy na moment, gdy parametr $t$ spełnia warunek, że drugi wierzchołek pierwszego pięciokąta pokryje się z czwartym wierzchołkiem drugiego pięciokąta. Wtedy nasze pudełko domyka się."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Chcemy zatem, aby następujące trzy wyrażenia przyjęły wartość $0$."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 289,
|
||
|
"metadata": {},
|
||
|
"outputs": [],
|
||
|
"source": [
|
||
|
"#boki zetkną się, gdy wyrażenia poniżej zerują się\n",
|
||
|
"wyrazenia=list(pol1_3d[1]-pol2_3d[3])\n",
|
||
|
"eq1=Eq(wyrazenia[0],0) #komenda Eq służy do formowania równań\n",
|
||
|
"eq2=Eq(wyrazenia[1],0)\n",
|
||
|
"eq3=Eq(wyrazenia[2],0)"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 290,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/latex": [
|
||
|
"$\\displaystyle - \\frac{\\sqrt{2 \\sqrt{5} + 10} \\cos{\\left(t \\right)}}{4} - \\frac{1}{4} + \\frac{\\sqrt{5}}{4} = 0$"
|
||
|
],
|
||
|
"text/plain": [
|
||
|
"Eq(-sqrt(2*sqrt(5) + 10)*cos(t)/4 - 1/4 + sqrt(5)/4, 0)"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 290,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"eq1"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 291,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/latex": [
|
||
|
"$\\displaystyle - \\cos{\\left(t \\right)} + \\left(\\frac{\\sqrt{2 \\sqrt{5} + 10}}{4} + 1\\right) \\cos{\\left(t \\right)} - \\frac{\\sqrt{5}}{4} + \\frac{1}{4} = 0$"
|
||
|
],
|
||
|
"text/plain": [
|
||
|
"Eq(-cos(t) + (sqrt(2*sqrt(5) + 10)/4 + 1)*cos(t) - sqrt(5)/4 + 1/4, 0)"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 291,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"eq2"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 292,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/latex": [
|
||
|
"$\\displaystyle - \\sin{\\left(t \\right)} - \\frac{\\sqrt{2 \\sqrt{5} + 10} \\sin{\\left(t \\right)}}{4} + \\left(\\frac{\\sqrt{2 \\sqrt{5} + 10}}{4} + 1\\right) \\sin{\\left(t \\right)} = 0$"
|
||
|
],
|
||
|
"text/plain": [
|
||
|
"Eq(-sin(t) - sqrt(2*sqrt(5) + 10)*sin(t)/4 + (sqrt(2*sqrt(5) + 10)/4 + 1)*sin(t), 0)"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 292,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"eq3"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"# Upraszczanie wyrażeń\n",
|
||
|
"\n",
|
||
|
"Nasze równania $eq_1,eq_2,eq_3$ możemy uprościć stosując komendę `.simplify()`. Zauważymy, że dwa pierwsze równania są równoważne. Trzecie upraszcza się do postaci $0=0$."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 296,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/latex": [
|
||
|
"$\\displaystyle \\frac{\\sqrt{2 \\sqrt{5} + 10} \\cos{\\left(t \\right)}}{4} - \\frac{\\sqrt{5}}{4} + \\frac{1}{4} = 0$"
|
||
|
],
|
||
|
"text/plain": [
|
||
|
"Eq(sqrt(2*sqrt(5) + 10)*cos(t)/4 - sqrt(5)/4 + 1/4, 0)"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 296,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"eq1.simplify()"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 297,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/latex": [
|
||
|
"$\\displaystyle \\frac{\\sqrt{2 \\sqrt{5} + 10} \\cos{\\left(t \\right)}}{4} - \\frac{\\sqrt{5}}{4} + \\frac{1}{4} = 0$"
|
||
|
],
|
||
|
"text/plain": [
|
||
|
"Eq(sqrt(2*sqrt(5) + 10)*cos(t)/4 - sqrt(5)/4 + 1/4, 0)"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 297,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"eq2.simplify()"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 299,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/plain": [
|
||
|
"True"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 299,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"(eq1.simplify())==(eq2.simplify())"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 300,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/latex": [
|
||
|
"$\\displaystyle \\text{True}$"
|
||
|
],
|
||
|
"text/plain": [
|
||
|
"True"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 300,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"eq3.simplify()"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Pozostaje nam zatem wyznaczyć wartość kąta $t$ z wykorzystaniem równania $1$. Do tego wykorzystamy funkcję `solve`, która równanie symboliczne rozwiązuje ze względu na wskazane zmienne. Zachowanie tej komendy będzie zależało w istotny sposób od wybranego równania."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 303,
|
||
|
"metadata": {},
|
||
|
"outputs": [],
|
||
|
"source": [
|
||
|
"#rozwiązujemy równanie ze względu na t (rozwiązanie dokładne)\n",
|
||
|
"solv=solve(eq1,t)"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Obiekt rozwiązania `solv` przechowuje listę wszystkich rozwiązań. Są dokłądnie 2 - jedno odpowiadające obrotowi naszych ścian w górę, drugie obrotowi w dół. Zauważmy, że rozwiązania są wyrażone symbolicznie za pomocą funkcji arcus cosinus."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 304,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/plain": [
|
||
|
"True"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 304,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"len(solv)==2"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 305,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/latex": [
|
||
|
"$\\displaystyle - \\operatorname{acos}{\\left(\\frac{- \\sqrt{2} + \\sqrt{10}}{2 \\sqrt{\\sqrt{5} + 5}} \\right)} + 2 \\pi$"
|
||
|
],
|
||
|
"text/plain": [
|
||
|
"-acos((-sqrt(2) + sqrt(10))/(2*sqrt(sqrt(5) + 5))) + 2*pi"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 305,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"solv[0]"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 306,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/latex": [
|
||
|
"$\\displaystyle \\operatorname{acos}{\\left(\\frac{- \\sqrt{2} + \\sqrt{10}}{2 \\sqrt{\\sqrt{5} + 5}} \\right)}$"
|
||
|
],
|
||
|
"text/plain": [
|
||
|
"acos((-sqrt(2) + sqrt(10))/(2*sqrt(sqrt(5) + 5)))"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 306,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"solv[1]"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Gdy interesuje nas wartość numeryczna tych kątów wyrażona w stopniach, możemy posłużyć się przybliżeniem."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 307,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/latex": [
|
||
|
"$\\displaystyle 288.960709881923$"
|
||
|
],
|
||
|
"text/plain": [
|
||
|
"288.960709881923"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 307,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"(solv[0]*180/pi).n()"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 308,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/latex": [
|
||
|
"$\\displaystyle 71.0392901180775$"
|
||
|
],
|
||
|
"text/plain": [
|
||
|
"71.0392901180775"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 308,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"(solv[1]*180/pi).n()"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Naszym \"magicznym\" kątem będzie wybór podyktowany obrotem w górę."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 309,
|
||
|
"metadata": {},
|
||
|
"outputs": [],
|
||
|
"source": [
|
||
|
"magiczny_kat=solv[1]"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Teraz zobaczmy, że faktycznie znaleziony przez nas kąt odpowiada prawidłowemu złożeniu pudełka."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 314,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"image/png": "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
|
||
|
"text/plain": [
|
||
|
"<Figure size 432x288 with 1 Axes>"
|
||
|
]
|
||
|
},
|
||
|
"metadata": {
|
||
|
"needs_background": "light"
|
||
|
},
|
||
|
"output_type": "display_data"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"from mpl_toolkits.mplot3d.art3d import Poly3DCollection\n",
|
||
|
"def VertFloat(li):\n",
|
||
|
" xl,yl,zl=zip(*li)\n",
|
||
|
" xl=[float(x) for x in xl]\n",
|
||
|
" yl=[float(x) for x in yl]\n",
|
||
|
" zl=[float(x) for x in zl]\n",
|
||
|
" return [list(zip(xl,yl,zl))]\n",
|
||
|
"fig = plt.figure()\n",
|
||
|
"ax = Axes3D(fig)\n",
|
||
|
"\n",
|
||
|
"#zakres\n",
|
||
|
"ax.set_xlim3d(-3,3)\n",
|
||
|
"ax.set_ylim3d(-3,3)\n",
|
||
|
"ax.set_zlim3d(0,3)\n",
|
||
|
"\n",
|
||
|
"#ustawienia kamery\n",
|
||
|
"ax.dist=5\n",
|
||
|
"ax.elev=8\n",
|
||
|
"ax.azim=170\n",
|
||
|
"\n",
|
||
|
"#wierzchołki wielokątów\n",
|
||
|
"tt=magiczny_kat\n",
|
||
|
"pol1_3d_float=[VertFloat(list(map(lambda x: ObrotWY1(x,tt),pi1_3d))),['red','black']]\n",
|
||
|
"pol2_3d_float=[VertFloat(list(map(lambda x: ObrotWX1(x,tt),pi2_3d))),['blue','black']]\n",
|
||
|
"pol3_3d_float=[VertFloat(list(map(lambda x: ObrotWY0(x,-tt),pi3_3d))),['green','black']]\n",
|
||
|
"pol4_3d_float=[VertFloat(list(map(lambda x: ObrotWX0(x,-tt),pi4_3d))),['black','white']]\n",
|
||
|
"#print(verts)\n",
|
||
|
"\n",
|
||
|
"#dodawanie figur\n",
|
||
|
"for verts in [pol1_3d_float,pol2_3d_float,pol3_3d_float,pol4_3d_float]:\n",
|
||
|
" ax.add_collection3d(Poly3DCollection(verts[0],facecolor =verts[1][0],edgecolor=verts[1][1]))\n",
|
||
|
"plt.show()"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"# Obliczamy odległość wierzchołków\n",
|
||
|
"\n",
|
||
|
"Pozostaje nam zatem ostatnie zadanie. Obliczymy odległość naprzeciwległych wierzchołków. Wybieramy je jako trzeci wierzchołek pierwszego pięciokąta i trzeci wierzchołek trzeciego pięciokąta."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 316,
|
||
|
"metadata": {},
|
||
|
"outputs": [],
|
||
|
"source": [
|
||
|
"wierzcholek1=pol1_3d[2]\n",
|
||
|
"wierzcholek2=pol3_3d[2]"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Odległość wierzchołków od siebie to długość wektora ich różnicy"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 318,
|
||
|
"metadata": {},
|
||
|
"outputs": [],
|
||
|
"source": [
|
||
|
"roznica=wierzcholek1-wierzcholek2"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Współrzędne pierwsza i trzecia wektora roznica zerują się. Jedno zerowanie wynika automatycznie, drugie uzyskujemy po zastosowaniu metody `simplify()`"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 319,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/latex": [
|
||
|
"$\\displaystyle 0$"
|
||
|
],
|
||
|
"text/plain": [
|
||
|
"0"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 319,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"roznica[0]"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 322,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/latex": [
|
||
|
"$\\displaystyle \\frac{\\sqrt{2 \\sqrt{5} + 10} \\cos{\\left(t \\right)}}{4} + \\frac{\\sqrt{10 \\sqrt{5} + 50} \\cos{\\left(t \\right)}}{4} + 1$"
|
||
|
],
|
||
|
"text/plain": [
|
||
|
"sqrt(2*sqrt(5) + 10)*cos(t)/4 + sqrt(10*sqrt(5) + 50)*cos(t)/4 + 1"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 322,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"roznica[1].simplify()"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 323,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/latex": [
|
||
|
"$\\displaystyle 0$"
|
||
|
],
|
||
|
"text/plain": [
|
||
|
"0"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 323,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"roznica[2].simplify()"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 64,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/latex": [
|
||
|
"$\\displaystyle \\frac{\\sqrt{2} \\sqrt{\\sqrt{5} + 5} \\cos{\\left(t \\right)} + \\sqrt{10} \\sqrt{\\sqrt{5} + 5} \\cos{\\left(t \\right)} + 4}{4}$"
|
||
|
],
|
||
|
"text/plain": [
|
||
|
"(sqrt(2)*sqrt(sqrt(5) + 5)*cos(t) + sqrt(10)*sqrt(sqrt(5) + 5)*cos(t) + 4)/4"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 64,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"(wierzcholek1-wierzcholek2)[1].factor()"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 65,
|
||
|
"metadata": {
|
||
|
"scrolled": true
|
||
|
},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/latex": [
|
||
|
"$\\displaystyle 0$"
|
||
|
],
|
||
|
"text/plain": [
|
||
|
"0"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 65,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"(wierzcholek1-wierzcholek2)[2].factor()"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Zatem odległość między wierzchołkami wynosi ostatecznie `abs(roznica[1])`. Obliczmy wprost to wyrażenie dla naszego kąta styku obliczonego wcześniej."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 324,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/latex": [
|
||
|
"$\\displaystyle 2$"
|
||
|
],
|
||
|
"text/plain": [
|
||
|
"2"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 324,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"(roznica)[1].subs({t:magiczny_kat}).expand()"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Zatem udowodniliśmy matematycznie, że odległość między wybranymi wierzchołkami wynosi dokładnie 2. Wykorzystana przez nas biblioteka obliczeń symbolicznych SymPy pozwala nam na tę absolutną konluzję."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"### Inny sposób obliczenia odległosci\n",
|
||
|
"\n",
|
||
|
"W naszych obliczeniach wyliczenie kąta $t$ dla styku nie było tak istotne. Kluczowe było, że obliczyliśmy wartość funkcji $cos(t)$ dla tego kąta. To pozwala nam inaczej podejść do poprzednich rachunków i wyrugować z użycia funkcji solve odwracanie funkcji cosinus."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 345,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/latex": [
|
||
|
"$\\displaystyle \\left[\\begin{matrix}0 & 2 & 0\\end{matrix}\\right]$"
|
||
|
],
|
||
|
"text/plain": [
|
||
|
"Matrix([[0, 2, 0]])"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 345,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"sol=(roznica).subs({cos(t):solve(eq1,cos(t))[0]})\n",
|
||
|
"sol.simplify()\n",
|
||
|
"sol"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Na koniec obejrzyjmy jeszcze raz całą sytuację z wybranego kąta. Korzystamy w naszej funkcji rysującej dodatkowo z interaktywnych widżetów zawartych w bibliotece `ipywidgets`"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 350,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"application/vnd.jupyter.widget-view+json": {
|
||
|
"model_id": "5527cbe2eed445faaeed7fdf612f5124",
|
||
|
"version_major": 2,
|
||
|
"version_minor": 0
|
||
|
},
|
||
|
"text/plain": [
|
||
|
"interactive(children=(FloatSlider(value=0.61, description='tt', max=1.2398695108399236, step=0.01), FloatSlide…"
|
||
|
]
|
||
|
},
|
||
|
"metadata": {},
|
||
|
"output_type": "display_data"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"from ipywidgets import interactive\n",
|
||
|
"from mpl_toolkits.mplot3d.art3d import Line3DCollection\n",
|
||
|
"\n",
|
||
|
"def VertFloat(li):\n",
|
||
|
" xl,yl,zl=zip(*li)\n",
|
||
|
" xl=[float(x) for x in xl]\n",
|
||
|
" yl=[float(x) for x in yl]\n",
|
||
|
" zl=[float(x) for x in zl]\n",
|
||
|
" return [list(zip(xl,yl,zl))]\n",
|
||
|
"def f(tt,dist,elev,azim):\n",
|
||
|
" fig = plt.figure(figsize=[3,3])\n",
|
||
|
" ax = Axes3D(fig)\n",
|
||
|
"\n",
|
||
|
" #zakres\n",
|
||
|
" ax.set_xlim3d(-3,3)\n",
|
||
|
" ax.set_ylim3d(-3,3)\n",
|
||
|
" ax.set_zlim3d(0,3)\n",
|
||
|
"\n",
|
||
|
" #ustawienia kamery\n",
|
||
|
" ax.dist=dist\n",
|
||
|
" ax.elev=elev\n",
|
||
|
" ax.azim=azim\n",
|
||
|
"\n",
|
||
|
" #wierzchołki wielokątów\n",
|
||
|
"\n",
|
||
|
" pol1_3d=[VertFloat(list(map(lambda x: ObrotWY1(x,tt),pi1_3d))),['red','black']]\n",
|
||
|
" pol2_3d=[VertFloat(list(map(lambda x: ObrotWX1(x,tt),pi2_3d))),['blue','black']]\n",
|
||
|
" pol3_3d=[VertFloat(list(map(lambda x: ObrotWY0(x,-tt),pi3_3d))),['green','black']]\n",
|
||
|
" pol4_3d=[VertFloat(list(map(lambda x: ObrotWX0(x,-tt),pi4_3d))),['black','white']]\n",
|
||
|
"\n",
|
||
|
" #dodawanie figur\n",
|
||
|
" for verts in [pol1_3d,pol2_3d,pol3_3d,pol4_3d]:\n",
|
||
|
" ax.add_collection3d(Poly3DCollection(verts[0],facecolor =verts[1][0],edgecolor=verts[1][1]))\n",
|
||
|
" w1=[float(x) for x in ObrotWY1(pi1_3d[2],tt)]\n",
|
||
|
" w2=[float(x) for x in ObrotWY0(pi3_3d[2],-tt)] \n",
|
||
|
" ax.add_collection3d(Line3DCollection([[w1,w2]], colors='black',linewidth=3,linestyle='dashed'))\n",
|
||
|
" plt.show()\n",
|
||
|
"\n",
|
||
|
"interactive_plot = interactive(f, tt=(0, float(magiczny_kat),0.01),dist=(0,10,0.1),elev=(0,10,0.1),azim=(0,360,1))\n",
|
||
|
"output = interactive_plot.children[-1]\n",
|
||
|
"output.layout.height = '350px'\n",
|
||
|
"interactive_plot"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": null,
|
||
|
"metadata": {},
|
||
|
"outputs": [],
|
||
|
"source": []
|
||
|
}
|
||
|
],
|
||
|
"metadata": {
|
||
|
"hide_input": false,
|
||
|
"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.9.1"
|
||
|
},
|
||
|
"varInspector": {
|
||
|
"cols": {
|
||
|
"lenName": 16,
|
||
|
"lenType": 16,
|
||
|
"lenVar": 40
|
||
|
},
|
||
|
"kernels_config": {
|
||
|
"python": {
|
||
|
"delete_cmd_postfix": "",
|
||
|
"delete_cmd_prefix": "del ",
|
||
|
"library": "var_list.py",
|
||
|
"varRefreshCmd": "print(var_dic_list())"
|
||
|
},
|
||
|
"r": {
|
||
|
"delete_cmd_postfix": ") ",
|
||
|
"delete_cmd_prefix": "rm(",
|
||
|
"library": "var_list.r",
|
||
|
"varRefreshCmd": "cat(var_dic_list()) "
|
||
|
}
|
||
|
},
|
||
|
"types_to_exclude": [
|
||
|
"module",
|
||
|
"function",
|
||
|
"builtin_function_or_method",
|
||
|
"instance",
|
||
|
"_Feature"
|
||
|
],
|
||
|
"window_display": false
|
||
|
}
|
||
|
},
|
||
|
"nbformat": 4,
|
||
|
"nbformat_minor": 4
|
||
|
}
|