Last active
December 31, 2019 17:55
-
-
Save mirrornerror/0ac20c84259eb82089a512c01a91a5ab to your computer and use it in GitHub Desktop.
Jupyters/Quaternion/Quaternion_Cube.ipynb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"metadata": {}, | |
"cell_type": "markdown", | |
"source": "# Quaternion: Rotation of Cube" | |
}, | |
{ | |
"metadata": { | |
"ExecuteTime": { | |
"start_time": "2019-12-27T05:16:29.904730Z", | |
"end_time": "2019-12-27T05:16:30.587317Z" | |
}, | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "import numpy as np\nimport matplotlib.pyplot as plt\nfrom mpl_toolkits.mplot3d import Axes3D\n%matplotlib inline", | |
"execution_count": 1, | |
"outputs": [] | |
}, | |
{ | |
"metadata": { | |
"ExecuteTime": { | |
"start_time": "2019-12-27T05:16:30.789196Z", | |
"end_time": "2019-12-27T05:16:30.929659Z" | |
}, | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "# quaternion multiplication function\ndef QbyQ(q1, q2): # q = [w, x, y, z]\n w = q1[0]*q2[0] - q1[1]*q2[1] - q1[2]*q2[2] - q1[3]*q2[3]\n i = q1[0]*q2[1] + q1[1]*q2[0] + q1[2]*q2[3] - q1[3]*q2[2]\n j = q1[0]*q2[2] - q1[1]*q2[3] + q1[2]*q2[0] + q1[3]*q2[1]\n k = q1[0]*q2[3] + q1[1]*q2[2] - q1[2]*q2[1] + q1[3]*q2[0]\n return np.array([w, i, j, k])\n\n# quaternion rotation function\ndef QPQc(P, UV, t): # P: quaternion, UV: unit vector, t: rotation angle theta\n q = [np.cos(t/2), UV[0] * np.sin(t/2), UV[1] * np.sin(t/2), UV[2] * np.sin(t/2)]\n qc = [np.cos(t/2), -UV[0] * np.sin(t/2), -UV[1] * np.sin(t/2), -UV[2] * np.sin(t/2)]\n qP = QbyQ(q, P)\n result = QbyQ(qP, qc)\n return result\n\n# plot unit sphere\ndef plot_base(elev=25, azim=-70):\n fig = plt.figure(figsize=(10, 10))\n ax = fig.add_subplot(111, projection='3d')\n ax.view_init(elev=elev, azim=azim)\n ax.set(xlim=(-1, 1), ylim=(-1 ,1), zlim=(-1, 1))\n ax.set(xlabel='X', ylabel='Y', zlabel='Z')\n ax.xaxis.pane.fill = ax.yaxis.pane.fill = ax.zaxis.pane.fill = False\n\n t = np.linspace(0, 2*np.pi, 128+1)\n alpha = 0.7\n ax.plot(np.cos(t), np.sin(t), [0]*len(t), linestyle=':', c='red', alpha=alpha)\n ax.plot(np.cos(t), [0]*len(t), np.sin(t), linestyle=':', c='red', alpha=alpha)\n ax.plot([0]*len(t), np.cos(t), np.sin(t), linestyle=':', c='red', alpha=alpha)\n ax.plot([-1, 1], [0, 0], [0, 0], linestyle=':', c='red', alpha=alpha)\n ax.plot([0, 0], [-1, 1], [0, 0], linestyle=':', c='red', alpha=alpha)\n ax.plot([0, 0], [0, 0], [-1, 1], linestyle=':', c='red', alpha=alpha)\n return ax", | |
"execution_count": 2, | |
"outputs": [] | |
}, | |
{ | |
"metadata": { | |
"ExecuteTime": { | |
"end_time": "2019-12-24T02:45:54.704700Z", | |
"start_time": "2019-12-24T02:45:54.699747Z" | |
} | |
}, | |
"cell_type": "markdown", | |
"source": "## Rotating Cube with ipywidgets" | |
}, | |
{ | |
"metadata": { | |
"ExecuteTime": { | |
"start_time": "2019-12-27T05:16:44.200242Z", | |
"end_time": "2019-12-27T05:16:44.726548Z" | |
}, | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "from ipywidgets import interact\nfrom mpl_toolkits.mplot3d.art3d import Poly3DCollection\n\n@interact(theta=(-np.pi, np.pi, np.pi/100), w=(0.1, 1, 0.1), l=(0.1, 1, 0.1), h=(0.1, 1, 0.1)) # theta: rotation angle on unit vector\ndef cube(theta=0, w=0.5, l=0.5, h=0.5):\n scale = np.array([w, l, h]) # scale of the cube\n pos = np.array([-w/2, -l/2, 1]) # position of the cube\n UV = [1, 0, 0] # unit vector: rotation axis\n\n CUBE = np.array([[0,0,0],[1,0,0],[1,1,0],[0,1,0], \n [0,0,1],[1,0,1],[1,1,1],[0,1,1]]) * scale + pos # cube vertices with scale and position\n CUBEs = np.vstack([np.linalg.norm(c) for c in CUBE]) # scalar\n CUBEn = np.array([v / s if s != 0 else v * 0 for v, s in zip(CUBE, CUBEs)]) # normalization\n QCUBE = np.insert(CUBEn, 0, 0, axis=1) # quaternion\n\n UV = np.array(UV) / np.linalg.norm(UV) # normalization of unit vector\n\n QCUBE_R = np.array([QPQc(qc, UV, theta) for qc in QCUBE]) # quaternion rotation\n CX, CY, CZ = (QCUBE_R[:, 1:] * CUBEs).T # vectors of cube\n\n ax = plot_base()\n ax.plot([0, UV[0]], [0, UV[1]], [0, UV[2]], c='r')\n ax.scatter(UV[0], UV[1], UV[2], c='r')\n ax.plot(np.r_[CX[:4], CX[0]], np.r_[CY[:4], CY[0]], np.r_[CZ[:4], CZ[0]], c='b') # 4 bottom edges\n ax.plot(np.r_[CX[4:], CX[4]], np.r_[CY[4:], CY[4]], np.r_[CZ[4:], CZ[4]], c='g') # 4 top edges\n [ax.plot([CX[i], CX[i+4]], [CY[i], CY[i+4]], [CZ[i], CZ[i+4]], c='m') for i in range(4)] # 4 colomns edges\n \n bottom = list(zip(CX[:4], CY[:4], CZ[:4]))\n ax.add_collection3d(Poly3DCollection([bottom], color='#ddddff')) # fill in color : bottom side\n top = list(zip(CX[4:], CY[4:], CZ[4:]))\n ax.add_collection3d(Poly3DCollection([top], color='#ddffdd')) # fill in color : top side", | |
"execution_count": 3, | |
"outputs": [ | |
{ | |
"output_type": "display_data", | |
"data": { | |
"text/plain": "interactive(children=(FloatSlider(value=0.0, description='theta', max=3.141592653589793, min=-3.14159265358979…", | |
"application/vnd.jupyter.widget-view+json": { | |
"version_major": 2, | |
"version_minor": 0, | |
"model_id": "805616efe6394cd2b648d4d961e8d128" | |
} | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"ExecuteTime": { | |
"end_time": "2019-12-26T10:16:10.686158Z", | |
"start_time": "2019-12-26T10:16:10.175231Z" | |
}, | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "from ipywidgets import interact\nfrom mpl_toolkits.mplot3d.art3d import Poly3DCollection\n\n@interact(theta=(-np.pi, np.pi, np.pi/100), ux=(-1, 1, 0.1), uy=(-1, 1, 0.1), uz=(-1, 1, 0.1)) # theta: rotation angle on unit vector\ndef cube(theta=0, ux=1, uy=0, uz=0):\n scale = np.array([1/2, 1/2, 1/2]) # scale of the cube\n pos = np.array([-1/4, -1/4, 1]) # position of the cube\n UV = [ux, uy, uz] # unit vector: rotation axis\n\n CUBE = np.array([[0,0,0],[1,0,0],[1,1,0],[0,1,0], \n [0,0,1],[1,0,1],[1,1,1],[0,1,1]]) * scale + pos # cube vertices with scale and position\n CUBEs = np.vstack([np.linalg.norm(c) for c in CUBE]) # scalar\n CUBEn = np.array([v / s if s != 0 else v * 0 for v, s in zip(CUBE, CUBEs)]) # normalization\n QCUBE = np.insert(CUBEn, 0, 0, axis=1) # quaternion\n\n UV = np.array(UV) / np.linalg.norm(UV) # normalization of unit vector\n\n QCUBE_R = np.array([QPQc(qc, UV, theta) for qc in QCUBE]) # quaternion rotation\n CX, CY, CZ = (QCUBE_R[:, 1:] * CUBEs).T # vectors of cube\n\n ax = plot_base()\n ax.plot([0, UV[0]], [0, UV[1]], [0, UV[2]], c='r')\n ax.scatter(UV[0], UV[1], UV[2], c='r')\n ax.plot(np.r_[CX[:4], CX[0]], np.r_[CY[:4], CY[0]], np.r_[CZ[:4], CZ[0]], c='b') # 4 bottom edges\n ax.plot(np.r_[CX[4:], CX[4]], np.r_[CY[4:], CY[4]], np.r_[CZ[4:], CZ[4]], c='g') # 4 top edges\n [ax.plot([CX[i], CX[i+4]], [CY[i], CY[i+4]], [CZ[i], CZ[i+4]], c='m') for i in range(4)] # 4 colomns edges\n ax.text(ux, uy, uz, s=' unit vector')\n \n bottom = list(zip(CX[:4], CY[:4], CZ[:4]))\n ax.add_collection3d(Poly3DCollection([bottom], color='#ddddff')) # fill in color : bottom side\n top = list(zip(CX[4:], CY[4:], CZ[4:]))\n ax.add_collection3d(Poly3DCollection([top], color='#ddffdd')) # fill in color : top side", | |
"execution_count": 3, | |
"outputs": [ | |
{ | |
"data": { | |
"application/vnd.jupyter.widget-view+json": { | |
"model_id": "fe33abe096184ed7a474b6ec6d7a5872", | |
"version_major": 2, | |
"version_minor": 0 | |
}, | |
"text/plain": "interactive(children=(FloatSlider(value=0.0, description='theta', max=3.141592653589793, min=-3.14159265358979…" | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "", | |
"execution_count": null, | |
"outputs": [] | |
} | |
], | |
"metadata": { | |
"kernelspec": { | |
"name": "py36", | |
"display_name": "py36", | |
"language": "python" | |
}, | |
"language_info": { | |
"name": "python", | |
"version": "3.6.7", | |
"mimetype": "text/x-python", | |
"codemirror_mode": { | |
"name": "ipython", | |
"version": 3 | |
}, | |
"pygments_lexer": "ipython3", | |
"nbconvert_exporter": "python", | |
"file_extension": ".py" | |
}, | |
"gist": { | |
"id": "", | |
"data": { | |
"description": "Jupyters/Quaternion/Quaternion_Cube.ipynb", | |
"public": true | |
} | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 2 | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
numpy | |
matplotlib | |
ipywidgets |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment