Remove small holes and reduce geojson precision.
Fixes #11, Fixes #17
diff --git a/index.js b/index.js
index c5f850b..9eabbd4 100644
--- a/index.js
+++ b/index.js
@@ -1,6 +1,7 @@
var exec = require('child_process').exec
var fs = require('fs')
+var area = require('@mapbox/geojson-area')
var helpers = require('@turf/helpers')
var multiPolygon = helpers.multiPolygon
var polygon = helpers.polygon
@@ -37,6 +38,8 @@
var geoJsonReader = new jsts.io.GeoJSONReader()
var geoJsonWriter = new jsts.io.GeoJSONWriter()
+var precisionModel = new jsts.geom.PrecisionModel(1000000)
+var precisionReducer = new jsts.precision.GeometryPrecisionReducer(precisionModel)
var distZones = {}
var minRequestGap = 4
var curRequestGap = 4
@@ -55,9 +58,6 @@
var result
if (reducePrecision) {
- var precisionModel = new jsts.geom.PrecisionModel(10000)
- var precisionReducer = new jsts.precision.GeometryPrecisionReducer(precisionModel)
-
a = precisionReducer.reduce(a)
b = precisionReducer.reduce(b)
}
@@ -198,6 +198,7 @@
var curGeom = geoJsonToGeom(curOsmGeom)
} catch (e) {
console.error('error converting overpass result to geojson')
+ console.error(e)
fs.writeFileSync(boundaryId + '_convert_to_geom_error.json', JSON.stringify(data))
throw e
}
@@ -249,6 +250,67 @@
return geoJsonToGeom(geoJson)
}
+/**
+ * Post process created timezone boundary.
+ * - remove small holes and exclaves
+ * - reduce geometry precision
+ *
+ * @param {Geometry} geom The jsts geometry of the timezone
+ * @return {String} Stringified geojson
+ */
+var postProcessZone = function (geom) {
+ // reduce precision of geometry
+ const geojson = geomToGeoJson(precisionReducer.reduce(geom))
+
+ // iterate through all polygons
+ const filteredPolygons = []
+ let allPolygons = geojson.coordinates
+ if (geojson.type === 'Polygon') {
+ allPolygons = [geojson.coordinates]
+ }
+
+ allPolygons.forEach((curPolygon, idx) => {
+ // remove any polygon with very small area
+ const polygonFeature = polygon(curPolygon)
+ const polygonArea = area.geometry(polygonFeature.geometry)
+
+ if (polygonArea < 1) return
+
+ // find all holes
+ const filteredLinearRings = []
+
+ curPolygon.forEach((curLinearRing, lrIdx) => {
+ if (lrIdx === 0) {
+ // always keep first linearRing
+ filteredLinearRings.push(curLinearRing)
+ } else {
+ const polygonFromLinearRing = polygon([curLinearRing])
+ const linearRingArea = area.geometry(polygonFromLinearRing.geometry)
+
+ // only include holes with relevant area
+ if (linearRingArea > 1) {
+ filteredLinearRings.push(curLinearRing)
+ }
+ }
+ })
+
+ filteredPolygons.push(filteredLinearRings)
+ })
+
+ // recompile to geojson string
+ const newGeojson = {
+ type: geojson.type
+ }
+
+ if (geojson.type === 'Polygon') {
+ newGeojson.coordinates = filteredPolygons[0]
+ } else {
+ newGeojson.coordinates = filteredPolygons
+ }
+
+ return JSON.stringify(newGeojson)
+}
+
var makeTimezoneBoundary = function (tzid, callback) {
console.log('makeTimezoneBoundary for', tzid)
@@ -277,7 +339,7 @@
function (err) {
if (err) { return callback(err) }
fs.writeFile(getTzDistFilename(tzid),
- geomToGeoJsonString(geom),
+ postProcessZone(geom),
callback)
})
}