agmission/Development/server/helpers/line_buffer.js

62 lines
1.9 KiB
JavaScript

'use strict';
const proj4 = require('proj4'),
turf = require('@turf/turf'),
jsts = require('jsts'),
utils = require('./utils');
/**
* Convert a line buffer to a polygon coordinates
* @param {*} lineGeoCoors buffer line coordinates
* @param {*} width in meters
*/
function lineBuffer(lineGeoCoors, width) {
let dBufCoors = [];
if (!utils.isEmptyArray(lineGeoCoors)) {
const _width = width || 10; // default is 10 meter
try {
// 1. Transform to Earth Azimuthal Equidistant projection centered by the centeroid of the geometry's bounds
const line = turf.lineString(lineGeoCoors);
const bbox = turf.bbox(line);
const bboxPolygon = turf.bboxPolygon(bbox);
const centroid = turf.centroid(bboxPolygon);
proj4.defs([
[
'EPSG:4326',
'+title=WGS 84 (long/lat) +proj=longlat +ellps=WGS84 +datum=WGS84 +units=degrees'],
]);
const aeqdProjection = `+proj=aeqd +lat_0=${centroid.geometry.coordinates[1]} +lon_0=${centroid.geometry.coordinates[0]} +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs`;
const projectedCoors = lineGeoCoors.map(co => {
return proj4(aeqdProjection, co);
});
// 2. Do the buffer using JSTS geolib
const pathCoords = projectedCoors.map(coor => {
return new jsts.geom.Coordinate(coor[0], coor[1]);
});
const geometryFactory = new jsts.geom.GeometryFactory();
const shell = geometryFactory.createLineString(pathCoords);
const meters = _width * .5;
const polygon = shell.buffer(meters, 16, 2); // 16: quadrants point for arc, 2: flat endStyle
const polygonCoords = polygon.getCoordinates();
// 3. Transform back to WGS84 latlon
dBufCoors = polygonCoords.map(co => {
const proj = proj4(aeqdProjection, proj4('EPSG:4326'), co);
return [proj.x, proj.y];
});
} catch (error) {
debug(error);
return [];
}
}
return dBufCoors;
};
module.exports = {
lineBuffer
};