]> dev.renevier.net Git - syp.git/blob - openlayers/lib/OpenLayers/Format/WKT.js
initial commit
[syp.git] / openlayers / lib / OpenLayers / Format / WKT.js
1 /* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
2  * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
3  * full text of the license. */
4
5 /**
6  * @requires OpenLayers/Format.js
7  * @requires OpenLayers/Feature/Vector.js
8  */
9
10 /**
11  * Class: OpenLayers.Format.WKT
12  * Class for reading and writing Well-Known Text.  Create a new instance
13  * with the <OpenLayers.Format.WKT> constructor.
14  * 
15  * Inherits from:
16  *  - <OpenLayers.Format>
17  */
18 OpenLayers.Format.WKT = OpenLayers.Class(OpenLayers.Format, {
19     
20     /**
21      * Constructor: OpenLayers.Format.WKT
22      * Create a new parser for WKT
23      *
24      * Parameters:
25      * options - {Object} An optional object whose properties will be set on
26      *           this instance
27      *
28      * Returns:
29      * {<OpenLayers.Format.WKT>} A new WKT parser.
30      */
31     initialize: function(options) {
32         this.regExes = {
33             'typeStr': /^\s*(\w+)\s*\(\s*(.*)\s*\)\s*$/,
34             'spaces': /\s+/,
35             'parenComma': /\)\s*,\s*\(/,
36             'doubleParenComma': /\)\s*\)\s*,\s*\(\s*\(/,  // can't use {2} here
37             'trimParens': /^\s*\(?(.*?)\)?\s*$/
38         };
39         OpenLayers.Format.prototype.initialize.apply(this, [options]);
40     },
41
42     /**
43      * Method: read
44      * Deserialize a WKT string and return a vector feature or an
45      * array of vector features.  Supports WKT for POINT, MULTIPOINT,
46      * LINESTRING, MULTILINESTRING, POLYGON, MULTIPOLYGON, and
47      * GEOMETRYCOLLECTION.
48      *
49      * Parameters:
50      * wkt - {String} A WKT string
51      *
52      * Returns:
53      * {<OpenLayers.Feature.Vector>|Array} A feature or array of features for
54      * GEOMETRYCOLLECTION WKT.
55      */
56     read: function(wkt) {
57         var features, type, str;
58         var matches = this.regExes.typeStr.exec(wkt);
59         if(matches) {
60             type = matches[1].toLowerCase();
61             str = matches[2];
62             if(this.parse[type]) {
63                 features = this.parse[type].apply(this, [str]);
64             }
65             if (this.internalProjection && this.externalProjection) {
66                 if (features && 
67                     features.CLASS_NAME == "OpenLayers.Feature.Vector") {
68                     features.geometry.transform(this.externalProjection,
69                                                 this.internalProjection);
70                 } else if (features &&
71                            type != "geometrycollection" &&
72                            typeof features == "object") {
73                     for (var i=0, len=features.length; i<len; i++) {
74                         var component = features[i];
75                         component.geometry.transform(this.externalProjection,
76                                                      this.internalProjection);
77                     }
78                 }
79             }
80         }    
81         return features;
82     },
83
84     /**
85      * Method: write
86      * Serialize a feature or array of features into a WKT string.
87      *
88      * Parameters:
89      * features - {<OpenLayers.Feature.Vector>|Array} A feature or array of
90      *            features
91      *
92      * Returns:
93      * {String} The WKT string representation of the input geometries
94      */
95     write: function(features) {
96         var collection, geometry, type, data, isCollection;
97         if(features.constructor == Array) {
98             collection = features;
99             isCollection = true;
100         } else {
101             collection = [features];
102             isCollection = false;
103         }
104         var pieces = [];
105         if(isCollection) {
106             pieces.push('GEOMETRYCOLLECTION(');
107         }
108         for(var i=0, len=collection.length; i<len; ++i) {
109             if(isCollection && i>0) {
110                 pieces.push(',');
111             }
112             geometry = collection[i].geometry;
113             type = geometry.CLASS_NAME.split('.')[2].toLowerCase();
114             if(!this.extract[type]) {
115                 return null;
116             }
117             if (this.internalProjection && this.externalProjection) {
118                 geometry = geometry.clone();
119                 geometry.transform(this.internalProjection, 
120                                    this.externalProjection);
121             }                       
122             data = this.extract[type].apply(this, [geometry]);
123             pieces.push(type.toUpperCase() + '(' + data + ')');
124         }
125         if(isCollection) {
126             pieces.push(')');
127         }
128         return pieces.join('');
129     },
130     
131     /**
132      * Object with properties corresponding to the geometry types.
133      * Property values are functions that do the actual data extraction.
134      */
135     extract: {
136         /**
137          * Return a space delimited string of point coordinates.
138          * @param {<OpenLayers.Geometry.Point>} point
139          * @returns {String} A string of coordinates representing the point
140          */
141         'point': function(point) {
142             return point.x + ' ' + point.y;
143         },
144
145         /**
146          * Return a comma delimited string of point coordinates from a multipoint.
147          * @param {<OpenLayers.Geometry.MultiPoint>} multipoint
148          * @returns {String} A string of point coordinate strings representing
149          *                  the multipoint
150          */
151         'multipoint': function(multipoint) {
152             var array = [];
153             for(var i=0, len=multipoint.components.length; i<len; ++i) {
154                 array.push(this.extract.point.apply(this, [multipoint.components[i]]));
155             }
156             return array.join(',');
157         },
158         
159         /**
160          * Return a comma delimited string of point coordinates from a line.
161          * @param {<OpenLayers.Geometry.LineString>} linestring
162          * @returns {String} A string of point coordinate strings representing
163          *                  the linestring
164          */
165         'linestring': function(linestring) {
166             var array = [];
167             for(var i=0, len=linestring.components.length; i<len; ++i) {
168                 array.push(this.extract.point.apply(this, [linestring.components[i]]));
169             }
170             return array.join(',');
171         },
172
173         /**
174          * Return a comma delimited string of linestring strings from a multilinestring.
175          * @param {<OpenLayers.Geometry.MultiLineString>} multilinestring
176          * @returns {String} A string of of linestring strings representing
177          *                  the multilinestring
178          */
179         'multilinestring': function(multilinestring) {
180             var array = [];
181             for(var i=0, len=multilinestring.components.length; i<len; ++i) {
182                 array.push('(' +
183                            this.extract.linestring.apply(this, [multilinestring.components[i]]) +
184                            ')');
185             }
186             return array.join(',');
187         },
188         
189         /**
190          * Return a comma delimited string of linear ring arrays from a polygon.
191          * @param {<OpenLayers.Geometry.Polygon>} polygon
192          * @returns {String} An array of linear ring arrays representing the polygon
193          */
194         'polygon': function(polygon) {
195             var array = [];
196             for(var i=0, len=polygon.components.length; i<len; ++i) {
197                 array.push('(' +
198                            this.extract.linestring.apply(this, [polygon.components[i]]) +
199                            ')');
200             }
201             return array.join(',');
202         },
203
204         /**
205          * Return an array of polygon arrays from a multipolygon.
206          * @param {<OpenLayers.Geometry.MultiPolygon>} multipolygon
207          * @returns {Array} An array of polygon arrays representing
208          *                  the multipolygon
209          */
210         'multipolygon': function(multipolygon) {
211             var array = [];
212             for(var i=0, len=multipolygon.components.length; i<len; ++i) {
213                 array.push('(' +
214                            this.extract.polygon.apply(this, [multipolygon.components[i]]) +
215                            ')');
216             }
217             return array.join(',');
218         }
219
220     },
221
222     /**
223      * Object with properties corresponding to the geometry types.
224      * Property values are functions that do the actual parsing.
225      */
226     parse: {
227         /**
228          * Return point feature given a point WKT fragment.
229          * @param {String} str A WKT fragment representing the point
230          * @returns {<OpenLayers.Feature.Vector>} A point feature
231          * @private
232          */
233         'point': function(str) {
234             var coords = OpenLayers.String.trim(str).split(this.regExes.spaces);
235             return new OpenLayers.Feature.Vector(
236                 new OpenLayers.Geometry.Point(coords[0], coords[1])
237             );
238         },
239
240         /**
241          * Return a multipoint feature given a multipoint WKT fragment.
242          * @param {String} A WKT fragment representing the multipoint
243          * @returns {<OpenLayers.Feature.Vector>} A multipoint feature
244          * @private
245          */
246         'multipoint': function(str) {
247             var points = OpenLayers.String.trim(str).split(',');
248             var components = [];
249             for(var i=0, len=points.length; i<len; ++i) {
250                 components.push(this.parse.point.apply(this, [points[i]]).geometry);
251             }
252             return new OpenLayers.Feature.Vector(
253                 new OpenLayers.Geometry.MultiPoint(components)
254             );
255         },
256         
257         /**
258          * Return a linestring feature given a linestring WKT fragment.
259          * @param {String} A WKT fragment representing the linestring
260          * @returns {<OpenLayers.Feature.Vector>} A linestring feature
261          * @private
262          */
263         'linestring': function(str) {
264             var points = OpenLayers.String.trim(str).split(',');
265             var components = [];
266             for(var i=0, len=points.length; i<len; ++i) {
267                 components.push(this.parse.point.apply(this, [points[i]]).geometry);
268             }
269             return new OpenLayers.Feature.Vector(
270                 new OpenLayers.Geometry.LineString(components)
271             );
272         },
273
274         /**
275          * Return a multilinestring feature given a multilinestring WKT fragment.
276          * @param {String} A WKT fragment representing the multilinestring
277          * @returns {<OpenLayers.Feature.Vector>} A multilinestring feature
278          * @private
279          */
280         'multilinestring': function(str) {
281             var line;
282             var lines = OpenLayers.String.trim(str).split(this.regExes.parenComma);
283             var components = [];
284             for(var i=0, len=lines.length; i<len; ++i) {
285                 line = lines[i].replace(this.regExes.trimParens, '$1');
286                 components.push(this.parse.linestring.apply(this, [line]).geometry);
287             }
288             return new OpenLayers.Feature.Vector(
289                 new OpenLayers.Geometry.MultiLineString(components)
290             );
291         },
292         
293         /**
294          * Return a polygon feature given a polygon WKT fragment.
295          * @param {String} A WKT fragment representing the polygon
296          * @returns {<OpenLayers.Feature.Vector>} A polygon feature
297          * @private
298          */
299         'polygon': function(str) {
300             var ring, linestring, linearring;
301             var rings = OpenLayers.String.trim(str).split(this.regExes.parenComma);
302             var components = [];
303             for(var i=0, len=rings.length; i<len; ++i) {
304                 ring = rings[i].replace(this.regExes.trimParens, '$1');
305                 linestring = this.parse.linestring.apply(this, [ring]).geometry;
306                 linearring = new OpenLayers.Geometry.LinearRing(linestring.components);
307                 components.push(linearring);
308             }
309             return new OpenLayers.Feature.Vector(
310                 new OpenLayers.Geometry.Polygon(components)
311             );
312         },
313
314         /**
315          * Return a multipolygon feature given a multipolygon WKT fragment.
316          * @param {String} A WKT fragment representing the multipolygon
317          * @returns {<OpenLayers.Feature.Vector>} A multipolygon feature
318          * @private
319          */
320         'multipolygon': function(str) {
321             var polygon;
322             var polygons = OpenLayers.String.trim(str).split(this.regExes.doubleParenComma);
323             var components = [];
324             for(var i=0, len=polygons.length; i<len; ++i) {
325                 polygon = polygons[i].replace(this.regExes.trimParens, '$1');
326                 components.push(this.parse.polygon.apply(this, [polygon]).geometry);
327             }
328             return new OpenLayers.Feature.Vector(
329                 new OpenLayers.Geometry.MultiPolygon(components)
330             );
331         },
332
333         /**
334          * Return an array of features given a geometrycollection WKT fragment.
335          * @param {String} A WKT fragment representing the geometrycollection
336          * @returns {Array} An array of OpenLayers.Feature.Vector
337          * @private
338          */
339         'geometrycollection': function(str) {
340             // separate components of the collection with |
341             str = str.replace(/,\s*([A-Za-z])/g, '|$1');
342             var wktArray = OpenLayers.String.trim(str).split('|');
343             var components = [];
344             for(var i=0, len=wktArray.length; i<len; ++i) {
345                 components.push(OpenLayers.Format.WKT.prototype.read.apply(this,[wktArray[i]]));
346             }
347             return components;
348         }
349
350     },
351
352     CLASS_NAME: "OpenLayers.Format.WKT" 
353 });