aboutsummaryrefslogtreecommitdiff
path: root/bin/conflate.js
diff options
context:
space:
mode:
Diffstat (limited to 'bin/conflate.js')
-rwxr-xr-xbin/conflate.js57
1 files changed, 48 insertions, 9 deletions
diff --git a/bin/conflate.js b/bin/conflate.js
index 3e0e321..f2b5328 100755
--- a/bin/conflate.js
+++ b/bin/conflate.js
@@ -8,8 +8,15 @@ const fs = require('fs')
const { Transform, pipeline } = require('stream')
const ndjson = require('ndjson')
const PolygonLookup = require('polygon-lookup')
+const Flatbush = require('flatbush')
+const bbox = require('@turf/bbox').default
+const booleanIntersects = require('@turf/boolean-intersects').default
const argv = require('yargs/yargs')(process.argv.slice(2))
+ .option('verbose', {
+ type: 'boolean',
+ description: 'Verbose logging'
+ })
.argv
if (argv._.length < 4) {
@@ -53,12 +60,17 @@ const lookupBlocks = new PolygonLookup({
features: blocksByOSMAddr
})
let lookupOSMAddressPoly
-const osmAddrPoly = []
+const osmAddrPolygons = []
const osmAddrLines = [] // address interpolation lines
+
// indexed by block
const osmAddrPoints = {
0: [] // this one is for any points not within a block
}
+const osmAddrPolygonsByBlock = {
+ 0: [] // this one is for any polygons not within a block
+}
+
// find OSM Addresses and store them
// polygons go into a simple array, which later we create a point in polygon index for
@@ -76,7 +88,7 @@ const filterOSMAddrPoly = new Transform({
if (feature && feature.geometry && feature.geometry.type) {
if (feature.geometry.type === 'Polygon' || feature.geometry.type === 'MultiPolygon') {
- osmAddrPoly.push(feature)
+ osmAddrPolygons.push(feature)
} else if (feature.geometry.type === 'Point') {
const results = lookupBlocks.search(...feature.geometry.coordinates.slice(0, 2), 1)
const block = results ? (results.type === 'FeatureCollection' ? (results.features ? results.features[0] : null) : results) : null
@@ -113,9 +125,11 @@ const conflate = new Transform({
process.stdout.write(` ${sourceCount / 1000}k\r`)
}
+ // find which block this vicmap address is in
const results = lookupBlocks.search(...feature.geometry.coordinates.slice(0, 2), 1)
const block = results ? (results.type === 'FeatureCollection' ? (results.features ? results.features[0] : null) : results) : null
if (block) {
+ // address within a block
if (block.properties.NUMPOINTS === 0) {
// no OSM addresses found within this block, so able to import without review
outputStreams.noOSMAddressWithinBlock.write(feature)
@@ -132,8 +146,8 @@ const conflate = new Transform({
// address not found within an existing OSM address polygon
// see if any address with the same number and street in the same block
- if (block.id in osmAddrPoints) {
- const osmAddrWithinBlock = osmAddrPoints[block.id]
+ if (block.id in osmAddrPoints || block.id in osmAddrPolygonsByBlock) {
+ const osmAddrWithinBlock = [osmAddrPoints[block.id] || [], osmAddrPolygonsByBlock[block.id] || []].flat()
const matches = osmAddrWithinBlock.filter(osmAddr => {
return (feature.properties['addr:street'] === osmAddr.properties['addr:street'] &&
feature.properties['addr:housenumber'] === osmAddr.properties['addr:housenumber'] )
@@ -147,9 +161,10 @@ const conflate = new Transform({
outputStreams.noExactMatch.write(feature)
}
} else {
- // block id not found in osmAddrPoints, meaning there are no osmAddress points in this block,
- // however in this case NUMPOINTS should have been 0
- console.log(`Block ID not found when expected`)
+ // block id not found in osmAddrPoints or osmAddrPolygonsByBlock, meaning there are no osmAddress points or polygons in this block,
+ // maybe there was an address as a linear way?
+ // we ignore address interpolation lines and only look at the endpoint nodes from the interpolation way
+ console.log(`Block ID ${block.id} not found when expected for `, JSON.stringify(feature), JSON.stringify(block))
}
}
}
@@ -183,12 +198,36 @@ pipeline(
console.log(err)
process.exit(1)
} else {
- console.log(` of ${osmAddrCount} OSM address features found ${osmAddrPoly.length} addresses represented as polygons, ${osmAddrLines.length} addresses represented as lines`)
+ console.log(` of ${osmAddrCount} OSM address features found ${osmAddrPolygons.length} addresses represented as polygons, ${osmAddrLines.length} addresses represented as lines`)
+
console.log('Creating index for OSM Address Polygon lookup')
lookupOSMAddressPoly = new PolygonLookup({
type: 'FeatureCollection',
- features: osmAddrPoly
+ features: osmAddrPolygons
})
+
+ // create an index of blocks
+ const blockIndex = new Flatbush(blocksByOSMAddr.length)
+ for (const block of blocksByOSMAddr) {
+ blockIndex.add(...bbox(block))
+ }
+ blockIndex.finish()
+
+ console.log(`Index OSM Address Polygons within each block`)
+ // for each OSM address polygon
+ for (const osmAddrPolygon of osmAddrPolygons) {
+ // find the blocks it might intersect
+ const candidateBlocks = blockIndex.search(...bbox(osmAddrPolygon))
+ // then test if it actually intersects
+ const intersectingBlocks = candidateBlocks.map(candidateBlock => booleanIntersects(osmAddrPolygon, blocksByOSMAddr[candidateBlock]))
+ for (const intersectingBlock of intersectingBlocks) {
+ if (!(intersectingBlock.id in osmAddrPolygonsByBlock)) {
+ osmAddrPolygonsByBlock[intersectingBlock.id] = []
+ }
+ osmAddrPolygonsByBlock[intersectingBlock.id].push(osmAddrPolygon)
+ }
+ }
+
// second pass to conflate with existing OSM data
console.log('Pass 2/2: Conflate with existing OSM data')
pipeline(