More trip planner testing with colors
[busui.git] / labs / openlayers / lib / OpenLayers / Format / WKT.js
blob:a/labs/openlayers/lib/OpenLayers/Format/WKT.js -> blob:b/labs/openlayers/lib/OpenLayers/Format/WKT.js
  /* 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"
  });