mirror of
https://github.com/enzet/map-machine.git
synced 2025-05-17 02:56:25 +02:00
Mapper.
This commit is contained in:
commit
becf68f7e1
3 changed files with 1079 additions and 0 deletions
120
flinger.py
Normal file
120
flinger.py
Normal file
|
@ -0,0 +1,120 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Author: Sergey Vartanov (me@enzet.ru)
|
||||
"""
|
||||
|
||||
import math
|
||||
import sys
|
||||
|
||||
sys.path.append('lib')
|
||||
|
||||
from vector import Vector
|
||||
|
||||
|
||||
class Flinger(object):
|
||||
"""
|
||||
Flinger. Coordinates repositioning.
|
||||
"""
|
||||
def __init__(self, minimum, maximum, target_minimum=None, target_maximum=None, ratio=None):
|
||||
self.minimum = minimum
|
||||
self.maximum = maximum
|
||||
|
||||
if not target_minimum:
|
||||
target_minimum = Vector()
|
||||
if not target_maximum:
|
||||
target_maximum = maximum - minimum
|
||||
|
||||
space = Vector()
|
||||
|
||||
if ratio:
|
||||
if ratio == 'geo':
|
||||
ratio = math.sin((90.0 - ((self.maximum.y + self.minimum.y) / 2.0)) / 180.0 * math.pi)
|
||||
|
||||
current_ratio = (self.maximum.x - self.minimum.x) * ratio / (self.maximum.y - self.minimum.y)
|
||||
target_ratio = (target_maximum.x - target_minimum.x) / (target_maximum.y - target_minimum.y)
|
||||
|
||||
if current_ratio >= target_ratio:
|
||||
n = (target_maximum.x - target_minimum.x) / (maximum.x - minimum.x) / ratio
|
||||
space.y = ((target_maximum.y - target_minimum.y) - (maximum.y - minimum.y) * n) / 2.0
|
||||
space.x = 0
|
||||
else:
|
||||
n = (target_maximum.y - target_minimum.y) / (maximum.y - minimum.y)
|
||||
space.x = ((target_maximum.x - target_minimum.x) - (maximum.x - minimum.x) * n) / 2.0
|
||||
space.y = 0
|
||||
|
||||
target_minimum.x += space
|
||||
target_maximum.x += space
|
||||
|
||||
self.target_minimum = target_minimum
|
||||
self.target_maximum = target_maximum
|
||||
|
||||
def fling(self, current):
|
||||
"""
|
||||
Fling current point to the surface.
|
||||
"""
|
||||
x = map_(current.x, self.minimum.x, self.maximum.x, self.target_minimum.x, self.target_maximum.x)
|
||||
y = map_(current.y, self.minimum.y, self.maximum.y, self.target_minimum.y, self.target_maximum.y)
|
||||
return Vector(x, y)
|
||||
|
||||
|
||||
class Geo:
|
||||
def __init__(self, lat, lon):
|
||||
self.lat = lat
|
||||
self.lon = lon
|
||||
def __add__(self, other):
|
||||
return Geo(self.lat + other.lat, self.lon + other.lon)
|
||||
def __sub__(self, other):
|
||||
return Geo(self.lat - other.lat, self.lon - other.lon)
|
||||
def __repr__(self):
|
||||
return `self.lat` + ', ' + `self.lon`
|
||||
|
||||
|
||||
class GeoFlinger:
|
||||
def __init__(self, minimum, maximum, target_minimum=None, target_maximum=None):
|
||||
self.minimum = minimum
|
||||
self.maximum = maximum
|
||||
|
||||
# Ratio is depended of latitude. It is always <= 1.
|
||||
# In one latitude degree is always 40 000 / 360 km.
|
||||
# In one current longitude degree is about 40 000 / 360 * ratio km.
|
||||
|
||||
ratio = math.sin((90.0 - ((self.maximum.lat + self.minimum.lat) / 2.0)) / 180.0 * math.pi)
|
||||
|
||||
# Longitude displayed as x.
|
||||
# Latitude displayed as y.
|
||||
|
||||
# Ratio is x / y.
|
||||
|
||||
space = Vector()
|
||||
current_ratio = (self.maximum.lon - self.minimum.lon) * ratio / (self.maximum.lat - self.minimum.lat)
|
||||
target_ratio = (target_maximum.x - target_minimum.x) / (target_maximum.y - target_minimum.y)
|
||||
|
||||
if current_ratio >= target_ratio:
|
||||
n = (target_maximum.x - target_minimum.x) / (maximum.lon - minimum.lon) / ratio
|
||||
space.y = ((target_maximum.y - target_minimum.y) - (maximum.lat - minimum.lat) * n) / 2.0
|
||||
space.x = 0
|
||||
else:
|
||||
n = (target_maximum.y - target_minimum.y) / (maximum.lat - minimum.lat) * ratio
|
||||
space.x = ((target_maximum.x - target_minimum.x) - (maximum.lon - minimum.lon) * n) / 2.0
|
||||
space.y = 0
|
||||
|
||||
self.target_minimum = target_minimum + space
|
||||
self.target_maximum = target_maximum - space
|
||||
|
||||
self.space = space
|
||||
|
||||
def fling(self, current):
|
||||
x = map_(current.lon, self.minimum.lon, self.maximum.lon,
|
||||
self.target_minimum.x, self.target_maximum.x)
|
||||
y = map_(self.maximum.lat + self.minimum.lat - current.lat,
|
||||
self.minimum.lat, self.maximum.lat,
|
||||
self.target_minimum.y, self.target_maximum.y)
|
||||
return Vector(x, y)
|
||||
|
||||
|
||||
def map_(value, current_min, current_max, target_min, target_max):
|
||||
"""
|
||||
Map current value in bounds of current_min and current_max to bounds of target_min and target_max.
|
||||
"""
|
||||
return target_min + (value - current_min) / (current_max - current_min) * (target_max - target_min)
|
301
icons.svg
Normal file
301
icons.svg
Normal file
|
@ -0,0 +1,301 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="800px"
|
||||
height="600px"
|
||||
id="svg2987"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.5 r10040"
|
||||
sodipodi:docname="icons copy.svg">
|
||||
<defs
|
||||
id="defs2989" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="11.313708"
|
||||
inkscape:cx="76.615247"
|
||||
inkscape:cy="511.71353"
|
||||
inkscape:current-layer="layer1"
|
||||
inkscape:document-units="px"
|
||||
showgrid="true"
|
||||
showguides="false"
|
||||
inkscape:guide-bbox="true"
|
||||
inkscape:object-paths="true"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:window-width="1389"
|
||||
inkscape:window-height="813"
|
||||
inkscape:window-x="97"
|
||||
inkscape:window-y="85"
|
||||
inkscape:window-maximized="0">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid2995" />
|
||||
<sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="16,600"
|
||||
id="guide2997" />
|
||||
<sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="0,600"
|
||||
id="guide2999" />
|
||||
<sodipodi:guide
|
||||
orientation="0,1"
|
||||
position="0,600"
|
||||
id="guide3001" />
|
||||
<sodipodi:guide
|
||||
orientation="0,1"
|
||||
position="0,584"
|
||||
id="guide3003" />
|
||||
<sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="32,600"
|
||||
id="guide3005" />
|
||||
<sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="48,600"
|
||||
id="guide3007" />
|
||||
<sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="64,600"
|
||||
id="guide3009" />
|
||||
<sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="80,600"
|
||||
id="guide3011" />
|
||||
<sodipodi:guide
|
||||
orientation="0,1"
|
||||
position="0,568"
|
||||
id="guide3013" />
|
||||
<sodipodi:guide
|
||||
orientation="0,1"
|
||||
position="0,552"
|
||||
id="guide3015" />
|
||||
<sodipodi:guide
|
||||
orientation="0,1"
|
||||
position="0,536"
|
||||
id="guide3017" />
|
||||
<sodipodi:guide
|
||||
orientation="0,1"
|
||||
position="0,520"
|
||||
id="guide3019" />
|
||||
<sodipodi:guide
|
||||
orientation="0,1"
|
||||
position="0,504"
|
||||
id="guide3170" />
|
||||
<sodipodi:guide
|
||||
orientation="0,1"
|
||||
position="0,488"
|
||||
id="guide3172" />
|
||||
<sodipodi:guide
|
||||
orientation="0,1"
|
||||
position="0,472"
|
||||
id="guide3174" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata2992">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer">
|
||||
<rect
|
||||
style="fill:#ffffff;fill-rule:evenodd;stroke:none"
|
||||
id="rect3023"
|
||||
width="16"
|
||||
height="16"
|
||||
x="48"
|
||||
y="32" />
|
||||
<path
|
||||
style="fill:#000000;stroke:none"
|
||||
d="m 40,66 -6,2 0,1 6,-2 6,2 0,-1 -6,-2 z m -5,8 0,1 2,0 -1,3 1,0 1,-3 4,0 1,3 1,0 -1,-3 2,0 0,-1 -10,0 z"
|
||||
id="path3033"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccccccccccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3043"
|
||||
d="m 19,74 0,1 2,0 -1,3 1,0 1,-3 4,0 1,3 1,0 -1,-3 2,0 0,-1 z"
|
||||
style="fill:#000000;stroke:none" />
|
||||
<path
|
||||
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m 52,72 2,6 4,0 2,-6 z"
|
||||
id="path3051"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="M 56.125,69.5 C 55.996341,69.48209 55.883367,69.4955 55.75,69.53125 55.483267,69.60272 55.252961,69.778365 55.125,70 L 53,70 l -1,1 8,0 -1,-1 -2.15625,0 C 56.68835,69.734915 56.425204,69.541799 56.125,69.5 z"
|
||||
id="path3053"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ssccccccs" />
|
||||
<path
|
||||
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m 71,77 1,1 3,0 2,-9 -8,0 0,8 z"
|
||||
id="path3062"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccc" />
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="fill:#ffffff;stroke:none"
|
||||
id="path3060"
|
||||
sodipodi:cx="53"
|
||||
sodipodi:cy="13"
|
||||
sodipodi:rx="2"
|
||||
sodipodi:ry="2"
|
||||
d="m 55,13 a 2,2 0 1 1 -4,0 2,2 0 1 1 4,0 z"
|
||||
transform="matrix(1.25,0,0,1.25,4.25,61.25)" />
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="fill:#000000;stroke:none"
|
||||
id="path3058"
|
||||
sodipodi:cx="53"
|
||||
sodipodi:cy="13"
|
||||
sodipodi:rx="1"
|
||||
sodipodi:ry="1"
|
||||
d="m 54,13 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"
|
||||
transform="matrix(1.5,0,0,1.5,-9,58)" />
|
||||
<path
|
||||
style="fill:#000000;stroke:none"
|
||||
d="m 70,67 6,0 1,1 -8,0 z"
|
||||
id="rect3064"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
style="fill:#000000;stroke:none"
|
||||
d="m 83,71 c 0,-1.662 1.338,-3 3,-3 l 4,0 c 1.662,0 3,1.338 3,3 z m 10,3 c 0,1.662 -1.338,3 -3,3 l -4,0 c -1.662,0 -3,-1.338 -3,-3 z"
|
||||
id="rect3068"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="csscccsscc" />
|
||||
<path
|
||||
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m 82,72 -1,1 1,1 1,-1 10.5,0 0.5,1 1,-1 -1,-1 z"
|
||||
id="path3082"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccccc" />
|
||||
<path
|
||||
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m 35,40 0,1.5 5,-2 5,2 0,-1.5 -5,-2 z"
|
||||
id="path3084"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccc" />
|
||||
<path
|
||||
style="fill:#000000;stroke:none"
|
||||
d="m 35.5,37 3.5,0 0,1 -1,0 0,2 -1.5,0 0,-2 -1,0 z"
|
||||
id="rect3086"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccccc" />
|
||||
<path
|
||||
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m 52,47 2,-10 1,0 -2,10 z"
|
||||
id="path3089"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3091"
|
||||
d="m 60,47 -2,-10 -1,0 2,10 z"
|
||||
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<path
|
||||
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m 50,38 12,0 0,-1 -12,0 z"
|
||||
id="path3099"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m 49,39 2,0 0,1 -2,0 z"
|
||||
id="path3101"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3103"
|
||||
d="m 49,41 2,0 0,1 -2,0 z"
|
||||
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3105"
|
||||
d="m 61,39 2,0 0,1 -2,0 z"
|
||||
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<path
|
||||
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m 61,41 2,0 0,1 -2,0 z"
|
||||
id="path3107"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m 50,37 5,-3 2,0 0,1 -2,0 -5,3 z"
|
||||
id="path3109"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccc" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3111"
|
||||
d="m 62,37 -5,-3 0,1 5,3 z"
|
||||
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<rect
|
||||
style="fill:#000000;stroke:none"
|
||||
id="rect3113"
|
||||
width="4"
|
||||
height="1"
|
||||
x="54"
|
||||
y="40" />
|
||||
<rect
|
||||
y="43"
|
||||
x="53"
|
||||
height="1"
|
||||
width="6"
|
||||
id="rect3117"
|
||||
style="fill:#000000;stroke:none" />
|
||||
<path
|
||||
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans"
|
||||
d="m 37.9063,82.71875 -0.8125,0.5625 c 0.97155,1.45733 1.41595,2.612931 1.71875,4.1875 0.0406,0.21092 0.0585,0.460437 0.0937,0.6875 -0.2244,-0.500887 -0.4751,-0.934507 -0.75,-1.3125 -0.54981,-0.755988 -1.22674,-1.279312 -2,-1.34375 -0.77326,-0.06444 -1.50205,0.378078 -2.0625,1.21875 l 0.8125,0.5625 c 0.43955,-0.659328 0.83576,-0.841812 1.1875,-0.8125 0.35174,0.02931 0.79981,0.318487 1.25,0.9375 0.39596,0.544443 0.74318,1.333784 1.03125,2.28125 C 37.97106,89.378811 37.52208,89.170957 37.0625,89.125 35.51694,88.970444 34,90.222222 34,92 l 1,0 c 0,-1.222223 0.98306,-1.970445 1.9375,-1.875 0.47722,0.04772 0.97831,0.27997 1.375,0.875 0.39669,0.59503 0.6875,1.569444 0.6875,3 0.67042,0.02556 1.32993,0.01396 2,0 0,-1.430556 0.29081,-2.40497 0.6875,-3 0.39669,-0.59503 0.89778,-0.827278 1.375,-0.875 C 44.01694,90.02956 45,90.777777 45,92 l 1,0 c 0,-1.777778 -1.51694,-3.029556 -3.0625,-2.875 -0.45958,0.04596 -0.90856,0.253811 -1.3125,0.5625 0.28807,-0.947466 0.63529,-1.736807 1.03125,-2.28125 0.45019,-0.619013 0.89826,-0.908189 1.25,-0.9375 0.35174,-0.02931 0.74795,0.153172 1.1875,0.8125 l 0.8125,-0.5625 C 45.3458,85.878078 44.61701,85.435561 43.84375,85.5 c -0.77326,0.06444 -1.45019,0.587762 -2,1.34375 -0.2749,0.377993 -0.5256,0.811613 -0.75,1.3125 0.0352,-0.227063 0.0532,-0.47658 0.0937,-0.6875 0.3028,-1.574569 0.7472,-2.73017 1.71875,-4.1875 l -0.8125,-0.5625 c -1.02845,1.542669 -1.58405,2.887069 -1.90625,4.5625 -0.0693,0.360376 -0.13392,0.757955 -0.1875,1.15625 -0.0536,-0.398295 -0.1182,-0.795874 -0.1875,-1.15625 -0.3222,-1.675431 -0.8778,-3.019831 -1.90625,-4.5625 z"
|
||||
id="path2989"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccscssccsscsccssccssccscssccsscsccscsc" />
|
||||
<path
|
||||
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.03606772;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans"
|
||||
d="m 55.5,85.03125 c -2.132814,0 -3.60923,0.937935 -4.4375,2.28125 C 50.23423,88.655815 50,90.330782 50,92 l 1.03125,0 c 0,-1.562748 0.27118,-3.075591 0.9375,-4.15625 0.66632,-1.080659 1.678491,-1.78125 3.53125,-1.78125 1.852759,0 2.86493,0.700591 3.53125,1.78125 0.66632,1.080659 0.9375,2.593502 0.9375,4.15625 L 61,92 C 61,90.330782 60.76577,88.655815 59.9375,87.3125 59.10923,85.969185 57.632814,85.03125 55.5,85.03125 z"
|
||||
id="path2989-9"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#000000;stroke:none"
|
||||
d="m 19,82 0,12 1,0 0,-6 c 2,0 1,1 3,1 2,0 1,-1 3,-1 2,0 1,1 3,1 0,-2 0,-4 0,-6 -2,0 -1,-1 -3,-1 -2,0 -1,1 -3,1 -2,0 -1,-1 -3,-1 -2,0 -1,0 -1,0 z"
|
||||
id="path2983"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccszcczssc" />
|
||||
<rect
|
||||
style="fill:#000000;fill-rule:evenodd;stroke:none"
|
||||
id="rect3176"
|
||||
width="8"
|
||||
height="6"
|
||||
x="68"
|
||||
y="87" />
|
||||
<path
|
||||
style="fill:#000000;stroke:none"
|
||||
d="m 75,90 c 0,0 0,-2.8556 0,-4 0,-1.656854 -1.343146,-3 -3,-3 -1.656854,0 -3,1.343146 -3,3 0,2.042046 0,4 0,4 l 1,0 c 0,0 0,-3 0,-4 0,-1.10457 0.89543,-2 2,-2 1.10457,0 2,0.89543 2,2 0,1 0,4 0,4 z"
|
||||
id="path3178"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccsccccsccc" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 14 KiB |
658
mapper.py
Normal file
658
mapper.py
Normal file
|
@ -0,0 +1,658 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*- from __future__ import unicode_literals
|
||||
|
||||
# Author: Sergey Vartnov
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import xml.dom.minidom
|
||||
|
||||
from flinger import GeoFlinger, Geo
|
||||
|
||||
sys.path.append('lib')
|
||||
|
||||
import svg
|
||||
from vector import Vector
|
||||
|
||||
# class OSMGetter:
|
||||
# def get(x1, x2, y1, y2):
|
||||
# input_file = open(cache_folder + '/osm-' + `x1` + '-' + `y1` + '-' + \
|
||||
# `x2` + '-' + `y2`
|
||||
# if not os.path.isfile(input_file):
|
||||
|
||||
input_file_name = sys.argv[1]
|
||||
|
||||
if not os.path.isfile(input_file_name):
|
||||
sys.exit(1)
|
||||
|
||||
print 'Reading input OSM file...'
|
||||
|
||||
input_file = open(input_file_name)
|
||||
content = xml.dom.minidom.parse(input_file)
|
||||
input_file.close()
|
||||
|
||||
print 'Done.'
|
||||
|
||||
output_file = svg.SVG(open(sys.argv[2], 'w+'))
|
||||
|
||||
w, h = 2000, 2000
|
||||
|
||||
background_color = 'EEEEEE'
|
||||
grass_color = 'C8DC94'
|
||||
sand_color = 'F0E0D0'
|
||||
beach_color = 'F0E0C0'
|
||||
desert_color = 'F0E0D0'
|
||||
playground_color = '884400'
|
||||
parking_color = 'DDCC99'
|
||||
water_color = 'AACCFF'
|
||||
water_border_color = '6688BB'
|
||||
wood_color = 'B8CC84'
|
||||
|
||||
output_file.begin(w, h)
|
||||
output_file.rect(0, 0, w, h, color=background_color)
|
||||
|
||||
minimum = Geo(180, 180)
|
||||
maximum = Geo(-180, -180)
|
||||
|
||||
if len(sys.argv) > 3:
|
||||
min1 = Geo(float(sys.argv[5]), float(sys.argv[3]))
|
||||
max1 = Geo(float(sys.argv[6]), float(sys.argv[4]))
|
||||
|
||||
authors = {}
|
||||
missed_tags = {}
|
||||
|
||||
d_street_lamp = 'm 7,1 -3.5,3 1.59375,0 1,5 1.40625,0 0,6 1,0 0,-6 1.40625,0 1,-5 L 12.5,4 9,1 z M 6.125,4 9.875,4 9.09375,8 6.90625,8 z'
|
||||
d_clinic = 'M 7,5 7,7 5,7 5,9 7,9 7,11 9,11 9,9 11,9 11,7 9,7 9,5 7,5'
|
||||
d_crossing = 'm 3,5 0,6 1,0 0,-6 z m 4,0 0,6 1,0 0,-6 z m 4,0 0,6 1,0 0,-6 z'
|
||||
d_traffic_signal = 'M 7,1 C 6.446,1 6,1.446 6,2 L 6,4 C 6,4.1879013 6.0668244,4.3501348 6.15625,4.5 6.0668244,4.6498652 6,4.8120987 6,5 L 6,7 C 6,7.1879013 6.0668244,7.3501348 6.15625,7.5 6.0668244,7.6498652 6,7.8120987 6,8 l 0,2 c 0,0.554 0.446,1 1,1 l 0.5,0 0,3 -1.5,0 0,1 4,0 0,-1 -1.5,0 0,-3 0.5,0 c 0.554,0 1,-0.446 1,-1 L 10,8 C 10,7.8120987 9.9331756,7.6498652 9.84375,7.5 9.9331756,7.3501348 10,7.1879013 10,7 L 10,5 C 10,4.8120987 9.9331756,4.6498652 9.84375,4.5 9.9331756,4.3501348 10,4.1879013 10,4 L 10,2 C 10,1.446 9.554,1 9,1 z M 7,2 9,2 9,4 7,4 z M 7,5 9,5 9,7 7,7 z m 0,3 2,0 0,2 -2,0 z'
|
||||
d_tree = 'M 7 2 C 6.446 2 6 2.446 6 3 C 5.446 3 5 3.4460001 5 4 L 5 7 C 5 7.5539999 5.446 8 6 8 C 6 8.554 6.446 9 7 9 L 7.5625 9 L 7.5625 12 L 8.4375 12 L 8.4375 9 L 9 9 C 9.554 9 10 8.554 10 8 C 10.554 8 11 7.5539999 11 7 L 11 4 C 11 3.4460001 10.554 3 10 3 C 10 2.446 9.554 2 9 2 L 7 2 z'
|
||||
|
||||
def get_d_from_file(file_name):
|
||||
if os.path.isfile('icons/' + file_name + '.svg'):
|
||||
file_name = 'icons/' + file_name + '.svg'
|
||||
size = 16
|
||||
elif os.path.isfile('icons/' + file_name + '.16.svg'):
|
||||
file_name = 'icons/' + file_name + '.16.svg'
|
||||
size = 16
|
||||
elif os.path.isfile('icons/' + file_name + '-12.svg'):
|
||||
file_name = 'icons/' + file_name + '-12.svg'
|
||||
size = 12
|
||||
elif os.path.isfile('icons/' + file_name + '.12.svg'):
|
||||
file_name = 'icons/' + file_name + '.12.svg'
|
||||
size = 12
|
||||
elif os.path.isfile('icons/' + file_name + '.10.svg'):
|
||||
file_name = 'icons/' + file_name + '.10.svg'
|
||||
size = 10
|
||||
else:
|
||||
print 'Unknown file:', file_name
|
||||
return 'M 4,4 L 4,10 10,10 10,4 4,4', 16
|
||||
f = open(file_name).read().split('\n')
|
||||
for line in f:
|
||||
m = re.match('.* d="(?P<path>[AaMmCcLlZz0-9Ee., -]*)".*', line)
|
||||
if m:
|
||||
return m.group('path'), size
|
||||
|
||||
# Construct node map
|
||||
|
||||
def construct_node_map():
|
||||
"""
|
||||
Construct map of nodes.
|
||||
"""
|
||||
print 'Construct node map...'
|
||||
node_map = {}
|
||||
for element in content.childNodes[0].childNodes:
|
||||
if element.nodeType != element.TEXT_NODE:
|
||||
if 'user' in element.attributes.keys():
|
||||
author = element.attributes['user'].value
|
||||
if author in authors:
|
||||
authors[author] += 1
|
||||
else:
|
||||
authors[author] = 1
|
||||
if not ('lat' in element.attributes.keys()):
|
||||
continue
|
||||
node_map[element.attributes['id'].value] = \
|
||||
Geo(float(element.attributes['lat'].value),
|
||||
float(element.attributes['lon'].value))
|
||||
if float(element.attributes['lat'].value) > maximum.lat:
|
||||
maximum.lat = float(element.attributes['lat'].value)
|
||||
if float(element.attributes['lat'].value) < minimum.lat:
|
||||
minimum.lat = float(element.attributes['lat'].value)
|
||||
if float(element.attributes['lon'].value) > maximum.lon:
|
||||
maximum.lon = float(element.attributes['lon'].value)
|
||||
if float(element.attributes['lon'].value) < minimum.lon:
|
||||
minimum.lon = float(element.attributes['lon'].value)
|
||||
print 'Done.'
|
||||
return node_map
|
||||
|
||||
node_map = construct_node_map()
|
||||
|
||||
if len(sys.argv) > 3:
|
||||
flinger = GeoFlinger(min1, max1, Vector(0, 0), Vector(w, h))
|
||||
else:
|
||||
flinger = GeoFlinger(minimum, maximum, Vector(25, 25), Vector(975, 975))
|
||||
|
||||
|
||||
def draw_path(nodes, style, shift=Vector()):
|
||||
prev_node = None
|
||||
for node_id in nodes:
|
||||
flinged1 = flinger.fling(node_map[node_id]) + shift
|
||||
if prev_node:
|
||||
flinged2 = flinger.fling(prev_node) + shift
|
||||
output_file.write('L ' + `flinged1.x` + ',' + `flinged1.y` + ' ')
|
||||
else:
|
||||
output_file.write('<path d="M ' + `flinged1.x` + \
|
||||
',' + `flinged1.y` + ' ')
|
||||
prev_node = node_map[node_id]
|
||||
output_file.write('" style="' + style + '" />\n')
|
||||
|
||||
def draw_point_shape(name, x, y, fill):
|
||||
shape, size = get_d_from_file(name)
|
||||
draw_point(shape, x, y, fill, size=size)
|
||||
|
||||
def draw_point(shape, x, y, fill, size=16):
|
||||
x = int(float(x))
|
||||
y = int(float(y))
|
||||
output_file.write('<path d="' + shape + \
|
||||
'" style="fill:#FFFFFF;opacity:0.5;stroke:#FFFFFF;stroke-width:3;stroke-linejoin:round;" transform="translate(' + \
|
||||
str(x - size / 2.0) + ',' + str(y - size / 2.0) + ')" />\n')
|
||||
output_file.write('<path d="' + shape + \
|
||||
'" style="fill:#' + fill + ';fill-opacity:1" transform="translate(' + \
|
||||
str(x - size / 2.0) + ',' + str(y - size / 2.0) + ')" />\n')
|
||||
|
||||
def draw_text(text, x, y, fill):
|
||||
if type(text) == unicode:
|
||||
text = text.encode('utf-8')
|
||||
text = text.replace('&', 'and')
|
||||
if text[:7] == 'http://' or text[:8] == 'https://':
|
||||
text = 'link'
|
||||
fill = '0000FF'
|
||||
return
|
||||
output_file.write('<text x="' + x + '" y="' + y + \
|
||||
'" style="font-size:10;text-anchor:middle;font-family:Myriad Pro;fill:#FFFFFF;stroke-linejoin:round;stroke-width:5;stroke:#FFFFFF;opacity:0.5;">' + text + '</text>')
|
||||
output_file.write('<text x="' + x + '" y="' + y + \
|
||||
'" style="font-size:10;text-anchor:middle;font-family:Myriad Pro;fill:#' + fill + ';">' + text + '</text>')
|
||||
|
||||
def point(k, v, x, y, fill):
|
||||
if ('node ' + k + ': ' + v) in missed_tags:
|
||||
missed_tags['node ' + k + ': ' + v] += 1
|
||||
else:
|
||||
missed_tags['node ' + k + ': ' + v] = 1
|
||||
output_file.circle(x, y, 2, fill=fill, color=fill)
|
||||
text = k + ': ' + v
|
||||
if type(text) == unicode:
|
||||
text = text.encode('utf-8')
|
||||
output_file.write('<text x="' + str(x) + '" y="' + str(int(y) + 10) + \
|
||||
'" style="font-size:10;text-anchor:middle;font-family:Myriad Pro;fill:#FF0000;">' + text + '</text>')
|
||||
|
||||
# Ways drawing
|
||||
|
||||
def construct_way_map():
|
||||
"""
|
||||
Construct map of ways and distribute them by layers. One layer may contain
|
||||
elements of different types.
|
||||
"""
|
||||
print 'Construct way map...'
|
||||
|
||||
layers = {}
|
||||
way_map = {}
|
||||
|
||||
for element in content.childNodes[0].childNodes:
|
||||
if element.nodeName == 'way':
|
||||
way = {'nodes': [], 'tags': {}}
|
||||
way_map[element.attributes['id'].value] = way
|
||||
|
||||
for element in content.childNodes[0].childNodes:
|
||||
if element.nodeName == 'relation':
|
||||
relation = {'members': [], 'tags': {}}
|
||||
for child_node in element.childNodes:
|
||||
if isinstance(child_node, xml.dom.minidom.Element):
|
||||
if child_node.tagName == 'tag':
|
||||
k = child_node.attributes['k'].value
|
||||
v = child_node.attributes['v'].value
|
||||
relation['tags'][k] = v
|
||||
for child_node in element.childNodes:
|
||||
if isinstance(child_node, xml.dom.minidom.Element):
|
||||
if child_node.tagName == 'member':
|
||||
index = child_node.attributes['ref'].value
|
||||
if index in way_map:
|
||||
way = way_map[index]
|
||||
for tag in relation['tags']:
|
||||
way['tags'][tag] = relation['tags'][tag]
|
||||
|
||||
for element in content.childNodes[0].childNodes:
|
||||
if element.nodeName == 'way':
|
||||
way = way_map[element.attributes['id'].value]
|
||||
for child_node in element.childNodes:
|
||||
if isinstance(child_node, xml.dom.minidom.Element):
|
||||
if child_node.tagName == 'tag':
|
||||
k = child_node.attributes['k'].value
|
||||
v = child_node.attributes['v'].value
|
||||
way['tags'][k] = v
|
||||
if child_node.tagName == 'nd':
|
||||
way['nodes'].append(child_node.attributes['ref'].value)
|
||||
if not ('layer' in way['tags']):
|
||||
way['tags']['layer'] = 0
|
||||
if not (int(way['tags']['layer']) in layers):
|
||||
layers[int(way['tags']['layer'])] = \
|
||||
{'b': [], 'h1': [], 'h2': [], 'r': [], 'n': [], 'l': [],
|
||||
'a': [], 'le': [], 'ba': [], 'bo': []}
|
||||
layer = layers[int(way['tags']['layer'])]
|
||||
if 'building' in way['tags']:
|
||||
layer['b'].append(way)
|
||||
if 'natural' in way['tags']:
|
||||
layer['n'].append(way)
|
||||
if 'landuse' in way['tags']:
|
||||
layer['l'].append(way)
|
||||
if 'railway' in way['tags']:
|
||||
layer['r'].append(way)
|
||||
if 'amenity' in way['tags']:
|
||||
layer['a'].append(way)
|
||||
if 'leisure' in way['tags']:
|
||||
layer['le'].append(way)
|
||||
if 'barrier' in way['tags']:
|
||||
layer['ba'].append(way)
|
||||
if 'highway' in way['tags']:
|
||||
layer['h1'].append(way)
|
||||
layer['h2'].append(way)
|
||||
if 'boundary' in way['tags']:
|
||||
layer['bo'].append(way)
|
||||
#else:
|
||||
# empty = True
|
||||
# for key in way['tags'].keys():
|
||||
# if not (key in ['layer', 'note']):
|
||||
# empty = False
|
||||
# if not empty:
|
||||
# print 'Unknown kind of way:', way['tags']
|
||||
return layers, way_map
|
||||
|
||||
|
||||
layers, way_map = construct_way_map()
|
||||
|
||||
def draw_raw_ways():
|
||||
for way_id in way_map:
|
||||
way = way_map[way_id]
|
||||
draw_path(way['nodes'], 'stroke:#FFFFFF;fill:none;stroke-width:0.2;')
|
||||
|
||||
def draw_ways():
|
||||
for level in sorted(layers.keys()):
|
||||
layer = layers[level]
|
||||
#for entity in ['b', 'h1', 'h2', 'r', 'n', 'l', 'a', 'le', 'ba']:
|
||||
for way in layer['le']:
|
||||
if way['tags']['leisure'] == 'park':
|
||||
style = 'fill:#' + grass_color + ';'
|
||||
else:
|
||||
continue
|
||||
draw_path(way['nodes'], style)
|
||||
for way in layer['l']:
|
||||
ma = Vector()
|
||||
mi = Vector(10000, 10000)
|
||||
for node_id in way['nodes']:
|
||||
node = node_map[node_id]
|
||||
flinged = flinger.fling(node)
|
||||
if flinged.x > ma.x: ma.x = flinged.x
|
||||
if flinged.y > ma.y: ma.y = flinged.y
|
||||
if flinged.x < mi.x: mi.x = flinged.x
|
||||
if flinged.y < mi.y: mi.y = flinged.y
|
||||
c = Vector((ma.x + mi.x) / 2.0, (ma.y + mi.y) / 2.0)
|
||||
if way['tags']['landuse'] == 'grass':
|
||||
style = 'fill:#' + grass_color + ';stroke:none;'
|
||||
draw_path(way['nodes'], style)
|
||||
elif way['tags']['landuse'] == 'conservation':
|
||||
style = 'fill:#' + grass_color + ';stroke:none;'
|
||||
draw_path(way['nodes'], style)
|
||||
elif way['tags']['landuse'] == 'forest':
|
||||
style = 'fill:#' + wood_color + ';stroke:none;'
|
||||
draw_path(way['nodes'], style)
|
||||
elif way['tags']['landuse'] == 'garages':
|
||||
style = 'fill:#' + parking_color + ';stroke:none;'
|
||||
draw_path(way['nodes'], style)
|
||||
draw_point_shape('parking', c.x, c.y, '444444')
|
||||
elif way['tags']['landuse'] in ['residential', 'commercial']:
|
||||
continue
|
||||
else:
|
||||
style = 'fill:#0000FF;stroke:none;'
|
||||
draw_path(way['nodes'], style)
|
||||
for way in layer['a']:
|
||||
ma = Vector()
|
||||
mi = Vector(10000, 10000)
|
||||
for node_id in way['nodes']:
|
||||
node = node_map[node_id]
|
||||
flinged = flinger.fling(node)
|
||||
if flinged.x > ma.x: ma.x = flinged.x
|
||||
if flinged.y > ma.y: ma.y = flinged.y
|
||||
if flinged.x < mi.x: mi.x = flinged.x
|
||||
if flinged.y < mi.y: mi.y = flinged.y
|
||||
c = Vector((ma.x + mi.x) / 2.0, (ma.y + mi.y) / 2.0)
|
||||
if way['tags']['amenity'] == 'parking':
|
||||
style = 'fill:#' + parking_color + ';stroke:none;'
|
||||
draw_path(way['nodes'], style)
|
||||
draw_point_shape('parking', c.x, c.y, '444444')
|
||||
elif way['tags']['amenity'] == 'school':
|
||||
continue
|
||||
else:
|
||||
style = 'fill:#0000FF;stroke:none;'
|
||||
draw_path(way['nodes'], style)
|
||||
for way in layer['n']:
|
||||
if way['tags']['natural'] == 'wood':
|
||||
style = 'fill:#' + wood_color + ';stroke:none;'
|
||||
elif way['tags']['natural'] == 'scrub':
|
||||
style = 'fill:#' + wood_color + ';stroke:none;'
|
||||
elif way['tags']['natural'] == 'sand':
|
||||
style = 'fill:#' + sand_color + ';stroke:none;'
|
||||
elif way['tags']['natural'] == 'beach':
|
||||
style = 'fill:#' + beach_color + ';stroke:none;'
|
||||
elif way['tags']['natural'] == 'desert':
|
||||
style = 'fill:#' + desert_color + ';stroke:none;'
|
||||
elif way['tags']['natural'] == 'water':
|
||||
style = 'fill:#' + water_color + ';stroke:#' + water_border_color + ';stroke-width:1.0;'
|
||||
elif way['tags']['natural'] == 'forest':
|
||||
style = 'fill:#' + wood_color + ';stroke:none;'
|
||||
else:
|
||||
continue
|
||||
draw_path(way['nodes'], style)
|
||||
for way in layer['r']:
|
||||
v = way['tags']['railway']
|
||||
style = 'fill:none;stroke-dasharray:none;stroke-linejoin:round;stroke-linecap:butt;stroke-width:'
|
||||
if v == 'subway': style += '10;stroke:#DDDDDD;'
|
||||
if v in ['narrow_gauge', 'tram']:
|
||||
style += '2;stroke:#000000;'
|
||||
else:
|
||||
continue
|
||||
draw_path(way['nodes'], style)
|
||||
for way in layer['h1']:
|
||||
if 'tunnel' in way['tags'] and way['tags']['tunnel'] == 'yes':
|
||||
style = 'fill:none;stroke:#FFFFFF;stroke-dasharray:none;stroke-linejoin:round;stroke-linecap:butt;stroke-width:10;'
|
||||
draw_path(way['nodes'], style)
|
||||
for way in layer['h1']:
|
||||
v = way['tags']['highway']
|
||||
style = 'fill:none;stroke:#AAAAAA;stroke-dasharray:none;stroke-linejoin:round;stroke-linecap:butt;stroke-width:'
|
||||
if v == 'motorway': style += '30'
|
||||
elif v == 'trunk': style += '25'
|
||||
elif v == 'primary': style += '20;stroke:#AA8800'
|
||||
elif v == 'secondary': style += '13'
|
||||
elif v == 'tertiary': style += '11'
|
||||
elif v == 'unclassified': style += '9'
|
||||
elif v == 'residential': style += '8'
|
||||
elif v == 'service': style += '7'
|
||||
elif v == 'track': style += '3'
|
||||
elif v in ['footway', 'pedestrian']: style += '2'
|
||||
elif v == 'steps': style += '5;stroke-dasharray:1,2;stroke-linecap:butt'
|
||||
elif v == 'path': style += '1;stroke-dasharray:5,5;stroke-linecap:butt'
|
||||
else:
|
||||
continue
|
||||
style += ';'
|
||||
draw_path(way['nodes'], style)
|
||||
for way in layer['h2']:
|
||||
v = way['tags']['highway']
|
||||
style = 'fill:none;stroke:#FFFFFF;stroke-linecap:butt;stroke-linejoin:round;stroke-width:'
|
||||
if v == 'motorway': style += '28'
|
||||
elif v == 'trunk': style += '23'
|
||||
elif v == 'primary': style += '19;stroke:#FFDD66'
|
||||
elif v == 'secondary': style += '11'
|
||||
elif v == 'tertiary': style += '9'
|
||||
elif v == 'unclassified': style += '7'
|
||||
elif v == 'residential': style += '6'
|
||||
elif v == 'service': style += '5'
|
||||
else:
|
||||
continue
|
||||
style += ';'
|
||||
draw_path(way['nodes'], style)
|
||||
for way in layer['b']:
|
||||
floors = 0
|
||||
text_y = 0
|
||||
#if 'building:levels' in way['tags']:
|
||||
#floors = float(way['tags']['building:levels'])
|
||||
draw_path(way['nodes'], 'fill:#D0D0C0;stroke:#AAAAAA;opacity:1.0;')
|
||||
ma = Vector()
|
||||
mi = Vector(10000, 10000)
|
||||
for node_id in way['nodes']:
|
||||
node = node_map[node_id]
|
||||
flinged = flinger.fling(node)
|
||||
if flinged.x > ma.x: ma.x = flinged.x
|
||||
if flinged.y > ma.y: ma.y = flinged.y
|
||||
if flinged.x < mi.x: mi.x = flinged.x
|
||||
if flinged.y < mi.y: mi.y = flinged.y
|
||||
c = Vector((ma.x + mi.x) / 2.0, (ma.y + mi.y) / 2.0)
|
||||
for tag in way['tags']:
|
||||
v = way['tags'][tag]
|
||||
if tag == 'building':
|
||||
if v == 'yes':
|
||||
pass
|
||||
elif v == 'apartments':
|
||||
draw_point_shape('apartments', c.x, c.y, '444444')
|
||||
elif v == 'kindergarten':
|
||||
draw_point_shape('playground', c.x, c.y, '444444')
|
||||
elif tag == 'amenity':
|
||||
if v == 'cafe':
|
||||
draw_point_shape('cafe', c.x, c.y, '444444')
|
||||
elif v == 'theatre':
|
||||
draw_point_shape('theatre', c.x, c.y, '444444')
|
||||
elif v == 'fast_food':
|
||||
draw_point_shape('fast_food', c.x, c.y, '444444')
|
||||
elif v == 'snack_cart':
|
||||
draw_point_shape('cafe', c.x, c.y, '444444')
|
||||
elif tag == 'shop':
|
||||
if v == 'clothes':
|
||||
draw_point_shape('shop_clothes', c.x, c.y, '444444')
|
||||
elif v == 'gift':
|
||||
draw_point_shape('shop_gift', c.x, c.y, '444444')
|
||||
elif tag == 'power':
|
||||
draw_point_shape('electricity', c.x, c.y, '444444')
|
||||
elif tag in ['name', 'addr:housenumber', 'cladr:code',
|
||||
'addr:city', 'addr:street', 'website',
|
||||
'wikidata'] or \
|
||||
'name' in tag or 'wikipedia' in tag:
|
||||
draw_text(v, str(c.x), str(c.y + 18 + text_y), '444444')
|
||||
text_y += 10
|
||||
elif tag == 'addr:country':
|
||||
if v == 'RU':
|
||||
draw_text('Россия', str(c.x), str(c.y + 18 + text_y), '444444')
|
||||
else:
|
||||
draw_text(v, str(c.x), str(c.y + 18 + text_y), '444444')
|
||||
text_y += 10
|
||||
elif tag in ['layer', 'height']:
|
||||
pass
|
||||
elif tag in ['building:levels']:
|
||||
pass
|
||||
else:
|
||||
kk = tag
|
||||
vv = unicode(v)
|
||||
if ('way ' + kk + ': ' + vv) in missed_tags:
|
||||
missed_tags['way ' + kk + ': ' + vv] += 1
|
||||
else:
|
||||
missed_tags['way ' + kk + ': ' + vv] = 1
|
||||
for way in layer['le']:
|
||||
ma = Vector()
|
||||
mi = Vector(10000, 10000)
|
||||
for node_id in way['nodes']:
|
||||
node = node_map[node_id]
|
||||
flinged = flinger.fling(node)
|
||||
if flinged.x > ma.x: ma.x = flinged.x
|
||||
if flinged.y > ma.y: ma.y = flinged.y
|
||||
if flinged.x < mi.x: mi.x = flinged.x
|
||||
if flinged.y < mi.y: mi.y = flinged.y
|
||||
c = Vector((ma.x + mi.x) / 2.0, (ma.y + mi.y) / 2.0)
|
||||
if way['tags']['leisure'] == 'playground':
|
||||
style = 'fill:#' + playground_color + ';opacity:0.2;'
|
||||
draw_point_shape('playground', c.x, c.y, '444444')
|
||||
elif way['tags']['leisure'] == 'garden':
|
||||
style = 'fill:#' + grass_color + ';'
|
||||
elif way['tags']['leisure'] == 'pitch':
|
||||
style = 'fill:#' + playground_color + ';opacity:0.2;'
|
||||
elif way['tags']['leisure'] == 'park':
|
||||
continue
|
||||
else:
|
||||
style = 'fill:#FF0000;opacity:0.2;'
|
||||
draw_path(way['nodes'], style)
|
||||
for way in layer['ba']:
|
||||
if way['tags']['barrier'] == 'hedge':
|
||||
style += 'fill:none;stroke:#' + wood_color + ';stroke-width:4;'
|
||||
else:
|
||||
style += 'fill:none;stroke:#000000;stroke-width:1;opacity:0.4;'
|
||||
draw_path(way['nodes'], style)
|
||||
for way in layer['bo']:
|
||||
style += 'fill:none;stroke:#FF0000;stroke-width:0.5;stroke-dahsarray:10,20;'
|
||||
draw_path(way['nodes'], style)
|
||||
|
||||
print 'Done.'
|
||||
|
||||
# Nodes drawing
|
||||
|
||||
def draw_raw_nodes():
|
||||
for node_id in node_map:
|
||||
node = node_map[node_id]
|
||||
flinged = flinger.fling(node)
|
||||
output_file.circle(flinged.x, flinged.y, 0.2, color='FFFFFF')
|
||||
|
||||
def draw_nodes():
|
||||
print 'Draw nodes...'
|
||||
|
||||
for element in content.childNodes[0].childNodes:
|
||||
if element.nodeName != 'node':
|
||||
continue
|
||||
flinged = flinger.fling(Geo(float(element.attributes['lat'].value),
|
||||
float(element.attributes['lon'].value)))
|
||||
text_y = 0
|
||||
pairs = {}
|
||||
for child_node in element.childNodes:
|
||||
if isinstance(child_node, xml.dom.minidom.Element):
|
||||
if child_node.tagName == 'tag':
|
||||
pairs[child_node.attributes['k'].value] = child_node.attributes['v'].value
|
||||
fill = '444444'
|
||||
if 'colour' in pairs:
|
||||
if pairs['colour'] == 'blue':
|
||||
fill='2233AA'
|
||||
radius=3
|
||||
for k in pairs:
|
||||
v = pairs[k]
|
||||
x = `flinged.x`
|
||||
y = `flinged.y`
|
||||
if k == 'amenity':
|
||||
if v in ['bench', 'bicycle_parking', 'waste_basket',
|
||||
'restaurant', 'pharmacy', 'drinking_water', 'toilets',
|
||||
'fast_food', 'theatre']:
|
||||
draw_point_shape(v, x, y, fill)
|
||||
elif v == 'clinic':
|
||||
draw_point(d_clinic, x, y, fill)
|
||||
elif v == 'fountain':
|
||||
draw_point_shape('fountain', x, y, water_border_color)
|
||||
elif v == 'recycling':
|
||||
if not 'recycling_type' in pairs:
|
||||
draw_point_shape('recycling', x, y, fill)
|
||||
else:
|
||||
point(k, v, flinged.x, flinged.y, fill)
|
||||
elif k == 'artwork_type':
|
||||
if v == 'statue':
|
||||
draw_point_shape('monument', x, y, fill)
|
||||
if v == 'sculpture':
|
||||
draw_point_shape('monument', x, y, fill)
|
||||
else:
|
||||
point(k, v, flinged.x, flinged.y, fill)
|
||||
elif k == 'barrier':
|
||||
if v == 'lift_gate':
|
||||
draw_point_shape('liftgate', x, y, fill)
|
||||
elif k in ['crossing', 'crossing_ref']:
|
||||
if v == 'zebra':
|
||||
draw_point(d_crossing, x, y, fill)
|
||||
elif k == 'entrance':
|
||||
draw_point_shape('entrance', x, y, fill)
|
||||
elif k == 'highway':
|
||||
if v == 'street_lamp':
|
||||
draw_point(d_street_lamp, x, y, fill)
|
||||
elif v == 'bus_stop':
|
||||
draw_point_shape('bus_stop', x, y, fill)
|
||||
elif v == 'traffic_signals':
|
||||
draw_point(d_traffic_signal, x, y, fill)
|
||||
elif v == 'crossing':
|
||||
if not ('crossing' in pairs):
|
||||
draw_point(d_crossing, x, y, fill)
|
||||
else:
|
||||
point(k, v, flinged.x, flinged.y, fill)
|
||||
elif k == 'man_made':
|
||||
if v == 'pole':
|
||||
draw_point_shape('pole', x, y, fill)
|
||||
elif v == 'flagpole':
|
||||
draw_point_shape('flagpole', x, y, fill)
|
||||
else:
|
||||
point(k, v, flinged.x, flinged.y, fill)
|
||||
elif k == 'natural':
|
||||
if v == 'tree':
|
||||
if 'denotation' in pairs and pairs['denotation'] == 'urban':
|
||||
draw_point_shape('urban_tree', x, y, wood_color)
|
||||
else:
|
||||
draw_point(d_tree, x, y, wood_color)
|
||||
elif v == 'cave_entrance':
|
||||
draw_point_shape('cave', x, y, fill)
|
||||
elif v == 'bush':
|
||||
draw_point_shape('bush', x, y, wood_color)
|
||||
else:
|
||||
point(k, v, flinged.x, flinged.y, fill)
|
||||
elif k == 'recycling_type':
|
||||
if v == 'centre':
|
||||
draw_point_shape('recycling', x, y, fill)
|
||||
else:
|
||||
draw_point_shape('recycling', x, y, fill)
|
||||
elif k == 'shop':
|
||||
if v == 'florist':
|
||||
draw_point_shape('florist', x, y, fill)
|
||||
elif v in ['clothes', 'shoes', 'gift']:
|
||||
draw_point_shape('shop_' + v, x, y, fill)
|
||||
else:
|
||||
point(k, v, flinged.x, flinged.y, fill)
|
||||
elif k == 'traffic_calming':
|
||||
if v == 'bump':
|
||||
draw_point_shape('bump', x, y, fill)
|
||||
else:
|
||||
point(k, v, flinged.x, flinged.y, fill)
|
||||
elif k == 'emergency':
|
||||
if v == 'fire_hydrant':
|
||||
draw_point_shape(v, x, y, fill)
|
||||
elif k == 'historic':
|
||||
if v == 'memorial':
|
||||
draw_point_shape('monument', x, y, fill)
|
||||
elif k == 'tourism':
|
||||
if v == 'artwork':
|
||||
if not ('artwork_type' in pairs):
|
||||
draw_point_shape('monument', x, y, fill)
|
||||
if v == 'attraction':
|
||||
draw_point_shape('monument', x, y, fill)
|
||||
elif k in [
|
||||
'operator', 'contact:facebook', 'contact:phone',
|
||||
'opening_hours', 'cuisine', 'network', 'website',
|
||||
'contact:website', 'phone', 'branch', 'route_ref',
|
||||
'addr:flats', 'brand', 'ref', 'addr:street', 'wikipedia',
|
||||
] or ('name' in k):
|
||||
if k == 'route_ref':
|
||||
v = v.replace(';', ' ')
|
||||
draw_text(v, x, str(flinged.y + 18 + text_y), fill)
|
||||
text_y += 10
|
||||
elif k in ['layer', 'level', 'source', 'note', 'description']:
|
||||
pass # NOTHING TO DRAW
|
||||
else:
|
||||
point(k, v, flinged.x, flinged.y, fill)
|
||||
|
||||
print 'Done.'
|
||||
|
||||
#draw_raw_nodes()
|
||||
#draw_raw_ways()
|
||||
|
||||
draw_ways()
|
||||
draw_nodes()
|
||||
|
||||
if flinger.space.x == 0:
|
||||
output_file.rect(0, 0, w, flinger.space.y, color='FFFFFF')
|
||||
output_file.rect(0, h - flinger.space.y, w, flinger.space.y, color='FFFFFF')
|
||||
|
||||
output_file.end()
|
||||
|
||||
print '\nMissing tags:\n'
|
||||
top_missed_tags = reversed(sorted(missed_tags.keys(), key=lambda x: -missed_tags[x]))
|
||||
for tag in top_missed_tags:
|
||||
print tag + ' (' + str(missed_tags[tag]) + ')'
|
||||
|
||||
sys.exit(1)
|
||||
|
||||
top_authors = sorted(authors.keys(), key=lambda x: -authors[x])
|
||||
for author in top_authors:
|
||||
print author + ': ' + str(authors[author])
|
Loading…
Add table
Add a link
Reference in a new issue