OpenLayers OpenLayers

Changeset 5750

Show
Ignore:
Timestamp:
01/15/08 11:55:01 (1 year ago)
Author:
crschmidt
Message:

Improvements to Format class.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • sandbox/crschmidt/osm/lib/OpenLayers/Format/OSM.js

    r4938 r5750  
    99 * @requires OpenLayers/Geometry/LineString.js 
    1010 * @requires OpenLayers/Geometry/Polygon.js 
    11  * 
     11 */ 
     12 
     13/**   
    1214 * Class: OpenLayers.Format.OSM 
    13  * Read/write OSM parser. Create a new instance with the  
     15 * OSM parser. Create a new instance with the  
    1416 *     <OpenLayers.Format.OSM> constructor. 
    1517 * 
     
    2022     
    2123    /** 
     24     * APIProperty: checkTags 
     25     * {Boolean} Should tags be checked to determine whether something 
     26     * should be treated as a seperate node. Will slow down parsing. 
     27     * Default is false. 
     28     */ 
     29    checkTags: false, 
     30 
     31    /** 
     32     * Property: interestingTagsExclude 
     33     * {Array} List of tags to exclude from 'interesting' checks on nodes. 
     34     * Must be set when creating the format. Will only be used if checkTags 
     35     * is set. 
     36     */ 
     37    interestingTagsExclude: null,  
     38     
     39    /** 
     40     * APIProperty: areaTags 
     41     * {Array} List of tags indicating that something is an area.   
     42     * Must be set when creating the format. Will only be used if  
     43     * checkTags is true. 
     44     */ 
     45    areaTags: null,  
     46     
     47    /** 
    2248     * Constructor: OpenLayers.Format.OSM 
    2349     * Create a new parser for OSM. 
     
    2854     */ 
    2955    initialize: function(options) { 
    30         OpenLayers.Format.XML.prototype.initialize.apply(this, [options]); 
     56        var layer_defaults = { 
     57          'interestingTagsExclude': ['source', 'source_ref',  
     58              'source:ref', 'history', 'attribution', 'created_by'], 
     59          'areaTags': ['area', 'building', 'leisure', 'tourism', 'ruins', 
     60              'historic', 'landuse', 'military', 'natural', 'sport']  
     61        }; 
     62           
     63        layer_defaults = OpenLayers.Util.extend(layer_defaults, options); 
     64         
     65        var interesting = {}; 
     66        for (var i = 0; i < layer_defaults.interestingTagsExclude.length; i++) { 
     67            interesting[layer_defaults.interestingTagsExclude[i]] = true; 
     68        } 
     69        layer_defaults.interestingTagsExclude = interesting; 
     70         
     71        var area = {}; 
     72        for (var i = 0; i < layer_defaults.areaTags.length; i++) { 
     73            area[layer_defaults.areaTags[i]] = true; 
     74        } 
     75        layer_defaults.areaTags = area; 
     76         
     77        OpenLayers.Format.XML.prototype.initialize.apply(this, [layer_defaults]); 
    3178    }, 
    3279     
     
    4693        } 
    4794 
    48         // first, build up a node list 
    4995        var nodes = this.getNodes(doc); 
    5096        var ways = this.getWays(doc); 
    51         var geom_list = []; 
     97         
     98        // Geoms will contain at least ways.length entries. 
     99        var feat_list = new Array(ways.length); 
     100         
    52101        for (var i = 0; i < ways.length; i++) { 
    53             var point_list = []; 
     102            // We know the minimal of this one ahead of time. (Could be -1 
     103            // due to areas/polygons) 
     104            var point_list = new Array(ways[i].nodes.length); 
     105             
     106            var poly = this.isWayArea(ways[i]) ? 1 : 0;  
    54107            for (var j = 0; j < ways[i].nodes.length; j++) { 
    55108               var node = nodes[ways[i].nodes[j]]; 
    56                point_list.push(new OpenLayers.Geometry.Point(node.lon, node.lat)); 
    57                node['used'] = true;  
     109                
     110               var point = new OpenLayers.Geometry.Point(node.lon, node.lat); 
     111                
     112               // Since OSM is topological, we stash the node ID internally.  
     113               point.id = ways[i].nodes[j]; 
     114               point_list[j] = point; 
     115                
     116               // We don't display nodes if they're used inside other  
     117               // elements. 
     118               node.used = true;  
    58119            } 
    59             var feat = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.LineString(point_list), ways[i].tags); 
     120            var geometry = null; 
     121            if (poly) {  
     122                geometry = new OpenLayers.Geometry.Polygon( 
     123                    new OpenLayers.Geometry.LinearRing(point_list)); 
     124            } else {     
     125                geometry = new OpenLayers.Geometry.LineString(point_list); 
     126            }     
     127            var feat = new OpenLayers.Feature.Vector(geometry, 
     128                ways[i].tags); 
    60129            feat.fid = ways[i].id; 
    61             geom_list.push(feat)
     130            feat_list[i] = feat
    62131        }  
    63132        for (var node_id in nodes) { 
    64133            var node = nodes[node_id]; 
    65             if (!node['used']) { 
    66                 var tags = {}; 
    67                 var tag_list = node.node.getElementsByTagName("tag"); 
    68                 for (var j = 0; j < tag_list.length; j++) { 
    69                     tags[tag_list[j].getAttribute("k")] = tag_list[j].getAttribute("v"); 
    70                 }   
    71                 var feat = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(node['lon'], node['lat']),tags); 
     134            if (!node.used || this.checkTags) { 
     135                var tags = null; 
     136                 
     137                if (this.checkTags) { 
     138                    var result = this.getTags(node.node, true); 
     139                    if (node.used && !result[1]) { 
     140                        continue; 
     141                    } 
     142                    tags = result[0]; 
     143                } else {  
     144                    tags = this.getTags(node.node); 
     145                }     
     146                 
     147                var feat = new OpenLayers.Feature.Vector( 
     148                    new OpenLayers.Geometry.Point(node['lon'], node['lat']), 
     149                    tags); 
    72150                feat.fid = node_id;  
    73                 geom_list.push(feat); 
     151                feat_list.push(feat); 
    74152            }    
    75153            // Memory cleanup 
    76154            node.node = null; 
    77155        }         
    78         return geom_list; 
    79     }, 
    80  
     156        return feat_list; 
     157    }, 
     158 
     159    /** 
     160     * Method: getNodes 
     161     * Return the node items from a doc.   
     162     * 
     163     * Parameters: 
     164     * node - {DOMElement} node to parse tags from 
     165     */ 
    81166    getNodes: function(doc) { 
    82167        var node_list = doc.getElementsByTagName("node"); 
     
    84169        for (var i = 0; i < node_list.length; i++) { 
    85170            var node = node_list[i]; 
    86             nodes[node.getAttribute("id")] = { 
     171            var id = node.getAttribute("id"); 
     172            nodes[id] = { 
    87173                'lat': node.getAttribute("lat"), 
    88174                'lon': node.getAttribute("lon"), 
     
    93179    }, 
    94180 
     181    /** 
     182     * Method: getWays 
     183     * Return the way items from a doc.   
     184     * 
     185     * Parameters: 
     186     * node - {DOMElement} node to parse tags from 
     187     */ 
    95188    getWays: function(doc) { 
    96189        var way_list = doc.getElementsByTagName("way"); 
     
    99192            var way = way_list[i]; 
    100193            var way_object = { 
    101               'id': way.getAttribute("id"), 
    102               'nodes': [], 
    103               'tags': {} 
     194              id: way.getAttribute("id") 
    104195            }; 
    105196             
    106             var tag_list = way.getElementsByTagName("tag"); 
    107             for (var j = 0; j < tag_list.length; j++) { 
    108                 way_object.tags[tag_list[j].getAttribute("k")] = tag_list[j].getAttribute("v"); 
    109             }   
     197            way_object.tags = this.getTags(way); 
    110198             
    111199            var node_list = way.getElementsByTagName("nd"); 
     200             
     201            way_object.nodes = new Array(node_list.length); 
     202             
    112203            for (var j = 0; j < node_list.length; j++) { 
    113                 way_object.nodes.push(node_list[j].getAttribute("ref")); 
     204                way_object.nodes[j] = node_list[j].getAttribute("ref"); 
    114205            }   
    115206            return_ways.push(way_object); 
     
    117208        return return_ways;  
    118209         
    119     },     
    120  
     210    },   
     211     
     212    /** 
     213     * Method: getTags 
     214     * Return the tags list attached to a specific DOM element. 
     215     * 
     216     * Parameters: 
     217     * node - {DOMElement} node to parse tags from 
     218     * interesting_tags - {Boolean} whether the return from this function should 
     219     *    return a boolean indicating that it has 'interesting tags' --  
     220     *    tags like attribution and source are ignored. (To change the list 
     221     *    of tags, see interestingTagsExclude) 
     222     *  
     223     * Returns: 
     224     * tags - {Object} hash of tags 
     225     * interesting - {Boolean} if interesting_tags is passed, returns 
     226     *     whether there are any interesting tags on this element. 
     227     */ 
     228    getTags: function(dom_node, interesting_tags) { 
     229        var tag_list = dom_node.getElementsByTagName("tag"); 
     230        var tags = {}; 
     231        var interesting = false; 
     232        for (var j = 0; j < tag_list.length; j++) { 
     233            var key = tag_list[j].getAttribute("k"); 
     234            tags[key] = tag_list[j].getAttribute("v"); 
     235            if (interesting_tags) { 
     236                if (!this.interestingTagsExclude[key]) { 
     237                    interesting = true; 
     238                } 
     239            }     
     240        }   
     241        return interesting_tags ? [tags, interesting] : tags;      
     242    }, 
     243 
     244    /**  
     245     * Method: isWayArea 
     246     * Given a way object from getWays, check whether the tags and geometry 
     247     * indicate something is an area. 
     248     * 
     249     * Returns: 
     250     * {Boolean} 
     251     */ 
     252    isWayArea: function(way) {  
     253        var poly_shaped = false; 
     254        var poly_tags = false; 
     255         
     256        if (way.nodes[0] == way.nodes[way.nodes.length - 1]) { 
     257            poly_shaped = true; 
     258        } 
     259        if (this.checkTags) { 
     260            for(var key in way.tags) { 
     261                if (this.areaTags[key]) { 
     262                    poly_tags = true; 
     263                    break; 
     264                } 
     265            } 
     266        }     
     267        return poly_shaped && (this.checkTags ? poly_tags : true);             
     268    },   
    121269    CLASS_NAME: "OpenLayers.Format.OSM"  
    122270});