geohash-poly
Advanced tools
Comparing version 0.4.1 to 0.5.2
102
index.js
var Readable = require('stream').Readable, | ||
geohash = require('ngeohash'), | ||
pip = require('point-in-polygon'), | ||
turf = require('turf'), | ||
turfExtent = require('turf-extent'), | ||
turfFeaturecollection = require('turf-featurecollection'), | ||
turfPolygon = require('turf-polygon'), | ||
turfIntersect = require('turf-intersect'), | ||
turf = { | ||
extent: turfExtent, | ||
featurecollection: turfFeaturecollection, | ||
polygon: turfPolygon, | ||
intersect: turfIntersect | ||
}, | ||
through2 = require('through2'), | ||
@@ -35,5 +44,7 @@ async = require('async'), | ||
var Hasher = function (options) { | ||
options = options || {}; | ||
var defaults = { | ||
precision: 6, | ||
precision: options.integerMode === true ? 32 : 6, | ||
rowMode: false, | ||
integerMode: false, | ||
geojson: [], | ||
@@ -44,3 +55,2 @@ splitAt: 2000, | ||
}; | ||
options = options || {}; | ||
for (var attrname in defaults) { | ||
@@ -55,2 +65,13 @@ this[attrname] = options.hasOwnProperty(attrname) && (options[attrname] !== null && typeof options[attrname] !== 'undefined') ? options[attrname] : defaults[attrname]; | ||
}); | ||
if (this.integerMode) { | ||
this.geohashEncode = geohash.encode_int; | ||
this.geohashDecode = geohash.decode_int; | ||
this.geohashDecodeBbox = geohash.decode_bbox_int; | ||
this.geohashNeighbor = geohash.neighbor_int; | ||
} else { | ||
this.geohashEncode = geohash.encode; | ||
this.geohashDecode = geohash.decode; | ||
this.geohashDecodeBbox = geohash.decode_bbox; | ||
this.geohashNeighbor = geohash.neighbor; | ||
} | ||
@@ -103,6 +124,6 @@ Readable.call(this, { | ||
if(!self.rowHash) { | ||
self.rowHash = geohash.encode(self.bounding[2], self.bounding[1], self.precision); | ||
self.rowHash = self.geohashEncode(self.bounding[2], self.bounding[1], self.precision); | ||
} | ||
var rowBox = geohash.decode_bbox(self.rowHash), | ||
var rowBox = self.geohashDecodeBbox(self.rowHash, self.precision), | ||
columnHash = self.rowHash, | ||
@@ -124,20 +145,16 @@ rowBuffer = 0.0002, | ||
turf.intersect(turf.featurecollection([clipper]), turf.featurecollection([currentGeojson]), function (err, intersection) { | ||
var prepare = null; | ||
if(intersection && intersection.features.length) { | ||
// Calculate the row bounding and column hash based on the intersection | ||
var intersectionFeature = { type: 'Feature', geometry: intersection.features[0], properties: {} }; | ||
turf.extent(turf.featurecollection([intersectionFeature]), function (err, extent) { | ||
// extent = [minX, minY, maxX, maxY], remap to match geohash lib | ||
self.rowBounding = [extent[1], extent[0], extent[3], extent[2]]; | ||
var midY = self.rowBounding[0]+(self.rowBounding[2]-self.rowBounding[0])/2; | ||
columnHash = geohash.encode(midY, self.rowBounding[1], self.precision); | ||
next(err, intersection.features[0]); | ||
}); | ||
} else { | ||
next(null, currentGeojson.geometry); | ||
} | ||
}); | ||
var intersection = turf.intersect(turf.featurecollection([clipper]), turf.featurecollection([currentGeojson])); | ||
if(intersection && intersection.features.length) { | ||
// Calculate the row bounding and column hash based on the intersection | ||
var intersectionFeature = { type: 'Feature', geometry: intersection.features[0], properties: {} }; | ||
var extent = turf.extent(turf.featurecollection([intersectionFeature])); | ||
// extent = [minX, minY, maxX, maxY], remap to match geohash lib | ||
self.rowBounding = [extent[1], extent[0], extent[3], extent[2]]; | ||
var midY = self.rowBounding[0]+(self.rowBounding[2]-self.rowBounding[0])/2; | ||
columnHash = self.geohashEncode(midY, self.rowBounding[1], self.precision); | ||
next(null, intersection.features[0]); | ||
} else { | ||
next(null, currentGeojson.geometry); | ||
} | ||
} else { | ||
@@ -150,4 +167,4 @@ next(null, currentGeojson.geometry); | ||
preparePoly(function (err, prepared) { | ||
var columnCenter = geohash.decode(columnHash), | ||
westerly = geohash.neighbor(geohash.encode(columnCenter.latitude, self.rowBounding[3], self.precision), [0, 1]); | ||
var columnCenter = self.geohashDecode(columnHash, self.precision), | ||
westerly = self.geohashNeighbor(self.geohashEncode(columnCenter.latitude, self.rowBounding[3], self.precision), [0, 1], self.precision); | ||
while (columnHash != westerly) { | ||
@@ -159,7 +176,7 @@ if(self.hashMode === 'inside' && inside(columnCenter, prepared)) { | ||
} | ||
columnHash = geohash.neighbor(columnHash, [0, 1]); | ||
columnCenter = geohash.decode(columnHash); | ||
columnHash = self.geohashNeighbor(columnHash, [0, 1], self.precision); | ||
columnCenter = self.geohashDecode(columnHash, self.precision); | ||
} | ||
var southNeighbour = geohash.neighbor(self.rowHash, [-1, 0]); | ||
var southNeighbour = self.geohashNeighbor(self.rowHash, [-1, 0], self.precision); | ||
@@ -183,3 +200,3 @@ // Check if the current rowHash was already the most southerly hash on the map. | ||
async.filter(rowHashes, function (h, cb) { | ||
var bb = geohash.decode_bbox(h); | ||
var bb = self.geohashDecodeBbox(h, self.precision); | ||
bb = turf.polygon([[ | ||
@@ -195,10 +212,9 @@ [bb[1], bb[2]], | ||
turf.intersect(turf.featurecollection([turf.polygon(prepared.coordinates)]), turf.featurecollection([bb]), function (err, intersected) { | ||
var keepIntersection = !self.threshold ? true : false; | ||
if(self.threshold && intersected.features.length && (intersected.features[0].type === 'Polygon' || intersected.features[0].type === 'MultiPolygon')) { | ||
var intersectedArea = geojsonArea.geometry(intersected.features[0]); | ||
keepIntersection = baseArea && intersectedArea / baseArea >= self.threshold; | ||
} | ||
cb(keepIntersection); | ||
}); | ||
var intersected = turf.intersect(turf.featurecollection([turf.polygon(prepared.coordinates)]), turf.featurecollection([bb])); | ||
var keepIntersection = !self.threshold ? true : false; | ||
if(self.threshold && intersected.features.length && (intersected.features[0].type === 'Polygon' || intersected.features[0].type === 'MultiPolygon')) { | ||
var intersectedArea = geojsonArea.geometry(intersected.features[0]); | ||
keepIntersection = baseArea && intersectedArea / baseArea >= self.threshold; | ||
} | ||
cb(keepIntersection); | ||
}, function (results) { | ||
@@ -213,8 +229,7 @@ done(null, results); | ||
if(!this.bounding) { | ||
turf.extent(turf.featurecollection([currentGeojson]), function (err, extent) { | ||
// extent = [minX, minY, maxX, maxY], remap to match geohash lib | ||
self.bounding = [extent[1], extent[0], extent[3], extent[2]]; | ||
self.rowBounding = self.bounding.slice(0); | ||
makeRow(); | ||
}); | ||
var extent = turf.extent(turf.featurecollection([currentGeojson])); | ||
// extent = [minX, minY, maxX, maxY], remap to match geohash lib | ||
self.bounding = [extent[1], extent[0], extent[3], extent[2]]; | ||
self.rowBounding = self.bounding.slice(0); | ||
makeRow(); | ||
} else { | ||
@@ -254,2 +269,3 @@ makeRow(); | ||
rowMode: options.rowMode ? true : false, | ||
integerMode: options.integerMode ? true : false, | ||
hashMode: options.hashMode, | ||
@@ -256,0 +272,0 @@ threshold: options.threshold |
{ | ||
"name": "geohash-poly", | ||
"version": "0.4.1", | ||
"version": "0.5.2", | ||
"description": "Transform a GeoJSON Polygon or MultiPolygon to a list of geohashes that form it.", | ||
@@ -21,7 +21,10 @@ "main": "index.js", | ||
"geojson-area": "^0.1.0", | ||
"ngeohash": "~0.2.0", | ||
"ngeohash": "0.6.0", | ||
"point-in-polygon": "0.0.0", | ||
"rc": "^0.6.0", | ||
"through2": "~0.4.0", | ||
"turf": "0.0.119" | ||
"turf-extent": "1.0.4", | ||
"turf-featurecollection": "1.0.1", | ||
"turf-intersect": "1.0.2", | ||
"turf-polygon": "1.0.3" | ||
}, | ||
@@ -28,0 +31,0 @@ "devDependencies": { |
@@ -57,2 +57,26 @@ # Geohash-poly | ||
Also, integer geohashes are available. | ||
```javascript | ||
geohashpoly({coords: polygon, precision: 34, integerMode: true}, function (err, hashes) { | ||
console.log(hashes); | ||
}); | ||
``` | ||
Results in: | ||
``` | ||
[ 5940702973, | ||
5940702975, | ||
5941052501, | ||
5940702972, | ||
5940702974, | ||
5941052500, | ||
5940702969, | ||
5940702971, | ||
5941052497, | ||
5940702968, | ||
5940702970, | ||
5941052496 ] | ||
``` | ||
## Options | ||
@@ -64,5 +88,5 @@ | ||
- `hashMode`: defines filtering of returned geohashes. See below. | ||
- `integerMode`: (true/false) Outputs integer versions of geohashes. Default precision for integer mode is 32 bits. | ||
## hashMode | ||
@@ -69,0 +93,0 @@ |
@@ -20,3 +20,4 @@ var hasher = require('../index'), | ||
async.timesSeries(geojson.properties.maxPrecision, function (n, next) { | ||
var precision = n + 1; | ||
var precision = n + 1, | ||
integerPrecision = precision * 5; | ||
var options = { | ||
@@ -42,2 +43,21 @@ coords: geojson.geometry.coordinates, | ||
}); | ||
if (integerPrecision % 2 == 0) { // https://github.com/sunng87/node-geohash says: "Bit depth must be even." | ||
it('should geohash ' + geojson.properties.comment + ' shape. Precision ' + integerPrecision + '. hashMode "extent" and integerMode true.', function (done) { | ||
options.integerMode = true; | ||
options.precision = integerPrecision; | ||
hasher(options, function (err, hashes) { | ||
should.not.exist(err); | ||
hashes.length.should.equal(geojson.properties.expectedExtent[n]); | ||
done(); | ||
}); | ||
}); | ||
it('should geohash ' + geojson.properties.comment + ' shape. Precision ' + integerPrecision + '. hashMode "inside" and integerMode true.', function (done) { | ||
options.hashMode = 'inside'; | ||
hasher(options, function (err, hashes) { | ||
should.not.exist(err); | ||
hashes.length.should.equal(geojson.properties.expectedInside[n]); | ||
done(); | ||
}); | ||
}); | ||
} | ||
next(); | ||
@@ -44,0 +64,0 @@ }, function (err) { |
245287
910
121
10
+ Addedturf-extent@1.0.4
+ Addedturf-featurecollection@1.0.1
+ Addedturf-intersect@1.0.2
+ Addedturf-polygon@1.0.3
+ Addedngeohash@0.6.0(transitive)
+ Addedturf-extent@1.0.4(transitive)
+ Addedturf-featurecollection@0.1.01.0.1(transitive)
+ Addedturf-intersect@1.0.2(transitive)
+ Addedturf-meta@1.0.2(transitive)
+ Addedturf-polygon@1.0.3(transitive)
- Removedturf@0.0.119
- Removedacorn@7.4.1(transitive)
- Removedbrfs@1.6.1(transitive)
- Removedbuffer-equal@0.0.1(transitive)
- Removedbuffer-from@1.1.2(transitive)
- Removedconcat-stream@1.6.2(transitive)
- Removedconvert-source-map@1.9.0(transitive)
- Removedd3@3.5.17(transitive)
- Removedd3-geo-projection@0.2.16(transitive)
- Removeddeep-is@0.1.4(transitive)
- Removedduplexer2@0.1.4(transitive)
- Removedescodegen@1.9.12.1.0(transitive)
- Removedesprima@3.1.34.0.1(transitive)
- Removedestraverse@4.3.05.3.0(transitive)
- Removedesutils@2.0.3(transitive)
- Removedfalafel@2.2.5(transitive)
- Removedfast-levenshtein@2.0.6(transitive)
- Removedfunction-bind@1.1.2(transitive)
- Removedhas@1.0.4(transitive)
- Removedhasown@2.0.2(transitive)
- Removediconv-lite@0.2.11(transitive)
- Removedis-core-module@2.13.1(transitive)
- Removedisarray@1.0.02.0.5(transitive)
- Removedlevn@0.3.0(transitive)
- Removedlodash@2.4.2(transitive)
- Removedmagic-string@0.22.5(transitive)
- Removedmerge-source-map@1.0.4(transitive)
- Removedminimist@1.2.8(transitive)
- Removedngeohash@0.2.0(transitive)
- Removedobject-inspect@1.4.1(transitive)
- Removedoptimist@0.3.7(transitive)
- Removedoptionator@0.8.3(transitive)
- Removedpath-parse@1.0.7(transitive)
- Removedprelude-ls@1.1.2(transitive)
- Removedprocess-nextick-args@2.0.1(transitive)
- Removedqueue-async@1.0.7(transitive)
- Removedquote-stream@1.0.2(transitive)
- Removedreadable-stream@2.3.8(transitive)
- Removedresolve@1.22.8(transitive)
- Removedsafe-buffer@5.1.2(transitive)
- Removedshallow-copy@0.0.1(transitive)
- Removedshapefile@0.1.4(transitive)
- Removedsimple-statistics@0.7.0(transitive)
- Removedsource-map@0.5.70.6.1(transitive)
- Removedstatic-eval@2.1.1(transitive)
- Removedstatic-module@2.2.5(transitive)
- Removedstring_decoder@1.1.1(transitive)
- Removedsupports-preserve-symlinks-flag@1.0.0(transitive)
- Removedthrough2@2.0.5(transitive)
- Removedtopojson@1.4.9(transitive)
- Removedturf@0.0.119(transitive)
- Removedtype-check@0.3.2(transitive)
- Removedtypedarray@0.0.6(transitive)
- Removedutil-deprecate@1.0.2(transitive)
- Removedvlq@0.2.3(transitive)
- Removedword-wrap@1.2.5(transitive)
- Removedwordwrap@0.0.3(transitive)
- Removedxtend@4.0.2(transitive)
Updatedngeohash@0.6.0