@@ -5,7 +5,10 @@ import {decode as decodePolyline} from 'polyline'
5
5
import { isEqual as coordinatesAreEqual } from '@conveyal/lonlat'
6
6
import qs from 'qs'
7
7
import lineString from 'turf-linestring'
8
- import lineSliceAlong from '@turf/line-slice-along'
8
+
9
+ // This can be used for logging line strings to geojson.io URLs for easy
10
+ // debugging.
11
+ // import {logCoordsToGeojsonio} from '../../editor/util/debug'
9
12
10
13
import type {
11
14
Coordinates ,
@@ -58,38 +61,29 @@ function handleGraphHopperRouting (path: Path, individualLegs: boolean = false):
58
61
// Decode polyline and reverse coordinates.
59
62
const decodedPolyline = decodePolyline ( points ) . map ( c => ( [ c [ 1 ] , c [ 0 ] ] ) )
60
63
if ( individualLegs ) {
61
- // Reconstruct individual legs from the instructions. NOTE: we do not simply
62
- // use the waypoints found in the response because for lines that share
63
- // street segments, slicing on these points results in unpredictable splits.
64
- // Slicing the line along distances is much more reliable.
65
64
const segments = [ ]
66
- const waypointDistances = [ 0 ]
67
- let distance = 0
68
- // Iterate over the instructions, accumulating distance and storing the
69
- // distance at each waypoint encountered. Distances are used to slice the
70
- // line geometry if individual legs are needed. NOTE: Waypoint === routing
71
- // point provided in the request.
72
- instructions . forEach ( instruction => {
73
- if ( instruction . text . match ( / W a y p o i n t ( \d + ) / ) ) {
74
- // Add distance value to list
75
- waypointDistances . push ( distance )
76
- } else {
77
- distance += instruction . distance
65
+ // Keep track of the segment point intervals to split the line segment at.
66
+ // This appears to be the most reliable way to split up the geometry
67
+ // (previously distance was used here, but that provided inconstent results).
68
+ const segmentPointIndices = [ 0 ]
69
+ // Iterate over the instructions, accumulating segment point indices at each
70
+ // waypoint encountered. Indices are used to slice the line geometry when
71
+ // individual legs are needed. NOTE: Waypoint === routing point provided in
72
+ // the request.
73
+ instructions . forEach ( ( instruction , i ) => {
74
+ if ( instruction . text . match ( / W a y p o i n t ( \d + ) / ) || i === instructions . length - 1 ) {
75
+ segmentPointIndices . push ( instruction . interval [ 0 ] )
78
76
}
79
77
} )
80
- // Add last distance measure.
81
- // FIXME: Should this just be the length of the entire line?
82
- // console.log(waypointDistances, json.paths[0].distance)
83
- waypointDistances . push ( distance )
84
- const decodedLineString = lineString ( decodedPolyline )
85
- if ( waypointDistances . length > 2 ) {
86
- for ( var i = 1 ; i < waypointDistances . length ; i ++ ) {
87
- const slicedSegment = lineSliceAlong (
88
- decodedLineString ,
89
- waypointDistances [ i - 1 ] / 1000 ,
90
- waypointDistances [ i ] / 1000
91
- )
92
- segments . push ( slicedSegment . geometry . coordinates )
78
+ // Once all of the indices have been found, slice the decoded polyline up
79
+ // at the provided indices.
80
+ if ( segmentPointIndices . length > 2 ) {
81
+ for ( var i = 1 ; i < segmentPointIndices . length ; i ++ ) {
82
+ // Get the indices of the points that the entire path should be sliced at
83
+ // Note: 'to' index is incremented by one because it is not inclusive.
84
+ const [ from , to ] = [ segmentPointIndices [ i - 1 ] , segmentPointIndices [ i ] + 1 ]
85
+ const segment = decodedPolyline . slice ( from , to )
86
+ segments . push ( segment )
93
87
}
94
88
// console.log('individual legs', segments)
95
89
return segments
@@ -126,15 +120,16 @@ export async function polyline (
126
120
let count = 0
127
121
const j = points . length
128
122
for ( let i = 0 ; i < j ; i += chunk ) {
129
- // Offset the slice indexes so that the next chunk begins with the
123
+ // Offset the slice indices so that the next chunk begins with the
130
124
const offset = count * - 1
131
125
const beginIndex = i + offset
132
126
const endIndex = i + chunk + offset
133
127
const chunkedPoints = points . slice ( beginIndex , endIndex )
134
128
json = await routeWithGraphHopper ( chunkedPoints )
129
+ const path = json && json . paths && json . paths [ 0 ]
135
130
// Route between chunked list of points
136
- if ( json && json . paths && json . paths [ 0 ] ) {
137
- const result = handleGraphHopperRouting ( json . paths [ 0 ] , individualLegs )
131
+ if ( path ) {
132
+ const result = handleGraphHopperRouting ( path , individualLegs )
138
133
geometry . push ( ...result )
139
134
} else {
140
135
// If any of the routed legs fails, default to straight line (return null).
0 commit comments