From d1ce83a7e364ae3a941f1f14f4a39b40fd85d13f Mon Sep 17 00:00:00 2001 From: Jeff ten Have Date: Mon, 6 Nov 2017 14:46:31 -0800 Subject: [PATCH 1/2] Added support for PointZ, PolylineZ, PolygonZ, MultiPoint, MultiPointZ --- README.md | 2 +- example/test_linestringZ.js | 31 +++++++++ example/test_multipoint.js | 31 +++++++++ example/test_multipointZ.js | 31 +++++++++ example/test_pointZ.js | 31 +++++++++ example/test_polygonZ.js | 32 +++++++++ src/extent.js | 14 +++- src/geojson.js | 36 +++++++++-- src/multipoint.js | 125 ++++++++++++++++++++++++++++++++++++ src/points.js | 28 ++++---- src/poly.js | 76 +++++++++++++++++++--- src/write.js | 14 +++- src/zip.js | 2 +- test/extent.test.js | 18 +++++- 14 files changed, 437 insertions(+), 34 deletions(-) create mode 100644 example/test_linestringZ.js create mode 100644 example/test_multipoint.js create mode 100644 example/test_multipointZ.js create mode 100644 example/test_pointZ.js create mode 100644 example/test_polygonZ.js create mode 100644 src/multipoint.js diff --git a/README.md b/README.md index b04c03e0..ff6b456c 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ Or in a browser * Requires a capable fancy modern browser with [Typed Arrays](http://caniuse.com/#feat=typedarrays) support -* Geometries: Point, LineString, Polygon, MultiLineString, MultiPolygon +* Geometries: Point, PointZ, MultiPoint, MultiPointZ, LineString, LineStringZ, Polygon, PolygonZ, MultiLineString, MultiPolygon * Tabular-style properties export with Shapefile's field name length limit * Uses jsZip for ZIP files, but [compression is buggy](https://github.com/Stuk/jszip/issues/53) so it uses STORE instead of DEFLATE. diff --git a/example/test_linestringZ.js b/example/test_linestringZ.js new file mode 100644 index 00000000..2cf54b73 --- /dev/null +++ b/example/test_linestringZ.js @@ -0,0 +1,31 @@ +var write = require('../src/write'), + fs = require('fs'); + +var lines = [[[ + [0, 0, 1000], + [10, 0, 2000], + [15, 5, 3000], + [20, -5, 4000] +]]]; + +write( + // feature data + [{ id: 0 }], + // geometry type + 'POLYLINEZ', + // geometries + lines, + finish); + +function finish(err, files) { + fs.writeFileSync('linesz.shp', toBuffer(files.shp.buffer)); + fs.writeFileSync('linesz.shx', toBuffer(files.shx.buffer)); + fs.writeFileSync('linesz.dbf', toBuffer(files.dbf.buffer)); +} + +function toBuffer(ab) { + var buffer = new Buffer(ab.byteLength), + view = new Uint8Array(ab); + for (var i = 0; i < buffer.length; ++i) { buffer[i] = view[i]; } + return buffer; +} diff --git a/example/test_multipoint.js b/example/test_multipoint.js new file mode 100644 index 00000000..44fff545 --- /dev/null +++ b/example/test_multipoint.js @@ -0,0 +1,31 @@ +var write = require('../src/write'), + fs = require('fs'); + +var points = [[ + [0, 0], + [10, 0], + [10, 10], + [0, 10] +]]; + +write( + // feature data + [{ id: 0 }], + // geometry type + 'MULTIPOINT', + // geometries + points, + finish); + +function finish(err, files) { + fs.writeFileSync('multipoint.shp', toBuffer(files.shp.buffer)); + fs.writeFileSync('multipoint.shx', toBuffer(files.shx.buffer)); + fs.writeFileSync('multipoint.dbf', toBuffer(files.dbf.buffer)); +} + +function toBuffer(ab) { + var buffer = new Buffer(ab.byteLength), + view = new Uint8Array(ab); + for (var i = 0; i < buffer.length; ++i) { buffer[i] = view[i]; } + return buffer; +} diff --git a/example/test_multipointZ.js b/example/test_multipointZ.js new file mode 100644 index 00000000..6fff4853 --- /dev/null +++ b/example/test_multipointZ.js @@ -0,0 +1,31 @@ +var write = require('../src/write'), + fs = require('fs'); + +var points = [[ + [0, 0, 300, 56], + [10, 0, 400, 34], + [10, 10, 500, 12], + [0, 10, 100] +]]; + +write( + // feature data + [{ id: 0 }], + // geometry type + 'MULTIPOINTZ', + // geometries + points, + finish); + +function finish(err, files) { + fs.writeFileSync('multipointz.shp', toBuffer(files.shp.buffer)); + fs.writeFileSync('multipointz.shx', toBuffer(files.shx.buffer)); + fs.writeFileSync('multipointz.dbf', toBuffer(files.dbf.buffer)); +} + +function toBuffer(ab) { + var buffer = new Buffer(ab.byteLength), + view = new Uint8Array(ab); + for (var i = 0; i < buffer.length; ++i) { buffer[i] = view[i]; } + return buffer; +} diff --git a/example/test_pointZ.js b/example/test_pointZ.js new file mode 100644 index 00000000..a1bfaa6c --- /dev/null +++ b/example/test_pointZ.js @@ -0,0 +1,31 @@ +var write = require('../src/write'), + fs = require('fs'); + +var points = [ + [0, 0, 500], + [10, 0, 400], + [10, 10, 600], + [0, 10, 800] +]; + +write( + // feature data + [{ id: 0 }, { id: 1 }, { id: 2 }, { id: 3 }], + // geometry type + 'POINTZ', + // geometries + points, + finish); + +function finish(err, files) { + fs.writeFileSync('pointz.shp', toBuffer(files.shp.buffer)); + fs.writeFileSync('pointz.shx', toBuffer(files.shx.buffer)); + fs.writeFileSync('pointz.dbf', toBuffer(files.dbf.buffer)); +} + +function toBuffer(ab) { + var buffer = new Buffer(ab.byteLength), + view = new Uint8Array(ab); + for (var i = 0; i < buffer.length; ++i) { buffer[i] = view[i]; } + return buffer; +} diff --git a/example/test_polygonZ.js b/example/test_polygonZ.js new file mode 100644 index 00000000..e8a28546 --- /dev/null +++ b/example/test_polygonZ.js @@ -0,0 +1,32 @@ +var write = require('../src/write'), + fs = require('fs'); + +var polygons = [[[ + [0, 0, 8000], + [10, 0, 9000], + [15, 5, 10000], + [20, -5, 11000], + [0, 0, 8000] +]]]; + +write( + // feature data + [{ id: 0 }], + // geometry type + 'POLYGONZ', + // geometries + polygons, + finish); + +function finish(err, files) { + fs.writeFileSync('polygonz.shp', toBuffer(files.shp.buffer)); + fs.writeFileSync('polygonz.shx', toBuffer(files.shx.buffer)); + fs.writeFileSync('polygonz.dbf', toBuffer(files.dbf.buffer)); +} + +function toBuffer(ab) { + var buffer = new Buffer(ab.byteLength), + view = new Uint8Array(ab); + for (var i = 0; i < buffer.length; ++i) { buffer[i] = view[i]; } + return buffer; +} diff --git a/src/extent.js b/src/extent.js index 64f929f3..af25694b 100644 --- a/src/extent.js +++ b/src/extent.js @@ -3,6 +3,10 @@ module.exports.enlarge = function enlargeExtent(extent, pt) { if (pt[0] > extent.xmax) extent.xmax = pt[0]; if (pt[1] < extent.ymin) extent.ymin = pt[1]; if (pt[1] > extent.ymax) extent.ymax = pt[1]; + if ((pt[2] || 0) < extent.zmin) extent.zmin = pt[2] || 0; + if ((pt[2] || 0) > extent.zmax) extent.zmax = pt[2] || 0; + if ((pt[3] || 0) < extent.mmin) extent.mmin = pt[3] || 0; + if ((pt[3] || 0) > extent.mmax) extent.mmax = pt[3] || 0; return extent; }; @@ -11,6 +15,10 @@ module.exports.enlargeExtent = function enlargeExtent(extent, ext) { if (ext.xmin < extent.xmin) extent.xmin = ext.xmin; if (ext.ymax > extent.ymax) extent.ymax = ext.ymax; if (ext.ymin < extent.ymin) extent.ymin = ext.ymin; + if (ext.zmax && ext.zmax > extent.zmax) extent.zmax = ext.zmax; + if (ext.zmin && ext.zmin < extent.zmin) extent.zmin = ext.zmin; + if (ext.mmax && ext.mmax > extent.mmax) extent.mmax = ext.mmax; + if (ext.mmin && ext.mmin < extent.mmin) extent.mmin = ext.mmin; return extent; }; @@ -18,7 +26,11 @@ module.exports.blank = function() { return { xmin: Number.MAX_VALUE, ymin: Number.MAX_VALUE, + zmin: Number.MAX_VALUE, + mmin: Number.MAX_VALUE, xmax: -Number.MAX_VALUE, - ymax: -Number.MAX_VALUE + ymax: -Number.MAX_VALUE, + zmax: -Number.MAX_VALUE, + mmax: -Number.MAX_VALUE }; }; diff --git a/src/geojson.js b/src/geojson.js index dfad6eee..32ceee64 100644 --- a/src/geojson.js +++ b/src/geojson.js @@ -1,13 +1,20 @@ -module.exports.point = justType('Point', 'POINT'); -module.exports.line = justType('LineString', 'POLYLINE'); -module.exports.polygon = justType('Polygon', 'POLYGON'); +module.exports.point = justType('Point', 'POINT', false); +module.exports.pointZ = justType('Point', 'POINTZ', true); +module.exports.multipoint = justType('MultiPoint', 'MULTIPOINT', false); +module.exports.multipointZ = justType('MultiPoint', 'MULTIPOINTZ', true); +module.exports.line = justType('LineString', 'POLYLINE', false); +module.exports.lineZ = justType('LineString', 'POLYLINEZ', true); +module.exports.polygon = justType('Polygon', 'POLYGON', false); +module.exports.polygonZ = justType('Polygon', 'POLYGONZ', true); -function justType(type, TYPE) { +function justType(type, TYPE, just3D) { return function(gj) { var oftype = gj.features.filter(isType(type)); + var ofDimension = oftype.filter(isOfDimension(TYPE, just3D)); + return { - geometries: (TYPE === 'POLYGON' || TYPE === 'POLYLINE') ? [oftype.map(justCoords)] : oftype.map(justCoords), - properties: oftype.map(justProps), + geometries: (TYPE === 'POLYGON' || TYPE === 'POLYLINE' || TYPE === 'POLYGONZ' || TYPE === 'POLYLINEZ') ? [ofDimension.map(justCoords)] : ofDimension.map(justCoords), + properties: ofDimension.map(justProps), type: TYPE }; }; @@ -30,3 +37,20 @@ function justProps(t) { function isType(t) { return function(f) { return f.geometry.type === t; }; } + +function isOfDimension(TYPE, just3d) { + return function(f) { + var coordinates; + if (TYPE === 'POINT' || TYPE === 'POINTZ') { + coordinates = [f.geometry.coordinates]; + } + else { + coordinates = Array.isArray(f.geometry.coordinates[0][0]) ? + f.geometry.coordinates.reduce(function(agg, c) { + return agg.concat(c); + }, []) : + f.geometry.coordinates; + } + return just3d ? coordinates.some(c => c.length >= 3) : coordinates.every(c => c.length === 2); + } +} \ No newline at end of file diff --git a/src/multipoint.js b/src/multipoint.js new file mode 100644 index 00000000..7d289a00 --- /dev/null +++ b/src/multipoint.js @@ -0,0 +1,125 @@ +var ext = require('./extent'); +var types = require('./types'); + +module.exports.write = function writePoints(coordinates, extent, shpView, shxView, TYPE) { + + var shpI = 0, + shxI = 0; + shxOffset = 100, + is3D = TYPE === types.geometries.MULTIPOINTZ; + + coordinates.forEach(writeMultipoint); + + function writeMultipoint(coords, i) { + // Length of multipoint record + var contentLength = 40 + (coords.length * 16); + if (is3D) { + contentLength += 32 + (coords.length * 16); + } + var totalLength = contentLength + 8; + + var featureExtent = coords.reduce(function(extent, c) { + return ext.enlarge(extent, c); + }, ext.blank()); + + // Write entry to index file. + shxView.setInt32(shxI, shxOffset / 2); // Offset in shx file. + shxView.setInt32(shxI + 4, totalLength / 2); // Record length. + shxI += 8; + shxOffset += totalLength; + + // Write record to shape file. + shpView.setInt32(shpI, i); // Record number + shpView.setInt32(shpI + 4, contentLength / 2); // Record length (in 16 bit words); + shpView.setInt32(shpI + 8, TYPE, true); // Record type. MULTIPOINT=8,MULTIPOINTZ=18 + shpView.setFloat64(shpI + 12, featureExtent.xmin, true); // Bounding box. + shpView.setFloat64(shpI + 20, featureExtent.ymin, true); + shpView.setFloat64(shpI + 28, featureExtent.xmax, true); + shpView.setFloat64(shpI + 36, featureExtent.ymax, true); + shpView.setInt32(shpI + 44, coords.length, true); // Number of points. + shpI += 48; + + // Write points. + var zMin = Number.MAX_VALUE; + var zMax = -Number.MAX_VALUE; + var mMin = Number.MAX_VALUE; + var mMax = -Number.MAX_VALUE; + coords.forEach(function(p, i) { + if ((coords[2] || 0) < zMin) { + zMin = coords[2] || 0; + } + + if ((coords[2] || 0) > zMax) { + zMax = coords[2] || 0; + } + + if ((coords[3] || 0) < mMin) { + mMin = coords[3] || 0; + } + + if ((coords[3] || 0) > mMax) { + mMax = coords[3] || 0; + } + + shpView.setFloat64(shpI, p[0], true); // X + shpView.setFloat64(shpI + 8, p[1], true); // Y + shpI += 16; + }); + + if (is3D) { + // Write z value range + shpView.setFloat64(shpI, zMin, true); + shpView.setFloat64(shpI + 8, zMax, true); + shpI += 16 + + // Write z values. + coords.forEach(function(p, i) { + shpView.setFloat64(shpI, p[2] || 0, true); + shpI += 8; + }); + + // Write m value range. + shpView.setFloat64(shpI, mMin, true); + shpView.setFloat64(shpI + 8, mMax, true); + shpI += 16; + + // Write m values; + coords.forEach(function(p, i) { + shpView.setFloat64(shpI, p[3] || 0, true); + shpI += 8; + }); + } + } +}; + +module.exports.extent = function(coordinates) { + var flattented = justCoords(coordinates); + return flattented.reduce(function(extent, coords) { + return ext.enlarge(extent, coords); + }, ext.blank()); +}; + +module.exports.parts = function parts(geometries, TYPE) { + return geometries.length; +}; + +module.exports.shxLength = function(coordinates) { + return coordinates.length * 8; +}; + +module.exports.shpLength = function(coordinates, TYPE) { + var flattented = justCoords(coordinates); + var length = coordinates.length * 48 + flattented.length * 16; + if (TYPE === types.geometries.MULTIPOINTZ) { + length += 32 + (flattented.length * 16); + } + + return length; +}; + +function justCoords(coords) { + var points = []; + return coords.reduce(function(agg, c) { + return agg.concat(c); + }, points); +} diff --git a/src/points.js b/src/points.js index af27df9f..087da500 100644 --- a/src/points.js +++ b/src/points.js @@ -1,32 +1,38 @@ var ext = require('./extent'); +var types = require('./types'); -module.exports.write = function writePoints(coordinates, extent, shpView, shxView) { +module.exports.write = function writePoints(coordinates, extent, shpView, shxView, TYPE) { - var contentLength = 28, // 8 header, 20 content + var is3D = TYPE === types.geometries.POINTZ; + var contentLength = is3D ? 36 : 20, // 20 for non-3D or 36 for 3D fileLength = 100, shpI = 0, shxI = 0; - + coordinates.forEach(function writePoint(coords, i) { // HEADER // 4 record number // 4 content length in 16-bit words (20/2) shpView.setInt32(shpI, i); - shpView.setInt32(shpI + 4, 10); + shpView.setInt32(shpI + 4, contentLength / 2); // record // (8 + 8) + 4 = 20 content length - shpView.setInt32(shpI + 8, 1, true); // POINT=1 + shpView.setInt32(shpI + 8, TYPE, true); // POINT=1, POINTZ=11 shpView.setFloat64(shpI + 12, coords[0], true); // X shpView.setFloat64(shpI + 20, coords[1], true); // Y - + if (is3D) { + shpView.setFloat64(shpI + 28, coords[2] || 0, true); // Z + shpView.setFloat64(shpI + 36, coords[3] || 0, true); // M + } + // index shxView.setInt32(shxI, fileLength / 2); // length in 16-bit words - shxView.setInt32(shxI + 4, 10); + shxView.setInt32(shxI + 4, contentLength / 2); shxI += 8; - shpI += contentLength; - fileLength += contentLength; + shpI += contentLength + 8; + fileLength += contentLength + 8; }); }; @@ -44,6 +50,6 @@ module.exports.shxLength = function(coordinates) { return coordinates.length * 8; }; -module.exports.shpLength = function(coordinates) { - return coordinates.length * 28; +module.exports.shpLength = function(coordinates, TYPE) { + return coordinates.length * (TYPE === types.geometries.POINTZ ? 44 : 28); }; diff --git a/src/poly.js b/src/poly.js index 4ba8c2de..4f5b0458 100644 --- a/src/poly.js +++ b/src/poly.js @@ -5,7 +5,8 @@ module.exports.write = function writePoints(geometries, extent, shpView, shxView var shpI = 0, shxI = 0, - shxOffset = 100; + shxOffset = 100, + is3D = TYPE === types.geometries.POLYLINEZ || TYPE === types.geometries.POLYGONZ; geometries.forEach(writePolyLine); @@ -15,6 +16,10 @@ module.exports.write = function writePoints(geometries, extent, shpView, shxView noParts = parts([coordinates], TYPE), contentLength = (flattened.length * 16) + 48 + (noParts - 1) * 4; + if (is3D) { + contentLength += 32 + flattened.length * 16; + } + var featureExtent = flattened.reduce(function(extent, c) { return ext.enlarge(extent, c); }, ext.blank()); @@ -28,7 +33,7 @@ module.exports.write = function writePoints(geometries, extent, shpView, shxView shpView.setInt32(shpI, i + 1); // record number shpView.setInt32(shpI + 4, contentLength / 2); // length - shpView.setInt32(shpI + 8, TYPE, true); // POLYLINE=3 + shpView.setInt32(shpI + 8, TYPE, true); // POLYLINE=3, POLYGON=5, POLYLINEZ=13, POLYGONZ=15 shpView.setFloat64(shpI + 12, featureExtent.xmin, true); // EXTENT shpView.setFloat64(shpI + 20, featureExtent.ymin, true); shpView.setFloat64(shpI + 28, featureExtent.xmax, true); @@ -55,19 +60,72 @@ module.exports.write = function writePoints(geometries, extent, shpView, shxView ); } + shpI += 56 + (noParts - 1) * 4; + + var zMin = Number.MAX_VALUE; + var zMax = -Number.MAX_VALUE; + var mMin = Number.MAX_VALUE; + var mMax = -Number.MAX_VALUE; flattened.forEach(function writeLine(coords, i) { - shpView.setFloat64(shpI + 56 + (i * 16) + (noParts - 1) * 4, coords[0], true); // X - shpView.setFloat64(shpI + 56 + (i * 16) + (noParts - 1) * 4 + 8, coords[1], true); // Y + if ((coords[2] || 0) < zMin) { + zMin = coords[2] || 0; + } + + if ((coords[2] || 0) > zMax) { + zMax = coords[2] || 0; + } + + if ((coords[3] || 0) < mMin) { + mMin = coords[3] || 0; + } + + if ((coords[3] || 0) > mMax) { + mMax = coords[3] || 0; + } + + shpView.setFloat64(shpI, coords[0], true); // X + shpView.setFloat64(shpI + 8, coords[1], true); // Y + + shpI += 16; }); - shpI += contentLength + 8; + if (is3D) { + // Write z value range + shpView.setFloat64(shpI, zMin, true); + shpView.setFloat64(shpI + 8, zMax, true); + shpI += 16 + + // Write z values. + flattened.forEach(function(p, i) { + shpView.setFloat64(shpI, p[2] || 0, true); + shpI += 8; + }); + + // Write m value range. + shpView.setFloat64(shpI, mMin, true); + shpView.setFloat64(shpI + 8, mMax, true); + shpI += 16; + + // Write m values; + flattened.forEach(function(p, i) { + shpView.setFloat64(shpI, p[3] || 0, true); + shpI += 8; + }); + } } }; -module.exports.shpLength = function(geometries) { - return (geometries.length * 56) + +module.exports.shpLength = function(geometries, TYPE) { + var flattened = justCoords(geometries); + var length = (geometries.length * 56) + // points - (justCoords(geometries).length * 16); + (flattened.length * 16); + + if (TYPE === types.geometries.POLYLINEZ || TYPE === types.geometries.POLYGONZ) { + length += 32 + flattened.length * 16; + } + + return length }; module.exports.shxLength = function(geometries) { @@ -82,7 +140,7 @@ module.exports.extent = function(coordinates) { function parts(geometries, TYPE) { var no = 1; - if (TYPE === types.geometries.POLYGON || TYPE === types.geometries.POLYLINE) { + if (TYPE === types.geometries.POLYGON || TYPE === types.geometries.POLYLINE || TYPE === types.geometries.POLYGONZ || TYPE === types.geometries.POLYLINEZ) { no = geometries.reduce(function (no, coords) { no += coords.length; if (Array.isArray(coords[0][0][0])) { // multi diff --git a/src/write.js b/src/write.js index 0f0cbbe7..804aa450 100644 --- a/src/write.js +++ b/src/write.js @@ -5,12 +5,18 @@ var types = require('./types'), getFields = require('./fields'), assert = require('assert'), pointWriter = require('./points'), + multipointWriter = require('./multipoint'), polyWriter = require('./poly'); var writers = { 1: pointWriter, + 3: polyWriter, 5: polyWriter, - 3: polyWriter + 8: multipointWriter, + 11: pointWriter, + 13: polyWriter, + 15: polyWriter, + 18: multipointWriter }; var recordHeaderLength = 8; @@ -23,7 +29,7 @@ function write(rows, geometry_type, geometries, callback) { var TYPE = types.geometries[geometry_type], writer = writers[TYPE], parts = writer.parts(geometries, TYPE), - shpLength = 100 + (parts - geometries.length) * 4 + writer.shpLength(geometries), + shpLength = 100 + (parts - geometries.length) * 4 + writer.shpLength(geometries, TYPE), shxLength = 100 + writer.shxLength(geometries), shpBuffer = new ArrayBuffer(shpLength), shpView = new DataView(shpBuffer), @@ -65,4 +71,8 @@ function writeExtent(extent, view) { view.setFloat64(44, extent.ymin, true); view.setFloat64(52, extent.xmax, true); view.setFloat64(60, extent.ymax, true); + view.setFloat64(68, extent.zmin, true); + view.setFloat64(76, extent.zmax, true); + view.setFloat64(84, extent.mmin, true); + view.setFloat64(92, extent.mmax, true); } diff --git a/src/zip.js b/src/zip.js index b8e89d85..fde66614 100644 --- a/src/zip.js +++ b/src/zip.js @@ -8,7 +8,7 @@ module.exports = function(gj, options) { var zip = new JSZip(), layers = zip.folder(options && options.folder ? options.folder : 'layers'); - [geojson.point(gj), geojson.line(gj), geojson.polygon(gj)] + [geojson.point(gj), geojson.multipoint(gj), geojson.line(gj), geojson.polygon(gj), geojson.pointZ(gj), geojson.multipointZ(gj), geojson.lineZ(gj), geojson.polygonZ(gj)] .forEach(function(l) { if (l.geometries.length && l.geometries[0].length) { write( diff --git a/test/extent.test.js b/test/extent.test.js index 28daf5ca..b45b09f8 100644 --- a/test/extent.test.js +++ b/test/extent.test.js @@ -10,17 +10,25 @@ describe('extent', function() { expect(ext.ymin).to.be.ok(); expect(ext.xmax).to.be.ok(); expect(ext.ymax).to.be.ok(); + expect(ext.zmin).to.be.ok(); + expect(ext.mmin).to.be.ok(); + expect(ext.zmax).to.be.ok(); + expect(ext.mmax).to.be.ok(); }); }); describe('#enlarge', function() { it('encloses a point', function() { var ext = extent.blank(); - extent.enlarge(ext, [0, 0]); + extent.enlarge(ext, [0, 0, 1, 2]); expect(ext.xmin).to.eql(0); expect(ext.ymin).to.eql(0); expect(ext.xmax).to.eql(0); expect(ext.ymax).to.eql(0); + expect(ext.zmin).to.eql(1); + expect(ext.mmin).to.eql(2); + expect(ext.zmax).to.eql(1); + expect(ext.mmax).to.eql(2); }); }); @@ -28,13 +36,17 @@ describe('extent', function() { it('encloses a extent', function() { var ext = extent.blank(), extB = extent.blank(); - extent.enlarge(ext, [0, 0]); - extent.enlarge(ext, [10, 10]); + extent.enlarge(ext, [0, 0, 0, 0]); + extent.enlarge(ext, [10, 10, 10, 10]); extent.enlargeExtent(extB, ext); expect(ext.xmin).to.eql(0); expect(ext.ymin).to.eql(0); expect(ext.xmax).to.eql(10); expect(ext.ymax).to.eql(10); + expect(ext.zmin).to.eql(0); + expect(ext.mmin).to.eql(0); + expect(ext.zmax).to.eql(10); + expect(ext.mmax).to.eql(10); }); }); }); From cef9f77ea1be5e959ea4e8d8ee752dbc41043f1c Mon Sep 17 00:00:00 2001 From: Jeff ten Have Date: Wed, 8 Nov 2017 08:57:04 -0800 Subject: [PATCH 2/2] geojson.js is compatible with ES5 --- src/geojson.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/geojson.js b/src/geojson.js index 32ceee64..84edeea3 100644 --- a/src/geojson.js +++ b/src/geojson.js @@ -51,6 +51,6 @@ function isOfDimension(TYPE, just3d) { }, []) : f.geometry.coordinates; } - return just3d ? coordinates.some(c => c.length >= 3) : coordinates.every(c => c.length === 2); + return just3d ? coordinates.some(function(c) { return c.length >= 3 }) : coordinates.every(function(c) { return c.length === 2 }); } -} \ No newline at end of file +}