aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Harvey <andrew@alantgeo.com.au>2021-07-05 22:06:26 +1000
committerAndrew Harvey <andrew@alantgeo.com.au>2021-07-05 22:06:26 +1000
commita552ff46a21b530c85dd871a1e4a41f0d827a545 (patch)
tree1f5333176b4553fb2ac357d2f3b49df82dea39ec
parent0275d9e79da1f72044737fb0fbcaa4f136f09c6f (diff)
fix reduceOverlap code which creates ranges if inputs are already ranges
-rwxr-xr-xbin/reduceOverlap.js8
-rw-r--r--package.json2
-rw-r--r--test/reduceOverlap.js171
3 files changed, 179 insertions, 2 deletions
diff --git a/bin/reduceOverlap.js b/bin/reduceOverlap.js
index 5546732..0941f49 100755
--- a/bin/reduceOverlap.js
+++ b/bin/reduceOverlap.js
@@ -117,14 +117,20 @@ const reduce = new Transform({
.every( (val, i, arr) => val === arr[0] ) // check if all values are the same
const firstNumber = noUnits && sameNonHousenumber ? overlappingFeatures.map(f => f.properties['addr:housenumber']).reduce((acc, cur) => {
+ if (cur && cur.split('-').length === 2) {
+ cur = cur.split('-')[0]
+ }
return (cur < acc) ? cur : acc
}) : null
const lastNumber = noUnits && sameNonHousenumber ? overlappingFeatures.map(f => f.properties['addr:housenumber']).reduce((acc, cur) => {
+ if (cur && cur.split('-').length === 2) {
+ cur = cur.split('-')[1]
+ }
return (cur > acc) ? cur : acc
}) : null
- if (noUnits && sameNonHousenumber && firstNumber && lastNumber) {
+ if (noUnits && sameNonHousenumber && firstNumber && lastNumber && (firstNumber !== lastNumber)) {
const featureAsRange = overlappingFeatures[0]
featureAsRange.properties['addr:housenumber'] = `${firstNumber}-${lastNumber}`
if (featureAsRange.properties._pfi) {
diff --git a/package.json b/package.json
index 5b86ed4..60166b8 100644
--- a/package.json
+++ b/package.json
@@ -6,7 +6,7 @@
"author": "Andrew Harvey <andrew@alantgeo.com.au>",
"license": "MIT",
"scripts": {
- "test": "./node_modules/.bin/tape test/toOSM.js test/cluster.js test/unitsToRanges.js test/withinRange.js test/valueLimits.js test/reduceRangeDuplicates.js"
+ "test": "./node_modules/.bin/tape test/toOSM.js test/cluster.js test/unitsToRanges.js test/withinRange.js test/valueLimits.js test/reduceRangeDuplicates.js test/reduceOverlap.js"
},
"dependencies": {
"@turf/bbox": "^6.3.0",
diff --git a/test/reduceOverlap.js b/test/reduceOverlap.js
new file mode 100644
index 0000000..6899930
--- /dev/null
+++ b/test/reduceOverlap.js
@@ -0,0 +1,171 @@
+const test = require('tape')
+const fs = require('fs')
+const child_process = require('child_process')
+const mktemp = require('mktemp')
+
+function createFeature(options) {
+ return {
+ type: 'Feature',
+ properties: {
+ ...(options.flats && {'addr:flats': options.flats}),
+ ...(options.unit && {'addr:unit': options.unit}),
+ 'addr:housenumber': options.housenumber,
+ 'addr:street': options.street,
+ 'addr:suburb': options.suburb,
+ 'addr:state': 'VIC',
+ 'addr:postcode': '0000'
+ },
+ geometry: options.coordinates ? {
+ type: 'Point',
+ coordinates: options.coordinates
+ } : null
+ }
+}
+
+test('reduceOverlap distinct geometries', t => {
+ const inputFile = mktemp.createFileSync('/tmp/input_XXXXX.geojson')
+ const outputFile = mktemp.createFileSync('/tmp/output_XXXXX.geojson')
+ const expectedFile = mktemp.createFileSync('/tmp/expected_XXXXX.geojson')
+
+ const A = createFeature({
+ housenumber: '304',
+ street: 'Cardigan Street',
+ suburb: 'Carlton',
+ coordinates: [0, 0]
+ })
+ const B = createFeature({
+ housenumber: '304',
+ street: 'Cardigan Street',
+ suburb: 'Carlton',
+ coordinates: [1, 1]
+ })
+
+ // both features to appear in input
+ fs.appendFileSync(inputFile, JSON.stringify(A) + '\n')
+ fs.appendFileSync(inputFile, JSON.stringify(B) + '\n')
+
+ // output expected to both inputs since they aren't overlapping
+ fs.appendFileSync(expectedFile, JSON.stringify(A) + '\n')
+ fs.appendFileSync(expectedFile, JSON.stringify(B) + '\n')
+
+ try {
+ child_process.execSync(`./bin/reduceOverlap.js --verbose ${inputFile} ${outputFile}`)
+ } catch (err) {
+ t.fail(err.stdout.toString())
+ }
+
+ t.same(
+ fs.readFileSync(outputFile, 'utf-8').trim().split('\n').map(JSON.parse),
+ fs.readFileSync(expectedFile, 'utf-8').trim().split('\n').map(JSON.parse),
+ 'same address at different location is not reduced'
+ )
+
+ fs.unlinkSync(inputFile)
+ fs.unlinkSync(outputFile)
+ fs.unlinkSync(expectedFile)
+
+ t.end()
+})
+
+test('reduceOverlap matching geometries different attributes', t => {
+ const inputFile = mktemp.createFileSync('/tmp/input_XXXXX.geojson')
+ const outputFile = mktemp.createFileSync('/tmp/output_XXXXX.geojson')
+ const expectedFile = mktemp.createFileSync('/tmp/expected_XXXXX.geojson')
+
+ const A = createFeature({
+ housenumber: '100',
+ street: 'Foo Street',
+ suburb: 'A',
+ coordinates: [0, 0]
+ })
+ const B = createFeature({
+ housenumber: '200',
+ street: 'Bar Street',
+ suburb: 'B',
+ coordinates: [0, 0]
+ })
+
+ // both features to appear in input
+ fs.appendFileSync(inputFile, JSON.stringify(A) + '\n')
+ fs.appendFileSync(inputFile, JSON.stringify(B) + '\n')
+
+ // output expected to retain both inputs
+ fs.appendFileSync(expectedFile, JSON.stringify(A) + '\n')
+ fs.appendFileSync(expectedFile, JSON.stringify(B) + '\n')
+
+ try {
+ child_process.execSync(`./bin/reduceOverlap.js --verbose ${inputFile} ${outputFile}`)
+ } catch (err) {
+ t.fail(err.stdout.toString())
+ }
+
+ t.same(
+ fs.readFileSync(outputFile, 'utf-8').trim().split('\n').map(JSON.parse),
+ fs.readFileSync(expectedFile, 'utf-8').trim().split('\n').map(JSON.parse),
+ 'different address at same location is retained'
+ )
+
+ fs.unlinkSync(inputFile)
+ fs.unlinkSync(outputFile)
+ fs.unlinkSync(expectedFile)
+
+ t.end()
+})
+
+test('reduceOverlap matching geometries adjoining ranges', t => {
+ const inputFile = mktemp.createFileSync('/tmp/input_XXXXX.geojson')
+ const outputFile = mktemp.createFileSync('/tmp/output_XXXXX.geojson')
+ const expectedFile = mktemp.createFileSync('/tmp/expected_XXXXX.geojson')
+
+ const A = createFeature({
+ housenumber: '51',
+ street: 'Cardigan Street',
+ suburb: 'Carlton',
+ coordinates: [0, 0]
+ })
+ const B = createFeature({
+ housenumber: '53',
+ street: 'Cardigan Street',
+ suburb: 'Carlton',
+ coordinates: [0, 0]
+ })
+ const C = createFeature({
+ housenumber: '55-57',
+ street: 'Cardigan Street',
+ suburb: 'Carlton',
+ coordinates: [0, 0]
+ })
+
+ const result = createFeature({
+ housenumber: '51-57',
+ street: 'Cardigan Street',
+ suburb: 'Carlton',
+ coordinates: [0, 0]
+ })
+
+ // all features to appear in input
+ fs.appendFileSync(inputFile, JSON.stringify(A) + '\n')
+ fs.appendFileSync(inputFile, JSON.stringify(B) + '\n')
+ fs.appendFileSync(inputFile, JSON.stringify(C) + '\n')
+
+ // output expected to join the ranges
+ fs.appendFileSync(expectedFile, JSON.stringify(result) + '\n')
+
+ try {
+ child_process.execSync(`./bin/reduceOverlap.js --verbose ${inputFile} ${outputFile}`)
+ } catch (err) {
+ t.fail(err.stdout.toString())
+ }
+
+ t.same(
+ fs.readFileSync(outputFile, 'utf-8').trim().split('\n').map(JSON.parse),
+ fs.readFileSync(expectedFile, 'utf-8').trim().split('\n').map(JSON.parse),
+ 'adjoining ranges at same location is merged'
+ )
+
+ fs.unlinkSync(inputFile)
+ fs.unlinkSync(outputFile)
+ fs.unlinkSync(expectedFile)
+
+ t.end()
+})