pcb-stator-coil-generator/coil.ipynb

159 lines
90 KiB
Text
Raw Normal View History

2022-10-01 20:09:14 +00:00
{
"cells": [
{
"cell_type": "code",
"execution_count": 133,
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd\n",
"import numpy as np\n",
"import matplotlib as plt\n",
"from skspatial.objects import LineSegment"
]
},
{
"cell_type": "code",
"execution_count": 142,
"metadata": {},
"outputs": [],
"source": [
"# create a square shape\n",
"template = [(-1, -0.95), (-0.95, -1), (0.95, -0.55), (1.0, -0.45), (1, 0.45), (0.95, 0.55), (-0.95, 1), (-1, 0.95)]\n",
"# create a triangle\n",
"# template = [(-1, -1), (1, -1), (0, 1)]\n",
"# interpolate the shape using numpy\n",
"\n",
"# create a circle template\n",
"# template = [(np.cos(theta), np.sin(theta)) for theta in np.linspace(0, 2*np.pi, 36)]\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 143,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[<matplotlib.lines.Line2D at 0x13f082a70>]"
]
},
"execution_count": 143,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAjgAAAGdCAYAAAAfTAk2AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy89olMNAAAACXBIWXMAAA9hAAAPYQGoP6dpAAA81ElEQVR4nO3deXxU9b3/8XcSyIRAJoEGMolGdhOQsAgljbXFSkoitIXqbcVqWWrDdUGrwYV4BQRURLlcFbmils1HRVyuuBQawSj606agLAISIlCULZMAMZkkQMjy/f0BGRmzL5Pl5PV8POYh8z3f853vN4cwb8/nnBkfY4wRAACAhfi29AQAAACaGgEHAABYDgEHAABYDgEHAABYDgEHAABYDgEHAABYDgEHAABYDgEHAABYToeWnkBLKC8v1/HjxxUUFCQfH5+Wng4AAKgDY4wKCgoUEREhX9+az9G0y4Bz/PhxRUZGtvQ0AABAAxw5ckSXXnppjX3aZcAJCgqSdP4HZLfbW3g2AACgLlwulyIjI93v4zVplwGnoixlt9sJOAAAtDF1ubyEi4wBAIDlEHAAAIDlEHAAAIDlEHAAAIDlEHAAAIDlEHAAAIDlEHAAAIDlEHAAAIDlEHAAAIDleDXgfPLJJ/r1r3+tiIgI+fj46O233651n82bN+vKK6+UzWZTv379tGrVqkp9li5dql69eikgIECxsbHaunVr008eAAC0WV4NOEVFRRoyZIiWLl1ap/6HDh3SuHHj9Itf/EI7d+7UPffcoz//+c96//333X1ee+01JScna86cOdq+fbuGDBmihIQE5eTkeGsZAACgjfExxphmeSEfH61bt04TJkyots+DDz6o9evXa8+ePe62iRMnKi8vT6mpqZKk2NhY/fjHP9Zzzz0nSSovL1dkZKTuuusuzZw5s05zcblcCg4OVn5+Pt9FBQBAG1Gf9+9WdQ1Oenq64uPjPdoSEhKUnp4uSTp37py2bdvm0cfX11fx8fHuPlUpLi6Wy+XyeLS00rJyrd16WEs/OqBNe7N1JPe0milrAgBgea3q28SdTqfCwsI82sLCwuRyuXTmzBl99913Kisrq7LPvn37qh13wYIFmjt3rlfm3BBZ+Wf0l1d3aus3uR7tXWwddHlYF0U57Ip2BF142BUc2LGFZgoAQNvUqgKOt6SkpCg5Odn93OVyKTIyskXm8tG+HCW/vlPfnS5RF1sHXRPVXQdyCnXwRKEKi0u1/XCeth/O89jHYQ9QVEXgCQ9SVJhdfXt0lq2DX4usAQCA1q5VBRyHw6Hs7GyPtuzsbNntdnXq1El+fn7y8/Orso/D4ah2XJvNJpvN5pU511VJWbkWvZ+pFz75tyRp0CV2PXfTleoV2tm9/dDJIu1zFmhflkuZzgLtcxboWN4ZOV1n5XSd1cdfn3CP5+froz6hnb8PPg67ohxBurRrJ/n4+LTIGgEAaC1aVcCJi4vThg0bPNo2bdqkuLg4SZK/v7+GDx+utLQ098XK5eXlSktL0/Tp05t7unV2LO+M7lqz3X1mZnJcTz00boDHGZiOfr66PCxIl4cF6TdDItztBWdL9HV2wYXgU3Ah+LjkOluq/TmF2p9TqL/vynL3p8wFAICXA05hYaEOHDjgfn7o0CHt3LlT3bp102WXXaaUlBQdO3ZML7/8siTptttu03PPPacHHnhAf/rTn/Thhx/q9ddf1/r1691jJCcna/LkyRoxYoRGjhypp59+WkVFRZo6dao3l9Jgm/Zm6743vlT+mRIFBXTQkzcM1nUx4XXePyigo4b37KbhPbu524wxcrrOXhR6XNrnLKDMBQDABV4NOF988YV+8YtfuJ9XXAczefJkrVq1SllZWTp8+LB7e+/evbV+/Xrde++9euaZZ3TppZfqr3/9qxISEtx9brzxRp04cUKzZ8+W0+nU0KFDlZqaWunC45Z2rrRcC1P3afmnhyRJQy4N1pKbrtRlPwps9Ng+Pj4KD+6k8OBO+kVUD3c7ZS4AAM5rts/BaU28/Tk4R3JPa/qa7fryaL4k6U8/7a2Z10XLv0PL3JVfUebKuFDiurjMVZWLy1wDwoMUFUaZCwDQ8urz/k3AaeKAk7onS/e/uUsFZ0sV3KmjFv1uiH45sHWdXZJqLnOVlFX9V4IyFwCgJRFwauGtgPPlkTyNX/qZJGnYZSFactMwXdq18SWp5lRTmasqHXx91PtCmWtAuF1RYUGUuQAAXlGf9+9WdRdVW/fV8fOfkHzlZSF67T/j1NGvVX1QdJ3UdjdXVWWu2u7moswFAGhuBBwvCO1ia5PhpibczQUAaEsIOGiw2u7myrhQ4qrtbi7KXACApkbAQZO7uMx1McpcAIDmQsBBs6mxzJV1/ixPvcpc4edLXZS5AAA/RMBBi/Ioc0VT5gIANA0CDlql6spcrrMl+tpZcbaHMhcAoGoEHLQp9oCOGtGrm0b0oswFAKgeAQdtXk1lrn+fKNI+J2UuAGhvCDiwrI5+vopynA8pF2tomSs63H7hbA9lLgBo7Qg4aHeqK3Nl5Z91n+WhzAUAbRsBB9D5MldESCdFhFDmAgArIOAANaDMBQBtEwEHaADKXADQuhFwgCbS1GWui8/2UOYCgPoh4ABe1pgy13tfft+fMhcA1B0BB2ghTVnmig4/H6AocwHAeQQcoBVpTJlrcyZlLgCoQMAB2oD6lLkynC4VUOYC0M4RcIA2jDIXAFSNgANYDGUuACDgAO1GU5a5KsahzAWgtSLgAO1cQ8pc2779Ttu+/c5jHMpcAFoTAg6ASihzAWjrCDgA6qyuZa59F874UOYC0FIIOAAajTIXgNaGgAPAK6orc50rLdehk9+XuSrO+tRU5urTvbOiHJS5ANQdAQdAs/LvUP8y19fZhfo6mzIXgLoj4ABoFepS5qo460OZC0BtmiXgLF26VE899ZScTqeGDBmiJUuWaOTIkVX2veaaa/Txxx9Xah87dqzWr18vSZoyZYpWr17tsT0hIUGpqalNP3kALYYyF4CG8nrAee2115ScnKxly5YpNjZWTz/9tBISEpSZmakePXpU6v/WW2/p3Llz7uenTp3SkCFD9Lvf/c6jX2JiolauXOl+brPZvLcIAK0KZS4AtfF6wFm8eLGSkpI0depUSdKyZcu0fv16rVixQjNnzqzUv1u3bh7P165dq8DAwEoBx2azyeFweG/iANqcpipzhQcH/CD4UOYC2hqvBpxz585p27ZtSklJcbf5+voqPj5e6enpdRpj+fLlmjhxojp37uzRvnnzZvXo0UNdu3bVtddeq0cffVQ/+tGPqhyjuLhYxcXF7ucul6sBqwHQFjWkzJWVf1ZZ+ZS5gLbMqwHn5MmTKisrU1hYmEd7WFiY9u3bV+v+W7du1Z49e7R8+XKP9sTERF1//fXq3bu3Dh48qIceekjXXXed0tPT5edX+f+wFixYoLlz5zZuMQAspS5lrovDT3VlriBbB11OmQtodVr1XVTLly9XTExMpQuSJ06c6P5zTEyMBg8erL59+2rz5s0aPXp0pXFSUlKUnJzsfu5yuRQZGem9iQNos+pb5iqgzAW0Sl4NOKGhofLz81N2drZHe3Z2dq3XzxQVFWnt2rWaN29era/Tp08fhYaG6sCBA1UGHJvNxkXIABqsLmWui7+NnTIX0PK8GnD8/f01fPhwpaWlacKECZKk8vJypaWlafr06TXu+8Ybb6i4uFi33HJLra9z9OhRnTp1SuHh4U0xbQCok4vLXOMvaqfMBbQ8r5eokpOTNXnyZI0YMUIjR47U008/raKiIvddVZMmTdIll1yiBQsWeOy3fPlyTZgwodKFw4WFhZo7d65uuOEGORwOHTx4UA888ID69eunhIQEby8HAGpVW5kr46JvY6fMBXiH1wPOjTfeqBMnTmj27NlyOp0aOnSoUlNT3RceHz58WL6+vh77ZGZm6tNPP9XGjRsrjefn56ddu3Zp9erVysvLU0REhMaMGaP58+dThgLQalHmApqXjzHGtPQkmpvL5VJwcLDy8/Nlt9ubbNw1Ww7roXW7NWZgmF6cNKLJxgXQ/lSUuTIufBP
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# plot the template shape wrapping around to the first point\n",
"plt.pyplot.plot([x for x, y in template] + [template[0][0]], [y for x, y in template] + [template[0][1]])"
]
},
{
"cell_type": "code",
"execution_count": 144,
"metadata": {},
"outputs": [],
"source": [
"SPACING = 0.2\n",
"TURNS = 5\n",
"# sweep a line from the origin through 360 degress times the number of turns in 1 degree increments\n",
"# and find the intersection points with the template shape\n",
"cache = {}\n",
"for angle in np.arange(0, 360, 1):\n",
" line = LineSegment(np.array([0, 0]), np.array([10 * np.cos(np.deg2rad(angle)), 10 * np.sin(np.deg2rad(angle))]))\n",
" for i in range(len(template)):\n",
" segment = LineSegment(np.array(template[i]), np.array(template[(i + 1) % len(template)]))\n",
" try:\n",
" intersection = line.intersect_line_segment(segment)\n",
" if intersection is not None:\n",
" cache[angle] = (intersection, segment)\n",
" except ValueError:\n",
" pass\n",
"\n",
"\n",
"points = []\n",
"for angle in np.arange(0, 360 * TURNS, 1):\n",
" intersection, segment = cache[angle % 360]\n",
" offset = SPACING * angle / 360\n",
" vector = np.array(segment.point_a) - np.array(segment.point_b)\n",
" normal = vector / np.linalg.norm(vector)\n",
" # rotate the vector 90 degrees\n",
" normal = np.array([-normal[1], normal[0]])\n",
" # move the intersection point along the normal vector by the spacing\n",
" points.append(intersection + normal * offset)\n"
]
},
{
"cell_type": "code",
"execution_count": 145,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<AxesSubplot: xlabel='x'>"
]
},
"execution_count": 145,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# plot the points\n",
"df = pd.DataFrame(points, columns=['x', 'y'])\n",
"df.plot.line(x='x', y='y')"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.10.7 ('venv': venv)",
"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.10.7"
},
"orig_nbformat": 4,
"vscode": {
"interpreter": {
"hash": "1ce20143987840b9786ebb5907032c9c3a8efacbb887dbb0ebc4934f2ad26cb3"
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}