GML parser.
This adds a parser (read/write) for GML v2 and v3. GML v3 is limited to the simple features profile of GML 3.1.1, just like OpenLayers 2 was. This will be the basis for the WFS parser, but it only makes sense to continue this work once feature modification (insert, update, delete) is in place in ol3. So the WFS parser will be another pull request.
This commit is contained in:
@@ -0,0 +1,422 @@
|
||||
goog.provide('ol.parser.ogc.GML_v3');
|
||||
|
||||
goog.require('goog.dom.xml');
|
||||
goog.require('goog.object');
|
||||
goog.require('ol.geom.GeometryType');
|
||||
goog.require('ol.parser.ogc.GML');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {ol.parser.GML3Options=} opt_options Optional configuration object.
|
||||
* @extends {ol.parser.ogc.GML}
|
||||
*/
|
||||
ol.parser.ogc.GML_v3 = function(opt_options) {
|
||||
this.schemaLocation = 'http://www.opengis.net/gml ' +
|
||||
'http://schemas.opengis.net/gml/3.1.1/profiles/gmlsfProfile/' +
|
||||
'1.0.0/gmlsf.xsd';
|
||||
goog.base(this, opt_options);
|
||||
if (!goog.isDef(this.surface)) {
|
||||
this.surface = false;
|
||||
}
|
||||
if (!goog.isDef(this.curve)) {
|
||||
this.curve = false;
|
||||
}
|
||||
if (!goog.isDef(this.multiCurve)) {
|
||||
this.multiCurve = true;
|
||||
}
|
||||
if (!goog.isDef(this.multiSurface)) {
|
||||
this.multiSurface = true;
|
||||
}
|
||||
this.featureNSWiters_['_geometry'] = function(geometry) {
|
||||
var node = this.createElementNS('feature:' + this.geometryName,
|
||||
this.featureNS);
|
||||
var type = geometry.getType(), child;
|
||||
if (type === ol.geom.GeometryType.POINT) {
|
||||
child = this.writeNode('Point', geometry, null, node);
|
||||
} else if (type === ol.geom.GeometryType.MULTIPOINT) {
|
||||
child = this.writeNode('MultiPoint', geometry, null, node);
|
||||
} else if (type === ol.geom.GeometryType.LINESTRING) {
|
||||
if (this.curve === true) {
|
||||
child = this.writeNode('Curve', geometry, null, node);
|
||||
} else {
|
||||
child = this.writeNode('LineString', geometry, null, node);
|
||||
}
|
||||
} else if (type === ol.geom.GeometryType.LINEARRING) {
|
||||
child = this.writeNode('LinearRing', geometry.getCoordinates(), null,
|
||||
node);
|
||||
} else if (type === ol.geom.GeometryType.MULTILINESTRING) {
|
||||
if (this.multiCurve === false) {
|
||||
child = this.writeNode('MultiLineString', geometry, null, node);
|
||||
} else {
|
||||
child = this.writeNode('MultiCurve', geometry, null, node);
|
||||
}
|
||||
} else if (type === ol.geom.GeometryType.POLYGON) {
|
||||
if (this.surface === true) {
|
||||
child = this.writeNode('Surface', geometry, null, node);
|
||||
} else {
|
||||
child = this.writeNode('Polygon', geometry, null, node);
|
||||
}
|
||||
} else if (type === ol.geom.GeometryType.MULTIPOLYGON) {
|
||||
if (this.multiSurface === false) {
|
||||
child = this.writeNode('MultiPolygon', geometry, null, node);
|
||||
} else {
|
||||
child = this.writeNode('MultiSurface', geometry, null, node);
|
||||
}
|
||||
} else if (type === ol.geom.GeometryType.GEOMETRYCOLLECTION) {
|
||||
child = this.writeNode('MultiGeometry', geometry, null, node);
|
||||
}
|
||||
if (goog.isDef(this.srsName)) {
|
||||
this.setAttributeNS(child, null, 'srsName', this.srsName);
|
||||
}
|
||||
return node;
|
||||
};
|
||||
goog.object.extend(this.readers['http://www.opengis.net/gml'], {
|
||||
'_inherit': function(node, obj, container) {
|
||||
// SRSReferenceGroup attributes
|
||||
var dim = parseInt(node.getAttribute('srsDimension'), 10) ||
|
||||
(container && container.srsDimension);
|
||||
if (dim) {
|
||||
obj.srsDimension = dim;
|
||||
}
|
||||
},
|
||||
'featureMembers': function(node, obj) {
|
||||
this.readChildNodes(node, obj);
|
||||
},
|
||||
'Curve': function(node, container) {
|
||||
var coordinates = [];
|
||||
this.readers[this.defaultNamespaceURI]['_inherit'].apply(this,
|
||||
[node, coordinates, container]);
|
||||
this.readChildNodes(node, coordinates);
|
||||
var linestring = {
|
||||
type: ol.geom.GeometryType.LINESTRING,
|
||||
coordinates: coordinates[0]
|
||||
};
|
||||
// in the case of a multi geometry this is parts
|
||||
if (goog.isArray(container)) {
|
||||
container.push(linestring);
|
||||
} else {
|
||||
container.geometry = linestring;
|
||||
}
|
||||
},
|
||||
'segments': function(node, obj) {
|
||||
this.readChildNodes(node, obj);
|
||||
},
|
||||
'LineStringSegment': function(node, container) {
|
||||
var coordinates = [];
|
||||
this.readChildNodes(node, coordinates);
|
||||
container.push(coordinates[0]);
|
||||
},
|
||||
'pos': function(node, obj) {
|
||||
var str = this.getChildValue(node).replace(
|
||||
this.regExes.trimSpace, '');
|
||||
var coords = str.split(this.regExes.splitSpace).map(parseFloat);
|
||||
if (this.xy) {
|
||||
obj.push([coords]);
|
||||
} else {
|
||||
if (coords.length === 2) {
|
||||
obj.push([coords.reverse()]);
|
||||
} else if (coords.length === 3) {
|
||||
obj.push([coords[1], coords[0], coords[2]]);
|
||||
}
|
||||
}
|
||||
},
|
||||
'posList': function(node, obj) {
|
||||
var str = this.getChildValue(node).replace(
|
||||
this.regExes.trimSpace, '');
|
||||
var coords = str.split(this.regExes.splitSpace);
|
||||
// The "dimension" attribute is from the GML 3.0.1 spec.
|
||||
var dim = obj.srsDimension ||
|
||||
parseInt(node.getAttribute('srsDimension') ||
|
||||
node.getAttribute('dimension'), 10) || 2;
|
||||
var j, x, y, z;
|
||||
var numPoints = coords.length / dim;
|
||||
var points = new Array(numPoints);
|
||||
for (var i = 0, ii = coords.length; i < ii; i += dim) {
|
||||
x = parseFloat(coords[i]);
|
||||
y = parseFloat(coords[i + 1]);
|
||||
if (dim === 3) {
|
||||
if (this.xy) {
|
||||
points[i / dim] = [x, y, parseFloat(coords[i + 2])];
|
||||
} else {
|
||||
points[i / dim] = [y, x, parseFloat(coords[i + 2])];
|
||||
}
|
||||
} else if (dim === 2) {
|
||||
if (this.xy) {
|
||||
points[i / dim] = [x, y];
|
||||
} else {
|
||||
points[i / dim] = [y, x];
|
||||
}
|
||||
}
|
||||
}
|
||||
obj.push(points);
|
||||
},
|
||||
'Surface': function(node, obj) {
|
||||
this.readChildNodes(node, obj);
|
||||
},
|
||||
'patches': function(node, obj) {
|
||||
this.readChildNodes(node, obj);
|
||||
},
|
||||
'PolygonPatch': function(node, obj) {
|
||||
this.readers[this.defaultNamespaceURI]['Polygon'].apply(this,
|
||||
[node, obj]);
|
||||
},
|
||||
'exterior': function(node, container) {
|
||||
var coordinates = [];
|
||||
this.readChildNodes(node, coordinates);
|
||||
container.outer = coordinates[0][0];
|
||||
},
|
||||
'interior': function(node, container) {
|
||||
var coordinates = [];
|
||||
this.readChildNodes(node, coordinates);
|
||||
container.inner.push(coordinates[0][0]);
|
||||
},
|
||||
'MultiCurve': function(node, container) {
|
||||
var parts = [];
|
||||
this.readers[this.defaultNamespaceURI]['_inherit'].apply(this,
|
||||
[node, parts, container]);
|
||||
this.readChildNodes(node, parts);
|
||||
container.geometry = {
|
||||
type: ol.geom.GeometryType.MULTILINESTRING,
|
||||
parts: parts
|
||||
};
|
||||
},
|
||||
'curveMember': function(node, obj) {
|
||||
this.readChildNodes(node, obj);
|
||||
},
|
||||
'MultiSurface': function(node, container) {
|
||||
var parts = [];
|
||||
this.readers[this.defaultNamespaceURI]['_inherit'].apply(this,
|
||||
[node, parts, container]);
|
||||
this.readChildNodes(node, parts);
|
||||
container.geometry = {
|
||||
type: ol.geom.GeometryType.MULTIPOLYGON,
|
||||
parts: parts
|
||||
};
|
||||
},
|
||||
'surfaceMember': function(node, obj) {
|
||||
this.readChildNodes(node, obj);
|
||||
},
|
||||
'surfaceMembers': function(node, obj) {
|
||||
this.readChildNodes(node, obj);
|
||||
},
|
||||
'pointMembers': function(node, obj) {
|
||||
this.readChildNodes(node, obj);
|
||||
},
|
||||
'lineStringMembers': function(node, obj) {
|
||||
this.readChildNodes(node, obj);
|
||||
},
|
||||
'polygonMembers': function(node, obj) {
|
||||
this.readChildNodes(node, obj);
|
||||
},
|
||||
'geometryMembers': function(node, obj) {
|
||||
this.readChildNodes(node, obj);
|
||||
},
|
||||
'Envelope': function(node, container) {
|
||||
var coordinates = [];
|
||||
this.readChildNodes(node, coordinates);
|
||||
container.bounds = [coordinates[0][0][0][0], coordinates[1][0][0][0],
|
||||
coordinates[0][0][0][1], coordinates[1][0][0][1]];
|
||||
},
|
||||
'lowerCorner': function(node, envelope) {
|
||||
var coordinates = [];
|
||||
this.readers[this.defaultNamespaceURI]['pos'].apply(this,
|
||||
[node, coordinates]);
|
||||
envelope.push(coordinates);
|
||||
},
|
||||
'upperCorner': function(node, envelope) {
|
||||
var coordinates = [];
|
||||
this.readers[this.defaultNamespaceURI]['pos'].apply(this,
|
||||
[node, coordinates]);
|
||||
envelope.push(coordinates);
|
||||
}
|
||||
});
|
||||
goog.object.extend(this.writers['http://www.opengis.net/gml'], {
|
||||
'featureMembers': function(features) {
|
||||
var node = this.createElementNS('gml:featureMembers');
|
||||
for (var i = 0, ii = features.length; i < ii; ++i) {
|
||||
this.writeNode('_typeName', features[i], this.featureNS, node);
|
||||
}
|
||||
return node;
|
||||
},
|
||||
'Point': function(geometry) {
|
||||
var node = this.createElementNS('gml:Point');
|
||||
this.writeNode('pos', geometry.getCoordinates(), null, node);
|
||||
return node;
|
||||
},
|
||||
'pos': function(point) {
|
||||
// only 2d for simple features profile
|
||||
var pos;
|
||||
if (this.xy) {
|
||||
pos = (point[0] + ' ' + point[1]);
|
||||
} else {
|
||||
pos = (point[1] + ' ' + point[0]);
|
||||
}
|
||||
var node = this.createElementNS('gml:pos');
|
||||
node.appendChild(this.createTextNode(pos));
|
||||
return node;
|
||||
},
|
||||
'LineString': function(geometry) {
|
||||
var node = this.createElementNS('gml:LineString');
|
||||
this.writeNode('posList', geometry.getCoordinates(), null, node);
|
||||
return node;
|
||||
},
|
||||
'Curve': function(geometry) {
|
||||
var node = this.createElementNS('gml:Curve');
|
||||
this.writeNode('segments', geometry, null, node);
|
||||
return node;
|
||||
},
|
||||
'segments': function(geometry) {
|
||||
var node = this.createElementNS('gml:segments');
|
||||
this.writeNode('LineStringSegment', geometry, null, node);
|
||||
return node;
|
||||
},
|
||||
'LineStringSegment': function(geometry) {
|
||||
var node = this.createElementNS('gml:LineStringSegment');
|
||||
this.writeNode('posList', geometry.getCoordinates(), null, node);
|
||||
return node;
|
||||
},
|
||||
'posList': function(points) {
|
||||
// only 2d for simple features profile
|
||||
var len = points.length;
|
||||
var parts = new Array(len);
|
||||
var point;
|
||||
for (var i = 0; i < len; ++i) {
|
||||
point = points[i];
|
||||
if (this.xy) {
|
||||
parts[i] = point[0] + ' ' + point[1];
|
||||
} else {
|
||||
parts[i] = point[1] + ' ' + point[0];
|
||||
}
|
||||
}
|
||||
var node = this.createElementNS('gml:posList');
|
||||
node.appendChild(this.createTextNode(parts.join(' ')));
|
||||
return node;
|
||||
},
|
||||
'Surface': function(geometry) {
|
||||
var node = this.createElementNS('gml:Surface');
|
||||
this.writeNode('patches', geometry, null, node);
|
||||
return node;
|
||||
},
|
||||
'patches': function(geometry) {
|
||||
var node = this.createElementNS('gml:patches');
|
||||
this.writeNode('PolygonPatch', geometry, null, node);
|
||||
return node;
|
||||
},
|
||||
'PolygonPatch': function(geometry) {
|
||||
var node = this.createElementNS('gml:PolygonPatch');
|
||||
node.setAttribute('interpolation', 'planar');
|
||||
var coordinates = geometry.getCoordinates();
|
||||
this.writeNode('exterior', coordinates[0], null, node);
|
||||
for (var i = 1, len = coordinates.length; i < len; ++i) {
|
||||
this.writeNode('interior', coordinates[i], null, node);
|
||||
}
|
||||
return node;
|
||||
},
|
||||
'Polygon': function(geometry) {
|
||||
var node = this.createElementNS('gml:Polygon');
|
||||
var coordinates = geometry.getCoordinates();
|
||||
this.writeNode('exterior', coordinates[0], null, node);
|
||||
for (var i = 1, len = coordinates.length; i < len; ++i) {
|
||||
this.writeNode('interior', coordinates[i], null, node);
|
||||
}
|
||||
return node;
|
||||
},
|
||||
'exterior': function(ring) {
|
||||
var node = this.createElementNS('gml:exterior');
|
||||
this.writeNode('LinearRing', ring, null, node);
|
||||
return node;
|
||||
},
|
||||
'interior': function(ring) {
|
||||
var node = this.createElementNS('gml:interior');
|
||||
this.writeNode('LinearRing', ring, null, node);
|
||||
return node;
|
||||
},
|
||||
'LinearRing': function(ring) {
|
||||
var node = this.createElementNS('gml:LinearRing');
|
||||
this.writeNode('posList', ring, null, node);
|
||||
return node;
|
||||
},
|
||||
'MultiCurve': function(geometry) {
|
||||
var node = this.createElementNS('gml:MultiCurve');
|
||||
for (var i = 0, len = geometry.components.length; i < len; ++i) {
|
||||
this.writeNode('curveMember', geometry.components[i], null, node);
|
||||
}
|
||||
return node;
|
||||
},
|
||||
'curveMember': function(geometry) {
|
||||
var node = this.createElementNS('gml:curveMember');
|
||||
if (this.curve) {
|
||||
this.writeNode('Curve', geometry, null, node);
|
||||
} else {
|
||||
this.writeNode('LineString', geometry, null, node);
|
||||
}
|
||||
return node;
|
||||
},
|
||||
'MultiSurface': function(geometry) {
|
||||
var node = this.createElementNS('gml:MultiSurface');
|
||||
for (var i = 0, len = geometry.components.length; i < len; ++i) {
|
||||
this.writeNode('surfaceMember', geometry.components[i], null, node);
|
||||
}
|
||||
return node;
|
||||
},
|
||||
'surfaceMember': function(polygon) {
|
||||
var node = this.createElementNS('gml:surfaceMember');
|
||||
if (this.surface) {
|
||||
this.writeNode('Surface', polygon, null, node);
|
||||
} else {
|
||||
this.writeNode('Polygon', polygon, null, node);
|
||||
}
|
||||
return node;
|
||||
},
|
||||
'Envelope': function(bounds) {
|
||||
var node = this.createElementNS('gml:Envelope');
|
||||
this.writeNode('lowerCorner', bounds, null, node);
|
||||
this.writeNode('upperCorner', bounds, null, node);
|
||||
// srsName attribute is required for gml:Envelope
|
||||
if (this.srsName) {
|
||||
node.setAttribute('srsName', this.srsName);
|
||||
}
|
||||
return node;
|
||||
},
|
||||
'lowerCorner': function(bounds) {
|
||||
// only 2d for simple features profile
|
||||
var pos;
|
||||
if (this.xy) {
|
||||
pos = (bounds.left + ' ' + bounds.bottom);
|
||||
} else {
|
||||
pos = (bounds.bottom + ' ' + bounds.left);
|
||||
}
|
||||
var node = this.createElementNS('gml:lowerCorner');
|
||||
node.appendChild(this.createTextNode(pos));
|
||||
return node;
|
||||
},
|
||||
'upperCorner': function(bounds) {
|
||||
// only 2d for simple features profile
|
||||
var pos;
|
||||
if (this.xy) {
|
||||
pos = (bounds.right + ' ' + bounds.top);
|
||||
} else {
|
||||
pos = (bounds.top + ' ' + bounds.right);
|
||||
}
|
||||
var node = this.createElementNS('gml:upperCorner');
|
||||
node.appendChild(this.createTextNode(pos));
|
||||
return node;
|
||||
}
|
||||
});
|
||||
};
|
||||
goog.inherits(ol.parser.ogc.GML_v3, ol.parser.ogc.GML);
|
||||
|
||||
|
||||
/**
|
||||
* @param {Object} obj Object structure to write out as XML.
|
||||
* @return {string} An string representing the XML document.
|
||||
*/
|
||||
ol.parser.ogc.GML_v3.prototype.write = function(obj) {
|
||||
var root = this.writeNode('featureMembers', obj.features);
|
||||
this.setAttributeNS(
|
||||
root, 'http://www.w3.org/2001/XMLSchema-instance',
|
||||
'xsi:schemaLocation', this.schemaLocation);
|
||||
return this.serialize(root);
|
||||
};
|
||||
Reference in New Issue
Block a user