Search code examples
gispolygonmapbox-gl-jsturfjs

Slice circular linestring by shortest distance between 2 points


I have a polygon of a farming field. I am dropping 2 Points along the field borders in order to easily measure the distance between those points.

This works great most of the time, but in some situations the sliced line takes "the long way round".

Question

How do I slice a linestring in the direction of the shortest distance between the 2 points?

More context

  1. First I take a polygon and convert it to a linestring
  2. Then I use Turf functions to slice the line at the start and end points
import { polygonToLine } from '@turf/polygon-to-line'
import lineSlice from '@turf/line-slice'

const slicedLineString = lineSlice(
    startPoint,
    endPoint,
    polygonToLine(polygonFeature)
)

Blank context image of the field:

starting point

The below image is correct, the shortest distance shown by the black line:

working correctly

The below image shows the black line measuring in the wrong direction, not the shortest distance/direction between the 2 points.

not working correctky


Solution

  • I solved this by:

    1. Looping through all the coordinates of the linestring, finding the coordinate pair that is furthest from both the start and coordinates
    2. Re-order the linestring coordinates so that it starts from this furthest away point
    const lineString = polygonToLine(JSON.parse(this.parcel.geometry))
    
    // Loop through all coordinates of linestring Feature, find coordinate pair that is furthest from both the start and end coordinates
    let furthestDistance = 0
    let furthestIndex = 0
    
    for (let i = 0; i < lineString.geometry.coordinates.length; i++) {
        const distanceToStart = distance(lineString.geometry.coordinates[i], this.startCoordinates, {
            units: 'kilometers'
        })
    
        const distanceToEnd = distance(lineString.geometry.coordinates[i], this.endCoordinates, {
            units: 'kilometers'
        })
    
        const totalDistance = distanceToStart + distanceToEnd
    
        if (totalDistance > furthestDistance) {
            furthestDistance = totalDistance
            furthestIndex = i
        }
    }
    
    // Re-order linestring geometry coordinates so that the furthest coordinate pair is at the start
    const reorderedCoordinates = lineString.geometry.coordinates
        .slice(furthestIndex)
        .concat(lineString.geometry.coordinates.slice(0, furthestIndex))
    
    lineString.geometry.coordinates = reorderedCoordinates
    
    this.slicedLine = lineSlice(this.startCoordinates, this.endCoordinates, lineString)