/* 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.js
* @requires OpenLayers/Feature/Vector.js
*/
/**
* Class: OpenLayers.Format.WKT
* Class for reading and writing Well-Known Text. Create a new instance
* with the <OpenLayers.Format.WKT> constructor.
*
* Inherits from:
* - <OpenLayers.Format>
*/
OpenLayers.Format.WKT = OpenLayers.Class(OpenLayers.Format, {
/**
* Constructor: OpenLayers.Format.WKT
* Create a new parser for WKT
*
* Parameters:
* options - {Object} An optional object whose properties will be set on
* this instance
*
* Returns:
* {<OpenLayers.Format.WKT>} A new WKT parser.
*/
initialize: function(options) {
this.regExes = {
'typeStr': /^\s*(\w+)\s*\(\s*(.*)\s*\)\s*$/,
'spaces': /\s+/,
'parenComma': /\)\s*,\s*\(/,
'doubleParenComma': /\)\s*\)\s*,\s*\(\s*\(/, // can't use {2} here
'trimParens': /^\s*\(?(.*?)\)?\s*$/
};
OpenLayers.Format.prototype.initialize.apply(this, [options]);
},
/**
* Method: read
* Deserialize a WKT string and return a vector feature or an
* array of vector features. Supports WKT for POINT, MULTIPOINT,
* LINESTRING, MULTILINESTRING, POLYGON, MULTIPOLYGON, and
* GEOMETRYCOLLECTION.
*
* Parameters:
* wkt - {String} A WKT string
*
* Returns:
* {<OpenLayers.Feature.Vector>|Array} A feature or array of features for
* GEOMETRYCOLLECTION WKT.
*/
read: function(wkt) {
var features, type, str;
var matches = this.regExes.typeStr.exec(wkt);
if(matches) {
type = matches[1].toLowerCase();
str = matches[2];
if(this.parse[type]) {
features = this.parse[type].apply(this, [str]);
}
if (this.internalProjection && this.externalProjection) {
if (features &&
features.CLASS_NAME == "OpenLayers.Feature.Vector") {
features.geometry.transform(this.externalProjection,
this.internalProjection);
} else if (features &&
type != "geometrycollection" &&
typeof features == "object") {
for (var i=0, len=features.length; i<len; i++) {
var component = features[i];
component.geometry.transform(this.externalProjection,
this.internalProjection);
}
}
}
}
return features;
},
/**
* Method: write
* Serialize a feature or array of features into a WKT string.
*
* Parameters:
* features - {<OpenLayers.Feature.Vector>|Array} A feature or array of
* features
*
* Returns:
* {String} The WKT string representation of the input geometries
*/
write: function(features) {
var collection, geometry, type, data, isCollection;
if(features.constructor == Array) {
collection = features;
isCollection = true;
} else {
collection = [features];
isCollection = false;
}
var pieces = [];
if(isCollection) {
pieces.push('GEOMETRYCOLLECTION(');
}
for(var i=0, len=collection.length; i<len; ++i) {
if(isCollection && i>0) {
pieces.push(',');
}
geometry = collection[i].geometry;
type = geometry.CLASS_NAME.split('.')[2].toLowerCase();
if(!this.extract[type]) {
return null;
}
if (this.internalProjection && this.externalProjection) {
geometry = geometry.clone();
geometry.transform(this.internalProjection,
this.externalProjection);
}
data = this.extract[type].apply(this, [geometry]);
pieces.push(type.toUpperCase() + '(' + data + ')');
}
if(isCollection) {
pieces.push(')');
}
return pieces.join('');
},
/**
* Object with properties corresponding to the geometry types.
* Property values are functions that do the actual data extraction.
*/
extract: {
/**
* Return a space delimited string of point coordinates.
* @param {<OpenLayers.Geometry.Point>} point
* @returns {String} A string of coordinates representing the point
*/
'point': function(point) {
return point.x + ' ' + point.y;
},
/**
* Return a comma delimited string of point coordinates from a multipoint.
* @param {<OpenLayers.Geometry.MultiPoint>} multipoint
* @returns {String} A string of point coordinate strings representing
* the multipoint
*/
'multipoint': function(multipoint) {
var array = [];
for(var i=0, len=multipoint.components.length; i<len; ++i) {
array.push('(' +
this.extract.point.apply(this, [multipoint.components[i]]) +
')');
}
return array.join(',');
},
/**
* Return a comma delimited string of point coordinates from a line.
* @param {<OpenLayers.Geometry.LineString>} linestring
* @returns {String} A string of point coordinate strings representing
* the linestring
*/
'linestring': function(linestring) {
var array = [];
for(var i=0, len=linestring.components.length; i<len; ++i) {
array.push(this.extract.point.apply(this, [linestring.components[i]]));
}
return array.join(',');
},
/**
* Return a comma delimited string of linestring strings from a multilinestring.
* @param {<OpenLayers.Geometry.MultiLineString>} multilinestring
* @returns {String} A string of of linestring strings representing
* the multilinestring
*/
'multilinestring': function(multilinestring) {
var array = [];
for(var i=0, len=multilinestring.components.length; i<len; ++i) {
array.push('(' +
this.extract.linestring.apply(this, [multilinestring.components[i]]) +
')');
}
return array.join(',');
},
/**
* Return a comma delimited string of linear ring arrays from a polygon.
* @param {<OpenLayers.Geometry.Polygon>} polygon
* @returns {String} An array of linear ring arrays representing the polygon
*/
'polygon': function(polygon) {
var array = [];
for(var i=0, len=polygon.components.length; i<len; ++i) {
array.push('(' +
this.extract.linestring.apply(this, [polygon.components[i]]) +
')');
}
return array.join(',');
},
/**
* Return an array of polygon arrays from a multipolygon.
* @param {<OpenLayers.Geometry.MultiPolygon>} multipolygon
* @returns {Array} An array of polygon arrays representing
* the multipolygon
*/
'multipolygon': function(multipolygon) {
var array = [];
for(var i=0, len=multipolygon.components.length; i<len; ++i) {
array.push('(' +
this.extract.polygon.apply(this, [multipolygon.components[i]]) +
')');
}
return array.join(',');
}
},
/**
* Object with properties corresponding to the geometry types.
* Property values are functions that do the actual parsing.
*/
parse: {
/**
* Return point feature given a point WKT fragment.
* @param {String} str A WKT fragment representing the point
* @returns {<OpenLayers.Feature.Vector>} A point feature
* @private
*/
'point': function(str) {
var coords = OpenLayers.String.trim(str).split(this.regExes.spaces);
return new OpenLayers.Feature.Vector(
new OpenLayers.Geometry.Point(coords[0], coords[1])
);
},
/**
* Return a multipoint feature given a multipoint WKT fragment.
* @param {String} A WKT fragment representing the multipoint
* @returns {<OpenLayers.Feature.Vector>} A multipoint feature
* @private
*/
'multipoint': function(str) {
var point;
var points = OpenLayers.String.trim(str).split(this.regExes.parenComma);
var components = [];
for(var i=0, len=points.length; i<len; ++i) {
point = points[i].replace(this.regExes.trimParens, '$1');
components.push(this.parse.point.apply(this, [point]).geometry);
}
return new OpenLayers.Feature.Vector(
new OpenLayers.Geometry.MultiPoint(components)
);
},
/**
* Return a linestring feature given a linestring WKT fragment.
* @param {String} A WKT fragment representing the linestring
* @returns {<OpenLayers.Feature.Vector>} A linestring feature
* @private
*/
'linestring': function(str) {
var points = OpenLayers.String.trim(str).split(',');
var components = [];
for(var i=0, len=points.length; i<len; ++i) {
components.push(this.parse.point.apply(this, [points[i]]).geometry);
}
return new OpenLayers.Feature.Vector(
new OpenLayers.Geometry.LineString(components)
);
},
/**
* Return a multilinestring feature given a multilinestring WKT fragment.
* @param {String} A WKT fragment representing the multilinestring
* @returns {<OpenLayers.Feature.Vector>} A multilinestring feature
* @private
*/
'multilinestring': function(str) {
var line;
var lines = OpenLayers.String.trim(str).split(this.regExes.parenComma);
var components = [];
for(var i=0, len=lines.length; i<len; ++i) {
line = lines[i].replace(this.regExes.trimParens, '$1');
components.push(this.parse.linestring.apply(this, [line]).geometry);
}
return new OpenLayers.Feature.Vector(
new OpenLayers.Geometry.MultiLineString(components)
);
},
/**
* Return a polygon feature given a polygon WKT fragment.
* @param {String} A WKT fragment representing the polygon
* @returns {<OpenLayers.Feature.Vector>} A polygon feature
* @private
*/
'polygon': function(str) {
var ring, linestring, linearring;
var rings = OpenLayers.String.trim(str).split(this.regExes.parenComma);
var components = [];
for(var i=0, len=rings.length; i<len; ++i) {
ring = rings[i].replace(this.regExes.trimParens, '$1');
linestring = this.parse.linestring.apply(this, [ring]).geometry;
linearring = new OpenLayers.Geometry.LinearRing(linestring.components);
components.push(linearring);
}
return new OpenLayers.Feature.Vector(
new OpenLayers.Geometry.Polygon(components)
);
},
/**
* Return a multipolygon feature given a multipolygon WKT fragment.
* @param {String} A WKT fragment representing the multipolygon
* @returns {<OpenLayers.Feature.Vector>} A multipolygon feature
* @private
*/
'multipolygon': function(str) {
var polygon;
var polygons = OpenLayers.String.trim(str).split(this.regExes.doubleParenComma);
var components = [];
for(var i=0, len=polygons.length; i<len; ++i) {
polygon = polygons[i].replace(this.regExes.trimParens, '$1');
components.push(this.parse.polygon.apply(this, [polygon]).geometry);
}
return new OpenLayers.Feature.Vector(
new OpenLayers.Geometry.MultiPolygon(components)
);
},
/**
* Return an array of features given a geometrycollection WKT fragment.
* @param {String} A WKT fragment representing the geometrycollection
* @returns {Array} An array of OpenLayers.Feature.Vector
* @private
*/
'geometrycollection': function(str) {
// separate components of the collection with |
str = str.replace(/,\s*([A-Za-z])/g, '|$1');
var wktArray = OpenLayers.String.trim(str).split('|');
var components = [];
for(var i=0, len=wktArray.length; i<len; ++i) {
components.push(OpenLayers.Format.WKT.prototype.read.apply(this,[wktArray[i]]));
}
return components;
}
},
CLASS_NAME: "OpenLayers.Format.WKT"
});