geochatt
Version:
JavaScript Utility Functions for Working with Open GeoSpatial Data about Chattanooga
83 lines (66 loc) • 2.03 kB
JavaScript
const fs = require("node:fs");
const path = require("node:path");
const zlib = require("node:zlib");
const { geojsonRbush } = require("@turf/geojson-rbush");
const { buffer } = require("@turf/buffer");
const { pointToPolygonDistance } = require("@turf/point-to-polygon-distance");
const parcels_path = path.join(__dirname, "live_parcels.geojson.gz");
let parcels = null;
function get_parcel_from_point(
point,
{ max_distance = 0.0001 } = { max_distance: 0.0001 }
) {
if (parcels === null) {
const tree = geojsonRbush();
parcels = tree.load(
JSON.parse(zlib.gunzipSync(fs.readFileSync(parcels_path)))
);
}
if (Array.isArray(point) && point.length === 2) {
point = {
type: "Feature",
properties: {},
geometry: {
type: "Point",
coordinates: point
}
};
}
// first check if point is inside a parcel
const container = parcels.search(point).features;
if (container.length === 1) return container[0];
const search_circle = buffer(point, max_distance, {
steps: 2,
units: "degrees"
});
// parcels within the search radius
const features = parcels.search(search_circle).features;
if (features.length === 1) {
return features[0];
}
const features_with_distance = features.map(feature => {
try {
let distance = pointToPolygonDistance(point, feature, {
method: "planar"
});
// if inside the polygon, distance would be negative
if (distance < 0) distance = 0;
return { feature, distance };
} catch (error) {
throw error;
}
});
features_with_distance.sort((a, b) => Math.sign(a.distance - b.distance));
const best = features_with_distance[0];
if (best) return best.feature;
}
function get_address(
point,
{ max_distance = 0.0001 } = { max_distance: 0.0001 }
) {
const parcel = get_parcel_from_point(point, { max_distance });
if (parcel) return parcel.properties.ADDRESS;
}
if (typeof module === "object") {
module.exports = { get_address };
}