Last active
January 6, 2017 00:46
-
-
Save darktrojan/4477d7244e71b1d3d5b9 to your computer and use it in GitHub Desktop.
Orthographic projection to SVG
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import csv, re | |
from hashlib import sha1 | |
from math import cos, radians, sin, atan, degrees, pi, sqrt, hypot | |
csv.field_size_limit(13107200) | |
paths = dict() | |
with open('tm-world-borders-03.csv', 'r') as csvfile: | |
csvreader = csv.reader(csvfile, delimiter=',', quotechar='"') | |
csvreader.next() | |
for a in csvreader: | |
paths[a[5]] = a[0] | |
def project(lat, lng): | |
lat = radians(lat) | |
lng = radians(lng) | |
lat0 = radians(-37) | |
lng0 = radians(174.75) | |
x = cos(lat) * sin(lng - lng0) | |
y = cos(lat0) * sin(lat) - sin(lat0) * cos(lat) * cos(lng - lng0) | |
c = sin(lat0) * sin(lat) + cos(lat0) * cos(lat) * cos(lng - lng0) | |
return (x, y, c < 0) | |
foreground = dict() | |
background = dict() | |
fgsweep = dict() | |
fgsweep2 = dict() | |
bgsweep = dict() | |
fgshadow = dict() | |
bgshadow = dict() | |
bgshadow2 = dict() | |
for (name, r) in paths.iteritems(): | |
foreground[name] = list() | |
background[name] = list() | |
fgsweep[name] = list() | |
fgsweep2[name] = list() | |
bgsweep[name] = list() | |
fgshadow[name] = list() | |
bgshadow[name] = list() | |
bgshadow2[name] = list() | |
for p in r.split(')),(('): | |
path = list() | |
previous = None | |
crossed = False | |
backgroundparts = list() | |
foregroundparts = list() | |
for pt in re.findall('((-?\d+\.\d+) (-?\d+\.\d+))+', p): | |
(x, y, c) = project(float(pt[2]), float(pt[1])) | |
if not c: | |
angle = atan(y / x) | |
distance = sqrt(x * x + y * y) | |
if x < 0: | |
if y > 0: | |
angle += pi | |
else: | |
angle -= pi | |
angle = int(round(degrees(angle))) | |
if previous is not None and previous != c: | |
if previous: | |
backgroundparts.append(path) | |
else: | |
foregroundparts.append(path) | |
path = list() | |
crossed = True | |
previous = c | |
path.append('%.2f,%.2f' % (x * 1000 + 1000, y * -1000 + 1000)) | |
if previous: | |
backgroundparts.append(path) | |
else: | |
foregroundparts.append(path) | |
if len(backgroundparts) > 0: | |
try: | |
for part in backgroundparts: | |
minx = 2000 | |
maxx = -1000 | |
minxpoint = None | |
maxxpoint = None | |
for point in part: | |
(x, y) = point.split(',') | |
x = float(x) - 1000 | |
y = 1000 - float(y) | |
angle = atan(y / x) | |
if angle < 0 and maxx > 1.3: | |
angle += pi * 2 | |
if angle > 0 and minx < -1.3: | |
angle -= pi * 2 | |
if angle < minx: | |
minx = angle | |
minxpoint = point | |
if angle > maxx: | |
maxx = angle | |
maxxpoint = point | |
(x, y) = minxpoint.split(',') | |
x = float(x) - 1000 | |
y = 1000 - float(y) | |
scale = 1000 / hypot(x, y) | |
bgshadow[name].append('1000,1000 %s %s' % (minxpoint, maxxpoint)) | |
minxshadowx = x * scale + 1000 | |
minxshadowy = 1000 - y * scale | |
(x, y) = maxxpoint.split(',') | |
x = float(x) - 1000 | |
y = 1000 - float(y) | |
scale = 1000 / hypot(x, y) | |
maxxshadowx = x * scale + 1000 | |
maxxshadowy = 1000 - y * scale | |
bgsweep[name].append('%s %s %s,%s A 1000,1000 0 0 1 %s,%s' % ( | |
minxpoint, maxxpoint, | |
maxxshadowx, maxxshadowy, | |
minxshadowx, minxshadowy | |
)) | |
fgsweep2[name].append('1000,1000 %s,%s A 1000,1000 0 0 1 %s,%s' % ( | |
maxxshadowx, maxxshadowy, | |
minxshadowx, minxshadowy | |
)) | |
except: | |
pass | |
if not crossed: | |
background[name].append(" L ".join(backgroundparts[0])) | |
else: | |
backgroundstr = " L ".join(backgroundparts[0]) | |
for part in backgroundparts[1:]: | |
first = part[0] | |
arc = " A 1000,1000 0 0 0 %s" % first | |
backgroundstr = backgroundstr + arc + " L " + " L ".join(part) | |
first = backgroundparts[0][0] | |
arc = " A 1000,1000 0 0 0 %s" % first | |
background[name].append(backgroundstr + arc) | |
if len(foregroundparts) > 0: | |
try: | |
for part in foregroundparts: | |
minx = 2000 | |
maxx = -1000 | |
minxpoint = None | |
maxxpoint = None | |
for point in part: | |
(x, y) = point.split(',') | |
x = float(x) - 1000 | |
y = 1000 - float(y) | |
if x == 0: | |
continue | |
angle = atan(y / x) | |
if angle < 0 and maxx > 1.3: | |
angle += pi * 2 | |
if angle > 0 and minx < -1.3: | |
angle -= pi * 2 | |
if angle < minx: | |
minx = angle | |
minxpoint = point | |
if angle > maxx: | |
maxx = angle | |
maxxpoint = point | |
(x, y) = minxpoint.split(',') | |
x = float(x) - 1000 | |
y = 1000 - float(y) | |
scale = 1100 / hypot(x, y) | |
if scale > 10: | |
continue | |
fgsweep[name].append('1000,1000 %s %s' % (minxpoint, maxxpoint)) | |
minxshadowx = x * scale + 1000 | |
minxshadowy = 1000 - y * scale | |
(x, y) = maxxpoint.split(',') | |
x = float(x) - 1000 | |
y = 1000 - float(y) | |
scale = 1100 / hypot(x, y) | |
maxxshadowx = x * scale + 1000 | |
maxxshadowy = 1000 - y * scale | |
fgshadow[name].append('%s %s %s,%s A 1100,1100 0 0 1 %s,%s' % ( | |
minxpoint, maxxpoint, | |
maxxshadowx, maxxshadowy, | |
minxshadowx, minxshadowy | |
)) | |
bgshadow2[name].append('1000,1000 %s,%s A 1100,1100 0 0 1 %s,%s' % ( | |
maxxshadowx, maxxshadowy, | |
minxshadowx, minxshadowy | |
)) | |
except: | |
pass | |
if not crossed: | |
foreground[name].append(" L ".join(foregroundparts[0])) | |
else: | |
foregroundstr = " L ".join(foregroundparts[0]) | |
for part in foregroundparts[1:]: | |
first = part[0] | |
arc = " A 1000,1000 0 0 1 %s" % first | |
foregroundstr = foregroundstr + arc + " L " + " L ".join(part) | |
first = foregroundparts[0][0] | |
arc = " A 1000,1000 0 0 1 %s" % first | |
foreground[name].append(foregroundstr + arc) | |
print '<?xml version="1.0" ?>' | |
print '''<svg width="4400" height="2200" viewBox="-100 -100 4400 2200" xmlns="http://www.w3.org/2000/svg" | |
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape">''' | |
print '\t<g inkscape:label="bgsweep" inkscape:groupmode="layer" '\ | |
'transform="matrix(-1,0,0,1,4200,0)">' | |
for (name, paths) in bgsweep.iteritems(): | |
if len(paths) == 0: | |
continue | |
print '\t\t<g id="%s_bgsweep" fill="#%s">' % \ | |
(name, sha1(name).hexdigest()[0:6]) | |
for path in paths: | |
print '\t\t\t<path d="M %s Z" />' % path | |
print '\t\t</g>' | |
print '\t</g>' | |
print '\t<g inkscape:label="bgshadow" inkscape:groupmode="layer" '\ | |
'transform="matrix(-1,0,0,1,4200,0)">' | |
for (name, paths) in bgshadow.iteritems(): | |
if len(paths) == 0: | |
continue | |
print '\t\t<g id="%s_bgshadow" fill="#eee">' % name | |
for path in paths: | |
print '\t\t\t<path d="M %s Z" />' % path | |
print '\t\t</g>' | |
print '\t</g>' | |
print '\t<g inkscape:label="bgshadow2" inkscape:groupmode="layer" '\ | |
'transform="matrix(-1,0,0,1,4200,0)">' | |
for (name, paths) in bgshadow2.iteritems(): | |
if len(paths) == 0: | |
continue | |
print '\t\t<g id="%s_bgshadow2" fill="#eee">' % name | |
for path in paths: | |
print '\t\t\t<path d="M %s Z" />' % path | |
print '\t\t</g>' | |
print '\t</g>' | |
print '\t<g inkscape:label="background" inkscape:groupmode="layer" '\ | |
'transform="matrix(-1,0,0,1,4200,0)">' | |
for (name, paths) in background.iteritems(): | |
if len(paths) == 0: | |
continue | |
print '\t\t<g id="%s_bg">' % name | |
for path in paths: | |
print '\t\t\t<path d="M %s Z" fill="black" />' % path | |
print '\t\t</g>' | |
print '\t</g>' | |
print '\t<g inkscape:label="fgsweep2" inkscape:groupmode="layer">' | |
for (name, paths) in fgsweep2.iteritems(): | |
if len(paths) == 0: | |
continue | |
print '\t\t<g id="%s_fgsweep2" fill="#%s">' % \ | |
(name, sha1(name).hexdigest()[0:6]) | |
for path in paths: | |
print '\t\t\t<path d="M %s Z" />' % path | |
print '\t\t</g>' | |
print '\t</g>' | |
print '\t<g inkscape:label="fgsweep" inkscape:groupmode="layer">' | |
for (name, paths) in fgsweep.iteritems(): | |
if len(paths) == 0: | |
continue | |
print '\t\t<g id="%s_fgsweep" fill="#%s">' % \ | |
(name, sha1(name).hexdigest()[0:6]) | |
for path in paths: | |
print '\t\t\t<path d="M %s Z" />' % path | |
print '\t\t</g>' | |
print '\t</g>' | |
print '\t<g inkscape:label="fgshadow" inkscape:groupmode="layer">' | |
for (name, paths) in fgshadow.iteritems(): | |
if len(paths) == 0: | |
continue | |
print '\t\t<g id="%s_fgshadow" fill="#eee">' % name | |
for path in paths: | |
print '\t\t\t<path d="M %s Z" />' % path | |
print '\t\t</g>' | |
print '\t</g>' | |
print '\t<g inkscape:label="foreground" inkscape:groupmode="layer">' | |
for (name, paths) in foreground.iteritems(): | |
if len(paths) == 0: | |
continue | |
print '\t\t<g id="%s_fg" fill="red">' % name | |
for path in paths: | |
print '\t\t\t<path d="M %s Z" />' % path | |
print '\t\t</g>' | |
print '\t</g>' | |
print '</svg>' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment