port to py3 and format with black
This commit is contained in:
parent
dffa71bbdd
commit
a4ced15215
1 changed files with 223 additions and 169 deletions
118
mapbender.py
118
mapbender.py
|
@ -20,23 +20,35 @@ from math import sqrt
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
from scipy import interpolate
|
from scipy import interpolate
|
||||||
from itertools import tee, izip
|
from itertools import tee
|
||||||
from matplotlib.patches import Polygon
|
from matplotlib.patches import Polygon
|
||||||
from matplotlib.collections import PatchCollection
|
from matplotlib.collections import PatchCollection
|
||||||
import matplotlib
|
import matplotlib
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
|
||||||
|
|
||||||
def y2lat(a):
|
def y2lat(a):
|
||||||
return 180.0/math.pi*(2.0*math.atan(math.exp(a*math.pi/180.0))-math.pi/2.0)
|
return (
|
||||||
|
180.0
|
||||||
|
/ math.pi
|
||||||
|
* (2.0 * math.atan(math.exp(a * math.pi / 180.0)) - math.pi / 2.0)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def lat2y(a):
|
def lat2y(a):
|
||||||
return 180.0/math.pi*math.log(math.tan(math.pi/4.0+a*(math.pi/180.0)/2.0))
|
return (
|
||||||
|
180.0
|
||||||
|
/ math.pi
|
||||||
|
* math.log(math.tan(math.pi / 4.0 + a * (math.pi / 180.0) / 2.0))
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def pairwise(iterable):
|
def pairwise(iterable):
|
||||||
"s -> (s0,s1), (s1,s2), (s2,s3), ..."
|
"s -> (s0,s1), (s1,s2), (s2,s3), ..."
|
||||||
a, b = tee(iterable, 2)
|
a, b = tee(iterable, 2)
|
||||||
next(b, None)
|
next(b, None)
|
||||||
return izip(a, b)
|
return zip(a, b)
|
||||||
|
|
||||||
|
|
||||||
def triplewise(iterable):
|
def triplewise(iterable):
|
||||||
"s -> (s0,s1,s2), (s1,s2,s3), (s2,s3,s4), ..."
|
"s -> (s0,s1,s2), (s1,s2,s3), (s2,s3,s4), ..."
|
||||||
|
@ -44,15 +56,26 @@ def triplewise(iterable):
|
||||||
next(b, None)
|
next(b, None)
|
||||||
next(c, None)
|
next(c, None)
|
||||||
next(c, None)
|
next(c, None)
|
||||||
return izip(a,b,c)
|
return zip(a, b, c)
|
||||||
|
|
||||||
|
|
||||||
# using barycentric coordinates
|
# using barycentric coordinates
|
||||||
def ptInTriangle(p, p0, p1, p2):
|
def ptInTriangle(p, p0, p1, p2):
|
||||||
A = 0.5 * (-p1[1] * p2[0] + p0[1] * (-p1[0] + p2[0]) + p0[0] * (p1[1] - p2[1]) + p1[0] * p2[1]);
|
A = 0.5 * (
|
||||||
sign = -1 if A < 0 else 1;
|
-p1[1] * p2[0]
|
||||||
s = (p0[1] * p2[0] - p0[0] * p2[1] + (p2[1] - p0[1]) * p[0] + (p0[0] - p2[0]) * p[1]) * sign;
|
+ p0[1] * (-p1[0] + p2[0])
|
||||||
t = (p0[0] * p1[1] - p0[1] * p1[0] + (p0[1] - p1[1]) * p[0] + (p1[0] - p0[0]) * p[1]) * sign;
|
+ p0[0] * (p1[1] - p2[1])
|
||||||
return s >= 0 and t >= 0 and (s + t) <= 2 * A * sign;
|
+ p1[0] * p2[1]
|
||||||
|
)
|
||||||
|
sign = -1 if A < 0 else 1
|
||||||
|
s = (
|
||||||
|
p0[1] * p2[0] - p0[0] * p2[1] + (p2[1] - p0[1]) * p[0] + (p0[0] - p2[0]) * p[1]
|
||||||
|
) * sign
|
||||||
|
t = (
|
||||||
|
p0[0] * p1[1] - p0[1] * p1[0] + (p0[1] - p1[1]) * p[0] + (p1[0] - p0[0]) * p[1]
|
||||||
|
) * sign
|
||||||
|
return s >= 0 and t >= 0 and (s + t) <= 2 * A * sign
|
||||||
|
|
||||||
|
|
||||||
def getxing(p0, p1, p2, p3):
|
def getxing(p0, p1, p2, p3):
|
||||||
ux = p1[0] - p0[0]
|
ux = p1[0] - p0[0]
|
||||||
|
@ -70,6 +93,7 @@ def getxing(p0, p1, p2, p3):
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
# the line p0-p1 is the upper normal to the path
|
# the line p0-p1 is the upper normal to the path
|
||||||
# the line p2-p3 is the lower normal to the path
|
# the line p2-p3 is the lower normal to the path
|
||||||
#
|
#
|
||||||
|
@ -88,6 +112,7 @@ def ptInQuadrilateral(p, p0, p1, p2, p3):
|
||||||
else:
|
else:
|
||||||
return ptInTriangle(p, p0, p1, p2) or ptInTriangle(p, p2, p3, p0)
|
return ptInTriangle(p, p0, p1, p2) or ptInTriangle(p, p2, p3, p0)
|
||||||
|
|
||||||
|
|
||||||
def get_st(Ax, Ay, Bx, By, Cx, Cy, Dx, Dy, Xx, Xy):
|
def get_st(Ax, Ay, Bx, By, Cx, Cy, Dx, Dy, Xx, Xy):
|
||||||
d = Bx - Ax - Cx + Dx
|
d = Bx - Ax - Cx + Dx
|
||||||
e = By - Ay - Cy + Dy
|
e = By - Ay - Cy + Dy
|
||||||
|
@ -138,6 +163,7 @@ def get_st(Ax,Ay,Bx,By,Cx,Cy,Dx,Dy,Xx,Xy):
|
||||||
t = [t[0], t[0]]
|
t = [t[0], t[0]]
|
||||||
return s, t
|
return s, t
|
||||||
|
|
||||||
|
|
||||||
def main(x, y, width, smoothing, subdiv):
|
def main(x, y, width, smoothing, subdiv):
|
||||||
halfwidth = width / 2.0
|
halfwidth = width / 2.0
|
||||||
tck, u = interpolate.splprep([x, y], s=smoothing)
|
tck, u = interpolate.splprep([x, y], s=smoothing)
|
||||||
|
@ -146,7 +172,7 @@ def main(x,y,width,smoothing,subdiv):
|
||||||
heights = []
|
heights = []
|
||||||
offs = []
|
offs = []
|
||||||
height = 0.0
|
height = 0.0
|
||||||
for (ax,ay),(bx,by) in pairwise(zip(*out)):
|
for (ax, ay), (bx, by) in pairwise(list(zip(*out))):
|
||||||
s = ax - bx
|
s = ax - bx
|
||||||
t = ay - by
|
t = ay - by
|
||||||
l = sqrt(s * s + t * t)
|
l = sqrt(s * s + t * t)
|
||||||
|
@ -164,7 +190,7 @@ def main(x,y,width,smoothing,subdiv):
|
||||||
py = [out[1][0] + cy / cl]
|
py = [out[1][0] + cy / cl]
|
||||||
qx = [out[0][0] + dx / dl]
|
qx = [out[0][0] + dx / dl]
|
||||||
qy = [out[1][0] + dy / dl]
|
qy = [out[1][0] + dy / dl]
|
||||||
for (ubx,uby),(ux,uy),(uax,uay) in triplewise(zip(*out)):
|
for (ubx, uby), (ux, uy), (uax, uay) in triplewise(list(zip(*out))):
|
||||||
# get adjacent line segment vectors
|
# get adjacent line segment vectors
|
||||||
ax = ux - ubx
|
ax = ux - ubx
|
||||||
ay = uy - uby
|
ay = uy - uby
|
||||||
|
@ -202,7 +228,9 @@ def main(x,y,width,smoothing,subdiv):
|
||||||
qy.append(out[1][-1] + dy / dl)
|
qy.append(out[1][-1] + dy / dl)
|
||||||
quads = []
|
quads = []
|
||||||
patches = []
|
patches = []
|
||||||
for (p3x,p3y,p2x,p2y),(p0x,p0y,p1x,p1y) in pairwise(zip(px,py,qx,qy)):
|
for (p3x, p3y, p2x, p2y), (p0x, p0y, p1x, p1y) in pairwise(
|
||||||
|
list(zip(px, py, qx, qy))
|
||||||
|
):
|
||||||
quads.append(((p0x, p0y), (p1x, p1y), (p2x, p2y), (p3x, p3y)))
|
quads.append(((p0x, p0y), (p1x, p1y), (p2x, p2y), (p3x, p3y)))
|
||||||
polygon = Polygon(((p0x, p0y), (p1x, p1y), (p2x, p2y), (p3x, p3y)), True)
|
polygon = Polygon(((p0x, p0y), (p1x, p1y), (p2x, p2y), (p3x, p3y)), True)
|
||||||
patches.append(polygon)
|
patches.append(polygon)
|
||||||
|
@ -215,7 +243,7 @@ def main(x,y,width,smoothing,subdiv):
|
||||||
found.append(i)
|
found.append(i)
|
||||||
if found:
|
if found:
|
||||||
if len(found) > 1:
|
if len(found) > 1:
|
||||||
print "point found in two quads"
|
print("point found in two quads")
|
||||||
return None
|
return None
|
||||||
containingquad.append(found[0])
|
containingquad.append(found[0])
|
||||||
else:
|
else:
|
||||||
|
@ -227,7 +255,7 @@ def main(x,y,width,smoothing,subdiv):
|
||||||
if q != None:
|
if q != None:
|
||||||
break
|
break
|
||||||
# find the last missing ones
|
# find the last missing ones
|
||||||
for j,q in izip(xrange(len(containingquad)-1, -1, -1), reversed(containingquad)):
|
for j, q in zip(range(len(containingquad) - 1, -1, -1), reversed(containingquad)):
|
||||||
if q != None:
|
if q != None:
|
||||||
break
|
break
|
||||||
# remove the first and last missing ones
|
# remove the first and last missing ones
|
||||||
|
@ -237,7 +265,7 @@ def main(x,y,width,smoothing,subdiv):
|
||||||
y = y[i : j + 1]
|
y = y[i : j + 1]
|
||||||
# check if there are any remaining missing ones:
|
# check if there are any remaining missing ones:
|
||||||
if None in containingquad:
|
if None in containingquad:
|
||||||
print "cannot find quad for point"
|
print("cannot find quad for point")
|
||||||
return None
|
return None
|
||||||
for off, h in zip(offs, heights):
|
for off, h in zip(offs, heights):
|
||||||
targetquad = ((0, off + h), (width, off + h), (width, off), (0, off))
|
targetquad = ((0, off + h), (width, off + h), (width, off), (0, off))
|
||||||
|
@ -245,8 +273,18 @@ def main(x,y,width,smoothing,subdiv):
|
||||||
tx = []
|
tx = []
|
||||||
ty = []
|
ty = []
|
||||||
assert len(containingquad) == len(x) == len(y)
|
assert len(containingquad) == len(x) == len(y)
|
||||||
assert len(out[0]) == len(out[1]) == len(px) == len(py) == len(qx) == len(qy) == len(quads)+1 == len(heights)+1 == len(offs)+1
|
assert (
|
||||||
for (rx,ry),i in zip(zip(x,y),containingquad):
|
len(out[0])
|
||||||
|
== len(out[1])
|
||||||
|
== len(px)
|
||||||
|
== len(py)
|
||||||
|
== len(qx)
|
||||||
|
== len(qy)
|
||||||
|
== len(quads) + 1
|
||||||
|
== len(heights) + 1
|
||||||
|
== len(offs) + 1
|
||||||
|
)
|
||||||
|
for (rx, ry), i in zip(list(zip(x, y)), containingquad):
|
||||||
if i == None:
|
if i == None:
|
||||||
continue
|
continue
|
||||||
(ax, ay), (bx, by), (cx, cy), (dx, dy) = quads[i]
|
(ax, ay), (bx, by), (cx, cy), (dx, dy) = quads[i]
|
||||||
|
@ -310,14 +348,24 @@ def main(x,y,width,smoothing,subdiv):
|
||||||
p1 = int(p1[0]), int(ih - p1[1])
|
p1 = int(p1[0]), int(ih - p1[1])
|
||||||
p2 = int(p2[0]), int(ih - p2[1])
|
p2 = int(p2[0]), int(ih - p2[1])
|
||||||
p3 = int(p3[0]), int(ih - p3[1])
|
p3 = int(p3[0]), int(ih - p3[1])
|
||||||
box=(0,int(ih*(height-off-h)/(bbox[3]-bbox[1])),
|
box = (
|
||||||
int(iw*width/(bbox[2]-bbox[0])),int(ih*(height-off)/(bbox[3]-bbox[1])))
|
0,
|
||||||
|
int(ih * (height - off - h) / (bbox[3] - bbox[1])),
|
||||||
|
int(iw * width / (bbox[2] - bbox[0])),
|
||||||
|
int(ih * (height - off) / (bbox[3] - bbox[1])),
|
||||||
|
)
|
||||||
quad = (p0[0], p0[1], p1[0], p1[1], p2[0], p2[1], p3[0], p3[1])
|
quad = (p0[0], p0[1], p1[0], p1[1], p2[0], p2[1], p3[0], p3[1])
|
||||||
data.append((box, quad))
|
data.append((box, quad))
|
||||||
im_out = im.transform((int(iw*width/(bbox[2]-bbox[0])),int(ih*height/(bbox[3]-bbox[1]))),Image.MESH,data,Image.BICUBIC)
|
im_out = im.transform(
|
||||||
|
(int(iw * width / (bbox[2] - bbox[0])), int(ih * height / (bbox[3] - bbox[1]))),
|
||||||
|
Image.MESH,
|
||||||
|
data,
|
||||||
|
Image.BICUBIC,
|
||||||
|
)
|
||||||
im_out.save("out.png")
|
im_out.save("out.png")
|
||||||
|
|
||||||
# np.random.seed(seed=0)
|
# np.random.seed(seed=0)
|
||||||
#colors = 100*np.random.rand(len(patches)/2)+100*np.random.rand(len(patches)/2)
|
# colors = 100*np.random.rand(len(patches)//2)+100*np.random.rand(len(patches)//2)
|
||||||
# p = PatchCollection(patches, cmap=matplotlib.cm.jet, alpha=0.4)
|
# p = PatchCollection(patches, cmap=matplotlib.cm.jet, alpha=0.4)
|
||||||
# p.set_array(np.array(colors))
|
# p.set_array(np.array(colors))
|
||||||
# plt.figure()
|
# plt.figure()
|
||||||
|
@ -333,20 +381,26 @@ def main(x,y,width,smoothing,subdiv):
|
||||||
# plt.show()
|
# plt.show()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
|
if __name__ == "__main__":
|
||||||
x = []
|
x = []
|
||||||
y = []
|
y = []
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
if len(sys.argv) != 5:
|
if len(sys.argv) != 5:
|
||||||
print "usage: %s data.csv width smoothing N"%sys.argv[0]
|
print("usage: %s data.csv width smoothing N" % sys.argv[0])
|
||||||
print ""
|
print("")
|
||||||
print " data.csv whitespace delimited lon/lat pairs of points along the path"
|
print(
|
||||||
print " width width of the resulting map in degrees"
|
" data.csv whitespace delimited lon/lat pairs of points along the path"
|
||||||
print " smoothing curve smoothing from 0 (exact fit) to higher values (looser fit)"
|
)
|
||||||
print " N amount of quads to split the path into"
|
print(" width width of the resulting map in degrees")
|
||||||
print ""
|
print(
|
||||||
print " example usage:"
|
" smoothing curve smoothing from 0 (exact fit) to higher values (looser fit)"
|
||||||
print " %s Weser-Radweg-Hauptroute.csv 0.286 6 20"%sys.argv[0]
|
)
|
||||||
|
print(" N amount of quads to split the path into")
|
||||||
|
print("")
|
||||||
|
print(" example usage:")
|
||||||
|
print(" %s Weser-Radweg-Hauptroute.csv 0.286 6 20" % sys.argv[0])
|
||||||
exit(1)
|
exit(1)
|
||||||
with open(sys.argv[1]) as f:
|
with open(sys.argv[1]) as f:
|
||||||
for l in f:
|
for l in f:
|
||||||
|
|
Loading…
Reference in a new issue