|
1 | 1 | #!/usr/bin/env python
|
2 | 2 | # -*- coding: utf-8 -*-
|
3 | 3 | #
|
4 |
| -# arc.py |
| 4 | +# arc.py {Point1},{Point2},{Point3} {Segments} {Params} |
| 5 | +# stdin: - |
| 6 | +# |
| 7 | +# Script creates an arc by three specified points - start, intermediate and end of an arc. Arc will have specified number of segments. |
| 8 | +# Params: 0 - nothing special, 1 - creates axes of an arc |
| 9 | +# Segments = 0 will use autocalculation for smooth arc |
| 10 | +# Note: arc will not be more than semicircle, if intermediate point is far from start and end |
| 11 | +# then script will create counterpart arc of same circle (TOFIX) |
5 | 12 | #
|
6 | 13 | # Copyright 2010-2011 Hind <foxhind@gmail.com>
|
| 14 | +# modified by OverQuantum: |
| 15 | +# 2014-12-13 Fix to 4 spaces indentation; added Params (0/1) - 1 for creation of axes |
7 | 16 | #
|
8 | 17 | # This program is free software; you can redistribute it and/or modify
|
9 | 18 | # it under the terms of the GNU General Public License as published by
|
|
12 | 21 | #
|
13 | 22 | # This program is distributed in the hope that it will be useful,
|
14 | 23 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15 |
| -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 24 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | 25 | # GNU General Public License for more details.
|
17 | 26 | #
|
18 | 27 | # You should have received a copy of the GNU General Public License
|
|
26 | 35 | from OsmData import OsmData, Map, LON, LAT, ACTION, MODIFY, TAG, CREATE, REF, NODES, WAYS
|
27 | 36 |
|
28 | 37 | if sys.version_info[0] < 3:
|
29 |
| - reload(sys) |
30 |
| - sys.setdefaultencoding("utf-8") # a hack to support UTF-8 |
| 38 | + reload(sys) |
| 39 | + sys.setdefaultencoding("utf-8") # a hack to support UTF-8 |
31 | 40 |
|
32 | 41 | def intersect(vector1, pivot1, vector2, pivot2): # intersection of 2 lines
|
33 |
| - k1 = vector1[1]/vector1[0] |
34 |
| - b1 = (vector1[0]*pivot1[1] - vector1[1]*pivot1[0]) / vector1[0] |
35 |
| - k2 = vector2[1]/vector2[0] |
36 |
| - b2 = (vector2[0]*pivot2[1] - vector2[1]*pivot2[0]) / vector2[0] |
37 |
| - x = (b1 - b2) / (k2 - k1) |
38 |
| - y = (k2*b1 - k1*b2) / (k2 - k1) |
39 |
| - return (x, y) |
| 42 | + k1 = vector1[1]/vector1[0] |
| 43 | + b1 = (vector1[0]*pivot1[1] - vector1[1]*pivot1[0]) / vector1[0] |
| 44 | + k2 = vector2[1]/vector2[0] |
| 45 | + b2 = (vector2[0]*pivot2[1] - vector2[1]*pivot2[0]) / vector2[0] |
| 46 | + x = (b1 - b2) / (k2 - k1) |
| 47 | + y = (k2*b1 - k1*b2) / (k2 - k1) |
| 48 | + return (x, y) |
40 | 49 |
|
41 | 50 | def createarc(C, P1, P2, r, segments):
|
42 |
| - arc = [P1] |
43 |
| - CP1 = (P1[0]-C[0], P1[1]-C[1]) |
44 |
| - CP2 = (P2[0]-C[0], P2[1]-C[1]) |
45 |
| - a1 = math.atan(CP1[1]/CP1[0]) # start angle |
46 |
| - if CP1[0] < 0: |
47 |
| - a1 += math.pi |
48 |
| - if a1 < 0: |
49 |
| - a1 += math.pi*2 |
50 |
| - a2 = math.atan(CP2[1]/CP2[0]) # end angle |
51 |
| - if CP2[0] < 0: |
52 |
| - a2 += math.pi |
53 |
| - if a2 < 0: |
54 |
| - a2 += math.pi*2 |
55 |
| - |
56 |
| - if a2-a1 > math.pi: |
57 |
| - a2 -= math.pi*2 |
58 |
| - elif a1-a2 > math.pi: |
59 |
| - a1 -= math.pi*2 |
60 |
| - |
61 |
| - if segments == 0: # optimal number of segments |
62 |
| - P1P2 = (P2[0]-P1[0], P2[1]-P1[1]) |
63 |
| - P1P2abs = math.sqrt(P1P2[0]*P1P2[0] + P1P2[1]*P1P2[1]) |
64 |
| - segments = int(math.ceil(math.log(P1P2abs, 4) * (math.cos((a2-a1)/2) + 1.5))) # cat's magic formula |
| 51 | + arc = [P1] |
| 52 | + CP1 = (P1[0]-C[0], P1[1]-C[1]) |
| 53 | + CP2 = (P2[0]-C[0], P2[1]-C[1]) |
| 54 | + a1 = math.atan(CP1[1]/CP1[0]) # start angle |
| 55 | + if CP1[0] < 0: |
| 56 | + a1 += math.pi |
| 57 | + if a1 < 0: |
| 58 | + a1 += math.pi*2 |
| 59 | + a2 = math.atan(CP2[1]/CP2[0]) # end angle |
| 60 | + if CP2[0] < 0: |
| 61 | + a2 += math.pi |
| 62 | + if a2 < 0: |
| 63 | + a2 += math.pi*2 |
65 | 64 |
|
66 |
| - interval = (a2 - a1) / segments |
67 |
| - for n in range(1, segments): |
68 |
| - val = a1 + interval * n |
69 |
| - arc.append(( C[0] + r * math.cos(val), C[1] + r * math.sin(val) )) |
70 |
| - arc.append(P2) |
71 |
| - return arc |
| 65 | + if a2-a1 > math.pi: |
| 66 | + a2 -= math.pi*2 |
| 67 | + elif a1-a2 > math.pi: |
| 68 | + a1 -= math.pi*2 |
| 69 | + |
| 70 | + if segments == 0: # optimal number of segments |
| 71 | + P1P2 = (P2[0]-P1[0], P2[1]-P1[1]) |
| 72 | + P1P2abs = math.sqrt(P1P2[0]*P1P2[0] + P1P2[1]*P1P2[1]) |
| 73 | + segments = int(math.ceil(math.log(P1P2abs, 4) * (math.cos((a2-a1)/2) + 1.5))) # cat's magic formula |
| 74 | + |
| 75 | + interval = (a2 - a1) / segments |
| 76 | + for n in range(1, segments): |
| 77 | + val = a1 + interval * n |
| 78 | + arc.append(( C[0] + r * math.cos(val), C[1] + r * math.sin(val) )) |
| 79 | + arc.append(P2) |
| 80 | + return arc |
72 | 81 |
|
73 | 82 | def main():
|
74 |
| - if len(sys.argv) != 3: |
| 83 | + if len(sys.argv) != 4: |
| 84 | + return 0 |
| 85 | + coords = (sys.argv[1].split(',')) |
| 86 | + A = projections.from4326((float(coords[0]),float(coords[1])), "EPSG:3857") |
| 87 | + B = projections.from4326((float(coords[2]),float(coords[3])), "EPSG:3857") |
| 88 | + C = projections.from4326((float(coords[4]),float(coords[5])), "EPSG:3857") |
| 89 | + segments = int(sys.argv[2]) |
| 90 | + params = int(sys.argv[3]) |
| 91 | + AM = ((B[0] - A[0])/2, (B[1] - A[1])/2) |
| 92 | + BN = ((C[0] - B[0])/2, (C[1] - B[1])/2) |
| 93 | + M = (A[0] + AM[0], A[1] + AM[1]) |
| 94 | + N = (B[0] + BN[0], B[1] + BN[1]) |
| 95 | + MM = (AM[1], -AM[0]) |
| 96 | + NN = (BN[1], -BN[0]) |
| 97 | + O = intersect(MM, M, NN, N) # circle center |
| 98 | + OA = (O[0] - A[0], O[1] - A[1]) |
| 99 | + r = math.sqrt(OA[0]*OA[0] + OA[1]*OA[1]) # radius |
| 100 | + arc = createarc(O, A, C, r, segments) |
| 101 | + |
| 102 | + tData = OsmData() |
| 103 | + wayid = tData.addway() |
| 104 | + for point in arc: |
| 105 | + p = projections.to4326(point, "EPSG:3857") |
| 106 | + newid = tData.addnode() |
| 107 | + tData.nodes[newid][LON] = p[0] |
| 108 | + tData.nodes[newid][LAT] = p[1] |
| 109 | + tData.nodes[newid][TAG] = {} |
| 110 | + tData.ways[wayid][REF].append(newid) |
| 111 | + if params == 1: |
| 112 | + p2 = projections.to4326(O, "EPSG:3857") # center |
| 113 | + p1 = projections.to4326((O[0]-r*1.05,O[1]), "EPSG:3857") # axes points |
| 114 | + p3 = projections.to4326((O[0]+r*1.05,O[1]), "EPSG:3857") |
| 115 | + p4 = projections.to4326((O[0],O[1]-r*1.05), "EPSG:3857") |
| 116 | + p5 = projections.to4326((O[0],O[1]+r*1.05), "EPSG:3857") |
| 117 | + wayid = tData.addway() |
| 118 | + newid = tData.addnode() |
| 119 | + tData.nodes[newid][LON] = p1[0] |
| 120 | + tData.nodes[newid][LAT] = p1[1] |
| 121 | + tData.nodes[newid][TAG] = {} |
| 122 | + tData.ways[wayid][REF].append(newid) |
| 123 | + newid2 = tData.addnode() |
| 124 | + tData.nodes[newid2][LON] = p2[0] |
| 125 | + tData.nodes[newid2][LAT] = p2[1] |
| 126 | + tData.nodes[newid2][TAG] = {} |
| 127 | + tData.ways[wayid][REF].append(newid2) |
| 128 | + newid = tData.addnode() |
| 129 | + tData.nodes[newid][LON] = p3[0] |
| 130 | + tData.nodes[newid][LAT] = p3[1] |
| 131 | + tData.nodes[newid][TAG] = {} |
| 132 | + tData.ways[wayid][REF].append(newid) |
| 133 | + wayid = tData.addway() |
| 134 | + newid = tData.addnode() |
| 135 | + tData.nodes[newid][LON] = p4[0] |
| 136 | + tData.nodes[newid][LAT] = p4[1] |
| 137 | + tData.nodes[newid][TAG] = {} |
| 138 | + tData.ways[wayid][REF].append(newid) |
| 139 | + tData.ways[wayid][REF].append(newid2) |
| 140 | + newid = tData.addnode() |
| 141 | + tData.nodes[newid][LON] = p5[0] |
| 142 | + tData.nodes[newid][LAT] = p5[1] |
| 143 | + tData.nodes[newid][TAG] = {} |
| 144 | + tData.ways[wayid][REF].append(newid) |
| 145 | + |
| 146 | + tData.addcomment("Done.") |
| 147 | + tData.write(sys.stdout) |
| 148 | + #f = open("out.txt", "w") |
| 149 | + #tData.write(f) |
| 150 | + #f.close() |
75 | 151 | return 0
|
76 |
| - coords = (sys.argv[1].split(',')) |
77 |
| - A = projections.from4326((float(coords[0]),float(coords[1])), "EPSG:3857") |
78 |
| - B = projections.from4326((float(coords[2]),float(coords[3])), "EPSG:3857") |
79 |
| - C = projections.from4326((float(coords[4]),float(coords[5])), "EPSG:3857") |
80 |
| - segments = int(sys.argv[2]) |
81 |
| - AM = ((B[0] - A[0])/2, (B[1] - A[1])/2) |
82 |
| - BN = ((C[0] - B[0])/2, (C[1] - B[1])/2) |
83 |
| - M = (A[0] + AM[0], A[1] + AM[1]) |
84 |
| - N = (B[0] + BN[0], B[1] + BN[1]) |
85 |
| - MM = (AM[1], -AM[0]) |
86 |
| - NN = (BN[1], -BN[0]) |
87 |
| - O = intersect(MM, M, NN, N) |
88 |
| - OA = (O[0] - A[0], O[1] - A[1]) |
89 |
| - r = math.sqrt(OA[0]*OA[0] + OA[1]*OA[1]) |
90 |
| - arc = createarc(O, A, C, r, segments) |
91 |
| - |
92 |
| - tData = OsmData() |
93 |
| - wayid = tData.addway() |
94 |
| - for point in arc: |
95 |
| - p = projections.to4326(point, "EPSG:3857") |
96 |
| - newid = tData.addnode() |
97 |
| - tData.nodes[newid][LON] = p[0] |
98 |
| - tData.nodes[newid][LAT] = p[1] |
99 |
| - tData.nodes[newid][TAG] = {} |
100 |
| - tData.ways[wayid][REF].append(newid) |
101 |
| - |
102 |
| - tData.addcomment("Done.") |
103 |
| - tData.write(sys.stdout) |
104 |
| - #f = open("out.txt", "w") |
105 |
| - #tData.write(f) |
106 |
| - #f.close() |
107 |
| - return 0 |
108 | 152 |
|
109 | 153 | if __name__ == '__main__':
|
110 |
| - main() |
| 154 | + main() |
0 commit comments