@@ -12,6 +12,9 @@ func arePositionsSorted(a []float64) bool {
1212 if len (a ) < 2 {
1313 return true
1414 }
15+ if a [0 ] == a [len (a )- 1 ] {
16+ return false
17+ }
1518 for i := 1 ; i < len (a ); i ++ {
1619 if a [i ] < a [i - 1 ] {
1720 return false
@@ -22,24 +25,27 @@ func arePositionsSorted(a []float64) bool {
2225
2326type ShapeInfo struct {
2427 Line []tlxy.Point
25- Dists []float64
2628 DistLength float64
27- Length float64
29+ }
30+
31+ type stopPositionInfo struct {
32+ Positions []float64
33+ DistLength float64
2834}
2935
3036// GeomCache helps speed up StopTime interpolating by caching various results
3137type GeomCache struct {
32- stopPositions map [string ][]float64
3338 stops map [string ]tlxy.Point
3439 shapes map [string ]ShapeInfo
40+ stopPositions map [string ]stopPositionInfo
3541}
3642
3743// NewGeomCache returns an initialized geomCache
3844func NewGeomCache () * GeomCache {
3945 return & GeomCache {
40- stopPositions : map [string ][]float64 {},
4146 stops : map [string ]tlxy.Point {},
4247 shapes : map [string ]ShapeInfo {},
48+ stopPositions : map [string ]stopPositionInfo {},
4349 }
4450}
4551
@@ -63,31 +69,16 @@ func (g *GeomCache) GetShapeInfo(eid string) ShapeInfo {
6369}
6470
6571func (g * GeomCache ) AddShapeGeom (eid string , line []tlxy.Point , dists []float64 ) {
66- // Check if already exists, re-use slice to reduce mem
67- for _ , s := range g .shapes {
68- if tlxy .LineEquals (line , s .Line ) {
69- line = s .Line
70- dists = s .Dists
71- }
72- }
7372 // Create shapeInfo
74- si := ShapeInfo {
75- Line : line ,
76- Length : tlxy .LengthHaversine (line ),
77- }
73+ si := ShapeInfo {Line : line }
7874 // Validate ShapeDistTraveled values
7975 if len (dists ) > 0 && len (dists ) == len (line ) && dists [len (dists )- 1 ]- dists [0 ] > 0 {
80- // Use supplied ShapeDistTraveled values
81- si .Dists = dists
82- si .DistLength = dists [len (dists )- 1 ]
83- } else {
84- // Calculate our own ShapeDistTraveled values
85- si .Dists = make ([]float64 , len (line ))
86- for i := 1 ; i < len (line ); i ++ {
87- si .Dists [i ] = si .Dists [i - 1 ] + tlxy .DistanceHaversine (line [i - 1 ], line [i ])
88- }
8976 si .DistLength = dists [len (dists )- 1 ]
9077 }
78+ // If we don't have ShapeDistTraveled values, calculate them
79+ if si .DistLength == 0 {
80+ si .DistLength = tlxy .LengthHaversine (line )
81+ }
9182 g .shapes [eid ] = si
9283}
9384
@@ -145,11 +136,10 @@ func (g *GeomCache) InterpolateStopTimes(trip *gtfs.Trip) ([]gtfs.StopTime, erro
145136// TODO: move to somewhere else
146137func (g * GeomCache ) setStopTimeDists (shapeId string , patternId int64 , sts []gtfs.StopTime ) error {
147138 // Check cache
148- length := 0.0
149139 stopPositionsKey := fmt .Sprintf ("%s-%d" , shapeId , patternId )
150- stopPositions , ok := g .stopPositions [stopPositionsKey ]
140+ stopPositionInfo , ok := g .stopPositions [stopPositionsKey ]
151141 if ! ok {
152- // Generate the stop-to-stop geometry as fallback
142+ // Generate the stop-to-stop geometry
153143 stopLine := make ([]tlxy.Point , len (sts ))
154144 for i := 0 ; i < len (sts ); i ++ {
155145 point , ok := g .stops [sts [i ].StopID .Val ]
@@ -159,34 +149,43 @@ func (g *GeomCache) setStopTimeDists(shapeId string, patternId int64, sts []gtfs
159149 stopLine [i ] = point
160150 }
161151
152+ // Get the known shape line and known shape distance
153+ var shapeLength float64
162154 var shapeLine []tlxy.Point
163155 if si , ok := g .shapes [shapeId ]; ok {
164156 shapeLine = si .Line
165- length = si .DistLength
157+ shapeLength = si .DistLength
166158 } else {
167159 shapeLine = stopLine
168- length = tlxy .LengthHaversine (stopLine )
160+ shapeLength = tlxy .LengthHaversine (stopLine )
169161 }
170162
171163 // Calculate positions
172- stopPositions = tlxy .LineRelativePositions (shapeLine , stopLine )
164+ stopPositions : = tlxy .LineRelativePositions (shapeLine , stopLine )
173165
174- // Check for simple or fallback positions
175- if ! arePositionsSorted (stopPositions ) || len ( stopLine ) == 0 {
166+ // Check if the positions are sorted
167+ if ! arePositionsSorted (stopPositions ) {
176168 // log.For(ctx).Debug().Msgf("positions %f not increasing, falling back to stop positions; shapeline %f stopLine %f", positions, shapeline, stopLine)
177169 stopPositions = tlxy .LineRelativePositionsFallback (stopLine )
178- if ! arePositionsSorted (stopPositions ) {
179- return errors .New ("fallback positions not sorted" )
180- }
181170 }
182- g .stopPositions [stopPositionsKey ] = stopPositions
171+
172+ // Check again
173+ if ! arePositionsSorted (stopPositions ) {
174+ return errors .New ("fallback positions not sorted" )
175+ }
176+
177+ stopPositionInfo .Positions = stopPositions
178+ stopPositionInfo .DistLength = shapeLength
179+ g .stopPositions [stopPositionsKey ] = stopPositionInfo
183180 }
184- if len (sts ) != len (stopPositions ) {
181+
182+ if len (sts ) != len (stopPositionInfo .Positions ) {
185183 return errors .New ("unequal stoptimes and positions" )
186184 }
185+
187186 // Set ShapeDistTraveled values
188187 for i := 0 ; i < len (sts ); i ++ {
189- sts [i ].ShapeDistTraveled .Set (stopPositions [i ] * length )
188+ sts [i ].ShapeDistTraveled .Set (stopPositionInfo . Positions [i ] * stopPositionInfo . DistLength )
190189 }
191190 return nil
192191}
0 commit comments