Changeset 3362


Ignore:
Timestamp:
11/02/08 10:29:34 (12 years ago)
Author:
mkochan
Message:

Made StationConvertor? class use the Station.py module.

Location:
DPPP/kml/csml2kml/python
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • DPPP/kml/csml2kml/python/csml2kml/KMLDocument.py

    r3302 r3362  
    11from cElementTree import ElementTree, Element, SubElement, XML 
    22 
     3class KMLElement: 
     4    ''' 
     5    Abstract class, representing any element of a KML document -- i.e. anything contained *within* 
     6    the <kml:Document> element. 
     7    ''' 
     8 
     9    def build(self): 
     10        ''' 
     11        It is required that each KMLElement instance is able to build() itself into an ElementTree.Element 
     12        instance of KML, which it represents. 
     13        ''' 
     14        raise NotImplementedError("Abstract method, to be overriden by child classes") 
     15 
    316class KMLDocument: 
    417    ''' 
    518    Wraps around a whole KML document and makes it possible to save it to a file directly. 
    6     Does *not* represent merely the <kml:Document> tag, but also the wrapping <kml:kml> tag. 
     19    Represent the <kml:Document>, so that the method build() builds the kml:Document element, 
     20    but also contains the method save() that allows saving that to a file, wrapped within the <kml> header. 
    721    ''' 
    822 
     
    1327        self.elements = [] 
    1428 
     29    def build(self): 
     30 
     31        # Create the <Document> an element to hold the document 
     32        documentElement = Element('Document') 
     33        SubElement(documentElement, 'name').text = self.name 
     34        SubElement(documentElement, 'open').text = '0' 
     35 
     36        # Build the associated styles 
     37        for style in self.styles: 
     38            documentElement.append( style.build() ) 
     39 
     40        # Build the sub-elements 
     41        for element in self.elements: 
     42            documentElement.append( element.build() ) 
     43         
     44        return documentElement 
     45         
    1546    def save(self, outputFilename): 
    1647        ''' 
     
    3465                    elem.tail = i 
    3566 
    36         # Create an element to hold the document 
    37         self.documentElement = Element('Document') 
    38         SubElement(self.documentElement, 'name').text = self.name 
    39         SubElement(self.documentElement, 'open').text = '0' 
    40  
    41         # Build the associated styles 
    42         for style in self.styles: 
    43             self.documentElement.append( style.build() ) 
    44  
    45         # Build the sub-elements 
    46         for element in self.elements: 
    47             self.documentElement.append( element.build() ) 
     67        # Build the Document element 
     68        documentElement = self.build() 
    4869 
    4970        # Attach the Document element as a subelement of a root 'kml' element 
    5071        rootElement=Element('kml', xmlns='http://earth.google.com/kml/2.2') 
    51         rootElement.append(self.documentElement) 
     72        rootElement.append(documentElement) 
    5273        _indentXML(rootElement) 
    5374 
     
    5778        elementTree.write(kmlFile) 
    5879        kmlFile.close() 
    59  
    60 class KMLElement: 
    61     ''' 
    62     Abstract class, representing any element of a KML document -- i.e. anything contained *within* 
    63     the <kml:Document> element. 
    64     ''' 
    65  
    66     def build(self): 
    67         ''' 
    68         It is required that each KMLElement instance is able to build() itself into an ElementTree.Element 
    69         instance of KML, which it represents. 
    70         ''' 
    71         raise NotImplementedError("Abstract method, to be overriden by child classes") 
    7280 
    7381class KMLStyle(KMLElement): 
  • DPPP/kml/csml2kml/python/csml2kml/Station.py

    r3327 r3362  
    55that contain *specifically* <np:Station> elements! 
    66''' 
     7 
     8from cElementTree import XML 
    79 
    810class NPStation: 
     
    1820        self.lon = lon; self.lat = lat 
    1921 
    20     def parseString(str): 
     22    def parseString(self, str): 
    2123        stationElement = XML(str) 
    2224        self.parseXML(stationElement) 
    2325 
    24     def parseXML(stationElement): 
     26    def parseXML(self, stationElement): 
    2527        (stationNameElement, stationIDElement, locationElement) = stationElement.getchildren() 
    2628        pointElement = locationElement.getchildren()[0] 
     
    3840        self.stations = [] 
    3941 
    40     def parseString(str): 
     42    def parseString(self, str): 
    4143        ''' 
    4244        Parse in the <wfs:FeatureCollection> element returned from GeoServer, save individual stations. 
     
    4648        self.parseXML(featureCollectionElement) 
    4749 
    48     def parseXML(featureCollectionElement): 
     50    def parseXML(self, featureCollectionElement): 
    4951        ''' 
    5052        Parse in the <wfs:FeatureCollection> element returned from GeoServer, save individual stations. 
  • DPPP/kml/csml2kml/python/csml2kml/StationConvertor.py

    r3327 r3362  
    88from QuadTree import * 
    99from utils import wget 
    10  
     10from Station import NPStation, WFSStationCollection 
    1111 
    1212class StationConvertor: 
     
    1717     
    1818    def __init__(self, config, kmlFilename): 
     19        '''Initialize the convertor and set it up according to the config file.''' 
     20         
    1921        self.config = config 
    2022        self.kmlFilename = kmlFilename 
     23 
     24        # Read config document name 
     25        self.documentName = self.config.find('name').text 
     26 
     27        # URL of GeoServer to get a <wfs:StationCollection> from 
     28        self.url = self.config.find('GeoServerRequest/URL').text 
     29 
     30        # Get template for placemark balloons; create a KML style for placemarks 
     31        self.balloonTemplate = self.config.find('GeoServerRequest/BalloonTemplate').text 
     32        self.placemarkKmlStyle = createDefaultPlacemarKMLStyle(balloonTemplate = self.balloonTemplate) 
     33 
     34        # Initialize placemark data -- i.e. values to be substituted for placeholders in the balloon template 
     35        self.stationData = {} 
     36        data = self.config.findall('GeoServerRequest/StationData/Datum') 
     37        for datum in data: 
     38            datumName = datum.get('name') 
     39            datumValue = datum.text 
     40            self.stationData[datumName] = datumValue 
     41 
     42        # Should we use KML regions? (recommended for high number of stations) 
     43        self.useSections = self.config.find('UseRegions').text == 'yes' 
     44 
     45        # Create a KML style to be used for holding a KML folder hierarchy in a folder that can't open 
     46        self.lockedFolderStyle = KMLStyle('locked_folder_style', listItemType = 'checkHideChildren') 
     47 
     48    def _npStationToKmlPlacemark(self, npStation): 
     49        '''Converts a Station.NPStation object into it's KMLDocument.KMLPlacemark representation''' 
     50        return KMLPlacemark(npStation.id, npStation.desc, npStation.lon, npStation.lat, 
     51                            styleID = self.placemarkKmlStyle.id, data = self.stationData 
     52                            ) 
     53 
     54    def _buildKmlDocumentDirectly(self, kmlDocument, npStations): 
     55        ''' 
     56        Returns an object of the KMLDocument class, kmlDocument, which will contain each station 
     57        represented by a placemark directly contained in the document (i.e. no intermediate folders). 
     58        ''' 
     59        for npStation in npStations: 
     60            kmlDocument.elements.append( self._npStationToKmlPlacemark(npStation) ) 
     61        return kmlDocument 
     62 
     63    def _buildKmlDocumentUsingSections(self, kmlDocument, npStations): 
     64        ''' 
     65        Returns an object of the KMLDocument class, kmlDocument, which contains the stations 
     66        organized into a hierarchy of folders, each containing ever smaller section of land.  
     67        The root of this hierarchy, a KMLFolder object, gets attached to the document, 
     68        and is "closed" i.e. it is not possible to open it in Google Earth's list view. 
     69        ''' 
     70 
     71        def _quadTreeToKMLFolder(t): 
     72            ''' 
     73            Convert the quad-tree into a KMLElement instance being a folder hierarchy with placemark leaves. 
     74            ''' 
     75            if isinstance(t, NilLeaf):                      # Do nothing 
     76                pass 
     77            elif isinstance(t, LocLeaf):                    # Create a folder with an embedded region and placemarks 
     78                kmlRegion = KMLRegion(t.bbox.west, t.bbox.south, t.bbox.east, t.bbox.north) 
     79                kmlFolder = KMLFolder(repr(t.bbox), [], region = kmlRegion) 
     80                for location in t.locations: 
     81                    npStation = location.obj 
     82                    kmlPlacemark = self._npStationToKmlPlacemark(npStation) 
     83                    kmlFolder.children.append(kmlPlacemark) 
     84                return kmlFolder 
     85            elif isinstance(t, Node):                       # Create a folder containing nested elements 
     86                kmlRegion = KMLRegion(t.bbox.west, t.bbox.south, t.bbox.east, t.bbox.north) 
     87                kmlFolder = KMLFolder(repr(t.bbox), [], region = kmlRegion) 
     88                for i in t.children: 
     89                    kmlChild = _quadTreeToKMLFolder(i) 
     90                    if kmlChild: 
     91                        kmlFolder.children.append(kmlChild) 
     92                return kmlFolder 
     93 
     94        # Create a list of locations (that is, of QuadTree.Location objects), associated with the stations; 
     95        # each location will also hold the npStation object it refers to. 
     96        locations = [] 
     97        for npStation in npStations: 
     98            locations.append( Location(npStation.lon, npStation.lat, npStation) ) 
     99 
     100        # Build a quad-tree from the locations, and convert it into a KMLFolder object. 
     101        quadTree = build_quadtree(locations) 
     102        kmlFolder = _quadTreeToKMLFolder(quadTree) 
     103 
     104        # Add kmlFolder to the current document 
     105        kmlDocument.elements.append(kmlFolder) 
     106 
     107        # Make the folder follow the "locked folder" style 
     108        kmlDocument.styles.append(self.lockedFolderStyle) 
     109        kmlFolder.styleID = self.lockedFolderStyle.id 
     110 
     111        return kmlDocument 
    21112 
    22113    def convert(self): 
     
    29120        ''' 
    30121 
    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) 
     122        # Get a collection of stations from a GeoServer, and put the stations into a list 
     123        geoServerResponse = wget(self.url) 
     124        wfsStationsCollection = WFSStationCollection() 
     125        wfsStationsCollection.parseString(geoServerResponse) 
     126        npStations = wfsStationsCollection.stations 
    44127 
    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) 
     128        # Create a KML document and attach the stations, either directly or using KML regions 
     129        kmlDocument = KMLDocument(self.documentName, [self.placemarkKmlStyle]) 
     130        if self.useSections: 
     131            kmlDocument = self._buildKmlDocumentUsingSections(kmlDocument, npStations) 
    130132        else: 
    131             kmlDocument = _buildKmlDocumentDirectly(kmlDocument, stations, placemarkKmlStyle, stationData) 
     133            kmlDocument = self._buildKmlDocumentDirectly(kmlDocument, npStations) 
    132134 
    133135        # Save the KML document 
  • DPPP/kml/csml2kml/python/csml2kml/tests/testStationConvertor.py

    r3323 r3362  
    99 
    1010# Do the conversion 
    11 convertor = StationConvertor(config, '../../../output/exampleps_stations.2.xml') 
     11convertor = StationConvertor(config, '../../../output/exampleps_stations.3.xml') 
    1212convertor.convert() 
  • DPPP/kml/csml2kml/python/notes.txt

    r3327 r3362  
    88|| KMLDocument.py / 
    99 
    10 [O] Make KMLDocument descended from KMLElement, hence add method KMLDocument.build() -- builds only the <kml:Document> 
    11     element -- but also keep KMLDocument.save(filename), which saves to a file with the <kml> wrapping. 
    12     Rename KMLDocument.py to KMLElement.py. 
     10[O] Rename KMLDocument.py to KML.py. 
    1311 
    1412---------------------------------------------------------------------------------------------------------------------------- 
    1513|| Station.py / 
    1614 
    17 [O] Write tests for both classes inside; rename Station.py to NPStation.py; make StationConvertor.py and 
    18     psOntoWMS.py use NPStation.py.  
     15[O] Write tests for both classes inside; make psOntoWMS.py use NPStation.py.  
    1916     
    2017---------------------------------------------------------------------------------------------------------------------------- 
Note: See TracChangeset for help on using the changeset viewer.