diff --git a/examples/worm_cutting_tool/.DS_Store b/examples/worm_cutting_tool/.DS_Store new file mode 100644 index 0000000..1df4713 Binary files /dev/null and b/examples/worm_cutting_tool/.DS_Store differ diff --git a/examples/worm_cutting_tool/cross_section.png b/examples/worm_cutting_tool/cross_section.png new file mode 100644 index 0000000..8740ba4 Binary files /dev/null and b/examples/worm_cutting_tool/cross_section.png differ diff --git a/examples/worm_cutting_tool/cutting_tool_worm_assembly.ipynb b/examples/worm_cutting_tool/cutting_tool_worm_assembly.ipynb new file mode 100644 index 0000000..b6acbcd --- /dev/null +++ b/examples/worm_cutting_tool/cutting_tool_worm_assembly.ipynb @@ -0,0 +1,218 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "5e24589a-461d-46b5-8141-37f948dcf4dc", + "metadata": {}, + "source": [ + "# cutting tool for a worm gear\n", + "\n", + "1. idea 1: \n", + "\n", + "" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "7eacf041-aa83-49e2-9cbe-066f177197f6", + "metadata": {}, + "outputs": [], + "source": [ + "import sympy as sp\n", + "import numpy as np" + ] + }, + { + "cell_type": "code", + "execution_count": 119, + "id": "980417d0-c79d-4501-a7cc-9725b3bbea83", + "metadata": {}, + "outputs": [], + "source": [ + "def symbolic_transformation(angle, axis, translation):\n", + " \"\"\"\n", + " see http://en.wikipedia.org/wiki/SO%284%29#The_Euler.E2.80.93Rodrigues_formula_for_3D_rotations\n", + " sympy enabled transformation\n", + " angle: angle of rotation\n", + " axis: the axis of the rotation\n", + " translation: translation of transformation\n", + " \"\"\"\n", + " assert len(axis) == 3\n", + " a = sp.cos(angle / 2)\n", + " axis_normalized = axis / sp.sqrt(axis.dot(axis))\n", + " (b, c, d) = -axis_normalized * sp.sin(angle / 2)\n", + " mat = sp.Matrix(\n", + " [\n", + " [\n", + " a**2 + b**2 - c**2 - d**2,\n", + " 2 * (b * c - a * d),\n", + " 2 * (b * d + a * c),\n", + " translation[0],\n", + " ],\n", + " [\n", + " 2 * (b * c + a * d),\n", + " a**2 + c**2 - b**2 - d**2,\n", + " 2 * (c * d - a * b),\n", + " translation[1],\n", + " ],\n", + " [\n", + " 2 * (b * d - a * c),\n", + " 2 * (c * d + a * b),\n", + " a**2 + d**2 - b**2 - c**2,\n", + " translation[2],\n", + " ],\n", + " [0.0, 0.0, 0.0, 1.0],\n", + " ]\n", + " )\n", + " return sp.nsimplify(mat,tolerance=1e-10,rational=True)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 219, + "id": "5852aa56-e66b-4f3c-a50d-0cb4cb21abd2", + "metadata": {}, + "outputs": [], + "source": [ + "T1 = symbolic_transformation(np.pi / 2.,\n", + " np.array([1., 0., 0.]),\n", + " np.array([12.5,0., 1.15]))\n", + "T2 = symbolic_transformation(-t / 7.5,\n", + " np.array([0., 0., 1.]),\n", + " np.array([0., 0., 0.]))\n", + "T3 = symbolic_transformation(0.,\n", + " np.array([1., 0., 0.]),\n", + " np.array([0., 0., t]))\n", + "\n", + "T = T2.inverse() @ T1.inverse() @ T3" + ] + }, + { + "cell_type": "code", + "execution_count": 220, + "id": "7c9837b8-caf7-4447-bf0d-eba9085197a5", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[ 0. , 0. , -0.13333333, 0.15333333],\n", + " [-0.13333333, 0. , 0. , 0.66666667],\n", + " [ 0. , 0. , 0. , 0. ],\n", + " [ 0. , 0. , 0. , 0. ]])" + ] + }, + "execution_count": 220, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "T_fn = sp.lambdify(t, T)\n", + "dT_fn = sp.lambdify(t, T.diff(t))\n", + "dT_fn(0.)" + ] + }, + { + "cell_type": "markdown", + "id": "e4354a36-409a-40a6-8f4f-bb5a6c84f3b7", + "metadata": {}, + "source": [ + "Diese Methode funktioniert nicht, weil die Bedingung zur Bestimmung des Kontaktpunktes falsch ist.\n", + "Eine Bedingung für die generierung einer konstanten Übersetzung ist, dass die Normale auf die Kontaktfläche (Zahnstange) immer durch den Punkt p (Eingriffspunkt für Ersatzzahnrad (Zylinder) und Ersatzzahnstange (Quader) gehen muss.\n", + "Gesucht sind also Punkte auf der Fläche S welche verbunden mit P normal auf die Fläche stehen. Dies kann auch als minimaler Abstand von P zur Fläche gesehen werden.\n", + "\n", + "für jedes u: min(norm(S(u,v)-P)) -> d(norm(S(u,v)-P)/dv = 0\n", + "die Änderung des Abstands ist 0 -> die Gerade steht normal auf die Fläche\n" + ] + }, + { + "cell_type": "markdown", + "id": "43f00b65-c05c-4734-8c5a-e7845a6f4dff", + "metadata": {}, + "source": [ + "## Vorgehensweise\n", + "\n", + "1. approximate the surface by a BSplineSurface\n", + "\n", + "- Erstellen eines \"Cross-Sektion\" objekts aus dem \"Werkzeug\"\n", + "\n", + " \n", + "\n", + "- Draft downgrade um Kanten zu bekommen\n", + "das Cross-section Objekt beinhaltet nicht die anfangs und end Kanten. Diese müssen zusätzlich vom Werkzeug extrahiert werden\n", + "\n", + "- Part Loft zum erstellen einer schönen BSplinefläche\n", + "\n", + " \n", + "\n", + "3. Loft -> Surface\n", + "\n", + "```python\n", + "# select the cutting faces\n", + "face_1 = App.ActiveDocument.Loft.Shape.Faces[0].copy()\n", + "face_2 = App.ActiveDocument.Loft001.Shape.Faces[0].copy()\n", + "\n", + "# compute the contact curve:\n", + "bsp_1 = face_1.Surface\n", + "bsp_2 = face_2.Surface\n", + "\n", + "```\n", + "\n", + "4. Minimierung des Abstands zum \"Pitch-Punkt\"\n", + "\n", + "```python\n", + "import scipy as scp\n", + "point = App.Vector(5., 0., 1.15 - time) \n", + "xyz_1 = []\n", + "for v in np.linspace(0, 1, 5):\n", + " def dist_1(u):\n", + " distance = bsp_1.value(u, v) - point\n", + " return distance.x ** 2 + distance.z ** 2\n", + " u_1 = scp.optimize.minimize(dist_1, 0.5, tol=1e-6).x[0]\n", + " xyz_1.append(bsp_1.value(u_1, v))\n", + "```\n", + "\n", + "5. erstellen einer B-Spline Kurve welche durch die Kinematik T transformiert wird\n", + "\n", + "```python\n", + "c_1 = Part.BSplineCurve()\n", + "c_1.interpolate(Points=xyz_1)\n", + "c_1 = c_1.toShape()\n", + "\n", + "Part.show(c_1.transformShape(T))\n", + "```\n", + "\n", + "6. Loft anwenden auf die erstellten BSpline Kurven\n", + "\n", + "\n", + "\n", + "7. Array für das Zahnrad\n", + "\n", + "" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.11.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/examples/worm_cutting_tool/gear_assembly.png b/examples/worm_cutting_tool/gear_assembly.png new file mode 100644 index 0000000..1e72464 Binary files /dev/null and b/examples/worm_cutting_tool/gear_assembly.png differ diff --git a/examples/worm_cutting_tool/loft_bspline_flaechen.png b/examples/worm_cutting_tool/loft_bspline_flaechen.png new file mode 100644 index 0000000..ba088a8 Binary files /dev/null and b/examples/worm_cutting_tool/loft_bspline_flaechen.png differ diff --git a/examples/worm_cutting_tool/loft_of_generated_bsplines.png b/examples/worm_cutting_tool/loft_of_generated_bsplines.png new file mode 100644 index 0000000..9dc9d9d Binary files /dev/null and b/examples/worm_cutting_tool/loft_of_generated_bsplines.png differ