|
/* 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 |
|
* <OpenLayers.Format.GeoJSON> constructor. |
|
* |
|
* Inherits from: |
|
* - <OpenLayers.Format.JSON> |
|
*/ |
|
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 <OpenLayers.Feature.Vector>. If type is "Geometry", the input json |
|
* must represent a single geometry, and the return will be an |
|
* <OpenLayers.Geometry>. If type is "Feature", the input json must |
|
* represent a single feature, and the return will be an |
|
* <OpenLayers.Feature.Vector>. |
|
*/ |
|
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<len; ++i) { |
|
try { |
|
results.push(this.parseFeature(obj.features[i])); |
|
} catch(err) { |
|
results = null; |
|
OpenLayers.Console.error(err); |
|
} |
|
} |
|
break; |
|
default: |
|
try { |
|
var geom = this.parseGeometry(obj); |
|
results.push(new OpenLayers.Feature.Vector(geom)); |
|
} catch(err) { |
|
results = null; |
|
OpenLayers.Console.error(err); |
|
} |
|
} |
|
break; |
|
} |
|
} |
|
return results; |
|
}, |
|
|
|
/** |
|
* Method: isValidType |
|
* Check if a GeoJSON object is a valid representative of the given type. |
|
* |
|
* Returns: |
|
* {Boolean} The object is valid GeoJSON object of the given type. |
|
*/ |
|
isValidType: function(obj, type) { |
|
var valid = false; |
|
switch(type) { |
|
case "Geometry": |
|
if(OpenLayers.Util.indexOf( |
|
["Point", "MultiPoint", "LineString", "MultiLineString", |
|
"Polygon", "MultiPolygon", "Box", "GeometryCollection"], |
|
obj.type) == -1) { |
|
// unsupported geometry type |
|
OpenLayers.Console.error("Unsupported geometry type: " + |
|
obj.type); |
|
} else { |
|
valid = true; |
|
} |
|
break; |
|
case "FeatureCollection": |
|
// allow for any type to be converted to a feature collection |
|
valid = true; |
|
break; |
|
default: |
|
// for Feature types must match |
|
if(obj.type == type) { |
|
valid = true; |
|
} else { |
|
OpenLayers.Console.error("Cannot convert types from " + |
|
obj.type + " to " + type); |
|
} |
|
} |
|
return valid; |
|
}, |
|
|
|
/** |
|
* Method: parseFeature |
|
* Convert a feature object from GeoJSON into an |
|
* <OpenLayers.Feature.Vector>. |
|
* |
|
* Parameters: |
|
* obj - {Object} An object created from a GeoJSON object |
|
* |
|
* Returns: |
|
* {<OpenLayers.Feature.Vector>} 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 <OpenLayers.Geometry>. |
|
* |
|
* Parameters: |
|
* obj - {Object} An object created from a GeoJSON object |
|
* |
|
* Returns: |
|
* {<OpenLayers.Geometry>} 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<numGeom; ++i) { |
|
components[i] = this.parseGeometry.apply( |
|
this, [obj.geometries[i]] |
|
); |
|
} |
|
geometry = new OpenLayers.Geometry.Collection(components); |
|
collection = true; |
|
} else { |
|
if(!(obj.coordinates instanceof Array)) { |
|
throw "Geometry must have coordinates array: " + obj; |
|
} |
|
if(!this.parseCoords[obj.type.toLowerCase()]) { |
|
throw "Unsupported geometry type: " + obj.type; |
|
} |
|
try { |
|
geometry = this.parseCoords[obj.type.toLowerCase()].apply( |
|
this, [obj.coordinates] |
|
); |
|
} catch(err) { |
|
// deal with bad coordinates |
|
throw err; |
|
} |
|
} |
|
// We don't reproject collections because the children are reprojected |
|
// for us when they are created. |
|
if (this.internalProjection && this.externalProjection && !collection) { |
|
geometry.transform(this.externalProjection, |
|
this.internalProjection); |
|
} |
|
return geometry; |
|
}, |
|
|
|
/** |
|
* Property: parseCoords |
|
* Object with properties corresponding to the GeoJSON geometry types. |
|
* Property values are functions that do the actual parsing. |
|
*/ |
|
parseCoords: { |
|
/** |
|
* Method: parseCoords.point |
|
* Convert a coordinate array from GeoJSON into an |
|
* <OpenLayers.Geometry>. |
|
* |
|
* Parameters: |
|
* array - {Object} The coordinates array from the GeoJSON fragment. |
|
* |
|
* Returns: |
|
* {<OpenLayers.Geometry>} 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 |
|
* <OpenLayers.Geometry>. |
|
* |
|
* Parameters: |
|
* array {Object} The coordinates array from the GeoJSON fragment. |
|
* |
|
* Returns: |
|
* {<OpenLayers.Geometry>} A geometry. |
|
*/ |
|
"multipoint": function(array) { |
|
var points = []; |
|
var p = null; |
|
for(var i=0, len=array.length; i<len; ++i) { |
|
try { |
|
p = this.parseCoords["point"].apply(this, [array[i]]); |
|
} catch(err) { |
|
throw err; |
|
} |
|
points.push(p); |
|
} |
|
return new OpenLayers.Geometry.MultiPoint(points); |
|
}, |
|
|
|
/** |
|
* Method: parseCoords.linestring |
|
* Convert a coordinate array from GeoJSON into an |
|
* <OpenLayers.Geometry>. |
|
* |
|
* Parameters: |
|
* array - {Object} The coordinates array from the GeoJSON fragment. |
|
* |
|
* Returns: |
|
* {<OpenLayers.Geometry>} A geometry. |
|
*/ |
|
"linestring": function(array) { |
|
var points = []; |
|
var p = null; |
|
for(var i=0, len=array.length; i<len; ++i) { |
|
try { |
|
p = this.parseCoords["point"].apply(this, [array[i]]); |
|
} catch(err) { |
|
throw err; |
|
} |
|
points.push(p); |
|
} |
|
return new OpenLayers.Geometry.LineString(points); |
|
}, |
|
|
|
/** |
|
* Method: parseCoords.multilinestring |
|
* Convert a coordinate array from GeoJSON into an |
|
* <OpenLayers.Geometry>. |
|
* |
|
* Parameters: |
|
* array - {Object} The coordinates array from the GeoJSON fragment. |
|
* |
|
* Returns: |
|
* {<OpenLayers.Geometry>} A geometry. |
|
*/ |
|
"multilinestring": function(array) { |
|
var lines = []; |
|
var l = null; |
|
for(var i=0, len=array.length; i<len; ++i) { |
|
try { |
|
l = this.parseCoords["linestring"].apply(this, [array[i]]); |
|
} catch(err) { |
|
throw err; |
|
} |
|
lines.push(l); |
|
} |
|
return new OpenLayers.Geometry.MultiLineString(lines); |
|
}, |
|
|
|
/** |
|
* Method: parseCoords.polygon |
|
* Convert a coordinate array from GeoJSON into an |
|
* <OpenLayers.Geometry>. |
|
* |
|
|