-
Notifications
You must be signed in to change notification settings - Fork 129
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Breakout geometry filters. * Fix envelope-intersects
- Loading branch information
Showing
17 changed files
with
523 additions
and
56 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
const _ = require('lodash') | ||
const { contains } = require('@terraformer/spatial') | ||
module.exports = function (featureGeometry = {}, filterGeometry = {}) { | ||
if (_.isEmpty(featureGeometry)) return false | ||
const { type, coordinates = [] } = featureGeometry | ||
if (!type || !coordinates || coordinates.length === 0) return false | ||
return contains(filterGeometry, featureGeometry) | ||
} |
30 changes: 30 additions & 0 deletions
30
packages/winnow/lib/filter-and-transform/filters/envelope-intersects.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
const _ = require('lodash') | ||
const { calculateBounds, intersects, contains } = require('@terraformer/spatial') | ||
const transformArray = require('../../geometry/transform-coordinate-array-to-polygon') | ||
const convertFromEsri = require('../../geometry/transfrom-esri-geometry-to-geojson-geometry') | ||
|
||
module.exports = function (featureGeometry = {}, filterGeometry = {}) { | ||
if (_.isEmpty(featureGeometry) || _.isEmpty(filterGeometry)) return false | ||
|
||
const normalizedFeatureGeometry = isGeoJsonGeometry(featureGeometry) ? featureGeometry : convertFromEsri(featureGeometry) | ||
|
||
const { type, coordinates = [] } = normalizedFeatureGeometry | ||
|
||
if (!type || coordinates.length === 0) return false | ||
|
||
const geometryFilterEnvelope = convertGeometryToEnvelope(filterGeometry) | ||
|
||
if (type === 'Point') return contains(geometryFilterEnvelope, normalizedFeatureGeometry) | ||
|
||
const featureEnvelope = convertGeometryToEnvelope(normalizedFeatureGeometry) | ||
return intersects(geometryFilterEnvelope, featureEnvelope) | ||
} | ||
|
||
function convertGeometryToEnvelope (geometry) { | ||
const bounds = calculateBounds(geometry) | ||
return transformArray(bounds) | ||
} | ||
|
||
function isGeoJsonGeometry ({ type, coordinates }) { | ||
return type && coordinates | ||
} |
24 changes: 24 additions & 0 deletions
24
packages/winnow/lib/filter-and-transform/filters/hashed-objectid-comparator.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
const createIntegerHash = require('../helpers/create-integer-hash') | ||
|
||
/** | ||
* This function is used when the where option includes an OBJECTID, but the data | ||
* contains no such property. In such cases, it is assumed that the client has been | ||
* leveraging winnow's "esriFy" feature that creates OBJECTID on the fly by | ||
* doing a numeric hash of a feature. In order to filter by OBJECTID, we have recreate | ||
* the numeric hash on the fly and compare it to the passed in OBJECTID. | ||
* | ||
* @param {object} properties GeoJSON feature properties | ||
* @param {*} geometry GeoJSON feature properties | ||
* @param {*} objectId the objectId the feature is being compared to. Presumed to have been created by feature hashing | ||
* @param {*} operator the predicate operator | ||
*/ | ||
module.exports = function (properties, geometry, objectId, operator) { | ||
const hashedFeature = createIntegerHash(JSON.stringify({ properties, geometry })) | ||
if (operator === '=' && hashedFeature === objectId) return true | ||
if (operator === '!=' && hashedFeature !== objectId) return true | ||
if (operator === '>' && hashedFeature > objectId) return true | ||
if (operator === '<' && hashedFeature < objectId) return true | ||
if (operator === '>=' && hashedFeature >= objectId) return true | ||
if (operator === '<=' && hashedFeature <= objectId) return true | ||
return false | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
module.exports = { | ||
within: require('./within'), | ||
contains: require('./contains'), | ||
intersects: require('./intersects'), | ||
envelopeIntersects: require('./envelope-intersects'), | ||
hashedObjectIdComparator: require('./hashed-objectid-comparator') | ||
} |
16 changes: 16 additions & 0 deletions
16
packages/winnow/lib/filter-and-transform/filters/intersects.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
const _ = require('lodash') | ||
const { intersects, contains } = require('@terraformer/spatial') | ||
const convertFromEsri = require('../../geometry/transfrom-esri-geometry-to-geojson-geometry') | ||
|
||
module.exports = function (featureGeometry = {}, filterGeometry = {}) { | ||
if (_.isEmpty(featureGeometry)) return false | ||
const geometry = isGeoJsonGeometry(featureGeometry) ? featureGeometry : convertFromEsri(featureGeometry) | ||
const { type, coordinates = [] } = geometry | ||
if (!type || !coordinates || coordinates.length === 0) return false | ||
if (type === 'Point') return contains(filterGeometry, geometry) | ||
return intersects(filterGeometry, geometry) | ||
} | ||
|
||
function isGeoJsonGeometry ({ type, coordinates }) { | ||
return type && coordinates | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
const _ = require('lodash') | ||
const { within } = require('@terraformer/spatial') | ||
|
||
module.exports = function (featureGeometry, filterGeometry = {}) { | ||
if (_.isEmpty(featureGeometry)) return false | ||
const { type, coordinates = [] } = featureGeometry | ||
if (!type || !coordinates || coordinates.length === 0) return false | ||
return within(featureGeometry, filterGeometry) | ||
} |
8 changes: 8 additions & 0 deletions
8
packages/winnow/lib/filter-and-transform/helpers/create-integer-hash.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
const hashFunction = require('./hash-function') | ||
|
||
module.exports = function createIntegerHash (inputStr) { | ||
// Hash to 32 bit unsigned integer | ||
const hash = hashFunction(inputStr) | ||
// Normalize to range of postive values of signed integer | ||
return Math.round((hash / 4294967295) * (2147483647)) | ||
} |
File renamed without changes.
File renamed without changes.
68 changes: 68 additions & 0 deletions
68
packages/winnow/test/unit/filter-and-transform/filters/constains.spec.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
const test = require('tape') | ||
const contains = require('../../../../lib/filter-and-transform/filters/contains') | ||
|
||
test('contains: empty input', t => { | ||
const result = contains() | ||
t.equals(result, false) | ||
t.end() | ||
}) | ||
|
||
test('contains: empty object input', t => { | ||
const result = contains({}, {}) | ||
t.equals(result, false) | ||
t.end() | ||
}) | ||
|
||
test('contains: null input', t => { | ||
const result = contains(null, {}) | ||
t.equals(result, false) | ||
t.end() | ||
}) | ||
|
||
test('contains: null input', t => { | ||
const result = contains({}, null) | ||
t.equals(result, false) | ||
t.end() | ||
}) | ||
|
||
test('contains: missing geometry type', t => { | ||
const result = contains({ coordinates: [44, 84] }, {}) | ||
t.equals(result, false) | ||
t.end() | ||
}) | ||
|
||
test('contains: missing coordinates', t => { | ||
const result = contains({ type: 'Point' }, {}) | ||
t.equals(result, false) | ||
t.end() | ||
}) | ||
|
||
test('contains: missing empty coordinates', t => { | ||
const result = contains({ type: 'Point', coordinates: [] }, {}) | ||
t.equals(result, false) | ||
t.end() | ||
}) | ||
|
||
test('contains: missing filter geometry', t => { | ||
const result = contains({ type: 'Point', coordinates: [44, -84.5] }) | ||
t.equals(result, false) | ||
t.end() | ||
}) | ||
|
||
test('contains: true', t => { | ||
const result = contains({ type: 'Point', coordinates: [44, -84.5] }, { | ||
type: 'Polygon', | ||
coordinates: [[[44, -85], [45, -85], [45, -84], [44, -84], [44, -85]]] | ||
}) | ||
t.equals(result, true) | ||
t.end() | ||
}) | ||
|
||
test('contains: false', t => { | ||
const result = contains({ type: 'Point', coordinates: [0, 0] }, { | ||
type: 'Polygon', | ||
coordinates: [[[44, -85], [45, -85], [45, -84], [44, -84], [44, -85]]] | ||
}) | ||
t.equals(result, false) | ||
t.end() | ||
}) |
Oops, something went wrong.