--- /dev/null
+Package: enigma2-plugin-extensions-googlemaps
+Version: 20081010
+Description: Google Maps Enigma2 Client
+Architecture: mipsel
+Section: extra
+Priority: optional
+Maintainer: 3c5x9 <3c5x9@gmx.net>
+Homepage: http://www.i-have-a-dreambox.com
+Depends: enigma2(>1.0cvs20081011), twisted-web
+Source: http://enigma2-plugins.schwerkraft.elitedvb.net/
--- /dev/null
+SUBDIRS = src
--- /dev/null
+###############################################################################
+# Copyright (c) 2008 Rico Schulte, 3c5x9. All rights reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+###############################################################################
+
+from globalmaptiles import GlobalMercator
+from xml.dom.minidom import parse
+from os import listdir
+
+class KmlPlace:
+ def __init__(self,kmlnode):
+ self.kmlnode = kmlnode
+ self.name = kmlnode.getElementsByTagName('name')[0].firstChild.data.encode("utf-8")
+ lons = kmlnode.getElementsByTagName('LookAt')[0].getElementsByTagName('longitude')[0].firstChild.data.encode("utf-8")
+ lats = kmlnode.getElementsByTagName('LookAt')[0].getElementsByTagName('latitude')[0].firstChild.data.encode("utf-8")
+
+ lat = float(lats)
+ lon = float(lons)
+ if lat<0.0:
+ lat = lat*(-1.0)
+ if lon<0.0:
+ lon=lon*(-1.0)
+ self.lat = lat
+ self.lon = lon
+
+ def getTile(self,zoomlevel):
+ mercator = GlobalMercator()
+ mx, my = mercator.LatLonToMeters( self.lat, self.lon )
+ tminx, tminy = mercator.MetersToTile( mx, my, zoomlevel )
+ gx, gy = mercator.GoogleTile(tminx, tminy, zoomlevel)#+1?
+ return gx,gy,zoomlevel
+
+ def __str__(self):
+ return "KmlPlace ('"+self.name+"','"+str(self.lat)+"','"+str(self.lon)+"')"
+
+class KmlFolder:
+ parent = None
+ def __init__(self,kmlnode):
+ self.kmlnode = kmlnode
+ self.name = kmlnode.getElementsByTagName('name')[0].firstChild.data.encode("utf-8")
+
+ def getFolders(self):
+ list = []
+ for i in self.kmlnode.getElementsByTagName('Folder'):
+ folder = KmlFolder(i)
+ folder.parent = self
+ list.append(folder)
+ #list.pop(0)
+ return list
+
+ def getPlacemarks(self):
+ list = []
+ for i in self.kmlnode.getElementsByTagName('Placemark'):
+ point = KmlPlace(i)
+ try: # test if we can handle this coords
+ point.getTile(15)# 15 is just a zoomlevel in the middle :)
+ list.append(point)
+ except ValueError,e:
+ print "Import Error: ",point.name,e
+ return list
+
+class RootFolder:
+ extension = '.kml'
+ def __init__(self):
+ pass
+
+ def getFolderFromFile(self,filepath):
+ return KmlFolder(self.parseFile(filepath))
+
+ def parseFile(self,filepath):
+ print "parsing ",filepath
+ return parse(filepath)
+
+ def getFiles(self,path):
+ list = []
+ for file in listdir(path):
+ if file.endswith(self.extension):
+ list.append((file.split('.')[0],path+file))
+ return list
+
--- /dev/null
+installdir = /usr/lib/enigma2/python/Plugins/Extensions/GoogleMaps\r
+\r
+install_PYTHON = __init__.py plugin.py WebPixmap.py KMLlib.py globalmaptiles.py\r
+\r
+install_DATA = Racetracks.kml Sightseeing.kml 404.png README \r
--- /dev/null
+Google Maps Enigma2 Client FAQ
+
+
+How to get own Placemarks into the List at Plugin Start?
+
+You can put your own KML-File in the Root Dir of the Plugin. This is in most
+cases /usr/lib/enigma2/python/Plugins/Extensions/GoogleMaps/
+
+
+How the Plugin will find my custom KML-File?
+
+The Plugin looks at Startup in his own Dir and will try to read and to display
+all Files that are ending with the Extension .kml .
+
+
+How to get a KML-File?
+
+The Plugin uses the same KML-Files as Google Earth does it. So, if you have
+your Collection of custom Placemarks in Google Earth for Example, export them
+into a File in the Format KMZ. Rename this exported KMZ file to xxzzyy.kmz.zip
+and extract it. You will find a KML-File that will contain your Placemarks.
+
+
+Why are there so much more Tags in the original KML-File from Google Earth than
+in the standart KML-Files of the Plugin are?
+
+This is because parsing unneeded Stuff costs Time we dont have :) To Speeding
+up the Start of the Plugin, we have kicked of all unneeded Stuff from the
+standart KML-Files. But a original KML from Google Earth has to work too, but
+slower.
+
+
+Which Tags are important for this Plugin?
+
+This is an example of a KML-Docoment :
+<?xml version="1.0" encoding="UTF-8"?>
+<kml xmlns="http://earth.google.com/kml/2.2">
+<Document>
+ <Folder>
+ <name>This is the Entry which will be shown in the Plugin Root List</name>
+ <Placemark>
+ <name>This is the Name of a Placemark</name>
+ <LookAt>
+ <longitude>13.3501</longitude>
+ <latitude>52.514553</latitude>
+ </LookAt>
+ </Placemark>
+ </Folder>
+</Document>
+</kml>
+
+
+What I am doing, if i want some Placemarks be added to the standart Plugin
+KML-Files?
+
+Just send me a email to 3c5x9%at%gmx.net .
+
+
+Who has portet this to Enigma2?
+
+Rico 3c5x9 Schulte :D
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<kml xmlns="http://earth.google.com/kml/2.2">
+ <Document>
+ <name>Rennstrecken.kmz</name>
+ <Folder>
+ <name>Rennstrecken</name>
+ <LookAt id="khLookAt542">
+ <longitude>6.929877072239468</longitude>
+ <latitude>50.32417204519953</latitude>
+ </LookAt>
+ <Folder>
+ <name>F1</name>
+ <Placemark>
+ <name>Bahrain International Circuit</name>
+ <LookAt>
+ <longitude>50.5159378129532</longitude>
+ <latitude>26.03093828168916</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Albert Park</name>
+ <LookAt>
+ <longitude>144.9715352947365</longitude>
+ <latitude>-37.84521648935841</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Sepang International Circuit</name>
+ <LookAt>
+ <longitude>101.7409446248163</longitude>
+ <latitude>2.764768574918148</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Autodromo Enzo e Dino Ferrari</name>
+ <LookAt>
+ <longitude>11.71462614473162</longitude>
+ <latitude>44.34481140631318</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Circuit de Catalunya</name>
+ <LookAt>
+ <longitude>2.257452207043378</longitude>
+ <latitude>41.56737738690407</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Circuit de Monaco</name>
+ <LookAt>
+ <longitude>7.422053181921657</longitude>
+ <latitude>43.73726313916431</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark id="khPlacemark570">
+ <name>Nürburgring</name>
+ <LookAt id="khLookAt571">
+ <longitude>7.334510988886211</longitude>
+ <latitude>49.94551673542702</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Gilles Villeneuve Circuit</name>
+ <LookAt>
+ <longitude>-73.52283623934387</longitude>
+ <latitude>45.50553627093121</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Indianapolis Motor Speedway</name>
+ <LookAt>
+ <longitude>-86.2362501146151</longitude>
+ <latitude>39.78823846100529</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Circuit de Nevers Magny Cours</name>
+ <LookAt>
+ <longitude>3.164362080205438</longitude>
+ <latitude>46.86192004355246</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Silverstone Circuit</name>
+ <LookAt>
+ <longitude>-1.017369648189376</longitude>
+ <latitude>52.07109668847959</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark id="khPlacemark576">
+ <name>Hockenheimring</name>
+ <LookAt id="khLookAt577">
+ <longitude>8.572361618019089</longitude>
+ <latitude>49.33636224642903</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Hungaroring</name>
+ <LookAt>
+ <longitude>19.25105448200226</longitude>
+ <latitude>47.58192955176471</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Autodromo Nazionale di Monza</name>
+ <LookAt>
+ <longitude>9.280119913989184</longitude>
+ <latitude>45.62789672197946</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark id="khPlacemark582">
+ <name>Spa-Francorchamps</name>
+ <LookAt id="khLookAt583">
+ <longitude>5.977347315065888</longitude>
+ <latitude>50.44233228871123</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Suzuka International Racing Course</name>
+ <LookAt>
+ <longitude>136.5406420907146</longitude>
+ <latitude>34.85060200750952</latitude>
+ </LookAt>
+ </Placemark>
+ </Folder>
+ <Folder>
+ <name>DTM</name>
+ <Placemark>
+ <name>Hockenheimring</name>
+ <LookAt>
+ <longitude>8.572361618019089</longitude>
+ <latitude>49.33636224642903</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Eurospeedway Lausitz</name>
+ <LookAt>
+ <longitude>13.91807812966808</longitude>
+ <latitude>51.53402323167359</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Spa-Francorchamps</name>
+ <LookAt>
+ <longitude>5.977347315065888</longitude>
+ <latitude>50.44233228871123</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>MOTOPARK Oschersleben</name>
+ <LookAt>
+ <longitude>11.27812960444814</longitude>
+ <latitude>52.03096083063715</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark id="khPlacemark559">
+ <name>Norisring, Nürnberg</name>
+ <LookAt id="khLookAt560">
+ <longitude>11.12471555353767</longitude>
+ <latitude>49.43081462347325</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Nürburgring</name>
+ <LookAt>
+ <longitude>6.949310568838253</longitude>
+ <latitude>50.33584418617244</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Circuit Park Zandvoort</name>
+ <LookAt>
+ <longitude>4.545550844066787</longitude>
+ <latitude>52.39075015985516</latitude>
+ </LookAt>
+ </Placemark>
+ </Folder>
+ <Folder>
+ <name>US Motorsport</name>
+ <Folder>
+ <name>Champcar</name>
+ <Folder>
+ <name>Toronto</name>
+ <Placemark>
+ <name>Toronto</name>
+ <LookAt>
+ <longitude>-79.41769175346289</longitude>
+ <latitude>43.63422231656372</latitude>
+ </LookAt>
+ </Placemark>
+ </Folder>
+ <Folder>
+ <name>Cleveland</name>
+ <Placemark>
+ <name>Cleveland</name>
+ <LookAt>
+ <longitude>-81.6796840786287</longitude>
+ <latitude>41.52051267648185</latitude>
+ </LookAt>
+ </Placemark>
+ </Folder>
+ <Folder>
+ <name>Long Beach</name>
+ <Placemark>
+ <name>Lon Beach</name>
+ <LookAt>
+ <longitude>-118.1908658946714</longitude>
+ <latitude>33.76449296786325</latitude>
+ </LookAt>
+ </Placemark>
+ </Folder>
+ <Placemark>
+ <name>Milwaukee</name>
+ <LookAt>
+ <longitude>-88.01004825224374</longitude>
+ <latitude>43.0209967618935</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Elkhart LAke/ Road America</name>
+ <LookAt>
+ <longitude>-87.99150919796183</longitude>
+ <latitude>43.80346097444006</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Gilles Villeneuve Circuit</name>
+ <LookAt>
+ <longitude>-73.52283623934387</longitude>
+ <latitude>45.50553627093121</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Surfers Paradise</name>
+ <LookAt>
+ <longitude>153.428094790144</longitude>
+ <latitude>-27.98541288223582</latitude>
+ </LookAt>
+ </Placemark>
+ </Folder>
+ <Folder>
+ <name>IRL</name>
+ <Placemark>
+ <name>Watkins Glen</name>
+ <LookAt>
+ <longitude>-76.92166099999996</longitude>
+ <latitude>42.33637900000002</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Homestead</name>
+ <LookAt>
+ <longitude>-80.4061733383281</longitude>
+ <latitude>25.45297806426108</latitude>
+ </LookAt>
+ </Placemark>
+ <Folder>
+ <name>St. Petersburg</name>
+ <Placemark>
+ <name>St. Petersburg</name>
+ <LookAt>
+ <longitude>-82.63261590428058</longitude>
+ <latitude>27.76798744075829</latitude>
+ </LookAt>
+ </Placemark>
+ </Folder>
+ <Placemark>
+ <name>Indianapolis Motor Speedway</name>
+ <LookAt>
+ <longitude>-86.2362501146151</longitude>
+ <latitude>39.78823846100529</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Motegi</name>
+ <LookAt>
+ <longitude>140.232014680432</longitude>
+ <latitude>36.53540338659351</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Texas Motor Speedway/ Fort Worth</name>
+ <LookAt>
+ <longitude>-97.27550294207562</longitude>
+ <latitude>33.03678639400341</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Kansas Speedway</name>
+ <LookAt>
+ <longitude>-94.82484477610788</longitude>
+ <latitude>39.11783961403013</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Richmond</name>
+ <LookAt>
+ <longitude>-77.41662262634702</longitude>
+ <latitude>37.5935680196662</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Milwaukee Mile</name>
+ <LookAt>
+ <longitude>-88.0098350887677</longitude>
+ <latitude>43.01999925128768</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Infineon Raceway/ Sears Point</name>
+ <LookAt>
+ <longitude>-122.4558002882116</longitude>
+ <latitude>38.16028154427657</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Michigan International Speedway</name>
+ <LookAt>
+ <longitude>-84.23577187579066</longitude>
+ <latitude>42.07005792982215</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Kentucky Speedway ????</name>
+ <LookAt>
+ <longitude>-84.90830080997644</longitude>
+ <latitude>38.71367651733355</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Chicagoland Speedway</name>
+ <LookAt>
+ <longitude>-88.05597050150595</longitude>
+ <latitude>41.47748099267035</latitude>
+ </LookAt>
+ </Placemark>
+ </Folder>
+ <Folder>
+ <name>NASCAR</name>
+ <Placemark>
+ <name>Daytona International Speedway</name>
+ <LookAt>
+ <longitude>-81.06831999999999</longitude>
+ <latitude>29.18544600000001</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Atlanta Motor Speedway</name>
+ <LookAt>
+ <longitude>-84.3136623599664</longitude>
+ <latitude>33.38460422804864</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Texas Motor Speedway/ Fort Worth</name>
+ <LookAt>
+ <longitude>-97.27550294207562</longitude>
+ <latitude>33.03678639400341</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Richmond</name>
+ <LookAt>
+ <longitude>-77.41662262634702</longitude>
+ <latitude>37.5935680196662</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Phoenix International -raceway</name>
+ <LookAt>
+ <longitude>-112.3091491344432</longitude>
+ <latitude>33.37530074796366</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Darlington Raceway</name>
+ <LookAt>
+ <longitude>-79.90363594690994</longitude>
+ <latitude>34.29921695793798</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Lowe´s Motor Speedway</name>
+ <LookAt>
+ <longitude>-80.67008655449148</longitude>
+ <latitude>35.36829159744103</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Dover International Speedway</name>
+ <LookAt>
+ <longitude>-75.52972156781868</longitude>
+ <latitude>39.19199056029645</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Michigan International Speedway</name>
+ <LookAt>
+ <longitude>-84.23577187579066</longitude>
+ <latitude>42.07005792982215</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Poccono Raceway</name>
+ <LookAt>
+ <longitude>-75.50245592993286</longitude>
+ <latitude>41.05779435922389</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Chicagoland Speedway</name>
+ <LookAt>
+ <longitude>-88.05597050150595</longitude>
+ <latitude>41.47748099267035</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Infineon Raceway/ Sears Point</name>
+ <LookAt>
+ <longitude>-122.4558002882116</longitude>
+ <latitude>38.16028154427657</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>New Hampshire Internatioal Speedway</name>
+ <LookAt>
+ <longitude>-71.46127156805834</longitude>
+ <latitude>43.36406290091922</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Indianapolis Motor Speedway</name>
+ <LookAt>
+ <longitude>-86.2362501146151</longitude>
+ <latitude>39.78823846100529</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Watkins Glen</name>
+ <LookAt>
+ <longitude>-76.92166099999996</longitude>
+ <latitude>42.33637900000002</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Homestead</name>
+ <LookAt>
+ <longitude>-80.4061733383281</longitude>
+ <latitude>25.45297806426108</latitude>
+ </LookAt>
+ </Placemark>
+ </Folder>
+ </Folder>
+ <Folder>
+ <name>Sonstige</name>
+ <Placemark>
+ <name>Auto Motodrom Brno</name>
+ <LookAt>
+ <longitude>16.45454428748549</longitude>
+ <latitude>49.20875429788457</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Truxton</name>
+ <LookAt>
+ <longitude>-1.597021973231723</longitude>
+ <latitude>51.21399910556353</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Singen</name>
+ <LookAt id="khLookAt691">
+ <longitude>8.875566759827366</longitude>
+ <latitude>47.7562905823079</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Avus</name>
+ <LookAt>
+ <longitude>13.27670532820685</longitude>
+ <latitude>52.50034570652288</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Estoril</name>
+ <LookAt>
+ <longitude>-9.391760237383039</longitude>
+ <latitude>38.75166059845908</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Valencia</name>
+ <LookAt>
+ <longitude>-0.6278296500164047</longitude>
+ <latitude>39.48646449983395</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Donnington</name>
+ <LookAt>
+ <longitude>-1.371583547425225</longitude>
+ <latitude>52.83180797680389</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Laguna Seca</name>
+ <LookAt>
+ <longitude>-121.7556610183761</longitude>
+ <latitude>36.59349433156462</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Fiorano</name>
+ <LookAt>
+ <longitude>10.85920782049148</longitude>
+ <latitude>44.53549492036529</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Mugello</name>
+ <LookAt>
+ <longitude>11.37120997751637</longitude>
+ <latitude>43.99844221241774</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Jerez</name>
+ <LookAt>
+ <longitude>-6.031852920691954</longitude>
+ <latitude>36.70980360887362</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>MotoGP Katar</name>
+ <LookAt>
+ <longitude>51.48282806639534</longitude>
+ <latitude>25.41545046468327</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Philip Island</name>
+ <LookAt>
+ <longitude>145.2374310713819</longitude>
+ <latitude>-38.50279471457448</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Sandown</name>
+ <LookAt>
+ <longitude>145.17092878827</longitude>
+ <latitude>-37.94997021698191</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Circuit Paul Ricard, Le Castelet</name>
+ <LookAt>
+ <longitude>5.79061054160506</longitude>
+ <latitude>43.24989074500129</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Zolder</name>
+ <LookAt>
+ <longitude>5.25576438347351</longitude>
+ <latitude>50.99091733010614</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Sachsenring</name>
+ <LookAt>
+ <longitude>12.69070956521054</longitude>
+ <latitude>50.79245262382773</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Rockingham</name>
+ <LookAt>
+ <longitude>-0.6559556270247314</longitude>
+ <latitude>52.51963769868555</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Adria International Raceway</name>
+ <LookAt>
+ <longitude>12.15437112029783</longitude>
+ <latitude>45.04506800936013</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Brands Hatch</name>
+ <LookAt>
+ <longitude>0.264311236154689</longitude>
+ <latitude>51.35808807072547</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Le Mans</name>
+ <LookAt>
+ <longitude>0.2147281803668639</longitude>
+ <latitude>47.95591199147226</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>A1 Ring</name>
+ <LookAt>
+ <longitude>14.76599309439062</longitude>
+ <latitude>47.22567493827706</latitude>
+ </LookAt>
+ </Placemark>
+ </Folder>
+ <Folder>
+ <name>Test Tracks</name>
+ <Placemark>
+ <name>Michelin Test-Center</name>
+ <LookAt>
+ <longitude>13.53603771864872</longitude>
+ <latitude>53.02450785494383</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Bosch TestTrack</name>
+ <LookAt>
+ <longitude>9.639937733529266</longitude>
+ <latitude>49.44881553243841</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>VW Test Center</name>
+ <LookAt>
+ <longitude>10.7671041989884</longitude>
+ <latitude>52.64178133413746</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Opel Test Center</name>
+ <LookAt>
+ <longitude>8.924521595490715</longitude>
+ <latitude>49.99360058193022</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>ATP Papenburg</name>
+ <LookAt>
+ <longitude>7.502614663982489</longitude>
+ <latitude>53.05391475731348</latitude>
+ </LookAt>
+ </Placemark>
+ </Folder>
+ </Folder>
+ </Document>
+</kml>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<kml xmlns="http://earth.google.com/kml/2.2">
+<Document>
+ <name>Sightseeing.kmz</name>
+ <Folder>
+ <name>Sightseeing</name>
+ <Placemark>
+ <name>Siegessäule</name>
+ <LookAt>
+ <longitude>13.3501</longitude>
+ <latitude>52.514553</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Speyer Cathedral</name>
+ <LookAt>
+ <longitude>8.441454</longitude>
+ <latitude>49.317504</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Lorelei Rock</name>
+ <LookAt>
+ <longitude>7.731134</longitude>
+ <latitude>50.14002</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Grand Canyon, USA</name>
+ <LookAt>
+ <longitude>-112.335374</longitude>
+ <latitude>36.227202</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Eiffelturm, Paris, Frankreich</name>
+ <LookAt>
+ <longitude>2.29426</longitude>
+ <latitude>48.858052</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>CN Tower, Kanada</name>
+ <LookAt>
+ <longitude>-79.387575</longitude>
+ <latitude>43.642574</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Hamburg, Deutschland</name>
+ <LookAt>
+ <longitude>9.994603</longitude>
+ <latitude>53.545719</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Kaiserpalast, Tokio, Japan</name>
+ <LookAt>
+ <longitude>139.752459</longitude>
+ <latitude>35.684753</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Christus der Erlöser, Rio, Brasilien</name>
+ <LookAt>
+ <longitude>-43.21044</longitude>
+ <latitude>-22.951736</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Las Vegas, USA</name>
+ <LookAt>
+ <longitude>-115.172887</longitude>
+ <latitude>36.100841</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Lissabon, Portugal</name>
+ <LookAt>
+ <longitude>-9.129564</longitude>
+ <latitude>38.763061</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Petersdom, Vatikanstadt</name>
+ <LookAt>
+ <longitude>12.454076</longitude>
+ <latitude>41.901828</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Basilika El Pilar, Spanien</name>
+ <LookAt>
+ <longitude>-0.878196</longitude>
+ <latitude>41.656896</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>London Eye, GB</name>
+ <LookAt>
+ <longitude>-0.119933</longitude>
+ <latitude>51.503277</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Olympiagelände Sydney, Australien</name>
+ <LookAt>
+ <longitude>151.066035</longitude>
+ <latitude>-33.847733</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Roter Platz, Moskau, Russland</name>
+ <LookAt>
+ <longitude>37.62018</longitude>
+ <latitude>55.753881</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Mount Saint Helens, USA</name>
+ <LookAt>
+ <longitude>-122.176504</longitude>
+ <latitude>46.209497</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Ehemaliger Republikpalast, Bagdad, Irak</name>
+ <LookAt>
+ <longitude>44.408542</longitude>
+ <latitude>33.304173</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Manhattan Island, USA</name>
+ <LookAt>
+ <longitude>-74.010987</longitude>
+ <latitude>40.707764</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Verbotene Stadt, Peking, China</name>
+ <LookAt>
+ <longitude>116.390506</longitude>
+ <latitude>39.916649</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Reichstag, Berlin, Deutschland</name>
+ <LookAt>
+ <longitude>13.37554</longitude>
+ <latitude>52.518299</latitude>
+ </LookAt>
+ </Placemark>
+ <Placemark>
+ <name>Google Campus, USA</name>
+ <LookAt>
+ <longitude>-122.083893</longitude>
+ <latitude>37.422066</latitude>
+ </LookAt>
+ </Placemark>
+ </Folder>
+</Document>
+</kml>
--- /dev/null
+###############################################################################
+# Copyright (c) 2008 Rico Schulte, 3c5x9. All rights reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+###############################################################################
+
+from enigma import loadPic,ePixmap, getDesktop
+from Components.Pixmap import Pixmap
+from twisted.web.client import downloadPage
+from urllib import quote_plus
+from os import remove as os_remove, mkdir as os_mkdir
+from os.path import isdir as os_path_isdir, isfile as os_isfile
+
+from Components.AVSwitch import AVSwitch
+
+def getAspect():
+ val = AVSwitch().getAspectRatioSetting()
+ if val == 0:
+ r = 3
+ elif val == 1:
+ r = 3
+ elif val == 2:
+ r = 1
+ elif val == 3:
+ r = 1
+ elif val == 4:
+ r = 2
+ elif val == 5:
+ r = 2
+ elif val == 6:
+ r = 1
+ return r
+
+class WebPixmap(Pixmap):
+ def __init__(self,url=None,text=""):
+ self.url = url
+ self.default = "/usr/lib/enigma2/python/Plugins/Extensions/GoogleMaps/404.png"
+ self.cachedir = "/tmp/googlemaps/"
+ Pixmap.__init__(self)
+
+ def load(self,url=None):
+ self.url = url
+ tmpfile = self.cachedir+quote_plus(url)+".jpg"
+ if os_path_isdir(self.cachedir) is False:
+ print "cachedir not existing, creating it"
+ os_mkdir(self.cachedir)
+ if os_isfile(tmpfile):
+ self.tmpfile = tmpfile
+ self.onLoadFinished(None)
+ elif url is not None:
+ self.tmpfile = tmpfile
+ head = {
+ "Accept":"image/png,image/*;q=0.8,*/*;q=0.5",
+ "Accept-Language":"de",
+ "Accept-Encoding":"gzip,deflate",
+ "Accept-Charset":"ISO-8859-1,utf-8;q=0.7,*;q=0.7",
+ "Keep-Alive":"300",
+ "Referer":"http://maps.google.de/",
+ "Cookie:": "khcookie=fzwq1BaIQeBvxLjHsDGOezbBcCBU1T_t0oZKpA; PREF=ID=a9eb9d6fbca69f5f:TM=1219251671:LM=1219251671:S=daYFLkncM3cSOKsF; NID=15=ADVC1mqIWQWyJ0Wz655SirSOMG6pXP2ocdXwdfBZX56SgYaDXNNySnaOav-6_lE8G37iWaD7aBFza-gsX-kujQeH_8WTelqP9PpaEg0A_vZ9G7r50tzRBAZ-8GUwnEfl",
+ "Connection":"keep-alive"
+ }
+ agt = "Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.0.2) Gecko/2008091620 Firefox/3.0.2"
+ downloadPage(url,self.tmpfile,headers=head,agent=agt).addCallback(self.onLoadFinished).addErrback(self.onLoadFailed)
+ else:
+ if self.default is not None:
+ self.setPixmapFromFile(self.default)
+
+ def onLoadFinished(self,result):
+ self.setPixmapFromFile(self.tmpfile)
+ if os_isfile(self.tmpfile):
+ os_remove(self.tmpfile)
+
+ def onLoadFailed(self,error):
+ print "WebPixmap:onLoadFAILED",error
+ if self.default is not None:
+ self.setPixmapFromFile(self.default)
+ if os_isfile(self.tmpfile):
+ os_remove(self.tmpfile)
+
+ def setPixmapFromFile(self,file):
+ if self.instance is not None:
+ h = self.instance.size().height()
+ w = self.instance.size().width()
+ aspect = getAspect()
+ resize = 1
+ rotate = 0
+ background = 1
+ self.pixmap = loadPic(file, w,h,aspect,resize, rotate,background)
+ if self.pixmap is not None:
+ self.instance.setPixmap(self.pixmap.__deref__())
+
+
\ No newline at end of file
--- /dev/null
+#!/usr/bin/env python
+###############################################################################
+# $Id$
+#
+# Project: GDAL2Tiles, Google Summer of Code 2007 & 2008
+# Global Map Tiles Classes
+# Purpose: Convert a raster into TMS tiles, create KML SuperOverlay EPSG:4326,
+# generate a simple HTML viewers based on Google Maps and OpenLayers
+# Author: Klokan Petr Pridal, klokan at klokan dot cz
+# Web: http://www.klokan.cz/projects/gdal2tiles/
+#
+###############################################################################
+# Copyright (c) 2008 Klokan Petr Pridal. All rights reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+###############################################################################
+
+"""
+globalmaptiles.py
+
+Global Map Tiles as defined in Tile Map Service (TMS) Profiles
+==============================================================
+
+Functions necessary for generation of global tiles used on the web.
+It contains classes implementing coordinate conversions for:
+
+ - GlobalMercator (based on EPSG:900913 = EPSG:3785)
+ for Google Maps, Yahoo Maps, Microsoft Maps compatible tiles
+ - GlobalGeodetic (based on EPSG:4326)
+ for OpenLayers Base Map and Google Earth compatible tiles
+
+More info at:
+
+http://wiki.osgeo.org/wiki/Tile_Map_Service_Specification
+http://wiki.osgeo.org/wiki/WMS_Tiling_Client_Recommendation
+http://msdn.microsoft.com/en-us/library/bb259689.aspx
+http://code.google.com/apis/maps/documentation/overlays.html#Google_Maps_Coordinates
+
+Created by Klokan Petr Pridal on 2008-07-03.
+Google Summer of Code 2008, project GDAL2Tiles for OSGEO.
+
+In case you use this class in your product, translate it to another language
+or find it usefull for your project please let me know.
+My email: klokan at klokan dot cz.
+I would like to know where it was used.
+
+Class is available under the open-source GDAL license (www.gdal.org).
+"""
+
+import math
+
+class GlobalMercator(object):
+ """
+ TMS Global Mercator Profile
+ ---------------------------
+
+ Functions necessary for generation of tiles in Spherical Mercator projection,
+ EPSG:900913 (EPSG:gOOglE, Google Maps Global Mercator), EPSG:3785, OSGEO:41001.
+
+ Such tiles are compatible with Google Maps, Microsoft Virtual Earth, Yahoo Maps,
+ UK Ordnance Survey OpenSpace API, ...
+ and you can overlay them on top of base maps of those web mapping applications.
+
+ Pixel and tile coordinates are in TMS notation (origin [0,0] in bottom-left).
+
+ What coordinate conversions do we need for TMS Global Mercator tiles::
+
+ LatLon <-> Meters <-> Pixels <-> Tile
+
+ WGS84 coordinates Spherical Mercator Pixels in pyramid Tiles in pyramid
+ lat/lon XY in metres XY pixels Z zoom XYZ from TMS
+ EPSG:4326 EPSG:900913
+ .----. --------- -- TMS
+ / \ <-> | | <-> /----/ <-> Google
+ \ / | | /--------/ QuadTree
+ ----- --------- /------------/
+ KML, public WebMapService Web Clients TileMapService
+
+ What is the coordinate extent of Earth in EPSG:900913?
+
+ [-20037508.342789244, -20037508.342789244, 20037508.342789244, 20037508.342789244]
+ Constant 20037508.342789244 comes from the circumference of the Earth in meters,
+ which is 40 thousand kilometers, the coordinate origin is in the middle of extent.
+ In fact you can calculate the constant as: 2 * math.pi * 6378137 / 2.0
+ $ echo 180 85 | gdaltransform -s_srs EPSG:4326 -t_srs EPSG:900913
+ Polar areas with abs(latitude) bigger then 85.05112878 are clipped off.
+
+ What are zoom level constants (pixels/meter) for pyramid with EPSG:900913?
+
+ whole region is on top of pyramid (zoom=0) covered by 256x256 pixels tile,
+ every lower zoom level resolution is always divided by two
+ initialResolution = 20037508.342789244 * 2 / 256 = 156543.03392804062
+
+ What is the difference between TMS and Google Maps/QuadTree tile name convention?
+
+ The tile raster itself is the same (equal extent, projection, pixel size),
+ there is just different identification of the same raster tile.
+ Tiles in TMS are counted from [0,0] in the bottom-left corner, id is XYZ.
+ Google placed the origin [0,0] to the top-left corner, reference is XYZ.
+ Microsoft is referencing tiles by a QuadTree name, defined on the website:
+ http://msdn2.microsoft.com/en-us/library/bb259689.aspx
+
+ The lat/lon coordinates are using WGS84 datum, yeh?
+
+ Yes, all lat/lon we are mentioning should use WGS84 Geodetic Datum.
+ Well, the web clients like Google Maps are projecting those coordinates by
+ Spherical Mercator, so in fact lat/lon coordinates on sphere are treated as if
+ the were on the WGS84 ellipsoid.
+
+ From MSDN documentation:
+ To simplify the calculations, we use the spherical form of projection, not
+ the ellipsoidal form. Since the projection is used only for map display,
+ and not for displaying numeric coordinates, we don't need the extra precision
+ of an ellipsoidal projection. The spherical projection causes approximately
+ 0.33 percent scale distortion in the Y direction, which is not visually noticable.
+
+ How do I create a raster in EPSG:900913 and convert coordinates with PROJ.4?
+
+ You can use standard GIS tools like gdalwarp, cs2cs or gdaltransform.
+ All of the tools supports -t_srs 'epsg:900913'.
+
+ For other GIS programs check the exact definition of the projection:
+ More info at http://spatialreference.org/ref/user/google-projection/
+ The same projection is degined as EPSG:3785. WKT definition is in the official
+ EPSG database.
+
+ Proj4 Text:
+ +proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0
+ +k=1.0 +units=m +nadgrids=@null +no_defs
+
+ Human readable WKT format of EPGS:900913:
+ PROJCS["Google Maps Global Mercator",
+ GEOGCS["WGS 84",
+ DATUM["WGS_1984",
+ SPHEROID["WGS 84",6378137,298.2572235630016,
+ AUTHORITY["EPSG","7030"]],
+ AUTHORITY["EPSG","6326"]],
+ PRIMEM["Greenwich",0],
+ UNIT["degree",0.0174532925199433],
+ AUTHORITY["EPSG","4326"]],
+ PROJECTION["Mercator_1SP"],
+ PARAMETER["central_meridian",0],
+ PARAMETER["scale_factor",1],
+ PARAMETER["false_easting",0],
+ PARAMETER["false_northing",0],
+ UNIT["metre",1,
+ AUTHORITY["EPSG","9001"]]]
+ """
+
+ def __init__(self, tileSize=256):
+ "Initialize the TMS Global Mercator pyramid"
+ self.tileSize = tileSize
+ self.initialResolution = 2 * math.pi * 6378137 / self.tileSize
+ # 156543.03392804062 for tileSize 256 pixels
+ self.originShift = 2 * math.pi * 6378137 / 2.0
+ # 20037508.342789244
+
+ def LatLonToMeters(self, lat, lon ):
+ "Converts given lat/lon in WGS84 Datum to XY in Spherical Mercator EPSG:900913"
+
+ mx = lon * self.originShift / 180.0
+ my = math.log( math.tan((90 + lat) * math.pi / 360.0 )) / (math.pi / 180.0)
+
+ my = my * self.originShift / 180.0
+ return mx, my
+
+ def MetersToLatLon(self, mx, my ):
+ "Converts XY point from Spherical Mercator EPSG:900913 to lat/lon in WGS84 Datum"
+
+ lon = (mx / self.originShift) * 180.0
+ lat = (my / self.originShift) * 180.0
+
+ lat = 180 / math.pi * (2 * math.atan( math.exp( lat * math.pi / 180.0)) - math.pi / 2.0)
+ return lat, lon
+
+ def PixelsToMeters(self, px, py, zoom):
+ "Converts pixel coordinates in given zoom level of pyramid to EPSG:900913"
+
+ res = self.Resolution( zoom )
+ mx = px * res - self.originShift
+ my = py * res - self.originShift
+ return mx, my
+
+ def MetersToPixels(self, mx, my, zoom):
+ "Converts EPSG:900913 to pyramid pixel coordinates in given zoom level"
+
+ res = self.Resolution( zoom )
+ px = (mx + self.originShift) / res
+ py = (my + self.originShift) / res
+ return px, py
+
+ def PixelsToTile(self, px, py):
+ "Returns a tile covering region in given pixel coordinates"
+
+ tx = int( math.ceil( px / float(self.tileSize) ) - 1 )
+ ty = int( math.ceil( py / float(self.tileSize) ) - 1 )
+ return tx, ty
+
+ def PixelsToRaster(self, px, py, zoom):
+ "Move the origin of pixel coordinates to top-left corner"
+
+ mapSize = self.tileSize << zoom
+ return px, mapSize - py
+
+ def MetersToTile(self, mx, my, zoom):
+ "Returns tile for given mercator coordinates"
+
+ px, py = self.MetersToPixels( mx, my, zoom)
+ return self.PixelsToTile( px, py)
+
+ def TileBounds(self, tx, ty, zoom):
+ "Returns bounds of the given tile in EPSG:900913 coordinates"
+
+ minx, miny = self.PixelsToMeters( tx*self.tileSize, ty*self.tileSize, zoom )
+ maxx, maxy = self.PixelsToMeters( (tx+1)*self.tileSize, (ty+1)*self.tileSize, zoom )
+ return ( minx, miny, maxx, maxy )
+
+ def TileLatLonBounds(self, tx, ty, zoom ):
+ "Returns bounds of the given tile in latutude/longitude using WGS84 datum"
+
+ bounds = self.TileBounds( tx, ty, zoom)
+ minLat, minLon = self.MetersToLatLon(bounds[0], bounds[1])
+ maxLat, maxLon = self.MetersToLatLon(bounds[2], bounds[3])
+
+ return ( minLat, minLon, maxLat, maxLon )
+
+ def Resolution(self, zoom ):
+ "Resolution (meters/pixel) for given zoom level (measured at Equator)"
+
+ # return (2 * math.pi * 6378137) / (self.tileSize * 2**zoom)
+ return self.initialResolution / (2**zoom)
+
+ def ZoomForPixelSize(self, pixelSize ):
+ "Maximal scaledown zoom of the pyramid closest to the pixelSize."
+
+ for i in range(30):
+ if pixelSize > self.Resolution(i):
+ return i-1 if i!=0 else 0 # We don't want to scale up
+
+ def GoogleTile(self, tx, ty, zoom):
+ "Converts TMS tile coordinates to Google Tile coordinates"
+
+ # coordinate origin is moved from bottom-left to top-left corner of the extent
+ return tx, (2**zoom - 1) - ty
+
+ def QuadTree(self, tx, ty, zoom ):
+ "Converts TMS tile coordinates to Microsoft QuadTree"
+
+ quadKey = ""
+ ty = (2**zoom - 1) - ty
+ for i in range(zoom, 0, -1):
+ digit = 0
+ mask = 1 << (i-1)
+ if (tx & mask) != 0:
+ digit += 1
+ if (ty & mask) != 0:
+ digit += 2
+ quadKey += str(digit)
+
+ return quadKey
+
+#---------------------
+
+class GlobalGeodetic(object):
+ """
+ TMS Global Geodetic Profile
+ ---------------------------
+
+ Functions necessary for generation of global tiles in Plate Carre projection,
+ EPSG:4326, "unprojected profile".
+
+ Such tiles are compatible with Google Earth (as any other EPSG:4326 rasters)
+ and you can overlay the tiles on top of OpenLayers base map.
+
+ Pixel and tile coordinates are in TMS notation (origin [0,0] in bottom-left).
+
+ What coordinate conversions do we need for TMS Global Geodetic tiles?
+
+ Global Geodetic tiles are using geodetic coordinates (latitude,longitude)
+ directly as planar coordinates XY (it is also called Unprojected or Plate
+ Carre). We need only scaling to pixel pyramid and cutting to tiles.
+ Pyramid has on top level two tiles, so it is not square but rectangle.
+ Area [-180,-90,180,90] is scaled to 512x256 pixels.
+ TMS has coordinate origin (for pixels and tiles) in bottom-left corner.
+ Rasters are in EPSG:4326 and therefore are compatible with Google Earth.
+
+ LatLon <-> Pixels <-> Tiles
+
+ WGS84 coordinates Pixels in pyramid Tiles in pyramid
+ lat/lon XY pixels Z zoom XYZ from TMS
+ EPSG:4326
+ .----. ----
+ / \ <-> /--------/ <-> TMS
+ \ / /--------------/
+ ----- /--------------------/
+ WMS, KML Web Clients, Google Earth TileMapService
+ """
+
+ def __init__(self, tileSize = 256):
+ self.tileSize = tileSize
+
+ def LatLonToPixels(self, lat, lon, zoom):
+ "Converts lat/lon to pixel coordinates in given zoom of the EPSG:4326 pyramid"
+
+ res = 180 / 256.0 / 2**zoom
+ px = (180 + lat) / res
+ py = (90 + lon) / res
+ return px, py
+
+ def PixelsToTile(self, px, py):
+ "Returns coordinates of the tile covering region in pixel coordinates"
+
+ tx = int( math.ceil( px / float(self.tileSize) ) - 1 )
+ ty = int( math.ceil( py / float(self.tileSize) ) - 1 )
+ return tx, ty
+
+ def Resolution(self, zoom ):
+ "Resolution (arc/pixel) for given zoom level (measured at Equator)"
+
+ return 180 / 256.0 / 2**zoom
+ #return 180 / float( 1 << (8+zoom) )
+
+ def TileBounds(tx, ty, zoom):
+ "Returns bounds of the given tile"
+ res = 180 / 256.0 / 2**zoom
+ return (
+ tx*256*res - 180,
+ ty*256*res - 90,
+ (tx+1)*256*res - 180,
+ (ty+1)*256*res - 90
+ )
+
+
+
+"""
+if __name__ == "__main__":
+ import sys, os
+
+ def Usage(s = ""):
+ print "Usage: globalmaptiles.py [-profile 'mercator'|'geodetic'] zoomlevel lat lon [latmax lonmax]"
+ print
+ if s:
+ print s
+ print
+ print "This utility prints for given WGS84 lat/lon coordinates (or bounding box) the list of tiles"
+ print "covering specified area. Tiles are in the given 'profile' (default is Google Maps 'mercator')"
+ print "and in the given pyramid 'zoomlevel'."
+ print "For each tile several information is printed including bonding box in EPSG:900913 and WGS84."
+ sys.exit(1)
+
+ profile = 'mercator'
+ zoomlevel = None
+ lat, lon, latmax, lonmax = None, None, None, None
+ boundingbox = False
+
+ argv = sys.argv
+ i = 1
+ while i < len(argv):
+ arg = argv[i]
+
+ if arg == '-profile':
+ i = i + 1
+ profile = argv[i]
+
+ if zoomlevel is None:
+ zoomlevel = int(argv[i])
+ elif lat is None:
+ lat = float(argv[i])
+ elif lon is None:
+ lon = float(argv[i])
+ elif latmax is None:
+ latmax = float(argv[i])
+ elif lonmax is None:
+ lonmax = float(argv[i])
+ else:
+ Usage("ERROR: Too many parameters")
+
+ i = i + 1
+
+ if profile != 'mercator':
+ Usage("ERROR: Sorry, given profile is not implemented yet.")
+
+ if zoomlevel == None or lat == None or lon == None:
+ Usage("ERROR: Specify at least 'zoomlevel', 'lat' and 'lon'.")
+ if latmax is not None and lonmax is None:
+ Usage("ERROR: Both 'latmax' and 'lonmax' must be given.")
+
+ if latmax != None and lonmax != None:
+ if latmax < lat:
+ Usage("ERROR: 'latmax' must be bigger then 'lat'")
+ if lonmax < lon:
+ Usage("ERROR: 'lonmax' must be bigger then 'lon'")
+ boundingbox = (lon, lat, lonmax, latmax)
+
+ tz = zoomlevel
+ mercator = GlobalMercator()
+
+ mx, my = mercator.LatLonToMeters( lat, lon )
+ print "Spherical Mercator (ESPG:900913) coordinates for lat/lon: "
+ print (mx, my)
+ tminx, tminy = mercator.MetersToTile( mx, my, tz )
+
+ if boundingbox:
+ mx, my = mercator.LatLonToMeters( latmax, lonmax )
+ print "Spherical Mercator (ESPG:900913) cooridnate for maxlat/maxlon: "
+ print (mx, my)
+ tmaxx, tmaxy = mercator.MetersToTile( mx, my, tz )
+ else:
+ tmaxx, tmaxy = tminx, tminy
+
+ for ty in range(tminy, tmaxy+1):
+ for tx in range(tminx, tmaxx+1):
+ tilefilename = "%s/%s/%s" % (tz, tx, ty)
+ print tilefilename, "( TileMapService: z / x / y )"
+
+ gx, gy = mercator.GoogleTile(tx, ty, tz)
+ print "\tGoogle:", gx, gy
+ quadkey = mercator.QuadTree(tx, ty, tz)
+ print "\tQuadkey:", quadkey, '(',int(quadkey, 4),')'
+ bounds = mercator.TileBounds( tx, ty, tz)
+ print
+ print "\tEPSG:900913 Extent: ", bounds
+ wgsbounds = mercator.TileLatLonBounds( tx, ty, tz)
+ print "\tWGS84 Extent:", wgsbounds
+ print "\tgdalwarp -ts 256 256 -te %s %s %s %s %s %s_%s_%s.tif" % (
+ bounds[0], bounds[1], bounds[2], bounds[3], "<your-raster-file-in-epsg900913.ext>", tz, tx, ty)
+ print
+"""
\ No newline at end of file
--- /dev/null
+###############################################################################
+# Copyright (c) 2008 Rico Schulte, 3c5x9. All rights reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+###############################################################################
+
+from enigma import getDesktop,eSize
+from Plugins.Plugin import PluginDescriptor
+from Screens.Screen import Screen
+from Components.ActionMap import ActionMap
+from Components.Label import Label
+from Components.MenuList import MenuList
+from Components.config import config, ConfigSubList, ConfigSubsection, ConfigInteger, ConfigYesNo, ConfigText
+
+from Plugins.Extensions.GoogleMaps.KMLlib import RootFolder,KmlFolder,KmlPlace
+from Plugins.Extensions.GoogleMaps.WebPixmap import WebPixmap
+
+config.plugins.GoogleMaps = ConfigSubsection()
+config.plugins.GoogleMaps.position = ConfigSubsection()
+config.plugins.GoogleMaps.position.x = ConfigInteger(33)
+config.plugins.GoogleMaps.position.y = ConfigInteger(21)
+config.plugins.GoogleMaps.position.z = ConfigInteger(6)
+
+
+def applySkinVars(skin,dict):
+ for key in dict.keys():
+ try:
+ skin = skin.replace('{'+key+'}',dict[key])
+ except Exception,e:
+ print e,"@key=",key
+ return skin
+
+class GoogleMapsMainScreen(Screen):
+ raw_skin = """
+ <screen position="0,0" size="{screen.size}" title="GoogleMaps" flags="wfNoBorder">
+ <widget name="bg" position="0,0" size="{screen.size}" backgroundColor="white" zPosition="0"/>
+ <widget name="pic1" position="{pixmap1.pos}" size="{pixmap.size}" zPosition="1" />
+ <widget name="pic2" position="{pixmap2.pos}" size="{pixmap.size}" zPosition="1"/>
+ <widget name="pic3" position="{pixmap3.pos}" size="{pixmap.size}" zPosition="1"/>
+ <widget name="pic4" position="{pixmap4.pos}" size="{pixmap.size}" zPosition="1"/>
+ <widget name="pic5" position="{pixmap5.pos}" size="{pixmap.size}" zPosition="1"/>
+ <widget name="pic6" position="{pixmap6.pos}" size="{pixmap.size}" zPosition="1"/>
+ <widget name="pic7" position="{pixmap7.pos}" size="{pixmap.size}" zPosition="1"/>
+ <widget name="pic8" position="{pixmap8.pos}" size="{pixmap.size}" zPosition="1"/>
+ <widget name="pic9" position="{pixmap9.pos}" size="{pixmap.size}" zPosition="1"/>
+
+ <widget name="infopanel" position="{infopanel.pos}" size="{infopanel.size}" zPosition="0" backgroundColor="blue"/>
+ <widget name="posx" position="{posx.pos}" size="{posx.size}" font="{font}" zPosition="1" />
+ <widget name="posy" position="{posy.pos}" size="{posy.size}" font="{font}" zPosition="1" />
+ <widget name="posz" position="{posz.pos}" size="{posz.size}" font="{font}" zPosition="1" />
+ <widget name="placeslist" position="{placeslist.pos}" size="{placeslist.size}" zPosition="1"/>
+
+ </screen>
+ """
+ def __init__(self, session):
+ self.session = session
+ size_w = getDesktop(0).size().width()
+ size_h = getDesktop(0).size().height()
+ print "DESKTOPsize is",size_w,size_h
+ p_h = size_h/3
+
+ infopanel_width = size_w - (p_h*3)
+ infopanel_height = size_h
+ label_height = 30
+ font = "Regular;21"
+ self.dict = {
+
+ 'font': font,
+
+ 'screen.size': "%i,%i"%(size_w,size_h),
+ 'pixmap.size': '%i,%i'%(p_h,p_h),
+
+ 'pixmap1.pos': '0,0',
+ 'pixmap2.pos': '%i,0'%(p_h),
+ 'pixmap3.pos': '%i,0'%(p_h*2),
+
+ 'pixmap4.pos': '0,%i'%(p_h),
+ 'pixmap5.pos': '%i,%i'%(p_h,p_h),
+ 'pixmap6.pos': '%i,%i'%(p_h*2,p_h),
+
+ 'pixmap7.pos': '0,%i'%(p_h*2),
+ 'pixmap8.pos': '%i,%i'%(p_h,p_h*2),
+ 'pixmap9.pos': '%i,%i'%(p_h*2,p_h*2),
+
+ 'infopanel.pos': '%i,0'%(p_h*3),
+ 'infopanel.size': '%i,%i'%(infopanel_width,infopanel_height),
+
+ 'posx.pos': '%i,0'%(p_h*3),
+ 'posx.size': '%i,%i'%(infopanel_width,label_height),
+
+ 'posy.pos': '%i,%i'%(p_h*3,label_height),
+ 'posy.size': '%i,%i'%(infopanel_width,label_height),
+
+ 'posz.pos': '%i,%i'%(p_h*3,label_height*2),
+ 'posz.size': '%i,%i'%(infopanel_width,label_height),
+
+ 'placeslist.pos': '%i,%i'%(p_h*3,label_height*3),
+ 'placeslist.size': '%i,%i'%(infopanel_width,infopanel_height-(label_height*3)),
+
+ }
+ #print self.dict
+
+ self.skin = applySkinVars(GoogleMapsMainScreen.raw_skin,self.dict)
+ Screen.__init__(self, session)
+ self["infopanel"] = Label()
+ self["posx"] = Label("")
+ self["posy"] = Label("")
+ self["posz"] = Label("")
+ self["placeslist"] = MenuList([])
+
+ self["bg"] = Label()
+ self["pic1"] = WebPixmap()
+ self["pic2"] = WebPixmap()
+ self["pic3"] = WebPixmap()
+ self["pic4"] = WebPixmap()
+ self["pic5"] = WebPixmap()
+ self["pic6"] = WebPixmap()
+ self["pic7"] = WebPixmap()
+ self["pic8"] = WebPixmap()
+ self["pic9"] = WebPixmap()
+ self["setupActions"] = ActionMap(["OkCancelActions", "NumberActions","DirectionActions"],
+ {
+ "cancel": self.close,
+ "ok": self.keyOk,
+ "1": self.key1,
+ "2": self.key2,
+ "3": self.key3,
+ "4": self.key4,
+ "5": self.key5,
+ "6": self.key6,
+ "7": self.key7,
+ "8": self.key8,
+ "9": self.key9,
+ "0": self.key0,
+ }, -1)
+ self.onLayoutFinish.append(self.onLayoutFinished)
+
+ def buildMenuRoot(self):
+ list = []
+ root = RootFolder()
+ for i in root.getFiles("/usr/lib/enigma2/python/Plugins/Extensions/GoogleMaps/"):
+ l = lambda name,filepath: self.openFolderRoot(name,filepath)
+ list.append((i[0],i[1],l))
+ self["placeslist"].setList(list)
+
+ def openFolderRoot(self,name,filepath):
+ print "openFolderRoot",name,filepath
+ root = RootFolder()
+ folderx = root.getFolderFromFile(filepath)
+ list = []
+ l = lambda name,filepath: self.buildMenuRoot()
+ list.append(("..",filepath,l))
+ for folderx in folderx.getFolders():
+ l = lambda name,folder: self.openFolder(name,folder)
+ list.append(("+ "+folderx.name,folderx,l))
+
+ for placex in folderx.getPlacemarks():
+ l = lambda name,place: self.showPlace(name,place)
+ list.append((""+placex.name,placex,l))
+
+ self["placeslist"].setList(list)
+
+ def openFolder(self,name,foldery):
+ print "open Folder",name,foldery
+ list = []
+ if foldery.parent is None:
+ l = lambda name,folder: self.buildMenuRoot()
+ list.append(("..",None,l))
+ else:
+ l = lambda name,folder: self.openFolder(name,folder)
+ list.append(("..",foldery.parent,l))
+
+ for folderx in foldery.getFolders():
+ l = lambda name,folder: self.openFolder(name,folder)
+ list.append(("+ "+folderx.name,folderx,l))
+
+ for placex in foldery.getPlacemarks():
+ l = lambda name,place: self.showPlace(name,place)
+ list.append((""+placex.name,placex,l))
+
+ self["placeslist"].setList(list)
+
+ def showPlace(self,name,place):
+ #print "show Place",name,place
+ x,y,z = place.getTile(self.z)
+ self.setNewXYZ(x,y,z)
+
+ def onLayoutFinished(self):
+ self.buildMenuRoot()
+ self.setNewXYZ(config.plugins.GoogleMaps.position.x.value,
+ config.plugins.GoogleMaps.position.y.value,
+ config.plugins.GoogleMaps.position.z.value)
+
+ #################
+ def keyOk(self):
+ listentry = self["placeslist"].getCurrent()
+ if listentry is not None:
+ if listentry[1] is not None:
+ listentry[2](listentry[0],listentry[1])
+
+ def key1(self):
+ # northwest
+ self.setNewXYZ(self.x-1,self.y-1,self.z)
+
+ def key3(self):
+ # northeast
+ self.setNewXYZ(self.x+1,self.y-1,self.z)
+
+ def key7(self):
+ # southwest
+ self.setNewXYZ(self.x-1,self.y+1,self.z)
+
+ def key9(self):
+ # southeast
+ self.setNewXYZ(self.x+1,self.y+1,self.z)
+
+ #################
+ def key2(self):
+ # north
+ self.setNewXYZ(self.x,self.y-1,self.z)
+
+ def key8(self):
+ # south
+ self.setNewXYZ(self.x,self.y+1,self.z)
+
+ def key4(self):
+ # west
+ self.setNewXYZ(self.x-1,self.y,self.z)
+
+ def key6(self):
+ # east
+ self.setNewXYZ(self.x+1,self.y,self.z)
+
+ #################
+ def key5(self):
+ #zoom in
+ self.setNewXYZ(self.x*2,self.y*2+1,self.z+1)
+
+ def key0(self):
+ #zoom out
+ self.setNewXYZ(self.x/2,self.y/2,self.z-1)
+
+ #################
+ def setNewXYZ(self,x,y,z):
+ print x,y,z
+ if z<0 or z>=30:
+ return
+ self.x = x
+ self.y = y
+ self.z = z
+ config.plugins.GoogleMaps.position.x.value = x
+ config.plugins.GoogleMaps.position.y.value = y
+ config.plugins.GoogleMaps.position.z.value = z
+
+ self["posx"].setText(_('Pos.')+" X: "+str(x))
+ self["posy"].setText(_('Pos.')+" Y: "+str(y))
+ self["posz"].setText(_('Zoom')+" : "+str(z))
+
+ self["pic1"].load(self.getURL(x-1,y-1,z))
+ self["pic2"].load(self.getURL(x,y-1,z))
+ self["pic3"].load(self.getURL(x+1,y-1,z))
+ self["pic4"].load(self.getURL(x-1,y,z))
+ self["pic5"].load(self.getURL(x,y,z))
+ self["pic6"].load(self.getURL(x+1,y,z))
+ self["pic7"].load(self.getURL(x-1,y+1,z))
+ self["pic8"].load(self.getURL(x,y+1,z))
+ self["pic9"].load(self.getURL(x+1,y+1,z))
+
+ def getURL(self,x,y,z):
+ url = "http://khm1.google.com/kh?v=32&hl=de&x=%i&y=%i&z=%i"%(x,y,z)
+ return url
+
+ def getMapURL(self,x,y,z):
+ url = "http://mt1.google.com/mt?v=w2t.99&hl=de&x=%i&y=%i&z=%i&s=G"%(x,y,z)
+ return url
+
+def menu(menuid, **kwargs):
+ #starting from main menu
+ if menuid == "mainmenu":
+ return [(_("Google Maps"), main, "googlemaps", 46)]
+ return []
+
+def main(session,**kwargs):
+ session.openWithCallback(mainCB,GoogleMapsMainScreen)
+
+def mainCB():
+ print "mainCB"
+ config.plugins.GoogleMaps.position.x.save()
+ config.plugins.GoogleMaps.position.y.save()
+ config.plugins.GoogleMaps.position.z.save()
+
+def Plugins(path,**kwargs):
+ return [PluginDescriptor(
+ name="Google Maps",
+ description="browse google maps",
+ where = PluginDescriptor.WHERE_MENU,
+ fnc = menu
+ )]
\ No newline at end of file