Skip to content

Instantly share code, notes, and snippets.

@chrispahm
Created December 5, 2017 12:53
Show Gist options
  • Save chrispahm/3b856016004a330d94f6f4191b47691e to your computer and use it in GitHub Desktop.
Save chrispahm/3b856016004a330d94f6f4191b47691e to your computer and use it in GitHub Desktop.
/*
Vorgewende
API Methods
lineString (poly, (angle), (distance)) - Returns array consisting of a GeoJSON lineString for each headland for the given field
Polygon (poly, workingWidth, (angle), (distance))- Returns an array consisting of a GeoJSON Polygon for each headland using the working width as its width for the given field
*/
const GJV = require("geojson-validation")
const turf = require('@turf/turf')
module.exports = {
lineString: function (poly, angle = 30, distance = 10) {
//console.log(angle)
// Will contain all headland LineStrings as features
let headlands = []
// first validate if polygon matches GeoJSON prerequisites
GJV.isPolygon(poly.geometry, function(valid, err) {
if (!valid) {
throw "Invalid Polygon, " + err
}
const coords = turf.getCoords(poly)[0]
// Start with first two coordinates in order to create an initial path
let curLineString = [coords[0], coords[1]]
// Get angle between the starting coordinates as a reference
let refAngle = angleCoords(coords[0],coords[1])
let j = 1
let uncertainPolys = []
let curAngle, curDistance, angleDiff
for (var i = 2; i < coords.length; i++) {
curAngle = angleCoords(coords[i-j],coords[i])
curDistance = turf.distance(turf.point(coords[i-j]), turf.point(coords[i])) * 1000
angleDiff = angleBetCoords(refAngle, curAngle)
if (curDistance <= distance && angleDiff <= angle && angleDiff >= -angle) {
curLineString.push(coords[i])
j++
}
else if (curDistance <= distance && angleDiff >= angle && angleDiff <= -angle) {
uncertainPolys.push(coords[i])
j++
}
else if (angleDiff <= angle && angleDiff >= -angle) {
if (j > 1) {
curLineString = curLineString.concat(uncertainPolys)
uncertainPolys = []
j = 1
}
curLineString.push(coords[i])
refAngle = curAngle
}
else {
headlands.push(turf.lineString(curLineString))
if (j > 1 && uncertainPolys.length > 0) {
curLineString = []
curLineString.push(coords[i - j])
curLineString = curLineString.concat(uncertainPolys)
curLineString.push(coords[i])
uncertainPolys = []
j = 1
}
else {
curLineString = [coords[i-1], coords[i]]
}
refAngle = curAngle
}
}
// Join headland LineStrings if first and last coordinates are equal,
// as in this case the headland was drawn from the "middle" of the headland
let finalAngle = angleBetCoords(angleCoords(coords[0],coords[1]), curAngle)
if (finalAngle <= angle && finalAngle >= -angle) {
headlandPartA = curLineString
headlandPartB = turf.getCoords(headlands[0])
headlandConcat = headlandPartA.concat(headlandPartB)
headlands[0] = turf.lineString(headlandConcat)
}
// Push the last headland into the array if the headlands are not connected
else {
headlands.push(turf.lineString(curLineString))
}
})
return headlands
}
}
function angleCoords(p1,p2) {
return Math.atan2(p2[1] - p1[1], p2[0] - p1[0]) * 180 / Math.PI
}
function angleBetCoords(a,b) {
let difference = a - (b)
if (difference < - 180) difference += 360
else if (difference > 180) difference -= 360
return difference
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment