/* Copyright (c) 2006-2010 by OpenLayers Contributors (see authors.txt for * full list of contributors). Published under the Clear BSD license. * See http://svn.openlayers.org/trunk/openlayers/license.txt for the * full text of the license. */ /** * @requires OpenLayers/Format/JSON.js * @requires OpenLayers/Feature/Vector.js * @requires OpenLayers/Geometry/Point.js * @requires OpenLayers/Geometry/MultiPoint.js * @requires OpenLayers/Geometry/LineString.js * @requires OpenLayers/Geometry/MultiLineString.js * @requires OpenLayers/Geometry/Polygon.js * @requires OpenLayers/Geometry/MultiPolygon.js * @requires OpenLayers/Console.js */ /** * Class: OpenLayers.Format.GeoJSON * Read and write GeoJSON. Create a new parser with the * constructor. * * Inherits from: * - */ OpenLayers.Format.GeoJSON = OpenLayers.Class(OpenLayers.Format.JSON, { /** * APIProperty: ignoreExtraDims * {Boolean} Ignore dimensions higher than 2 when reading geometry * coordinates. */ ignoreExtraDims: false, /** * Constructor: OpenLayers.Format.GeoJSON * Create a new parser for GeoJSON. * * Parameters: * options - {Object} An optional object whose properties will be set on * this instance. */ initialize: function(options) { OpenLayers.Format.JSON.prototype.initialize.apply(this, [options]); }, /** * APIMethod: read * Deserialize a GeoJSON string. * * Parameters: * json - {String} A GeoJSON string * type - {String} Optional string that determines the structure of * the output. Supported values are "Geometry", "Feature", and * "FeatureCollection". If absent or null, a default of * "FeatureCollection" is assumed. * filter - {Function} A function which will be called for every key and * value at every level of the final result. Each value will be * replaced by the result of the filter function. This can be used to * reform generic objects into instances of classes, or to transform * date strings into Date objects. * * Returns: * {Object} The return depends on the value of the type argument. If type * is "FeatureCollection" (the default), the return will be an array * of . If type is "Geometry", the input json * must represent a single geometry, and the return will be an * . If type is "Feature", the input json must * represent a single feature, and the return will be an * . */ read: function(json, type, filter) { type = (type) ? type : "FeatureCollection"; var results = null; var obj = null; if (typeof json == "string") { obj = OpenLayers.Format.JSON.prototype.read.apply(this, [json, filter]); } else { obj = json; } if(!obj) { OpenLayers.Console.error("Bad JSON: " + json); } else if(typeof(obj.type) != "string") { OpenLayers.Console.error("Bad GeoJSON - no type: " + json); } else if(this.isValidType(obj, type)) { switch(type) { case "Geometry": try { results = this.parseGeometry(obj); } catch(err) { OpenLayers.Console.error(err); } break; case "Feature": try { results = this.parseFeature(obj); results.type = "Feature"; } catch(err) { OpenLayers.Console.error(err); } break; case "FeatureCollection": // for type FeatureCollection, we allow input to be any type results = []; switch(obj.type) { case "Feature": try { results.push(this.parseFeature(obj)); } catch(err) { results = null; OpenLayers.Console.error(err); } break; case "FeatureCollection": for(var i=0, len=obj.features.length; i. * * Parameters: * obj - {Object} An object created from a GeoJSON object * * Returns: * {} A feature. */ parseFeature: function(obj) { var feature, geometry, attributes, bbox; attributes = (obj.properties) ? obj.properties : {}; bbox = (obj.geometry && obj.geometry.bbox) || obj.bbox; try { geometry = this.parseGeometry(obj.geometry); } catch(err) { // deal with bad geometries throw err; } feature = new OpenLayers.Feature.Vector(geometry, attributes); if(bbox) { feature.bounds = OpenLayers.Bounds.fromArray(bbox); } if(obj.id) { feature.fid = obj.id; } return feature; }, /** * Method: parseGeometry * Convert a geometry object from GeoJSON into an . * * Parameters: * obj - {Object} An object created from a GeoJSON object * * Returns: * {} A geometry. */ parseGeometry: function(obj) { if (obj == null) { return null; } var geometry, collection = false; if(obj.type == "GeometryCollection") { if(!(obj.geometries instanceof Array)) { throw "GeometryCollection must have geometries array: " + obj; } var numGeom = obj.geometries.length; var components = new Array(numGeom); for(var i=0; i. * * Parameters: * array - {Object} The coordinates array from the GeoJSON fragment. * * Returns: * {} A geometry. */ "point": function(array) { if (this.ignoreExtraDims == false && array.length != 2) { throw "Only 2D points are supported: " + array; } return new OpenLayers.Geometry.Point(array[0], array[1]); }, /** * Method: parseCoords.multipoint * Convert a coordinate array from GeoJSON into an * . * * Parameters: * array {Object} The coordinates array from the GeoJSON fragment. * * Returns: * {} A geometry. */ "multipoint": function(array) { var points = []; var p = null; for(var i=0, len=array.length; i. * * Parameters: * array - {Object} The coordinates array from the GeoJSON fragment. * * Returns: * {} A geometry. */ "linestring": function(array) { var points = []; var p = null; for(var i=0, len=array.length; i. * * Parameters: * array - {Object} The coordinates array from the GeoJSON fragment. * * Returns: * {} A geometry. */ "multilinestring": function(array) { var lines = []; var l = null; for(var i=0, len=array.length; i. * * Returns: * {} A geometry. */ "polygon": function(array) { var rings = []; var r, l; for(var i=0, len=array.length; i. * * Parameters: * array - {Object} The coordinates array from the GeoJSON fragment. * * Returns: * {} A geometry. */ "multipolygon": function(array) { var polys = []; var p = null; for(var i=0, len=array.length; i. * * Parameters: * array - {Object} The coordinates array from the GeoJSON fragment. * * Returns: * {} A geometry. */ "box": function(array) { if(array.length != 2) { throw "GeoJSON box coordinates must have 2 elements"; } return new OpenLayers.Geometry.Polygon([ new OpenLayers.Geometry.LinearRing([ new OpenLayers.Geometry.Point(array[0][0], array[0][1]), new OpenLayers.Geometry.Point(array[1][0], array[0][1]), new OpenLayers.Geometry.Point(array[1][0], array[1][1]), new OpenLayers.Geometry.Point(array[0][0], array[1][1]), new OpenLayers.Geometry.Point(array[0][0], array[0][1]) ]) ]); } }, /** * APIMethod: write * Serialize a feature, geometry, array of features into a GeoJSON string. * * Parameters: * obj - {Object} An , , * or an array of features. * pretty - {Boolean} Structure the output with newlines and indentation. * Default is false. * * Returns: * {String} The GeoJSON string representation of the input geometry, * features, or array of features. */ write: function(obj, pretty) { var geojson = { "type": null }; if(obj instanceof Array) { geojson.type = "FeatureCollection"; var numFeatures = obj.length; geojson.features = new Array(numFeatures); for(var i=0; i} * * Returns: * {Object} An object which can be assigned to the crs property * of a GeoJSON object. */ createCRSObject: function(object) { var proj = object.layer.projection.toString(); var crs = {}; if (proj.match(/epsg:/i)) { var code = parseInt(proj.substring(proj.indexOf(":") + 1)); if (code == 4326) { crs = { "type": "OGC", "properties": { "urn": "urn:ogc:def:crs:OGC:1.3:CRS84" } }; } else { crs = { "type": "EPSG", "properties": { "code": code } }; } } return crs; }, /** * Property: extract * Object with properties corresponding to the GeoJSON types. * Property values are functions that do the actual value extraction. */ extract: { /** * Method: extract.feature * Return a partial GeoJSON object representing a single feature. * * Parameters: * feature - {} * * Returns: * {Object} An object representing the point. */ 'feature': function(feature) { var geom = this.extract.geometry.apply(this, [feature.geometry]); return { "type": "Feature", "id": feature.fid == null ? feature.id : feature.fid, "properties": feature.attributes, "geometry": geom }; }, /** * Method: extract.geometry * Return a GeoJSON object representing a single geometry. * * Parameters: * geometry - {} * * Returns: * {Object} An object representing the geometry. */ 'geometry': function(geometry) { if (geometry == null) { return null; } if (this.internalProjection && this.externalProjection) { geometry = geometry.clone(); geometry.transform(this.internalProjection, this.externalProjection); } var geometryType = geometry.CLASS_NAME.split('.')[2]; var data = this.extract[geometryType.toLowerCase()].apply(this, [geometry]); var json; if(geometryType == "Collection") { json = { "type": "GeometryCollection", "geometries": data }; } else { json = { "type": geometryType, "coordinates": data }; } return json; }, /** * Method: extract.point * Return an array of coordinates from a point. * * Parameters: * point - {} * * Returns: * {Array} An array of coordinates representing the point. */ 'point': function(point) { return [point.x, point.y]; }, /** * Method: extract.multipoint * Return an array of point coordinates from a multipoint. * * Parameters: * multipoint - {} * * Returns: * {Array} An array of point coordinate arrays representing * the multipoint. */ 'multipoint': function(multipoint) { var array = []; for(var i=0, len=multipoint.components.length; i} * * Returns: * {Array} An array of coordinate arrays representing * the linestring. */ 'linestring': function(linestring) { var array = []; for(var i=0, len=linestring.components.length; i} * * Returns: * {Array} An array of linestring arrays representing * the multilinestring. */ 'multilinestring': function(multilinestring) { var array = []; for(var i=0, len=multilinestring.components.length; i} * * Returns: * {Array} An array of linear ring arrays representing the polygon. */ 'polygon': function(polygon) { var array = []; for(var i=0, len=polygon.components.length; i} * * Returns: * {Array} An array of polygon arrays representing * the multipolygon */ 'multipolygon': function(multipolygon) { var array = []; for(var i=0, len=multipolygon.components.length; i} * * Returns: * {Array} An array of geometry objects representing the geometry * collection. */ 'collection': function(collection) { var len = collection.components.length; var array = new Array(len); for(var i=0; i