{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"from shapely.geometry import LineString, Polygon, MultiPolygon, MultiLineString, GeometryCollection, Point, MultiPoint, box, shape\n",
"from shapely.geometry.polygon import orient\n",
"from shapely.affinity import rotate, scale, translate\n",
"from shapely.geometry import mapping, shape\n",
"import json"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"- We've calculated `ymin_P` and `ymax_Q`, and drawn lines of support parallel to the x axis, using minimum and maximum X values\n",
"- We've calculated the angles between the support lines and line `PQ`, and taken the minimum"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
"<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"300\" height=\"300\" viewBox=\"-585.5 -241.0 1188.0 488.0\" preserveAspectRatio=\"xMinYMin meet\"><g transform=\"matrix(1,0,0,-1,0,6.0)\"><g><path fill-rule=\"evenodd\" fill=\"#66cc99\" stroke=\"#555555\" stroke-width=\"7.92\" opacity=\"0.6\" d=\"M -341.5,-197.0 L -441.5,-97.0 L -441.5,3.0 L -341.5,103.0 L -241.5,103.0 L -141.5,3.0 L -141.5,-97.0 L -241.5,-197.0 L -341.5,-197.0 z\" /><path fill-rule=\"evenodd\" fill=\"#66cc99\" stroke=\"#555555\" stroke-width=\"7.92\" opacity=\"0.6\" d=\"M 158.5,-197.0 L 258.5,-197.0 L 358.5,-97.0 L 358.5,3.0 L 158.5,203.0 L 58.5,3.0 L 8.5,-47.0 L 58.5,-97.0 L 158.5,-197.0 z\" /><polyline fill=\"none\" stroke=\"#66cc99\" stroke-width=\"7.92\" points=\"-341.5,-197.0 -541.5,-197.0\" opacity=\"0.8\" /><polyline fill=\"none\" stroke=\"#66cc99\" stroke-width=\"7.92\" points=\"158.5,203.0 558.5,203.0\" opacity=\"0.8\" /><circle cx=\"-341.5\" cy=\"-197.0\" r=\"11.88\" stroke=\"#555555\" stroke-width=\"3.96\" fill=\"#66cc99\" opacity=\"0.6\" /><circle cx=\"158.5\" cy=\"203.0\" r=\"11.88\" stroke=\"#555555\" stroke-width=\"3.96\" fill=\"#66cc99\" opacity=\"0.6\" /><polyline fill=\"none\" stroke=\"#66cc99\" stroke-width=\"7.92\" points=\"-341.5,-197.0 158.5,203.0\" opacity=\"0.8\" /></g></g></svg>"
],
"text/plain": [
"<shapely.geometry.collection.GeometryCollection at 0x104fdb150>"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# left\n",
"P = [(5., 1.), (4., 2.), (4., 3.), (5., 4.), (6., 4.), (7., 3.), (7., 2.), (6., 1.), (5., 1.)]\n",
"# right\n",
"Q = [(10., 1.), (11., 1.), (12., 2.), (12., 3.), (10., 5.), (9., 3.), (8.5, 2.5), (9., 2.), (10., 1.)]\n",
"\n",
"yminp = P[0]\n",
"ymaxq = Q[4]\n",
"\n",
"p_support = LineString([yminp, (3., 1.)])\n",
"q_support = LineString([ymaxq, (14., 5.)])\n",
"\n",
"\n",
"gc = GeometryCollection([\n",
" # polygon P\n",
" Polygon(P),\n",
" # polygon Q\n",
" Polygon(Q),\n",
" # Lower line of support\n",
" p_support,\n",
" # Upper line of support\n",
" q_support,\n",
" # poly1 ymin\n",
" Point(yminp),\n",
" # poly2 ymax\n",
" Point(ymaxq),\n",
" # line pq\n",
" LineString([yminp, ymaxq]),\n",
"])\n",
"\n",
"scale(gc, 100., 100.)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1.5"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Polygon(P).distance(Polygon(Q))"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1.5"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Polygon(Q).convex_hull.distance(Polygon(P).convex_hull)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## First Iteration"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
"<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"300\" height=\"300\" viewBox=\"-545.395490323 -237.970562748 1106.20519421 481.941125497\" preserveAspectRatio=\"xMinYMin meet\"><g transform=\"matrix(1,0,0,-1,0,6.0)\"><g><path fill-rule=\"evenodd\" fill=\"#66cc99\" stroke=\"#555555\" stroke-width=\"7.37470129473\" opacity=\"0.6\" d=\"M -263.003571337,-197.0 L -363.003571337,-97.0 L -363.003571337,3.0 L -263.003571337,103.0 L -163.003571337,103.0 L -63.0035713375,3.0 L -63.0035713375,-97.0 L -163.003571337,-197.0 L -263.003571337,-197.0 z\" /><path fill-rule=\"evenodd\" fill=\"#66cc99\" stroke=\"#555555\" stroke-width=\"7.37470129473\" opacity=\"0.6\" d=\"M 236.996428663,-197.0 L 336.996428663,-197.0 L 436.996428663,-97.0 L 436.996428663,3.0 L 236.996428663,203.0 L 136.996428663,3.0 L 86.9964286625,-47.0 L 136.996428663,-97.0 L 236.996428663,-197.0 z\" /><circle cx=\"-363.003571337\" cy=\"-97.0\" r=\"11.0620519421\" stroke=\"#555555\" stroke-width=\"3.68735064736\" fill=\"#66cc99\" opacity=\"0.6\" /><circle cx=\"236.996428663\" cy=\"203.0\" r=\"11.0620519421\" stroke=\"#555555\" stroke-width=\"3.68735064736\" fill=\"#66cc99\" opacity=\"0.6\" /><polyline fill=\"none\" stroke=\"#66cc99\" stroke-width=\"7.37470129473\" points=\"236.996428663,203.0 -363.003571337,-97.0\" opacity=\"0.8\" /><polyline fill=\"none\" stroke=\"#66cc99\" stroke-width=\"7.37470129473\" points=\"-363.003571337,-97.0 -504.424927575,-97.0\" opacity=\"0.8\" /><polyline fill=\"none\" stroke=\"#66cc99\" stroke-width=\"7.37470129473\" points=\"236.996428663,203.0 519.839141137,-79.8427124746\" opacity=\"0.8\" /><circle cx=\"-63.0035713375\" cy=\"-97.0\" r=\"11.0620519421\" stroke=\"#555555\" stroke-width=\"3.68735064736\" fill=\"#66cc99\" opacity=\"0.6\" /><circle cx=\"436.996428663\" cy=\"3.0\" r=\"11.0620519421\" stroke=\"#555555\" stroke-width=\"3.68735064736\" fill=\"#66cc99\" opacity=\"0.6\" /></g></g></svg>"
],
"text/plain": [
"<shapely.geometry.collection.GeometryCollection at 0x104fd90d0>"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# calipers following initial rotation by 45 degrees\n",
"rotated_p = rotate(p_support, -45., origin=Point(yminp))\n",
"rotated_q = rotate(q_support, -45., origin=Point(ymaxq))\n",
"\n",
"gc = GeometryCollection([\n",
" # polygon P\n",
" Polygon(P),\n",
" # polygon Q\n",
" Polygon(Q),\n",
" # poly1 ymin\n",
" Point(yminp),\n",
" # poly2 ymax\n",
" Point(ymaxq),\n",
" # line pq\n",
" LineString([ymaxq, yminp]),\n",
" rotated_p,\n",
" rotated_q,\n",
" Point(P[6]),\n",
" Point(Q[3]),\n",
"# Point(3.778326271485311, +3)\n",
"])\n",
"scale(gc, 100., 100.)"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1.5811388300841898"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Point(7., 2.).distance(Point(8.5, 2.5))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### It is evident that our calipers now coincide with a vertex on `P`, and are flush with a line edge on `Q`\n",
"### Vertices at `P[6]` and `Q[3]`\n",
"#### Next vertices will be in decreasing order\n",
"\n",
"However, we need to determine this using programatically, given that we know:\n",
"- The vertices of `P` and `Q`, which are sorted by their `x` coordinates, in clockwise order\n",
"- The caliper anchor points on `P` and `Q`\n",
"- The rotation angle θ"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"- If the vertex Q<sub>i</sub> is the anchor point for caliper Q<sub>c</sub>\n",
" - we can check if the angle between initial caliper and new caliper is **equal** to initial caliper and segment Q<sub>i</sub>, Q<sub>i + 1</sub>\n",
" - if it is, the caliper **coincides with an edge**\n",
" - if it doesn't, the caliper **coincides with a point**\n",
" - **How do we determine the end point?**"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If only one line coincides with an edge, then:\n",
"- the vertex-edge anti-podal pair distance should be computed\n",
"- the new vertex-vertex anti-podal pair distance should be computed\n",
"- Both distances are compared the current minimum, which is updated if necessary."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If both lines of support coincide with edges, then the situation is somewhat more complex:\n",
"- If the edges \"overlap\", that is if one can construct a line perpendicular to both edges and intersecting both edges (but not at vertices), then the edge-edge distance should be computed.\n",
"- Otherwise the three new vertex-vertex anti-podal pair distances are computed.\n",
"\n",
"All distances are compared to the current minimum, which is updated if necessary."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Tasks\n",
"- How do we check whether we've hit a vertex?\n",
"- How do we check whether we're flush with an edge (implies that we've hit a vertex)?\n",
"- How do we calculate the next rotation angle?"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"> The next event a caliper can generate is when it is coincident with the next line segment from that point. Take the dot product of the direction of that caliper with the direction of that next line segment and divide by the length of the next line segment.\n",
"The resulting value is proportional to the cosine of angle between the caliper and the segment. Since this angle is between 0 and 180 degrees and the cosine function is strictly decreasing on that inverval, the order is preserved and we can just compare these values to find the one that has the least angle. If the polygon and the calipers have the same winding (both clockwise or both counterclockwise) then the one with the highest value will be the next event (if the windings are different then the lowest value corresponds to the next event)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Next Iteration"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
"<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"300\" height=\"300\" viewBox=\"-435.705841992 -229.87520314 887.630484769 465.750406279\" preserveAspectRatio=\"xMinYMin meet\"><g transform=\"matrix(1,0,0,-1,0,6.0)\"><g><path fill-rule=\"evenodd\" fill=\"#66cc99\" stroke=\"#555555\" stroke-width=\"5.91753656513\" opacity=\"0.6\" d=\"M -302.830638853,-197.0 L -202.830638853,-197.0 L -102.830638853,-97.0 L -102.830638853,3.0 L -202.830638853,103.0 L -302.830638853,103.0 L -402.830638853,3.0 L -402.830638853,-97.0 L -302.830638853,-197.0 z\" /><path fill-rule=\"evenodd\" fill=\"#66cc99\" stroke=\"#555555\" stroke-width=\"5.91753656513\" opacity=\"0.6\" d=\"M 197.169361147,-197.0 L 297.169361147,-197.0 L 397.169361147,-97.0 L 397.169361147,3.0 L 197.169361147,203.0 L 97.1693611474,3.0 L 97.1693611474,-97.0 L 197.169361147,-197.0 z\" /><circle cx=\"-202.830638853\" cy=\"-197.0\" r=\"8.87630484769\" stroke=\"#555555\" stroke-width=\"2.95876828256\" fill=\"#66cc99\" opacity=\"0.6\" /><circle cx=\"197.169361147\" cy=\"203.0\" r=\"8.87630484769\" stroke=\"#555555\" stroke-width=\"2.95876828256\" fill=\"#66cc99\" opacity=\"0.6\" /><polyline fill=\"none\" stroke=\"#66cc99\" stroke-width=\"5.91753656513\" points=\"197.169361147,203.0 -202.830638853,-197.0\" opacity=\"0.8\" /><polyline fill=\"none\" stroke=\"#66cc99\" stroke-width=\"5.91753656513\" points=\"-202.830638853,-197.0 -369.24069772,52.6150883014\" opacity=\"0.8\" /><polyline fill=\"none\" stroke=\"#66cc99\" stroke-width=\"5.91753656513\" points=\"197.169361147,203.0 419.049439637,-129.820117735\" opacity=\"0.8\" /><circle cx=\"-302.830638853\" cy=\"103.0\" r=\"8.87630484769\" stroke=\"#555555\" stroke-width=\"2.95876828256\" fill=\"#66cc99\" opacity=\"0.6\" /><circle cx=\"397.169361147\" cy=\"-97.0\" r=\"8.87630484769\" stroke=\"#555555\" stroke-width=\"2.95876828256\" fill=\"#66cc99\" opacity=\"0.6\" /></g></g></svg>"
],
"text/plain": [
"<shapely.geometry.collection.GeometryCollection at 0x104f74410>"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# next vertices are P[5] and Q[2]\n",
"# calculate angles between p support line and (ymin_p, P[5]), q support line (ymax_p, Q[2])\n",
"# => 71.56505117707799, 56.309932474020215, and take the minimum\n",
"\n",
"rotated_p_2 = rotate(p_support, -56.309932474020215, origin=Point(yminp))\n",
"rotated_q_2 = rotate(q_support, -56.309932474020215, origin=Point(ymaxq))\n",
"\n",
"gc = GeometryCollection([\n",
" # polygon P\n",
" Polygon(P),\n",
" # polygon Q\n",
" Polygon(Q),\n",
" # poly1 ymin\n",
" Point(yminp),\n",
" # poly2 ymax\n",
" Point(ymaxq),\n",
" # line pq\n",
" LineString([ymaxq, yminp]),\n",
" rotated_p_2,\n",
" rotated_q_2,\n",
" Point(P[5]),\n",
" Point(Q[2]),\n",
"])\n",
"scale(gc, 100., 100.)"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1.5811388300841898"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# P1: Point(Coordinate { x: 7, y: 2 })\n",
"# Q2PREV: Point(Coordinate { x: 10, y: 1 })\n",
"# Q2: Point(Coordinate { x: 8.5, y: 2.5 })\n",
"\n",
"p = Point(7., 2.)\n",
"ls = LineString([(10., 1.), (8.5, 2.5)])\n",
"p.distance(ls)"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1.5"
]
},
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Point(8.5, 2.5).distance(LineString([(7., 2.), (7., 3)]))"
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"shell = Polygon(\n",
" [(0., 0.), (10., 0.), (10., 10.), (0., 10.), (0., 0)],\n",
" holes=[[(1., 1.), (9., 1.), (9., 9.), (1., 9), (1., 1.)]]\n",
")\n",
"\n",
"inside = Polygon([(5., 5), (6., 5.), (6., 6.), (5., 6.), (5., 5.)])"
]
},
{
"cell_type": "code",
"execution_count": 35,
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
"<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"100.0\" height=\"100.0\" viewBox=\"-0.4 -0.4 10.8 10.8\" preserveAspectRatio=\"xMinYMin meet\"><g transform=\"matrix(1,0,0,-1,0,10.0)\"><g><path fill-rule=\"evenodd\" fill=\"#66cc99\" stroke=\"#555555\" stroke-width=\"0.216\" opacity=\"0.6\" d=\"M 0.0,0.0 L 10.0,0.0 L 10.0,10.0 L 0.0,10.0 L 0.0,0.0 z M 1.0,1.0 L 9.0,1.0 L 9.0,9.0 L 1.0,9.0 L 1.0,1.0 z\" /><path fill-rule=\"evenodd\" fill=\"#66cc99\" stroke=\"#555555\" stroke-width=\"0.216\" opacity=\"0.6\" d=\"M 5.0,5.0 L 6.0,5.0 L 6.0,6.0 L 5.0,6.0 L 5.0,5.0 z\" /></g></g></svg>"
],
"text/plain": [
"<shapely.geometry.collection.GeometryCollection at 0x104f9b590>"
]
},
"execution_count": 35,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"GeometryCollection([\n",
" shell,\n",
" inside\n",
"])"
]
},
{
"cell_type": "code",
"execution_count": 36,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3.0"
]
},
"execution_count": 36,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"shell.distance(inside)"
]
},
{
"cell_type": "code",
"execution_count": 37,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 37,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"shell.disjoint(inside)"
]
},
{
"cell_type": "code",
"execution_count": 40,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 40,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"shell.convex_hull.contains(inside)"
]
},
{
"cell_type": "code",
"execution_count": 41,
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
"<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"100.0\" height=\"100.0\" viewBox=\"85.2 200.2 42.6 48.6\" preserveAspectRatio=\"xMinYMin meet\"><g transform=\"matrix(1,0,0,-1,0,449.0)\"><path fill-rule=\"evenodd\" fill=\"#66cc99\" stroke=\"#555555\" stroke-width=\"0.972\" opacity=\"0.6\" d=\"M 97.0,204.0 L 112.0,202.0 L 126.0,212.0 L 126.0,232.0 L 118.0,247.0 L 100.0,246.0 L 87.0,232.0 L 87.0,215.0 L 97.0,204.0 z\" /></g></svg>"
],
"text/plain": [
"<shapely.geometry.polygon.Polygon at 0x104feea50>"
]
},
"execution_count": 41,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"poly1 = Polygon([\n",
" (97, 204),\n",
" (112, 202),\n",
" (126, 212),\n",
" (126, 232),\n",
" (118, 247),\n",
" (100, 246),\n",
" (87, 232),\n",
" (87, 215),\n",
" (97, 204),\n",
"])\n",
"poly1"
]
},
{
"cell_type": "code",
"execution_count": 42,
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
"<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"100.0\" height=\"100.0\" viewBox=\"145.16 194.16 45.68 49.68\" preserveAspectRatio=\"xMinYMin meet\"><g transform=\"matrix(1,0,0,-1,0,438.0)\"><path fill-rule=\"evenodd\" fill=\"#66cc99\" stroke=\"#555555\" stroke-width=\"0.9936\" opacity=\"0.6\" d=\"M 164.0,196.0 L 174.0,196.0 L 189.0,207.0 L 188.0,231.0 L 177.0,242.0 L 158.0,242.0 L 147.0,220.0 L 164.0,196.0 z\" /></g></svg>"
],
"text/plain": [
"<shapely.geometry.polygon.Polygon at 0x104feec10>"
]
},
"execution_count": 42,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"poly2 = Polygon([\n",
" (164, 196),\n",
" (174, 196),\n",
" (189, 207),\n",
" (188, 231),\n",
" (177, 242),\n",
" (158, 242),\n",
" (147, 220),\n",
" (164, 196)\n",
" ])\n",
"poly2"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"p1 = Point(126., 212)\n",
"p2 = Point(126., 232)\n",
"q1 = Point(147., 220)"
]
},
{
"cell_type": "code",
"execution_count": 57,
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
"<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"300\" height=\"300\" viewBox=\"-963.6 -370.1 2203.2 1183.2\" preserveAspectRatio=\"xMinYMin meet\"><g transform=\"matrix(1,0,0,-1,0,443.0)\"><g><path fill-rule=\"evenodd\" fill=\"#66cc99\" stroke=\"#555555\" stroke-width=\"14.688\" opacity=\"0.6\" d=\"M -682.0,-128.5 L -382.0,-168.5 L -102.0,31.5 L -102.0,431.5 L -262.0,731.5 L -622.0,711.5 L -882.0,431.5 L -882.0,91.5 L -682.0,-128.5 z\" /><path fill-rule=\"evenodd\" fill=\"#66cc99\" stroke=\"#555555\" stroke-width=\"14.688\" opacity=\"0.6\" d=\"M 658.0,-288.5 L 858.0,-288.5 L 1158.0,-68.5 L 1138.0,411.5 L 918.0,631.5 L 538.0,631.5 L 318.0,191.5 L 658.0,-288.5 z\" /><circle cx=\"-102.0\" cy=\"31.5\" r=\"22.032\" stroke=\"#555555\" stroke-width=\"7.344\" fill=\"#66cc99\" opacity=\"0.6\" /><circle cx=\"-102.0\" cy=\"431.5\" r=\"22.032\" stroke=\"#555555\" stroke-width=\"7.344\" fill=\"#66cc99\" opacity=\"0.6\" /><circle cx=\"318.0\" cy=\"191.5\" r=\"22.032\" stroke=\"#555555\" stroke-width=\"7.344\" fill=\"#66cc99\" opacity=\"0.6\" /><polyline fill=\"none\" stroke=\"#66cc99\" stroke-width=\"14.688\" points=\"318.0,191.5 -102.0,191.5\" opacity=\"0.8\" /></g></g></svg>"
],
"text/plain": [
"<shapely.geometry.collection.GeometryCollection at 0x104fee8d0>"
]
},
"execution_count": 57,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ex_gc = GeometryCollection([\n",
" poly1,\n",
" poly2,\n",
" p1,\n",
" p2,\n",
" q1,\n",
" LineString([q1, translate(q1, xoff=-21.)])\n",
"])\n",
"scale(ex_gc, 20, 20)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"1, 0, x\n",
"0, 1, y\n",
"0, 0, 1"
]
},
{
"cell_type": "code",
"execution_count": 72,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[(1.5, 3.5), (6.5, 8.5), (11.5, 13.5)]"
]
},
"execution_count": 72,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"list(translate(LineString([(0., 0), (5., 5.), (10., 10.)]), xoff=1.5, yoff=3.5).coords)"
]
},
{
"cell_type": "code",
"execution_count": 70,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[(22.0, 19.3), (22.5, 20.0), (23.0, 19.3), (22.0, 19.3)]"
]
},
"execution_count": 70,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"list(translate(\n",
" Polygon(\n",
" [(5., 1.), (4., 2.), (4., 3.), (5., 4.), (6., 4.), (7., 3.), (7., 2.), (6., 1.), (5., 1.)],\n",
" holes=[[(5.0, 1.3), (5.5, 2.0), (6.0, 1.3), (5.0, 1.3)]]), xoff=17, yoff=18\n",
").interiors[0].coords)\n",
"\n",
"# [(5., 1.), (4., 2.), (4., 3.), (5., 4.), (6., 4.), (7., 3.), (7., 2.), (6., 1.), (5., 1.)]"
]
},
{
"cell_type": "code",
"execution_count": 77,
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
"<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"100.0\" height=\"100.0\" viewBox=\"85.4 152.4 70.2 50.2\" preserveAspectRatio=\"xMinYMin meet\"><g transform=\"matrix(1,0,0,-1,0,355.0)\"><path fill-rule=\"evenodd\" fill=\"#66cc99\" stroke=\"#555555\" stroke-width=\"1.404\" opacity=\"0.6\" d=\"M 118.0,200.0 L 153.0,179.0 L 106.0,155.0 L 88.0,190.0 L 118.0,200.0 z\" /></g></svg>"
],
"text/plain": [
"<shapely.geometry.polygon.Polygon at 0x105064410>"
]
},
"execution_count": 77,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"a = Polygon(\n",
" [(118, 200),\n",
" (153, 179),\n",
" (106, 155),\n",
" (88, 190),\n",
" (118, 200)]\n",
")\n",
"a"
]
},
{
"cell_type": "code",
"execution_count": 78,
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
"<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"100.0\" height=\"100.0\" viewBox=\"178.88 142.88 84.24 53.24\" preserveAspectRatio=\"xMinYMin meet\"><g transform=\"matrix(1,0,0,-1,0,339.0)\"><path fill-rule=\"evenodd\" fill=\"#66cc99\" stroke=\"#555555\" stroke-width=\"1.6848\" opacity=\"0.6\" d=\"M 242.0,186.0 L 260.0,146.0 L 182.0,175.0 L 216.0,193.0 L 242.0,186.0 z\" /></g></svg>"
],
"text/plain": [
"<shapely.geometry.polygon.Polygon at 0x105064c50>"
]
},
"execution_count": 78,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"b = Polygon(\n",
" [(242, 186),\n",
" (260, 146),\n",
" (182, 175),\n",
" (216, 193),\n",
" (242, 186)]\n",
")\n",
"b"
]
},
{
"cell_type": "code",
"execution_count": 79,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"29.274562336608895"
]
},
"execution_count": 79,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"a.distance(b)"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"with open(\"/users/sth/Downloads/norway.geojson\", 'r') as f:\n",
" norway = json.load(f)"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[u'type', u'features']"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"norway.keys()"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{u'geometry': {u'coordinates': [[[7.7214153002417, 58.742944416892726],\n",
" [7.717505467254093, 58.999440208560095],\n",
" [8.09309541253975, 58.999384446502326],\n",
" [8.468580627437314, 58.999127337819196],\n",
" [8.468835587250046, 58.7496128272988],\n",
" [7.7214153002417, 58.742944416892726]]],\n",
" u'type': u'Polygon'},\n",
" u'properties': {u'id': u'010S',\n",
" u'name': u'010S Norge 1:50 000',\n",
" u'series': u'N50',\n",
" u'vendor': u'Kartverket'},\n",
" u'type': u'Feature'}"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"norway['features'][0]"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [],
"source": [
"polygons = [shape(feature['geometry']) for feature in norway['features']]"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [],
"source": [
"gc = GeometryCollection(polygons)\n",
"gc_convex = gc.convex_hull"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [],
"source": [
"poly = Polygon([\n",
" (-6.064453, 68.49604),\n",
" (-7.426758, 68.688521),\n",
" (-8.569336, 68.544315),\n",
" (-9.272461, 68.431513),\n",
" (-10.063477, 68.285651),\n",
" (-10.898438, 68.056889),\n",
" (-11.337891, 67.792641),\n",
" (-11.601563, 67.458082),\n",
" (-11.601563, 66.964476),\n",
" (-11.425781, 66.583217),\n",
" (-11.25, 66.319861),\n",
" (-10.898438, 65.964377),\n",
" (-10.678711, 65.802776),\n",
" (-10.283203, 65.549367),\n",
" (-9.975586, 65.385147),\n",
" (-9.448242, 65.127638),\n",
" (-8.701172, 64.848937),\n",
" (-7.910156, 64.642704),\n",
" (-7.075195, 64.642704),\n",
" (-6.416016, 64.75539),\n",
" (-5.361328, 64.979359),\n",
" (-4.790039, 65.366837),\n",
" (-4.526367, 65.676381),\n",
" (-4.482422, 66.196009),\n",
" (-4.614258, 66.705169),\n",
" (-4.87793, 67.118748),\n",
" (-4.174805, 67.474922),\n",
" (-4.833984, 67.958148),\n",
" (-6.064453, 68.49604),\n",
"])"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The slowest run took 10.67 times longer than the fastest. This could mean that an intermediate result is being cached.\n",
"10000 loops, best of 3: 173 µs per loop\n"
]
}
],
"source": [
"%%timeit\n",
"gc_convex.distance(poly)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 2",
"language": "python",
"name": "python2"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.15"
}
},
"nbformat": 4,
"nbformat_minor": 2
}