merge with master - solving conflicts

This commit is contained in:
Bart van den Eijnden
2013-08-09 09:55:44 +02:00
209 changed files with 14572 additions and 1847 deletions

View File

@@ -18,7 +18,7 @@ ol.parser.DomFeatureParser = function() {};
/**
* @param {Element|Document} node Document or element node.
* @param {ol.parser.ReadFeaturesOptions=} opt_options Feature reading options.
* @return {Array.<ol.Feature>} Array of features.
* @return {ol.parser.ReadFeaturesResult} Features and metadata.
*/
ol.parser.DomFeatureParser.prototype.readFeaturesFromNode =
goog.abstractMethod;
@@ -34,7 +34,7 @@ ol.parser.ObjectFeatureParser = function() {};
/**
* @param {Object} obj Object representing features.
* @param {ol.parser.ReadFeaturesOptions=} opt_options Feature reading options.
* @return {Array.<ol.Feature>} Array of features.
* @return {ol.parser.ReadFeaturesResult} Features and metadata.
*/
ol.parser.ObjectFeatureParser.prototype.readFeaturesFromObject =
goog.abstractMethod;
@@ -50,7 +50,7 @@ ol.parser.StringFeatureParser = function() {};
/**
* @param {string} data String data.
* @param {ol.parser.ReadFeaturesOptions=} opt_options Feature reading options.
* @return {Array.<ol.Feature>} Array of features.
* @return {ol.parser.ReadFeaturesResult} Features and metadata.
*/
ol.parser.StringFeatureParser.prototype.readFeaturesFromString =
goog.abstractMethod;
@@ -65,8 +65,8 @@ ol.parser.AsyncStringFeatureParser = function() {};
/**
* @param {string} data String data.
* @param {function(Array.<ol.Feature>)} callback Callback which is called
* after parsing.
* @param {function(ol.parser.ReadFeaturesResult)} callback Callback which is
* called after parsing.
* @param {ol.parser.ReadFeaturesOptions=} opt_options Feature reading options.
*/
ol.parser.AsyncStringFeatureParser.prototype.readFeaturesFromStringAsync =
@@ -82,8 +82,8 @@ ol.parser.AsyncObjectFeatureParser = function() {};
/**
* @param {Object} obj Object representing features.
* @param {function(Array.<ol.Feature>)} callback Callback which is called
* after parsing.
* @param {function(ol.parser.ReadFeaturesResult)} callback Callback which is
* called after parsing.
* @param {ol.parser.ReadFeaturesOptions=} opt_options Feature reading options.
*/
ol.parser.AsyncObjectFeatureParser.prototype.readFeaturesFromObjectAsync =
@@ -96,7 +96,20 @@ ol.parser.AsyncObjectFeatureParser.prototype.readFeaturesFromObjectAsync =
ol.parser.ReadFeaturesCallback;
/**
* @typedef {{projection: ol.ProjectionLike}}
*/
ol.parser.ReadFeaturesMetadata;
/**
* @typedef {{callback: ol.parser.ReadFeaturesCallback}}
*/
ol.parser.ReadFeaturesOptions;
/**
* @typedef {{features: Array.<ol.Feature>,
* metadata: ol.parser.ReadFeaturesMetadata}}
*/
ol.parser.ReadFeaturesResult;

View File

@@ -58,12 +58,13 @@ ol.parser.GeoJSON.read = function(str) {
* Parse a GeoJSON feature collection.
* @param {string} str GeoJSON feature collection.
* @param {ol.parser.ReadFeaturesOptions=} opt_options Reader options.
* @return {Array.<ol.Feature>} Array of features.
* @return {ol.parser.ReadFeaturesResult} Features and metadata.
*/
ol.parser.GeoJSON.prototype.readFeaturesFromString =
function(str, opt_options) {
var json = /** @type {GeoJSONFeatureCollection} */ (JSON.parse(str));
return this.parseFeatureCollection_(json, opt_options);
return {features: this.parseAsFeatureCollection_(json, opt_options),
metadata: {projection: 'EPSG:4326'}};
};
@@ -72,67 +73,86 @@ ol.parser.GeoJSON.prototype.readFeaturesFromString =
* @param {GeoJSONFeatureCollection} object GeoJSON feature collection decoded
* from JSON.
* @param {ol.parser.ReadFeaturesOptions=} opt_options Reader options.
* @return {Array.<ol.Feature>} Array of features.
* @return {ol.parser.ReadFeaturesResult} Features and metadata.
*/
ol.parser.GeoJSON.prototype.readFeaturesFromObject =
function(object, opt_options) {
return this.parseFeatureCollection_(object, opt_options);
return {features: this.parseAsFeatureCollection_(object, opt_options),
metadata: {projection: 'EPSG:4326'}};
};
/**
* Parse any GeoJSON object. Note that this method should not be called
* recursively due to the shared vertex creation.
*
* @param {GeoJSONObject} json GeoJSON object.
* @param {ol.parser.ReadFeaturesOptions=} opt_options Reader options.
* @return {ol.Feature|Array.<ol.Feature>|
* ol.geom.Geometry|Array.<ol.geom.Geometry>} Parsed geometry or array
* of geometries.
* @private
*/
ol.parser.GeoJSON.prototype.parse_ = function(json) {
ol.parser.GeoJSON.prototype.parse_ = function(json, opt_options) {
var result;
switch (json.type) {
case 'FeatureCollection':
result = this.parseFeatureCollection_(
/** @type {GeoJSONFeatureCollection} */ (json));
break;
case 'Feature':
result = this.parseFeature_(
/** @type {GeoJSONFeature} */ (json));
break;
case 'GeometryCollection':
result = this.parseGeometryCollection_(
/** @type {GeoJSONGeometryCollection} */ (json));
break;
case 'Point':
result = this.parsePoint_(
/** @type {GeoJSONGeometry} */ (json));
break;
case 'LineString':
result = this.parseLineString_(
/** @type {GeoJSONGeometry} */ (json));
break;
case 'Polygon':
result = this.parsePolygon_(
/** @type {GeoJSONGeometry} */ (json));
break;
case 'MultiPoint':
result = this.parseMultiPoint_(
/** @type {GeoJSONGeometry} */ (json));
break;
case 'MultiLineString':
result = this.parseMultiLineString_(
/** @type {GeoJSONGeometry} */ (json));
break;
case 'MultiPolygon':
result = this.parseMultiPolygon_(
/** @type {GeoJSONGeometry} */ (json));
break;
default:
throw new Error('GeoJSON parsing not implemented for type: ' + json.type);
if (json.type === 'FeatureCollection') {
result = this.parseFeatureCollection_(
/** @type {GeoJSONFeatureCollection} */ (json), opt_options);
} else if (json.type === 'Feature') {
result = this.parseFeature_(
/** @type {GeoJSONFeature} */ (json), opt_options);
} else if (json.type === 'GeometryCollection') {
result = this.parseGeometryCollection_(
/** @type {GeoJSONGeometryCollection} */ (json), opt_options);
} else {
// we've been called with a geometry or an unknown object
// create a feature to get shared vertices handling
var feature = this.parseFeature_(
/** @type {GeoJSONFeature} */ ({type: 'Feature', geometry: json}),
opt_options);
result = feature.getGeometry();
}
return result;
};
/**
* @param {GeoJSONObject} json GeoJSON object.
* @param {ol.parser.ReadFeaturesOptions=} opt_options Reader options.
* @return {Array.<ol.Feature>} Parsed object coerced into array of features.
* @private
*/
ol.parser.GeoJSON.prototype.parseAsFeatureCollection_ = function(json,
opt_options) {
var obj = this.parse_(json, opt_options);
var features = [];
var feature;
if (obj instanceof ol.Feature) {
features = [obj];
} else if (obj instanceof ol.geom.Geometry) {
feature = new ol.Feature();
feature.setGeometry(obj);
features = [feature];
} else if (goog.isArray(obj)) {
var item, geomArray;
for (var i = 0, ii = obj.length; i < ii; ++i) {
item = obj[i];
geomArray = geomArray || (item instanceof ol.geom.Geometry);
if (!geomArray) {
goog.asserts.assert(item instanceof ol.Feature, 'expected feature');
features = obj;
break;
} else {
feature = new ol.Feature();
feature.setGeometry(item);
features[i] = feature;
}
}
}
return features;
};
/**
* @param {GeoJSONFeature} json GeoJSON feature.
* @param {ol.parser.ReadFeaturesOptions=} opt_options Read options.
@@ -207,17 +227,20 @@ ol.parser.GeoJSON.prototype.parseFeatureCollection_ = function(
/**
* @param {GeoJSONGeometryCollection} json GeoJSON geometry collection.
* @param {ol.parser.ReadFeaturesOptions=} opt_options Read options.
* @return {Array.<ol.geom.Geometry>} Parsed array of geometries.
* @private
*/
ol.parser.GeoJSON.prototype.parseGeometryCollection_ = function(json) {
ol.parser.GeoJSON.prototype.parseGeometryCollection_ = function(json,
opt_options) {
var geometries = json.geometries,
len = geometries.length,
result = new Array(len),
i;
for (i = 0; i < len; ++i) {
result[i] = this.parse_(/** @type {GeoJSONGeometry} */ (geometries[i]));
result[i] = this.parse_(/** @type {GeoJSONGeometry} */ (geometries[i]),
opt_options);
}
return result;
};

View File

@@ -234,7 +234,7 @@ goog.inherits(ol.parser.GPX, ol.parser.XML);
/**
* @param {string|Document|Element|Object} data Data to read.
* @return {Object} An object representing the document.
* @return {ol.parser.ReadFeaturesResult} An object representing the document.
*/
ol.parser.GPX.prototype.read = function(data) {
if (goog.isString(data)) {
@@ -243,7 +243,8 @@ ol.parser.GPX.prototype.read = function(data) {
if (data && data.nodeType == 9) {
data = data.documentElement;
}
var obj = {};
var obj = /** @type {ol.parser.ReadFeaturesResult} */
({metadata: {projection: 'EPSG:4326'}});
this.readNode(data, obj);
return obj;
};
@@ -253,12 +254,12 @@ ol.parser.GPX.prototype.read = function(data) {
* Parse a GPX document provided as a string.
* @param {string} str GPX document.
* @param {ol.parser.ReadFeaturesOptions=} opt_options Reader options.
* @return {Array.<ol.Feature>} Array of features.
* @return {ol.parser.ReadFeaturesResult} Features and metadata.
*/
ol.parser.GPX.prototype.readFeaturesFromString =
function(str, opt_options) {
this.readFeaturesOptions_ = opt_options;
return this.read(str).features;
return this.read(str);
};
@@ -266,24 +267,24 @@ ol.parser.GPX.prototype.readFeaturesFromString =
* Parse a GPX document provided as a DOM structure.
* @param {Element|Document} node Document or element node.
* @param {ol.parser.ReadFeaturesOptions=} opt_options Feature reading options.
* @return {Array.<ol.Feature>} Array of features.
* @return {ol.parser.ReadFeaturesResult} Features and metadata.
*/
ol.parser.GPX.prototype.readFeaturesFromNode =
function(node, opt_options) {
this.readFeaturesOptions_ = opt_options;
return this.read(node).features;
return this.read(node);
};
/**
* @param {Object} obj Object representing features.
* @param {ol.parser.ReadFeaturesOptions=} opt_options Feature reading options.
* @return {Array.<ol.Feature>} Array of features.
* @return {ol.parser.ReadFeaturesResult} Features and metadata.
*/
ol.parser.GPX.prototype.readFeaturesFromObject =
function(obj, opt_options) {
this.readFeaturesOptions_ = opt_options;
return this.read(obj).features;
return this.read(obj);
};

View File

@@ -184,24 +184,25 @@ ol.parser.KML = function(opt_options) {
var buckets = goog.array.bucket(parts, function(val) {
return val.type;
});
// homogeneous collection
var obj = {};
if (goog.object.getCount(buckets) === 1) {
// homogeneous collection
var type = goog.object.getAnyKey(buckets);
switch (type) {
case ol.geom.GeometryType.POINT:
container.geometry = {
obj.geometry = {
type: ol.geom.GeometryType.MULTIPOINT,
parts: parts
};
break;
case ol.geom.GeometryType.LINESTRING:
container.geometry = {
obj.geometry = {
type: ol.geom.GeometryType.MULTILINESTRING,
parts: parts
};
break;
case ol.geom.GeometryType.POLYGON:
container.geometry = {
obj.geometry = {
type: ol.geom.GeometryType.MULTIPOLYGON,
parts: parts
};
@@ -210,11 +211,18 @@ ol.parser.KML = function(opt_options) {
break;
}
} else {
container.geometry = {
// mixed collection
obj.geometry = {
type: ol.geom.GeometryType.GEOMETRYCOLLECTION,
parts: parts
};
}
if (goog.isArray(container)) {
// MultiGeometry nested inside another
container.push(obj.geometry);
} else {
container.geometry = obj.geometry;
}
},
'Point': function(node, container) {
var coordinates = [];
@@ -334,7 +342,7 @@ ol.parser.KML = function(opt_options) {
this.readChildNodes(node, symbolizer);
if (symbolizer.color) {
symbolizer.strokeColor = symbolizer.color.color;
symbolizer.opacity = symbolizer.color.opacity;
symbolizer.strokeOpacity = symbolizer.color.opacity;
}
if (symbolizer.width) {
symbolizer.strokeWidth = parseFloat(symbolizer.width);
@@ -345,30 +353,31 @@ ol.parser.KML = function(opt_options) {
obj['symbolizers'].push(new ol.style.Line(symbolizer));
},
'PolyStyle': function(node, obj) {
var symbolizer = {};
this.readChildNodes(node, symbolizer);
if (symbolizer.color) {
symbolizer.fillColor = symbolizer.color.color;
var style = {}; // from KML
var symbolizer = {}; // for ol.style.Polygon
this.readChildNodes(node, style);
// check if poly has fill
if (!(style.fill === '0' || style.fill === 'false')) {
if (style.color) {
symbolizer.fillColor = style.color.color;
symbolizer.fillOpacity = style.color.opacity;
} else {
// KML defaults
symbolizer.fillColor = '#ffffff';
symbolizer.fillOpacity = 1;
}
}
if (symbolizer.fill === '0' || symbolizer.fill === 'false') {
// TODO we need a better way in the symbolizer to disable fill
// now we are using opacity for this, but it's a workaround
// see also: https://github.com/openlayers/ol3/issues/475
symbolizer.opacity = 0;
} else {
symbolizer.opacity = symbolizer.color.opacity;
// check if poly has stroke
if (!(style.outline === '0' || style.outline === 'false')) {
if (style.color) {
symbolizer.strokeColor = style.color.color;
symbolizer.strokeOpacity = style.color.opacity;
} else {
// KML defaults
symbolizer.strokeColor = '#ffffff';
symbolizer.strokeOpacity = 1;
}
}
if (symbolizer.width) {
symbolizer.strokeWidth = parseFloat(symbolizer.width);
}
// outline disabled
if (symbolizer.outline === '0' || symbolizer.outline === 'false') {
symbolizer.strokeWidth = 0;
}
delete symbolizer.outline;
delete symbolizer.width;
delete symbolizer.color;
delete symbolizer.fill;
obj['ids'].push(node.getAttribute('id'));
obj['symbolizers'].push(new ol.style.Polygon(symbolizer));
},
@@ -615,6 +624,11 @@ ol.parser.KML = function(opt_options) {
}
},
'PolyStyle': function(symbolizerObj) {
/**
* There is not a 1:1 mapping between KML PolyStyle and
* ol.style.Polygon. In KML, if a PolyStyle has <outline>1</outline>
* then the "current" LineStyle is used to stroke the polygon.
*/
var node = this.createElementNS('PolyStyle');
if (symbolizerObj.id) {
this.setAttributeNS(node, null, 'id', symbolizerObj.id);
@@ -622,16 +636,27 @@ ol.parser.KML = function(opt_options) {
var symbolizer = symbolizerObj.symbolizer;
var literal = symbolizer instanceof ol.style.PolygonLiteral ?
symbolizer : symbolizer.createLiteral();
if (literal.opacity !== 0) {
var color, opacity;
if (literal.fillOpacity !== 0) {
this.writeNode('fill', '1', null, node);
color = literal.fillColor;
opacity = literal.fillOpacity;
} else {
this.writeNode('fill', '0', null, node);
}
this.writeNode('color', {
color: literal.fillColor.substring(1),
opacity: literal.opacity
}, null, node);
this.writeNode('width', literal.strokeWidth, null, node);
if (literal.strokeOpacity) {
this.writeNode('outline', '1', null, node);
color = color || literal.strokeColor;
opacity = opacity || literal.strokeOpacity;
} else {
this.writeNode('outline', '0', null, node);
}
if (color && opacity) {
this.writeNode('color', {
color: color.substring(1),
opacity: opacity
}, null, node);
}
return node;
},
'fill': function(fill) {
@@ -639,6 +664,11 @@ ol.parser.KML = function(opt_options) {
node.appendChild(this.createTextNode(fill));
return node;
},
'outline': function(outline) {
var node = this.createElementNS('outline');
node.appendChild(this.createTextNode(outline));
return node;
},
'LineStyle': function(symbolizerObj) {
var node = this.createElementNS('LineStyle');
if (symbolizerObj.id) {
@@ -649,7 +679,7 @@ ol.parser.KML = function(opt_options) {
symbolizer : symbolizer.createLiteral();
this.writeNode('color', {
color: literal.strokeColor.substring(1),
opacity: literal.opacity
opacity: literal.strokeOpacity
}, null, node);
this.writeNode('width', literal.strokeWidth, null, node);
return node;
@@ -755,6 +785,10 @@ ol.parser.KML = function(opt_options) {
return node;
},
'Polygon': function(geometry) {
/**
* KML doesn't specify the winding order of coordinates in linear
* rings. So we keep them as they are in the geometries.
*/
var node = this.createElementNS('Polygon');
var coordinates = geometry.getCoordinates();
this.writeNode('outerBoundaryIs', coordinates[0], null, node);
@@ -809,8 +843,8 @@ goog.inherits(ol.parser.KML, ol.parser.XML);
/**
* @param {Object} obj Object representing features.
* @param {function(Array.<ol.Feature>)} callback Callback which is called
* after parsing.
* @param {function(ol.parser.ReadFeaturesResult)} callback Callback which is
* called after parsing.
* @param {ol.parser.ReadFeaturesOptions=} opt_options Feature reading options.
*/
ol.parser.KML.prototype.readFeaturesFromObjectAsync =
@@ -821,9 +855,9 @@ ol.parser.KML.prototype.readFeaturesFromObjectAsync =
/**
* @param {string} str KML document.
* @param {function(Array.<ol.Feature>)} callback Callback which is called
* after parsing.
* @param {string} str String data.
* @param {function(ol.parser.ReadFeaturesResult)}
* callback Callback which is called after parsing.
* @param {ol.parser.ReadFeaturesOptions=} opt_options Feature reading options.
*/
ol.parser.KML.prototype.readFeaturesFromStringAsync =
@@ -837,12 +871,12 @@ ol.parser.KML.prototype.readFeaturesFromStringAsync =
* Parse a KML document provided as a string.
* @param {string} str KML document.
* @param {ol.parser.ReadFeaturesOptions=} opt_options Reader options.
* @return {Array.<ol.Feature>} Array of features.
* @return {ol.parser.ReadFeaturesResult} Features and metadata.
*/
ol.parser.KML.prototype.readFeaturesFromString =
function(str, opt_options) {
this.readFeaturesOptions_ = opt_options;
return this.read(str).features;
return /** @type {ol.parser.ReadFeaturesResult} */ (this.read(str));
};
@@ -850,24 +884,24 @@ ol.parser.KML.prototype.readFeaturesFromString =
* Parse a KML document provided as a DOM structure.
* @param {Element|Document} node Document or element node.
* @param {ol.parser.ReadFeaturesOptions=} opt_options Feature reading options.
* @return {Array.<ol.Feature>} Array of features.
* @return {ol.parser.ReadFeaturesResult} Features and metadata.
*/
ol.parser.KML.prototype.readFeaturesFromNode =
function(node, opt_options) {
this.readFeaturesOptions_ = opt_options;
return this.read(node).features;
return /** @type {ol.parser.ReadFeaturesResult} */ (this.read(node));
};
/**
* @param {Object} obj Object representing features.
* @param {ol.parser.ReadFeaturesOptions=} opt_options Feature reading options.
* @return {Array.<ol.Feature>} Array of features.
* @return {ol.parser.ReadFeaturesResult} Features and metadata.
*/
ol.parser.KML.prototype.readFeaturesFromObject =
function(obj, opt_options) {
this.readFeaturesOptions_ = opt_options;
return this.read(obj).features;
return /** @type {ol.parser.ReadFeaturesResult} */ (this.read(obj));
};
@@ -918,9 +952,11 @@ ol.parser.KML.prototype.parseLinks = function(deferreds, obj, done) {
/**
* @param {string|Document|Element|Object} data Data to read.
* @param {Function=} opt_callback Optional callback to call when reading
* is done.
* @return {Object} An object representing the document.
* @param {function(ol.parser.ReadFeaturesResult)=} opt_callback Optional
* callback to call when reading is done. If provided, this method will
* return undefined.
* @return {ol.parser.ReadFeaturesResult|undefined} An object representing the
* document if `opt_callback` was not provided.
*/
ol.parser.KML.prototype.read = function(data, opt_callback) {
if (goog.isString(data)) {
@@ -929,7 +965,8 @@ ol.parser.KML.prototype.read = function(data, opt_callback) {
if (data && data.nodeType == 9) {
data = data.documentElement;
}
var obj = {};
var obj = /** @type {ol.parser.ReadFeaturesResult} */
({metadata: {projection: 'EPSG:4326'}});
this.readNode(data, obj);
if (goog.isDef(opt_callback)) {
var deferreds = [];
@@ -943,7 +980,7 @@ ol.parser.KML.prototype.read = function(data, opt_callback) {
var feature = obj.features[i];
this.applyStyle_(feature, obj['styles']);
}
opt_callback.call(null, obj.features);
opt_callback.call(null, obj);
}, function() {
throw new Error('KML: parsing of NetworkLinks failed');
}, this);
@@ -951,7 +988,6 @@ ol.parser.KML.prototype.read = function(data, opt_callback) {
} else {
return obj;
}
return null;
};
@@ -1020,7 +1056,7 @@ ol.parser.KML.prototype.createGeometry_ = function(container,
for (i = 0, ii = container.geometry.parts.length; i < ii; i++) {
coordinates.push(container.geometry.parts[i].coordinates);
}
geometry = ol.geom.MultiPoint.fromParts(coordinates, opt_vertices);
geometry = new ol.geom.MultiPoint(coordinates, opt_vertices);
break;
case ol.geom.GeometryType.MULTILINESTRING:
coordinates = [];
@@ -1034,7 +1070,7 @@ ol.parser.KML.prototype.createGeometry_ = function(container,
for (i = 0, ii = container.geometry.parts.length; i < ii; i++) {
coordinates.push(container.geometry.parts[i].coordinates);
}
geometry = ol.geom.MultiPolygon.fromParts(coordinates, opt_vertices);
geometry = new ol.geom.MultiPolygon(coordinates, opt_vertices);
break;
case ol.geom.GeometryType.GEOMETRYCOLLECTION:
var geometries = [];

View File

@@ -1,5 +1,6 @@
goog.provide('ol.parser.ogc.GML');
goog.require('goog.array');
goog.require('goog.asserts');
goog.require('goog.dom.xml');
goog.require('ol.Feature');
goog.require('ol.geom.Geometry');
@@ -14,6 +15,7 @@ goog.require('ol.geom.Point');
goog.require('ol.geom.Polygon');
goog.require('ol.parser.StringFeatureParser');
goog.require('ol.parser.XML');
goog.require('ol.proj');
@@ -27,8 +29,6 @@ goog.require('ol.parser.XML');
ol.parser.ogc.GML = function(opt_options) {
var options = /** @type {ol.parser.GMLOptions} */
(goog.isDef(opt_options) ? opt_options : {});
this.axisOrientation = goog.isDef(options.axisOrientation) ?
options.axisOrientation : 'enu';
this.extractAttributes = goog.isDef(options.extractAttributes) ?
options.extractAttributes : true;
this.surface = goog.isDef(options.surface) ?
@@ -39,8 +39,21 @@ ol.parser.ogc.GML = function(opt_options) {
options.multiCurve : true;
this.multiSurface = goog.isDef(options.multiSurface) ?
options.multiSurface : true;
this.srsName = goog.isDef(options.srsName) ?
options.srsName : null;
this.readOptions = options.readOptions;
this.writeOptions = options.writeOptions;
/**
* @protected
* @type {string|undefined}
*/
this.srsName;
/**
* @protected
* @type {string|undefined}
*/
this.axisOrientation;
if (goog.isDef(options.schemaLocation)) {
this.schemaLocation = options.schemaLocation;
}
@@ -61,7 +74,18 @@ ol.parser.ogc.GML = function(opt_options) {
},
'http://www.opengis.net/gml': {
'_inherit': function(node, obj, container) {
// To be implemented by version specific parsers
// Version specific parsers extend this with goog.functions.sequence
var srsName;
if (!goog.isDef(this.srsName)) {
srsName = this.srsName = node.getAttribute('srsName');
}
if (!goog.isDef(this.axisOrientation)) {
if (goog.isDefAndNotNull(srsName)) {
this.axisOrientation = ol.proj.get(srsName).getAxisOrientation();
} else {
this.axisOrientation = 'enu';
}
}
},
'name': function(node, obj) {
obj.name = this.getChildValue(node);
@@ -126,6 +150,8 @@ ol.parser.ogc.GML = function(opt_options) {
},
'Point': function(node, container) {
var coordinates = [];
this.readers[this.defaultNamespaceURI]['_inherit'].apply(this,
[node, coordinates, container]);
this.readChildNodes(node, coordinates);
var point = {
type: ol.geom.GeometryType.POINT,
@@ -315,9 +341,9 @@ ol.parser.ogc.GML = function(opt_options) {
}
this.writers = {
'http://www.opengis.net/gml': {
'featureMember': function(feature) {
'featureMember': function(obj) {
var node = this.createElementNS('gml:featureMember');
this.writeNode('_typeName', feature, this.featureNS, node);
this.writeNode('_typeName', obj, this.featureNS, node);
return node;
},
'MultiPoint': function(geometry) {
@@ -455,17 +481,38 @@ goog.inherits(ol.parser.ogc.GML, ol.parser.XML);
/**
* @param {string|Document|Element|Object} data Data to read.
* @return {Object} An object representing the document.
* @param {ol.parser.GMLReadOptions=} opt_options Read options.
* @return {ol.parser.ReadFeaturesResult} An object representing the document.
*/
ol.parser.ogc.GML.prototype.read = function(data) {
ol.parser.ogc.GML.prototype.read = function(data, opt_options) {
var srsName;
if (goog.isDef(opt_options) && goog.isDef(opt_options.srsName)) {
srsName = opt_options.srsName;
} else if (goog.isDef(this.readOptions) &&
goog.isDef(this.readOptions.srsName)) {
srsName = this.readOptions.srsName;
}
if (goog.isDef(srsName)) {
this.srsName = goog.isString(srsName) ? srsName : srsName.getCode();
}
if (goog.isDef(opt_options) && goog.isDef(opt_options.axisOrientation)) {
this.axisOrientation = opt_options.axisOrientation;
} else if (goog.isDef(this.readOptions) &&
goog.isDef(this.readOptions.axisOrientation)) {
this.axisOrientation = this.readOptions.axisOrientation;
}
if (typeof data == 'string') {
data = goog.dom.xml.loadXml(data);
}
if (data && data.nodeType == 9) {
data = data.documentElement;
}
var obj = {features: []};
var obj = /** @type {ol.parser.ReadFeaturesResult} */
({features: [], metadata: {}});
this.readNode(data, obj, true);
obj.metadata.projection = this.srsName;
delete this.srsName;
delete this.axisOrientation;
return obj;
};
@@ -569,10 +616,41 @@ ol.parser.ogc.GML.prototype.createGeometry = function(container,
* Parse a GML document provided as a string.
* @param {string} str GML document.
* @param {ol.parser.ReadFeaturesOptions=} opt_options Reader options.
* @return {Array.<ol.Feature>} Array of features.
* @return {ol.parser.ReadFeaturesResult} Features and metadata.
*/
ol.parser.ogc.GML.prototype.readFeaturesFromString =
function(str, opt_options) {
this.readFeaturesOptions_ = opt_options;
return this.read(str).features;
return this.read(str);
};
/**
* Applies the writeOptions passed into the write function.
* @param {ol.parser.ReadFeaturesResult} obj Object structure to write out as
* GML.
* @param {ol.parser.GMLWriteOptions=} opt_options Write options.
*/
ol.parser.ogc.GML.prototype.applyWriteOptions = function(obj, opt_options) {
// srsName handling: opt_options -> this.writeOptions -> obj.metadata
var srsName;
if (goog.isDef(opt_options) && goog.isDef(opt_options.srsName)) {
srsName = opt_options.srsName;
} else if (goog.isDef(this.writeOptions) &&
goog.isDef(this.writeOptions.srsName)) {
srsName = this.writeOptions.srsName;
} else if (goog.isDef(obj.metadata)) {
srsName = obj.metadata.projection;
}
goog.asserts.assert(goog.isDef(srsName), 'srsName required for writing GML');
this.srsName = goog.isString(srsName) ? srsName : srsName.getCode();
// axisOrientation handling: opt_options -> this.writeOptions
if (goog.isDef(opt_options) && goog.isDef(opt_options.axisOrientation)) {
this.axisOrientation = opt_options.axisOrientation;
} else if (goog.isDef(this.writeOptions) &&
goog.isDef(this.writeOptions.axisOrientation)) {
this.axisOrientation = this.writeOptions.axisOrientation;
} else {
this.axisOrientation = ol.proj.get(this.srsName).getAxisOrientation();
}
};

View File

@@ -28,6 +28,8 @@ ol.parser.ogc.GML_v2 = function(opt_options) {
},
'Box': function(node, container) {
var coordinates = [];
this.readers[this.defaultNamespaceURI]['_inherit'].apply(this,
[node, coordinates, container]);
this.readChildNodes(node, coordinates);
container.projection = node.getAttribute('srsName');
container.bounds = [coordinates[0][0][0], coordinates[0][1][0],
@@ -68,9 +70,17 @@ ol.parser.ogc.GML_v2 = function(opt_options) {
'Polygon': function(geometry) {
var node = this.createElementNS('gml:Polygon');
var coordinates = geometry.getCoordinates();
this.writeNode('outerBoundaryIs', coordinates[0], null, node);
/**
* Though there continues to be ambiguity around this, GML references
* ISO 19107, which says polygons have counter-clockwise exterior rings
* and clockwise interior rings. The ambiguity comes because the
* the Simple Feature Access - SQL spec (ISO 19125-2) says that no
* winding order is enforced. Anyway, we write out counter-clockwise
* exterior and clockwise interior here but accept either when reading.
*/
this.writeNode('outerBoundaryIs', coordinates[0].reverse(), null, node);
for (var i = 1; i < coordinates.length; ++i) {
this.writeNode('innerBoundaryIs', coordinates[i], null, node);
this.writeNode('innerBoundaryIs', coordinates[i].reverse(), null, node);
}
return node;
},
@@ -105,14 +115,20 @@ goog.inherits(ol.parser.ogc.GML_v2, ol.parser.ogc.GML);
/**
* @param {Object} obj Object structure to write out as XML.
* @return {string} An string representing the XML document.
* @param {ol.parser.ReadFeaturesResult} obj Object structure to write out as
* GML.
* @param {ol.parser.GMLWriteOptions=} opt_options Write options.
* @return {string} A string representing the GML document.
*/
ol.parser.ogc.GML_v2.prototype.write = function(obj) {
ol.parser.ogc.GML_v2.prototype.write = function(obj, opt_options) {
this.applyWriteOptions(obj, opt_options);
var root = this.writeNode('FeatureCollection', obj.features,
'http://www.opengis.net/wfs');
this.setAttributeNS(
root, 'http://www.w3.org/2001/XMLSchema-instance',
'xsi:schemaLocation', this.schemaLocation);
return this.serialize(root);
var gml = this.serialize(root);
delete this.srsName;
delete this.axisOrientation;
return gml;
};

View File

@@ -1,6 +1,7 @@
goog.provide('ol.parser.ogc.GML_v3');
goog.require('goog.array');
goog.require('goog.functions');
goog.require('goog.object');
goog.require('ol.geom.GeometryType');
goog.require('ol.parser.ogc.GML');
@@ -61,14 +62,16 @@ ol.parser.ogc.GML_v3 = function(opt_options) {
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;
}
},
'_inherit': goog.functions.sequence(
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);
},
@@ -205,6 +208,8 @@ ol.parser.ogc.GML_v3 = function(opt_options) {
},
'Envelope': function(node, container) {
var coordinates = [];
this.readers[this.defaultNamespaceURI]['_inherit'].apply(this,
[node, coordinates, container]);
this.readChildNodes(node, coordinates);
container.projection = node.getAttribute('srsName');
container.bounds = [coordinates[0][0][0][0], coordinates[1][0][0][0],
@@ -299,18 +304,26 @@ ol.parser.ogc.GML_v3 = function(opt_options) {
var node = this.createElementNS('gml:PolygonPatch');
node.setAttribute('interpolation', 'planar');
var coordinates = geometry.getCoordinates();
this.writeNode('exterior', coordinates[0], null, node);
this.writeNode('exterior', coordinates[0].reverse(), null, node);
for (var i = 1, len = coordinates.length; i < len; ++i) {
this.writeNode('interior', coordinates[i], null, node);
this.writeNode('interior', coordinates[i].reverse(), null, node);
}
return node;
},
'Polygon': function(geometry) {
var node = this.createElementNS('gml:Polygon');
var coordinates = geometry.getCoordinates();
this.writeNode('exterior', coordinates[0], null, node);
/**
* Though there continues to be ambiguity around this, GML references
* ISO 19107, which says polygons have counter-clockwise exterior rings
* and clockwise interior rings. The ambiguity comes because the
* the Simple Feature Access - SQL spec (ISO 19125-2) says that no
* winding order is enforced. Anyway, we write out counter-clockwise
* exterior and clockwise interior here but accept either when reading.
*/
this.writeNode('exterior', coordinates[0].reverse(), null, node);
for (var i = 1, len = coordinates.length; i < len; ++i) {
this.writeNode('interior', coordinates[i], null, node);
this.writeNode('interior', coordinates[i].reverse(), null, node);
}
return node;
},
@@ -366,7 +379,7 @@ ol.parser.ogc.GML_v3 = function(opt_options) {
this.writeNode('lowerCorner', bounds, null, node);
this.writeNode('upperCorner', bounds, null, node);
// srsName attribute is required for gml:Envelope
if (this.srsName) {
if (goog.isDef(this.srsName)) {
node.setAttribute('srsName', this.srsName);
}
return node;
@@ -401,13 +414,19 @@ goog.inherits(ol.parser.ogc.GML_v3, ol.parser.ogc.GML);
/**
* @param {Object} obj Object structure to write out as XML.
* @param {ol.parser.ReadFeaturesResult} obj Object structure to write out as
* XML.
* @param {ol.parser.GMLWriteOptions=} opt_options Write options.
* @return {string} An string representing the XML document.
*/
ol.parser.ogc.GML_v3.prototype.write = function(obj) {
ol.parser.ogc.GML_v3.prototype.write = function(obj, opt_options) {
this.applyWriteOptions(obj, opt_options);
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);
var gml = this.serialize(root);
delete this.srsName;
delete this.axisOrientation;
return gml;
};

View File

@@ -0,0 +1,4 @@
@exportSymbol ol.parser.TopoJSON
@exportProperty ol.parser.TopoJSON.prototype.read
@exportProperty ol.parser.TopoJSON.read

441
src/ol/parser/topojson.js Normal file
View File

@@ -0,0 +1,441 @@
goog.provide('ol.parser.TopoJSON');
goog.require('ol.Feature');
goog.require('ol.geom.GeometryType');
goog.require('ol.geom.LineString');
goog.require('ol.geom.MultiLineString');
goog.require('ol.geom.MultiPoint');
goog.require('ol.geom.MultiPolygon');
goog.require('ol.geom.Point');
goog.require('ol.geom.Polygon');
goog.require('ol.geom.Vertex');
goog.require('ol.geom.VertexArray');
goog.require('ol.parser.Parser');
goog.require('ol.parser.ReadFeaturesOptions');
goog.require('ol.parser.StringFeatureParser');
/**
* @constructor
* @implements {ol.parser.StringFeatureParser}
* @extends {ol.parser.Parser}
*/
ol.parser.TopoJSON = function() {
/**
* Common feature for all shared vertex creation.
* // TODO: make feature optional in shared vertex callback
*
* @type {ol.Feature}
* @private
*/
this.feature_ = new ol.Feature();
};
goog.inherits(ol.parser.TopoJSON, ol.parser.Parser);
goog.addSingletonGetter(ol.parser.TopoJSON);
/**
* Concatenate arcs into a coordinate array.
* @param {Array.<number>} indices Indices of arcs to concatenate. Negative
* values indicate arcs need to be reversed.
* @param {Array.<ol.geom.VertexArray>} arcs Arcs (already transformed).
* @return {ol.geom.VertexArray} Coordinate array.
* @private
*/
ol.parser.TopoJSON.prototype.concatenateArcs_ = function(indices, arcs) {
var coordinates = [];
var index, arc;
for (var i = 0, ii = indices.length; i < ii; ++i) {
index = indices[i];
if (i > 0) {
// splicing together arcs, discard last point
coordinates.pop();
}
if (index >= 0) {
// forward arc
arc = arcs[index];
} else {
// reverse arc
arc = arcs[~index].slice().reverse();
}
coordinates.push.apply(coordinates, arc);
}
return coordinates;
};
/**
* Parse a TopoJSON string.
* @param {string} str TopoJSON string.
* @return {Array.<ol.Feature>} Array of features.
*/
ol.parser.TopoJSON.prototype.read = function(str) {
var topology = /** @type {TopoJSONTopology} */ (JSON.parse(str));
return this.readFeaturesFromObject(topology).features;
};
/**
* Create features from a TopoJSON topology string.
*
* @param {string} str TopoJSON topology string.
* @param {ol.parser.ReadFeaturesOptions=} opt_options Reader options.
* @return {ol.parser.ReadFeaturesResult} Features and metadata.
*/
ol.parser.TopoJSON.prototype.readFeaturesFromString =
function(str, opt_options) {
var topology = /** @type {TopoJSONTopology} */ (JSON.parse(str));
if (topology.type !== 'Topology') {
throw new Error('Not a "Topology" type object');
}
return {features: this.readFeaturesFromTopology_(topology, opt_options),
metadata: {projection: 'EPSG:4326'}};
};
/**
* Create features from a TopoJSON topology object.
*
* @param {TopoJSONTopology} topology TopoJSON topology object.
* @param {ol.parser.ReadFeaturesOptions=} opt_options Reader options.
* @return {ol.parser.ReadFeaturesResult} Features and metadata.
*/
ol.parser.TopoJSON.prototype.readFeaturesFromObject =
function(topology, opt_options) {
if (topology.type !== 'Topology') {
throw new Error('Not a "Topology" type object');
}
return {features: this.readFeaturesFromTopology_(topology, opt_options),
metadata: {projection: 'EPSG:4326'}};
};
/**
* Create a feature from a TopoJSON geometry object.
*
* @param {TopoJSONGeometry} object TopoJSON geometry object.
* @param {Array.<ol.geom.VertexArray>} arcs Array of arcs.
* @param {Array.<number>} scale Scale for each dimension.
* @param {Array.<number>} translate Translation for each dimension.
* @param {ol.parser.ReadFeaturesOptions=} opt_options Reader options.
* @return {ol.Feature} Feature.
* @private
*/
ol.parser.TopoJSON.prototype.readFeatureFromGeometry_ = function(object, arcs,
scale, translate, opt_options) {
var geometry;
var type = object.type;
if (type === 'Point') {
geometry = this.readPoint_(/** @type {TopoJSONPoint} */ (object), scale,
translate, opt_options);
} else if (type === 'LineString') {
geometry = this.readLineString_(/** @type {TopoJSONLineString} */ (object),
arcs, opt_options);
} else if (type === 'Polygon') {
geometry = this.readPolygon_(/** @type {TopoJSONPolygon} */ (object), arcs,
opt_options);
} else if (type === 'MultiPoint') {
geometry = this.readMultiPoint_(/** @type {TopoJSONMultiPoint} */ (object),
scale, translate, opt_options);
} else if (type === 'MultiLineString') {
geometry = this.readMultiLineString_(
/** @type {TopoJSONMultiLineString} */(object), arcs, opt_options);
} else if (type === 'MultiPolygon') {
geometry = this.readMultiPolygon_(
/** @type {TopoJSONMultiPolygon} */ (object), arcs, opt_options);
} else {
throw new Error('Unsupported geometry type: ' + type);
}
var feature = new ol.Feature();
feature.setGeometry(geometry);
if (goog.isDef(object.id)) {
feature.setFeatureId(String(object.id));
}
return feature;
};
/**
* Create features from a TopoJSON GeometryCollection object.
*
* @param {TopoJSONGeometryCollection} collection TopoJSON GeometryCollection
* object.
* @param {Array.<ol.geom.VertexArray>} arcs Array of arcs.
* @param {Array.<number>} scale Scale for each dimension.
* @param {Array.<number>} translate Translation for each dimension.
* @param {ol.parser.ReadFeaturesOptions=} opt_options Reader options.
* @return {Array.<ol.Feature>} Array of features.
* @private
*/
ol.parser.TopoJSON.prototype.readFeaturesFromGeometryCollection_ = function(
collection, arcs, scale, translate, opt_options) {
var geometries = collection.geometries;
var num = geometries.length;
var features = new Array(num);
for (var i = 0; i < num; ++i) {
features[i] = this.readFeatureFromGeometry_(geometries[i], arcs, scale,
translate, opt_options);
}
return features;
};
/**
* @param {TopoJSONTopology} topology TopoJSON object.
* @param {ol.parser.ReadFeaturesOptions=} opt_options Reader options.
* @return {Array.<ol.Feature>} Parsed features.
* @private
*/
ol.parser.TopoJSON.prototype.readFeaturesFromTopology_ = function(
topology, opt_options) {
var transform = topology.transform;
var scale = transform.scale;
var translate = transform.translate;
var arcs = topology.arcs;
this.transformArcs_(arcs, scale, translate);
var objects = topology.objects;
var features = [];
for (var key in objects) {
if (objects[key].type === 'GeometryCollection') {
features.push.apply(features, this.readFeaturesFromGeometryCollection_(
/** @type {TopoJSONGeometryCollection} */ (objects[key]),
arcs, scale, translate, opt_options));
} else {
features.push(this.readFeatureFromGeometry_(
/** @type {TopoJSONGeometry} */ (objects[key]),
arcs, scale, translate, opt_options));
}
}
return features;
};
/**
* Create a linestring from a TopoJSON geometry object.
*
* @param {TopoJSONLineString} object TopoJSON object.
* @param {Array.<ol.geom.VertexArray>} arcs Array of arcs.
* @param {ol.parser.ReadFeaturesOptions=} opt_options Reader options.
* @return {ol.geom.LineString} Geometry.
* @private
*/
ol.parser.TopoJSON.prototype.readLineString_ = function(object, arcs,
opt_options) {
var coordinates = this.concatenateArcs_(object.arcs, arcs);
// TODO: make feature optional in callback
var callback = opt_options && opt_options.callback;
var sharedVertices;
if (callback) {
sharedVertices = callback(this.feature_, ol.geom.GeometryType.LINESTRING);
}
return new ol.geom.LineString(coordinates, sharedVertices);
};
/**
* Create a multi-linestring from a TopoJSON geometry object.
*
* @param {TopoJSONMultiLineString} object TopoJSON object.
* @param {Array.<ol.geom.VertexArray>} arcs Array of arcs.
* @param {ol.parser.ReadFeaturesOptions=} opt_options Reader options.
* @return {ol.geom.MultiLineString} Geometry.
* @private
*/
ol.parser.TopoJSON.prototype.readMultiLineString_ = function(object, arcs,
opt_options) {
var array = object.arcs; // I'm out of good names
var num = array.length;
var coordinates = new Array(num);
for (var i = 0; i < num; ++i) {
coordinates[i] = this.concatenateArcs_(array[i], arcs);
}
// TODO: make feature optional in callback
var callback = opt_options && opt_options.callback;
var sharedVertices;
if (callback) {
sharedVertices = callback(this.feature_,
ol.geom.GeometryType.MULTILINESTRING);
}
return new ol.geom.MultiLineString(coordinates, sharedVertices);
};
/**
* Create a multi-point from a TopoJSON geometry object.
*
* @param {TopoJSONMultiPoint} object TopoJSON object.
* @param {Array.<number>} scale Scale for each dimension.
* @param {Array.<number>} translate Translation for each dimension.
* @param {ol.parser.ReadFeaturesOptions=} opt_options Reader options.
* @return {ol.geom.MultiPoint} Geometry.
* @private
*/
ol.parser.TopoJSON.prototype.readMultiPoint_ = function(object, scale,
translate, opt_options) {
var coordinates = object.coordinates;
for (var i = 0, ii = coordinates.length; i < ii; ++i) {
this.transformVertex_(coordinates[i], scale, translate);
}
// TODO: make feature optional in callback
var callback = opt_options && opt_options.callback;
var sharedVertices;
if (callback) {
sharedVertices = callback(this.feature_, ol.geom.GeometryType.MULTIPOINT);
}
return new ol.geom.MultiPoint(coordinates, sharedVertices);
};
/**
* Create a multi-polygon from a TopoJSON geometry object.
*
* @param {TopoJSONMultiPolygon} object TopoJSON object.
* @param {Array.<ol.geom.VertexArray>} arcs Array of arcs.
* @param {ol.parser.ReadFeaturesOptions=} opt_options Reader options.
* @return {ol.geom.MultiPolygon} Geometry.
* @private
*/
ol.parser.TopoJSON.prototype.readMultiPolygon_ = function(object, arcs,
opt_options) {
var array = object.arcs;
var numPolys = array.length;
var coordinates = new Array(numPolys);
var polyArray, numRings, ringCoords, j;
for (var i = 0; i < numPolys; ++i) {
// for each polygon
polyArray = array[i];
numRings = polyArray.length;
ringCoords = new Array(numRings);
for (j = 0; j < numRings; ++j) {
// for each ring
ringCoords[j] = this.concatenateArcs_(polyArray[j], arcs);
}
coordinates[i] = ringCoords;
}
// TODO: make feature optional in callback
var callback = opt_options && opt_options.callback;
var sharedVertices;
if (callback) {
sharedVertices = callback(this.feature_, ol.geom.GeometryType.MULTIPOLYGON);
}
return new ol.geom.MultiPolygon(coordinates, sharedVertices);
};
/**
* Create a point from a TopoJSON geometry object.
*
* @param {TopoJSONPoint} object TopoJSON object.
* @param {Array.<number>} scale Scale for each dimension.
* @param {Array.<number>} translate Translation for each dimension.
* @param {ol.parser.ReadFeaturesOptions=} opt_options Reader options.
* @return {ol.geom.Point} Geometry.
* @private
*/
ol.parser.TopoJSON.prototype.readPoint_ = function(object, scale, translate,
opt_options) {
var coordinates = object.coordinates;
this.transformVertex_(coordinates, scale, translate);
// TODO: make feature optional in callback
var callback = opt_options && opt_options.callback;
var sharedVertices;
if (callback) {
sharedVertices = callback(this.feature_, ol.geom.GeometryType.POINT);
}
return new ol.geom.Point(coordinates, sharedVertices);
};
/**
* Create a polygon from a TopoJSON geometry object.
*
* @param {TopoJSONPolygon} object TopoJSON object.
* @param {Array.<ol.geom.VertexArray>} arcs Array of arcs.
* @param {ol.parser.ReadFeaturesOptions=} opt_options Reader options.
* @return {ol.geom.Polygon} Geometry.
* @private
*/
ol.parser.TopoJSON.prototype.readPolygon_ = function(object, arcs,
opt_options) {
var array = object.arcs; // I'm out of good names
var num = array.length;
var coordinates = new Array(num);
for (var i = 0; i < num; ++i) {
coordinates[i] = this.concatenateArcs_(array[i], arcs);
}
// TODO: make feature optional in callback
var callback = opt_options && opt_options.callback;
var sharedVertices;
if (callback) {
sharedVertices = callback(this.feature_, ol.geom.GeometryType.POLYGON);
}
return new ol.geom.Polygon(coordinates, sharedVertices);
};
/**
* Apply a linear transform to array of arcs. The provided array of arcs is
* modified in place.
*
* @param {Array.<ol.geom.VertexArray>} arcs Array of arcs.
* @param {Array.<number>} scale Scale for each dimension.
* @param {Array.<number>} translate Translation for each dimension.
* @private
*/
ol.parser.TopoJSON.prototype.transformArcs_ = function(arcs, scale, translate) {
for (var i = 0, ii = arcs.length; i < ii; ++i) {
this.transformArc_(arcs[i], scale, translate);
}
};
/**
* Apply a linear transform to an arc. The provided arc is modified in place.
*
* @param {ol.geom.VertexArray} arc Arc.
* @param {Array.<number>} scale Scale for each dimension.
* @param {Array.<number>} translate Translation for each dimension.
* @private
*/
ol.parser.TopoJSON.prototype.transformArc_ = function(arc, scale, translate) {
var x = 0;
var y = 0;
var vertex;
for (var i = 0, ii = arc.length; i < ii; ++i) {
vertex = arc[i];
x += vertex[0];
y += vertex[1];
vertex[0] = x;
vertex[1] = y;
this.transformVertex_(vertex, scale, translate);
}
};
/**
* Apply a linear transform to a vertex. The provided vertex is modified in
* place.
*
* @param {ol.geom.Vertex} vertex Vertex.
* @param {Array.<number>} scale Scale for each dimension.
* @param {Array.<number>} translate Translation for each dimension.
* @private
*/
ol.parser.TopoJSON.prototype.transformVertex_ = function(vertex, scale,
translate) {
vertex[0] = vertex[0] * scale[0] + translate[0];
vertex[1] = vertex[1] * scale[1] + translate[1];
};
/**
* Parse a TopoJSON string.
* @param {string} str TopoJSON string.
* @return {Array.<ol.Feature>} Array of features.
*/
ol.parser.TopoJSON.read = function(str) {
return ol.parser.TopoJSON.getInstance().read(str);
};