source: DPPP/kml/csml2kml/python/csml2kml/StationConvertor.py @ 3327

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/DPPP/kml/csml2kml/python/csml2kml/StationConvertor.py@3327
Revision 3327, 6.6 KB checked in by mkochan, 13 years ago (diff)

Created module Station.py (but untested)

Line 
1from cElementTree import ElementTree, Element, SubElement, XML
2from pylab import *
3from datetime import datetime, timedelta
4import re
5import csml
6import urllib
7from KMLDocument import *
8from QuadTree import *
9from utils import wget
10
11
12class StationConvertor:
13    '''
14    Converter from GML+CSML to KML.
15    Contains functionality for converting GML containing a collection of Station elements into KML.
16    '''
17   
18    def __init__(self, config, kmlFilename):
19        self.config = config
20        self.kmlFilename = kmlFilename
21
22    def convert(self):
23        '''
24        Convert GML input from GeoServer (containing the <Station> tags with station information)
25        to the KML representation.
26        [NOTE] At the moment, since the <Station> GML-feature element does not contain a list of CSML features,
27               the output of this code is not entirely correct. In particular, the HTTP reference to the grapher web-service
28               cannot be correctly determined.
29        '''
30
31        def _parseGMLStationsCollection(textGml):
32            '''
33            Parse the GML returned from GeoServer and yield Station objects with info about each station.
34            '''
35            root = XML(textGml)
36            featureCollectionElement = root
37            for featureMember in featureCollectionElement.getchildren():
38                stationElement = featureMember.getchildren()[0]
39                (stationNameElement, stationIDElement, locationElement) = stationElement.getchildren()
40                pointElement = locationElement.getchildren()[0]
41                posElement = pointElement.getchildren()[0]
42                (lon,lat) = map(float, posElement.text.split())
43                yield Station(stationElement.get('{http://www.opengis.net/gml}id'), stationNameElement.text, lon, lat)
44
45        def _buildKmlDocumentDirectly(kmlDocument, stations, placemarkKmlStyle, stationData):
46            '''
47            Returns an object of the KMLDocument class, kmlDocument, which will contain each station
48            represented by a placemark directly contained in the document (i.e. no intermediate folders).
49            '''
50            for station in stations:
51                kmlStation = KMLPlacemark(station.id, station.desc, station.lon, station.lat,
52                                          styleID = placemarkKmlStyle.id, data = stationData
53                                          )
54                kmlDocument.elements.append(kmlStation)
55            return kmlDocument
56
57        def _buildKmlDocumentUsingSections(kmlDocument, stations, placemarkKmlStyle, stationData):
58            '''
59            Returns an object of the KMLDocument class, kmlDocument, which contains the stations
60            organized into a hierarchy of folders, each containing ever smaller section of land.
61            The root of this hierarchy, a KMLFolder object, gets attached to the document,
62            and is "closed" i.e. it is not possible to open it in Google Earth's list view.
63            '''
64
65            def _quadTreeToKMLFolder(t):
66                '''
67                Convert the quad-tree into a KMLElement instance being a folder hierarchy with placemark leaves.
68                '''
69                if isinstance(t, NilLeaf):                      # Do nothing
70                    pass
71                elif isinstance(t, LocLeaf):                    # Create a folder with an embedded region and placemarks
72                    kmlRegion = KMLRegion(t.bbox.west, t.bbox.south, t.bbox.east, t.bbox.north)
73                    kmlFolder = KMLFolder(repr(t.bbox), [], region = kmlRegion)
74                    for location in t.locations:
75                        station = location.obj
76                        kmlPlacemark = KMLPlacemark(
77                            station.desc, station.desc, station.lon, station.lat,
78                            styleID = placemarkKmlStyle.id, data = stationData
79                            )
80                        kmlFolder.children.append(kmlPlacemark)
81                    return kmlFolder
82                elif isinstance(t, Node):                       # Create a folder containing nested elements
83                    kmlRegion = KMLRegion(t.bbox.west, t.bbox.south, t.bbox.east, t.bbox.north)
84                    kmlFolder = KMLFolder(repr(t.bbox), [], region = kmlRegion)
85                    for i in t.children:
86                        kmlChild = _quadTreeToKMLFolder(i)
87                        if kmlChild:
88                            kmlFolder.children.append(kmlChild)
89                    return kmlFolder
90           
91            locations = []
92            for station in stations:
93                locations.append( Location(station.lon, station.lat, station) )
94            quadTree = build_quadtree(locations)
95            kmlFolder = _quadTreeToKMLFolder(quadTree)
96
97            lockedFolderStyle = KMLStyle('locked_folder_style', listItemType = 'checkHideChildren')
98            kmlFolder.styleID = lockedFolderStyle.id
99            kmlDocument.styles.append(lockedFolderStyle)
100
101            kmlDocument.elements.append(kmlFolder)
102            return kmlDocument
103
104        #-----------------------------------------------------------------------------
105
106        # Read conversion configuration
107        documentName = self.config.find('name').text
108        url = self.config.find('GeoServerRequest/URL').text
109        balloonTemplate = self.config.find('GeoServerRequest/BalloonTemplate').text
110        stationData = {}
111        data = self.config.findall('GeoServerRequest/StationData/Datum')
112        for datum in data:
113            datumName = datum.get('name')
114            datumValue = datum.text
115            stationData[datumName] = datumValue
116        useSections = self.config.find('UseRegions').text == 'yes'
117
118        # Read in GML containing the stations, and extract them into a list of Station objects
119        textGml = wget(url)
120        stations = _parseGMLStationsCollection(textGml)
121
122        # Create a KML style for each station/placemark -- can contain appropriate HTML balloon template
123        placemarkKmlStyle = createDefaultPlacemarKMLStyle(balloonTemplate = balloonTemplate)
124
125        # Create a KML document and attach the stations either directly to it, or using a folder hierarchy
126        # of KML sections (derived by means of quad-tree)
127        kmlDocument = KMLDocument(documentName, [placemarkKmlStyle])
128        if useSections:
129            kmlDocument = _buildKmlDocumentUsingSections(kmlDocument, stations, placemarkKmlStyle, stationData)
130        else:
131            kmlDocument = _buildKmlDocumentDirectly(kmlDocument, stations, placemarkKmlStyle, stationData)
132
133        # Save the KML document
134        kmlDocument.save(self.kmlFilename)
Note: See TracBrowser for help on using the repository browser.