]> dev.renevier.net Git - syp.git/blob - openlayers/lib/OpenLayers/Format/GML/v3.js
initial commit
[syp.git] / openlayers / lib / OpenLayers / Format / GML / v3.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/GML/Base.js
7  */
8
9 /**
10  * Class: OpenLayers.Format.GML.v3
11  * Parses GML version 3.
12  *
13  * Inherits from:
14  *  - <OpenLayers.Format.GML.Base>
15  */
16 OpenLayers.Format.GML.v3 = OpenLayers.Class(OpenLayers.Format.GML.Base, {
17     
18     /**
19      * Property: schemaLocation
20      * {String} Schema location for a particular minor version.  The writers
21      *     conform with the Simple Features Profile for GML.
22      */
23     schemaLocation: "http://www.opengis.net/gml http://schemas.opengis.net/gml/3.1.1/profiles/gmlsfProfile/1.0.0/gmlsf.xsd",
24
25     /**
26      * Property: curve
27      * {Boolean} Write gml:Curve instead of gml:LineString elements.  This also
28      *     affects the elements in multi-part geometries.  Default is false.
29      *     To write gml:Curve elements instead of gml:LineString, set curve
30      *     to true in the options to the contstructor (cannot be changed after
31      *     instantiation).
32      */
33     curve: false,
34     
35     /**
36      * Property: multiCurve
37      * {Boolean} Write gml:MultiCurve instead of gml:MultiLineString.  Since
38      *     the latter is deprecated in GML 3, the default is true.  To write
39      *     gml:MultiLineString instead of gml:MultiCurve, set multiCurve to
40      *     false in the options to the constructor (cannot be changed after
41      *     instantiation).
42      */
43     multiCurve: true,
44     
45     /**
46      * Property: surface
47      * {Boolean} Write gml:Surface instead of gml:Polygon elements.  This also
48      *     affects the elements in multi-part geometries.  Default is false.
49      *     To write gml:Surface elements instead of gml:Polygon, set surface
50      *     to true in the options to the contstructor (cannot be changed after
51      *     instantiation).
52      */
53     surface: false,
54
55     /**
56      * Property: multiSurface
57      * {Boolean} Write gml:multiSurface instead of gml:MultiPolygon.  Since
58      *     the latter is deprecated in GML 3, the default is true.  To write
59      *     gml:MultiPolygon instead of gml:multiSurface, set multiSurface to
60      *     false in the options to the constructor (cannot be changed after
61      *     instantiation).
62      */
63     multiSurface: true,
64
65     /**
66      * Constructor: OpenLayers.Format.GML.v3
67      * Create a parser for GML v3.
68      *
69      * Parameters:
70      * options - {Object} An optional object whose properties will be set on
71      *     this instance.
72      *
73      * Valid options properties:
74      * featureType - {String} Local (without prefix) feature typeName (required).
75      * featureNS - {String} Feature namespace (required).
76      * geometryName - {String} Geometry element name.
77      */
78     initialize: function(options) {
79         OpenLayers.Format.GML.Base.prototype.initialize.apply(this, [options]);
80     },
81
82     /**
83      * Property: readers
84      * Contains public functions, grouped by namespace prefix, that will
85      *     be applied when a namespaced node is found matching the function
86      *     name.  The function will be applied in the scope of this parser
87      *     with two arguments: the node being read and a context object passed
88      *     from the parent.
89      */
90     readers: {
91         "gml": OpenLayers.Util.applyDefaults({
92             "featureMembers": function(node, obj) {
93                 this.readChildNodes(node, obj);
94             },
95             "Curve": function(node, container) {
96                 var obj = {points: []};
97                 this.readChildNodes(node, obj);
98                 if(!container.components) {
99                     container.components = [];
100                 }
101                 container.components.push(
102                     new OpenLayers.Geometry.LineString(obj.points)
103                 );
104             },
105             "segments": function(node, obj) {
106                 this.readChildNodes(node, obj);
107             },
108             "LineStringSegment": function(node, container) {
109                 var obj = {};
110                 this.readChildNodes(node, obj);
111                 if(obj.points) {
112                     Array.prototype.push.apply(container.points, obj.points);
113                 }
114             },
115             "pos": function(node, obj) {
116                 var str = this.getChildValue(node).replace(
117                     this.regExes.trimSpace, ""
118                 );
119                 var coords = str.split(this.regExes.splitSpace);
120                 var point;
121                 if(this.xy) {
122                     point = new OpenLayers.Geometry.Point(
123                         coords[0], coords[1], coords[2]
124                     );
125                 } else {
126                     point = new OpenLayers.Geometry.Point(
127                         coords[1], coords[0], coords[2]
128                     );
129                 }
130                 obj.points = [point];
131             },
132             "posList": function(node, obj) {
133                 var str = this.getChildValue(node).replace(
134                     this.regExes.trimSpace, ""
135                 );
136                 var coords = str.split(this.regExes.splitSpace);
137                 var dim = parseInt(node.getAttribute("dimension")) || 2;
138                 var j, x, y, z;
139                 var numPoints = coords.length / dim;
140                 var points = new Array(numPoints);
141                 for(var i=0, len=coords.length; i<len; i += dim) {
142                     x = coords[i];
143                     y = coords[i+1];
144                     z = (dim == 2) ? undefined : coords[i+2];
145                     if (this.xy) {
146                         points[i/dim] = new OpenLayers.Geometry.Point(x, y, z);
147                     } else {
148                         points[i/dim] = new OpenLayers.Geometry.Point(y, x, z);
149                     }
150                 }
151                 obj.points = points;
152             },
153             "Surface": function(node, obj) {
154                 this.readChildNodes(node, obj);
155             },
156             "patches": function(node, obj) {
157                 this.readChildNodes(node, obj);
158             },
159             "PolygonPatch": function(node, obj) {
160                 this.readers.gml.Polygon.apply(this, [node, obj]);
161             },
162             "exterior": function(node, container) {
163                 var obj = {};
164                 this.readChildNodes(node, obj);
165                 container.outer = obj.components[0];
166             },
167             "interior": function(node, container) {
168                 var obj = {};
169                 this.readChildNodes(node, obj);
170                 container.inner.push(obj.components[0]);
171             },
172             "MultiCurve": function(node, container) {
173                 var obj = {components: []};
174                 this.readChildNodes(node, obj);
175                 if(obj.components.length > 0) {
176                     container.components = [
177                         new OpenLayers.Geometry.MultiLineString(obj.components)
178                     ];
179                 }
180             },
181             "curveMember": function(node, obj) {
182                 this.readChildNodes(node, obj);
183             },
184             "MultiSurface": function(node, container) {
185                 var obj = {components: []};
186                 this.readChildNodes(node, obj);
187                 if(obj.components.length > 0) {
188                     container.components = [
189                         new OpenLayers.Geometry.MultiPolygon(obj.components)
190                     ];
191                 }
192             },
193             "surfaceMember": function(node, obj) {
194                 this.readChildNodes(node, obj);
195             },
196             "surfaceMembers": function(node, obj) {
197                 this.readChildNodes(node, obj);
198             },
199             "pointMembers": function(node, obj) {
200                 this.readChildNodes(node, obj);
201             },
202             "lineStringMembers": function(node, obj) {
203                 this.readChildNodes(node, obj);
204             },
205             "polygonMembers": function(node, obj) {
206                 this.readChildNodes(node, obj);
207             },
208             "geometryMembers": function(node, obj) {
209                 this.readChildNodes(node, obj);
210             },
211             "Envelope": function(node, container) {
212                 var obj = {points: new Array(2)};
213                 this.readChildNodes(node, obj);
214                 if(!container.components) {
215                     container.components = [];
216                 }
217                 var min = obj.points[0];
218                 var max = obj.points[1];
219                 container.components.push(
220                     new OpenLayers.Bounds(min.x, min.y, max.x, max.y)
221                 );
222             },
223             "lowerCorner": function(node, container) {
224                 var obj = {};
225                 this.readers.gml.pos.apply(this, [node, obj]);
226                 container.points[0] = obj.points[0];
227             },
228             "upperCorner": function(node, container) {
229                 var obj = {};
230                 this.readers.gml.pos.apply(this, [node, obj]);
231                 container.points[1] = obj.points[0];
232             }
233         }, OpenLayers.Format.GML.Base.prototype.readers["gml"]),            
234         "feature": OpenLayers.Format.GML.Base.prototype.readers["feature"],
235         "wfs": OpenLayers.Format.GML.Base.prototype.readers["wfs"]
236     },
237     
238     /**
239      * Method: write
240      *
241      * Parameters:
242      * features - {Array(<OpenLayers.Feature.Vector>) | OpenLayers.Feature.Vector}
243      *     An array of features or a single feature.
244      *
245      * Returns:
246      * {String} Given an array of features, a doc with a gml:featureMembers
247      *     element will be returned.  Given a single feature, a doc with a
248      *     gml:featureMember element will be returned.
249      */
250     write: function(features) {
251         var name;
252         if(features instanceof Array) {
253             name = "featureMembers";
254         } else {
255             name = "featureMember";
256         }
257         var root = this.writeNode("gml:" + name, features);
258         this.setAttributeNS(
259             root, this.namespaces["xsi"],
260             "xsi:schemaLocation", this.schemaLocation
261         );
262
263         return OpenLayers.Format.XML.prototype.write.apply(this, [root]);
264     },
265
266     /**
267      * Property: writers
268      * As a compliment to the readers property, this structure contains public
269      *     writing functions grouped by namespace alias and named like the
270      *     node names they produce.
271      */
272     writers: {
273         "gml": OpenLayers.Util.applyDefaults({
274             "featureMembers": function(features) {
275                 var node = this.createElementNSPlus("gml:featureMembers");
276                 for(var i=0, len=features.length; i<len; ++i) {
277                     this.writeNode("feature:_typeName", features[i], node);
278                 }
279                 return node;
280             },
281             "Point": function(geometry) {
282                 var node = this.createElementNSPlus("gml:Point");
283                 this.writeNode("pos", geometry, node);
284                 return node;
285             },
286             "pos": function(point) {
287                 // only 2d for simple features profile
288                 var pos = (this.xy) ?
289                     (point.x + " " + point.y) : (point.y + " " + point.x);
290                 return this.createElementNSPlus("gml:pos", {
291                     value: pos
292                 });
293             },
294             "LineString": function(geometry) {
295                 var node = this.createElementNSPlus("gml:LineString");
296                 this.writeNode("posList", geometry.components, node);
297                 return node;
298             },
299             "Curve": function(geometry) {
300                 var node = this.createElementNSPlus("gml:Curve");
301                 this.writeNode("segments", geometry, node);
302                 return node;
303             },
304             "segments": function(geometry) {
305                 var node = this.createElementNSPlus("gml:segments");
306                 this.writeNode("LineStringSegment", geometry, node);
307                 return node;
308             },
309             "LineStringSegment": function(geometry) {
310                 var node = this.createElementNSPlus("gml:LineStringSegment");
311                 this.writeNode("posList", geometry.components, node);
312                 return node;
313             },
314             "posList": function(points) {
315                 // only 2d for simple features profile
316                 var len = points.length;
317                 var parts = new Array(len);
318                 var point;
319                 for(var i=0; i<len; ++i) {
320                     point = points[i];
321                     if(this.xy) {
322                         parts[i] = point.x + " " + point.y;
323                     } else {
324                         parts[i] = point.y + " " + point.x;
325                     }
326                 }
327                 return this.createElementNSPlus("gml:posList", {
328                     value: parts.join(" ")
329                 }); 
330             },
331             "Surface": function(geometry) {
332                 var node = this.createElementNSPlus("gml:Surface");
333                 this.writeNode("patches", geometry, node);
334                 return node;
335             },
336             "patches": function(geometry) {
337                 var node = this.createElementNSPlus("gml:patches");
338                 this.writeNode("PolygonPatch", geometry, node);
339                 return node;
340             },
341             "PolygonPatch": function(geometry) {
342                 var node = this.createElementNSPlus("gml:PolygonPatch", {
343                     attributes: {interpolation: "planar"}
344                 });
345                 this.writeNode("exterior", geometry.components[0], node);
346                 for(var i=1, len=geometry.components.length; i<len; ++i) {
347                     this.writeNode(
348                         "interior", geometry.components[i], node
349                     );
350                 }
351                 return node;
352             },
353             "Polygon": function(geometry) {
354                 var node = this.createElementNSPlus("gml:Polygon");
355                 this.writeNode("exterior", geometry.components[0], node);
356                 for(var i=1, len=geometry.components.length; i<len; ++i) {
357                     this.writeNode(
358                         "interior", geometry.components[i], node
359                     );
360                 }
361                 return node;
362             },
363             "exterior": function(ring) {
364                 var node = this.createElementNSPlus("gml:exterior");
365                 this.writeNode("LinearRing", ring, node);
366                 return node;
367             },
368             "interior": function(ring) {
369                 var node = this.createElementNSPlus("gml:interior");
370                 this.writeNode("LinearRing", ring, node);
371                 return node;
372             },
373             "LinearRing": function(ring) {
374                 var node = this.createElementNSPlus("gml:LinearRing");
375                 this.writeNode("posList", ring.components, node);
376                 return node;
377             },
378             "MultiCurve": function(geometry) {
379                 var node = this.createElementNSPlus("gml:MultiCurve");
380                 for(var i=0, len=geometry.components.length; i<len; ++i) {
381                     this.writeNode("curveMember", geometry.components[i], node);
382                 }
383                 return node;
384             },
385             "curveMember": function(geometry) {
386                 var node = this.createElementNSPlus("gml:curveMember");
387                 if(this.curve) {
388                     this.writeNode("Curve", geometry, node);
389                 } else {
390                     this.writeNode("LineString", geometry, node);
391                 }
392                 return node;
393             },
394             "MultiSurface": function(geometry) {
395                 var node = this.createElementNSPlus("gml:MultiSurface");
396                 for(var i=0, len=geometry.components.length; i<len; ++i) {
397                     this.writeNode("surfaceMember", geometry.components[i], node);
398                 }
399                 return node;
400             },
401             "surfaceMember": function(polygon) {
402                 var node = this.createElementNSPlus("gml:surfaceMember");
403                 if(this.surface) {
404                     this.writeNode("Surface", polygon, node);
405                 } else {
406                     this.writeNode("Polygon", polygon, node);
407                 }
408                 return node;
409             },
410             "Envelope": function(bounds) {
411                 var node = this.createElementNSPlus("gml:Envelope");
412                 this.writeNode("lowerCorner", bounds, node);
413                 this.writeNode("upperCorner", bounds, node);
414                 // srsName attribute is required for gml:Envelope
415                 if(this.srsName) {
416                     node.setAttribute("srsName", this.srsName);
417                 }
418                 return node;
419             },
420             "lowerCorner": function(bounds) {
421                 // only 2d for simple features profile
422                 var pos = (this.xy) ?
423                     (bounds.left + " " + bounds.bottom) :
424                     (bounds.bottom + " " + bounds.left);
425                 return this.createElementNSPlus("gml:lowerCorner", {
426                     value: pos
427                 });
428             },
429             "upperCorner": function(bounds) {
430                 // only 2d for simple features profile
431                 var pos = (this.xy) ?
432                     (bounds.right + " " + bounds.top) :
433                     (bounds.top + " " + bounds.right);
434                 return this.createElementNSPlus("gml:upperCorner", {
435                     value: pos
436                 });
437             }
438         }, OpenLayers.Format.GML.Base.prototype.writers["gml"]),
439         "feature": OpenLayers.Format.GML.Base.prototype.writers["feature"],
440         "wfs": OpenLayers.Format.GML.Base.prototype.writers["wfs"]
441     },
442
443     /**
444      * Function: setGeometryTypes
445      * Sets the <geometryTypes> mapping.
446      */
447     setGeometryTypes: function() {
448         this.geometryTypes = {
449             "OpenLayers.Geometry.Point": "Point",
450             "OpenLayers.Geometry.MultiPoint": "MultiPoint",
451             "OpenLayers.Geometry.LineString": (this.curve === true) ? "Curve": "LineString",
452             "OpenLayers.Geometry.MultiLineString": (this.multiCurve === false) ? "MultiLineString" : "MultiCurve",
453             "OpenLayers.Geometry.Polygon": (this.surface === true) ? "Surface" : "Polygon",
454             "OpenLayers.Geometry.MultiPolygon": (this.multiSurface === false) ? "MultiPolygon" : "MultiSurface",
455             "OpenLayers.Geometry.Collection": "GeometryCollection"
456         };
457     },
458     
459     CLASS_NAME: "OpenLayers.Format.GML.v3" 
460
461 });