--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kml/kml.py Mon May 18 08:48:51 2020 +0200
@@ -0,0 +1,263 @@
+import sys
+import xml.sax.saxutils
+from math import *
+
+class Kml():
+ def __init__(self):
+ self.out = sys.stdout
+ self.placemark = Placemark(self)
+ self.tour = Tour(self)
+ self.playlist = Playlist(self)
+ self.flyto = FlyTo(self)
+ self.lookat = LookAt(self)
+ self.camera = Camera(self)
+ self.document = Document(self)
+ self.folder = Folder(self)
+ self.xml = Xml(self)
+
+ def documentProlog(self, fn):
+ self.xml.head()
+ self.document.head(fn)
+
+ def documentEpilog(self):
+ self.document.tail()
+ self.xml.tail()
+
+ def folderProlog(self, fn):
+ self.folder.head(fn)
+
+ def folderEpilog(self):
+ self.folder.tail()
+
+ def tourProlog(self, fn):
+ self.tour.head(fn)
+ self.playlist.head()
+
+ def tourEpilog(self):
+ self.playlist.tail()
+ self.tour.tail()
+
+ def placemarkProlog(self, fn):
+ self.xml.head()
+ self.placemark.head(fn)
+
+ def placemarkEpilog(self):
+ self.placemark.tail()
+ self.xml.tail()
+
+ def urlPlacemark(self, url, path):
+ # ref = '<a href="http://{}/index.py">{}</a>'.format(qualname, qualname)
+ ref = '<a href="{}">{}</a>'.format(url, path)
+ p = self.pr
+ p('<Placemark>')
+ p('<name>{ref}</name>'.format(ref = xml.sax.saxutils.escape(ref)))
+ p('</Placemark>')
+
+ def wait(self, dur):
+ self.pr('\n<gx:Wait><gx:duration>{}</gx:duration></gx:Wait>'.format(dur))
+
+ def comm(self, c):
+ self.pr('\n<!-- {} -->'.format(c))
+
+ def pr(self, s):
+ print(s, file=self.out)
+
+class Xml():
+ def __init__(self, kml):
+ self.kml = kml
+
+ def head(self):
+ self.kml.pr('<?xml version="1.0" encoding="UTF-8"?>')
+ self.kml.pr('<kml')
+ self.kml.pr('xmlns="http://www.opengis.net/kml/2.2"')
+ self.kml.pr('xmlns:gx="http://www.google.com/kml/ext/2.2"')
+ self.kml.pr('>')
+
+ def tail(self):
+ self.kml.pr('\n</kml>')
+
+class Document():
+ def __init__(self, kml):
+ self.kml = kml
+
+ def head(self, fn):
+ self.kml.pr('<Document>')
+ self.kml.pr('<name>{}</name>'.format(fn))
+ self.kml.pr('<open>1</open>')
+
+ def tail(self):
+ self.kml.pr('\n</Document>')
+
+
+class Folder():
+ def __init__(self, kml):
+ self.kml = kml
+
+ def head(self, fn):
+ self.kml.pr('<Folder>')
+ self.kml.pr('<name>{}</name>'.format(fn))
+ self.kml.pr('<open>1</open>')
+
+ def tail(self):
+ self.kml.pr('\n</Folder>')
+
+class Tour():
+ def __init__(self, kml):
+ self.kml = kml
+
+ def head(self, fn):
+ self.kml.pr('\n<gx:Tour>')
+ self.kml.pr('<name>{}</name>'.format(fn))
+
+ def tail(self):
+ self.kml.pr('\n</gx:Tour>')
+
+class Playlist():
+ def __init__(self, kml):
+ self.kml = kml
+
+ def head(self):
+ self.kml.pr('\n<gx:Playlist>')
+
+ def tail(self):
+ self.kml.wait(1)
+ self.kml.pr('\n</gx:Playlist>')
+
+class FlyTo():
+ def __init__(self, kml):
+ self.kml = kml
+
+ def head(self, dur, smooth):
+ self.kml.pr('<gx:FlyTo>')
+ self.kml.pr('<gx:duration>{}</gx:duration>'.format(dur))
+ self.kml.pr('<gx:flyToMode>{}</gx:flyToMode>'.format('smooth' if smooth else 'bounce'))
+
+ def tail(self):
+ self.kml.pr('\n</gx:FlyTo>')
+
+class LookAt():
+ def __init__(self, kml):
+ self.kml = kml
+
+ def run(self, long,lat,alt,head,tilt,range):
+ self.kml.pr('\n<LookAt>')
+ self.kml.pr('<latitude>{}</latitude>'.format(lat))
+ self.kml.pr('<longitude>{}</longitude>'.format(long))
+ self.kml.pr('<altitude>{}</altitude>'.format(alt))
+ self.kml.pr('<heading>{}</heading>'.format(head))
+ self.kml.pr('<tilt>{}</tilt>'.format(tilt))
+ self.kml.pr('<range>{}</range>'.format(range))
+ self.kml.pr('<altitudeMode>relativeToGround</altitudeMode>')
+ self.kml.pr('</LookAt>')
+
+class Camera():
+ def __init__(self, kml):
+ self.kml = kml
+
+ def run(self,long,lat,alt,head,tilt,roll):
+ self.kml.pr('<Camera>')
+ self.kml.pr('<latitude>{}</latitude>'.format(lat))
+ self.kml.pr('<longitude>{}</longitude>'.format(long))
+ self.kml.pr('<altitude>{}</altitude>'.format(alt))
+ self.kml.pr('<heading>{}</heading>'.format(head))
+ self.kml.pr('<tilt>{}</tilt>'.format(tilt))
+ self.kml.pr('<roll>{}</roll>'.format(roll))
+ self.kml.pr('<altitudeMode>relativeToSeaFloor</altitudeMode>')
+ self.kml.pr('</Camera>')
+
+ def runL(self, long, lat, alt, head, tilt, range, roll):
+ # dostává parametry LookAt, které konvertuje na parametry Camera tak, aby pohled byl stejný
+ dLO, dLA, Z = l2c(lat, head, tilt, range)
+ self.run(long + dLO, lat + dLA, Z, head, tilt, roll)
+
+class Placemark():
+ def __init__(self, kml):
+ self.kml = kml
+
+ def head(self, fn):
+ self.kml.pr('<Placemark>')
+ self.kml.pr('<name>{}</name>'.format(fn))
+ self.kml.pr('<visibility>0</visibility>')
+ self.kml.pr('<styleUrl>#PIN_YELLOW</styleUrl>')
+
+ def tail(self):
+ self.kml.pr('\n</Placemark>')
+
+class SpeedAdjust():
+ keys = ['none', 'linear', 'parabolic', 'tangential', 'exponential']
+ abrv = {'none':'none', 'linear':'lin', 'parabolic':'par', 'tangential':'tang', 'exponential':'exp'}
+
+ def __init__(self, const, koef, steps, config):
+ self.slowdowns = {'none':self.Const, 'linear':self.Linear, 'parabolic':self.Parabolic, 'tangential':self.Tangent, 'exponential':self.Exponential}
+ self.const = const
+ self.koef = koef
+ self.steps = steps
+ self.c = config
+
+ def phase(self):
+ return 1 - self.c.xi / self.c.x0.val
+
+ class Const():
+ p = 1 # empirická konstanta
+ def __init__(self, sa):
+ self.sa = sa
+ def koef(self):
+ return self.p / self.sa.const
+
+ class Linear():
+ p = 2 # empirická konstanta
+ def __init__(self, sa):
+ self.sa = sa
+ def koef(self):
+ return self.p * self.sa.koef * self.sa.phase() / self.sa.const
+
+ class Parabolic():
+ p = 2 # empirická konstanta
+ def __init__(self, sa):
+ self.sa = sa
+ def koef(self):
+ return self.p * pow(self.sa.koef * self.sa.phase(), 2) / self.sa.const
+
+ class Tangent():
+ p = 1 # empirická konstanta
+ def __init__(self, sa):
+ self.sa = sa
+ def koef(self):
+ margin = atan(self.sa.koef) # < pi/2
+ return (1 + self.p * tan(self.sa.phase() * margin)) / self.sa.const
+
+ class Exponential():
+ p = 1 # empirická konstanta
+ def __init__(self, sa):
+ self.sa = sa
+ def koef(self):
+ return pow(e, self.p * self.sa.koef * self.sa.phase()) / self.sa.const
+
+def canonGeodetic(a):
+ if(a > 360 or a < -360): a = a % 360
+ if(a > 180): a = a - 360
+ if(a < -180): a = a + 360
+ return a
+
+def can360(a360):
+ if(a360 < 0): a360 = a360 + 360
+ elif(a360 > 360): a360 = a360 - 360
+ return a360
+
+def can180(a180):
+ if(a180 < -180): a180 = a180 + 360
+ elif(a180 > 180): a180 = a180 - 360
+ return a180
+
+def l2c(lat, head, tilt, range):
+ RZ = 6378000
+ RL = RZ * cos(radians(lat))
+ Hc = can360(head + 180)
+ Z = range * cos(radians(tilt))
+ d = sqrt(pow(range,2) - pow(Z,2))
+ dLA = degrees(atan(d * cos(radians(Hc)) / RZ))
+ dLO = degrees(atan(d * sin(radians(Hc)) / RL))
+ return dLO, dLA, Z
+
+def deb(s):
+ print('+++ {}'.format(s), file=sys.stderr)