diff options
author | Andrew Harvey <andrew@alantgeo.com.au> | 2021-07-05 22:06:26 +1000 |
---|---|---|
committer | Andrew Harvey <andrew@alantgeo.com.au> | 2021-07-05 22:06:26 +1000 |
commit | a552ff46a21b530c85dd871a1e4a41f0d827a545 (patch) | |
tree | 1f5333176b4553fb2ac357d2f3b49df82dea39ec | |
parent | 0275d9e79da1f72044737fb0fbcaa4f136f09c6f (diff) |
fix reduceOverlap code which creates ranges if inputs are already ranges
-rwxr-xr-x | bin/reduceOverlap.js | 8 | ||||
-rw-r--r-- | package.json | 2 | ||||
-rw-r--r-- | test/reduceOverlap.js | 171 |
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() +}) |