[Adept Software Development] appengine service for google maps/earth (kml)

2 views
Skip to first unread message

Paul Marrington

unread,
Nov 15, 2009, 8:05:00 PM11/15/09
to adeptr...@googlegroups.com
[http://golfadept.com]

This example is called TripKML. It reads pre-recorded GeoPt records and generates KML for Google Maps/Earth. The basic webapp is as normal:



class TripKML(webapp.RequestHandler):

    def get(self):

        try:

            ...

        except DeadlineExceededError:

            self.response.clear()

            self.response.set_status(500)

            self.message("This operation could not be completed in time...")



application = webapp.WSGIApplication([('/service/tripKML', TripKML)], debug = True)

def main():

    run_wsgi_app(application)



if __name__ == '__main__':

    main()





First we parse the command line:



            self.traveller = User.fromId(int(self.request.get('traveller')))

            trip = self.request.get('trip')





As the code creates KML, tell the browser what do do with it:



        self.response.headers['Content-Type'] = 'application/vnd.google-earth.kml+xml'





I have attached my lightweight class for generating XML. You give it the root XML tag name and attributes. Wrap everything in a folder for clarity in the tree. The last line is XML to be inserted (saved as )



            rootElement = self.kml = xml('kml', xmlns = 'http://www.opengis.net/kml/2.2')

            self.kml = rootElement.Folder

            self.kml.name(trip)

            self.kml.Style.IconStyle(id = 'noteStyle').Icon.href(iconUrl)





My style is to read the records and have factory code to call methods based on the record type. Because most records will be of one or two types, I have cached the parser method:



            parsers = dict()

            query = Record.gql(

                'WHERE userId=:1 AND trip=:2 ORDER BY time', self.traveller.id, trip)

            for self.record in query:

                try:

                    parser = parsers[self.record.type]

                except KeyError:

                    method = self.record.type + "RecordProcessor";

                    parser = getattr(self, method, self.defaultRecordProcessor)

                    parsers[self.record.type] = parser

                parser()





A record type called "notes" generates a note indicated by an icon on the map:



    def notesRecordProcessor(self):

        self.kml.Placemark.name(self.record.title).styleUrl('noteStyle').\

            description(self.record.notes).Point.coordinates(

                "%f,%f" % (self.record.location.lon, self.record.location.lat))()





The “here” record processor does more work as it collects coordinates to make a line.

Back to the TripKml class, I also overlay kml generated by Picasa to display images:



            albums = Album.forTrip(self.traveller.id, trip)

            for album in albums:

                try:

          self.kml.NetworkLink.name(trip).Link.refreshMode('onInterval').\

              refreshInterval(3600).hreflang(\

              album.feedUri + '&alt=kml&kind=photo')

                except Exception, e:

                    logging.warning('Can\'t access Picasa album for trip %s: %s' % (trip.name, e.message))





The last thing we need to do is generate the KML and send it to the browser:



            self.response.out.write(str(self.kml))





I have attached TripKML.py as it is in use and xml.py for generating the XML.



--
Posted By Paul Marrington to Adept Software Development at 11/16/2009 11:05:00 AM
Reply all
Reply to author
Forward
0 new messages