Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

TopoJSON parser #844

Merged
merged 12 commits into from

2 participants

This page is out of date. Refresh to see the latest.
View
1  build.py
@@ -312,6 +312,7 @@ def action(t):
'../externs/bingmaps.js',
'../externs/bootstrap.js',
'../externs/geojson.js',
+ '../externs/topojson.js',
'../externs/oli.js',
'../externs/proj4js.js',
'../externs/tilejson.js',
View
1  buildcfg/base.json
@@ -42,6 +42,7 @@
"//json.js",
"../externs/bingmaps.js",
"../externs/geojson.js",
+ "../externs/topojson.js",
"../externs/oli.js",
"../externs/proj4js.js",
"../externs/tilejson.js"
View
1  buildcfg/ol-all.json
@@ -7,6 +7,7 @@
"../build/src/external/externs/types.js",
"../externs/bingmaps.js",
"../externs/geojson.js",
+ "../externs/topojson.js",
"../externs/oli.js",
"../externs/proj4js.js",
"../externs/tilejson.js"
View
1  buildcfg/ol-simple.json
@@ -16,6 +16,7 @@
"//json.js",
"../externs/bingmaps.js",
"../externs/geojson.js",
+ "../externs/topojson.js",
"../externs/oli.js",
"../externs/proj4js.js",
"../externs/tilejson.js"
View
1  buildcfg/ol-whitespace.json
@@ -17,6 +17,7 @@
"//json.js",
"../externs/bingmaps.js",
"../externs/geojson.js",
+ "../externs/topojson.js",
"../externs/oli.js",
"../externs/proj4js.js",
"../externs/tilejson.js"
View
1  buildcfg/ol.json
@@ -17,6 +17,7 @@
"../build/src/external/externs/types.js",
"../externs/bingmaps.js",
"../externs/geojson.js",
+ "../externs/topojson.js",
"../externs/oli.js",
"../externs/proj4js.js",
"../externs/tilejson.js"
View
1  examples/data/topojson/world-110m.json
1 addition, 0 deletions not shown
View
56 examples/topojson.html
@@ -0,0 +1,56 @@
+<!doctype html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="chrome=1">
+ <meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
+ <link rel="stylesheet" href="../resources/bootstrap/css/bootstrap.min.css" type="text/css">
+ <link rel="stylesheet" href="../resources/layout.css" type="text/css">
+ <link rel="stylesheet" href="../resources/bootstrap/css/bootstrap-responsive.min.css" type="text/css">
+ <title>TopoJSON Example</title>
+ </head>
+ <body>
+
+ <div class="navbar navbar-inverse navbar-fixed-top">
+ <div class="navbar-inner">
+ <div class="container">
+ <a class="brand" href="./">OpenLayers 3 Examples</a>
+ <ul class="nav pull-right">
+ <li><iframe class="github-watch-button" src="http://ghbtns.com/github-btn.html?user=openlayers&repo=ol3&type=watch&count=true"
+ allowtransparency="true" frameborder="0" scrolling="0" height="20" width="90"></iframe></li>
+ <li><a href="https://twitter.com/share" class="twitter-share-button" data-count="none" data-hashtags="openlayers">&nbsp;</a></li>
+ <li><div class="g-plusone-wrapper"><div class="g-plusone" data-size="medium" data-annotation="none"></div></div></li>
+ </ul>
+ </div>
+ </div>
+ </div>
+
+ <div class="container-fluid">
+
+ <div class="row-fluid">
+ <div class="span12">
+ <div id="map" class="map"></div>
+ </div>
+ </div>
+
+ <div class="row-fluid">
+
+ <div class="span8">
+ <h4 id="title">TopoJSON example</h4>
+ <p id="shortdesc">Demonstrates rendering of features from a TopoJSON topology.</p>
+ <div id="docs">
+ <p>See the <a href="topojson.js" target="_blank">topojson.js source</a> to see how this is done.</p>
+ </div>
+ <div id="tags">vector, topojson, style</div>
+ </div>
+ <div id="info" class="span4">&nbsp;</div>
+
+ </div>
+
+ </div>
+
+ <script src="loader.js?id=topojson" type="text/javascript"></script>
+ <script src="../resources/social-links.js" type="text/javascript"></script>
+
+ </body>
+</html>
View
47 examples/topojson.js
@@ -0,0 +1,47 @@
+goog.require('ol.Map');
+goog.require('ol.RendererHint');
+goog.require('ol.View2D');
+goog.require('ol.layer.TileLayer');
+goog.require('ol.layer.Vector');
+goog.require('ol.parser.TopoJSON');
+goog.require('ol.source.TileJSON');
+goog.require('ol.source.Vector');
+goog.require('ol.style.Polygon');
+goog.require('ol.style.Rule');
+goog.require('ol.style.Style');
+
+
+var raster = new ol.layer.TileLayer({
+ source: new ol.source.TileJSON({
+ url: 'http://api.tiles.mapbox.com/v3/mapbox.world-dark.jsonp'
+ })
+});
+
+var vector = new ol.layer.Vector({
+ source: new ol.source.Vector({
+ url: 'data/topojson/world-110m.json',
+ parser: new ol.parser.TopoJSON()
+ }),
+ style: new ol.style.Style({rules: [
+ new ol.style.Rule({
+ symbolizers: [
+ new ol.style.Polygon({
+ strokeColor: '#FFF',
+ fillColor: '#BADA55',
+ strokeWidth: 1.5,
+ opacity: 0.5
+ })
+ ]
+ })
+ ]})
+});
+
+var map = new ol.Map({
+ layers: [raster, vector],
+ renderer: ol.RendererHint.CANVAS,
+ target: 'map',
+ view: new ol.View2D({
+ center: [0, 0],
+ zoom: 1
+ })
+});
View
172 externs/topojson.js
@@ -0,0 +1,172 @@
+
+/**
+ * @fileoverview Externs for TopoJSON.
+ * @see https://github.com/mbostock/topojson/wiki/Specification
+ * @externs
+ */
+
+
+
+/**
+ * @constructor
+ */
+var TopoJSONTopology = function() {};
+
+
+/**
+ * @type {string}
+ */
+TopoJSONTopology.prototype.type;
+
+
+/**
+ * @type {TopoJSONTransform}
+ */
+TopoJSONTopology.prototype.transform;
+
+
+/**
+ * @type {Object.<string, (TopoJSONGeometry|TopoJSONGeometryCollection)>}
+ */
+TopoJSONTopology.prototype.objects;
+
+
+/**
+ * @type {!Array.<Array.<Array.<number>>>}
+ */
+TopoJSONTopology.prototype.arcs;
+
+
+
+/**
+ * @constructor
+ */
+var TopoJSONTransform = function() {};
+
+
+/**
+ * @type {!Array.<number>}
+ */
+TopoJSONTransform.prototype.scale;
+
+
+/**
+ * @type {!Array.<number>}
+ */
+TopoJSONTransform.prototype.translate;
+
+
+
+/**
+ * @constructor
+ */
+var TopoJSONGeometry = function() {};
+
+
+/**
+ * @type {string}
+ */
+TopoJSONGeometry.prototype.type;
+
+
+/**
+ * @type {string|number|undefined}
+ */
+TopoJSONGeometry.prototype.id;
+
+
+
+/**
+ * @constructor
+ */
+var TopoJSONGeometryCollection = function() {};
+
+
+/**
+ * @type {Array.<TopoJSONGeometry>}
+ */
+TopoJSONGeometryCollection.prototype.geometries;
+
+
+
+/**
+ * @constructor
+ * @extends {TopoJSONGeometry}
+ */
+var TopoJSONPoint = function() {};
+
+
+/**
+ * @type {!Array.<number>}
+ */
+TopoJSONPoint.prototype.coordinates;
+
+
+
+/**
+ * @constructor
+ * @extends {TopoJSONGeometry}
+ */
+var TopoJSONLineString = function() {};
+
+
+/**
+ * @type {!Array.<number>}
+ */
+TopoJSONLineString.prototype.arcs;
+
+
+
+/**
+ * @constructor
+ * @extends {TopoJSONGeometry}
+ */
+var TopoJSONPolygon = function() {};
+
+
+/**
+ * @type {!Array.<Array.<number>>}
+ */
+TopoJSONPolygon.prototype.arcs;
+
+
+
+/**
+ * @constructor
+ * @extends {TopoJSONGeometry}
+ */
+var TopoJSONMultiPoint = function() {};
+
+
+/**
+ * @type {!Array.<Array.<number>>}
+ */
+TopoJSONMultiPoint.prototype.coordinates;
+
+
+
+/**
+ * @constructor
+ * @extends {TopoJSONGeometry}
+ */
+var TopoJSONMultiLineString = function() {};
+
+
+/**
+ * @type {!Array.<Array.<number>>}
+ */
+TopoJSONMultiLineString.prototype.arcs;
+
+
+
+/**
+ * @constructor
+ * @extends {TopoJSONGeometry}
+ */
+var TopoJSONMultiPolygon = function() {};
+
+
+/**
+ * @type {!Array.<Array.<Array.<number>>>}
+ */
+TopoJSONMultiPolygon.prototype.arcs;
View
4 src/ol/parser/topojson.exports
@@ -0,0 +1,4 @@
+@exportSymbol ol.parser.TopoJSON
+
+@exportProperty ol.parser.TopoJSON.prototype.read
+@exportProperty ol.parser.TopoJSON.read
View
439 src/ol/parser/topojson.js
@@ -0,0 +1,439 @@
+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);
+};
+
+
+/**
+ * Create features from a TopoJSON topology string.
+ *
+ * @param {string} str TopoJSON topology string.
+ * @param {ol.parser.ReadFeaturesOptions=} opt_options Reader options.
+ * @return {Array.<ol.Feature>} Array of features.
+ */
+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 this.readFeaturesFromTopology_(topology, opt_options);
+};
+
+
+/**
+ * Create features from a TopoJSON topology object.
+ *
+ * @param {TopoJSONTopology} topology TopoJSON topology object.
+ * @param {ol.parser.ReadFeaturesOptions=} opt_options Reader options.
+ * @return {Array.<ol.Feature>} Array of features.
+ */
+ol.parser.TopoJSON.prototype.readFeaturesFromObject =
+ function(topology, opt_options) {
+ if (topology.type !== 'Topology') {
+ throw new Error('Not a "Topology" type object');
+ }
+ return this.readFeaturesFromTopology_(topology, opt_options);
+};
+
+
+/**
+ * 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);
+};
View
118 test/spec/ol/parser/topojson.test.js
@@ -0,0 +1,118 @@
+goog.provide('ol.test.parser.TopoJSON');
+
+var aruba = {
+ type: 'Topology',
+ transform: {
+ scale: [0.036003600360036005, 0.017361589674592462],
+ translate: [-180, -89.99892578124998]
+ },
+ objects: {
+ aruba: {
+ type: 'Polygon',
+ arcs: [[0]],
+ id: 533
+ }
+ },
+ arcs: [
+ [[3058, 5901], [0, -2], [-2, 1], [-1, 3], [-2, 3], [0, 3], [1, 1], [1, -3],
+ [2, -5], [1, -1]]
+ ]
+};
+
+
+describe('ol.parser.TopoJSON', function() {
+
+ var parser;
+ before(function() {
+ parser = new ol.parser.TopoJSON();
+ });
+
+ describe('constructor', function() {
+ it('creates a new parser', function() {
+ expect(parser).to.be.a(ol.parser.Parser);
+ expect(parser).to.be.a(ol.parser.TopoJSON);
+ });
+ });
+
+ describe('#readFeaturesFromTopology_()', function() {
+
+ it('creates an array of features from a topology', function() {
+ var features = parser.readFeaturesFromTopology_(aruba);
+ expect(features).to.have.length(1);
+
+ var feature = features[0];
+ expect(feature).to.be.a(ol.Feature);
+
+ var geometry = feature.getGeometry();
+ expect(geometry).to.be.a(ol.geom.Polygon);
+
+ expect(geometry.getBounds()).to.eql([
+ -70.08100810081008,
+ -69.9009900990099,
+ 12.417091709170947,
+ 12.608069195591469
+ ]);
+ });
+
+ });
+
+ describe('#readFeaturesFromString()', function() {
+
+ it('parses world-110m.geojson with shared vertices', function(done) {
+ afterLoadText('spec/ol/parser/topojson/world-110m.json', function(text) {
+
+ var pointVertices = new ol.geom.SharedVertices();
+ var lineVertices = new ol.geom.SharedVertices();
+ var polygonVertices = new ol.geom.SharedVertices();
+
+ var lookup = {
+ 'point': pointVertices,
+ 'linestring': lineVertices,
+ 'polygon': polygonVertices,
+ 'multipoint': pointVertices,
+ 'multilinstring': lineVertices,
+ 'multipolygon': polygonVertices
+ };
+
+ var callback = function(feature, type) {
+ return lookup[type];
+ };
+
+ var result = parser.readFeaturesFromString(text, {callback: callback});
+ expect(result.length).to.be(178);
+
+ expect(pointVertices.coordinates.length).to.be(0);
+ expect(lineVertices.coordinates.length).to.be(0);
+ expect(polygonVertices.coordinates.length).to.be(31400);
+
+ var first = result[0];
+ expect(first).to.be.a(ol.Feature);
+ var firstGeom = first.getGeometry();
+ expect(firstGeom).to.be.a(ol.geom.MultiPolygon);
+ expect(firstGeom.getBounds()).to.eql([
+ -180, 180, -85.60903777459777, 83.64513000000002
+ ]);
+
+ var last = result[177];
+ expect(last).to.be.a(ol.Feature);
+ var lastGeom = last.getGeometry();
+ expect(lastGeom).to.be.a(ol.geom.Polygon);
+ expect(lastGeom.getBounds()).to.eql([
+ 25.26325263252633, 32.848528485284874,
+ -22.271802279310577, -15.50833810039586
+ ]);
+
+ done();
+ });
+ });
+
+ });
+
+});
+
+goog.require('ol.Feature');
+goog.require('ol.geom.MultiPolygon');
+goog.require('ol.geom.Polygon');
+goog.require('ol.geom.SharedVertices');
+goog.require('ol.parser.Parser');
+goog.require('ol.parser.TopoJSON');
View
1  test/spec/ol/parser/topojson/world-110m.json
1 addition, 0 deletions not shown
Something went wrong with that request. Please try again.