-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbifrost.go
237 lines (197 loc) · 6.21 KB
/
bifrost.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
package bifrost
import (
"fmt"
"github.com/kyroy/kdtree"
)
const DayInMs uint32 = 24 * 60 * 60 * 1000
const (
TripIdWalk uint32 = 0xffffffff
TripIdCycle uint32 = 0xfffffffe
TripIdCar uint32 = 0xfffffffd
TripIdNoChange uint32 = 0xfffffffc
TripIdOrigin uint32 = 0xfffffffb
ArrivalTimeNotReached uint64 = 0xffffffffffffffff
)
type Bifrost struct {
TransferLimit int
TransferPaddingMs uint64 // only search for trips, padded a bit after transitioning
WalkingSpeed float64 // in meters per ms
CycleSpeed float64 // in meters per ms
CarMaxSpeed float64 // in meters per ms
CarMinAvgSpeed float64 // in meters per ms
MaxWalkingMs uint32 // duration of walks not allowed to be higher than this per transfer
MaxCyclingMs uint32 // duration of cycles not allowed to be higher than this per transfer
MaxStopsConnectionSeconds uint32 // max length of added arcs between stops and street graph in deciseconds
Data *RoutingData
}
var DefaultBifrost = &Bifrost{
TransferLimit: 4,
TransferPaddingMs: 3 * 60 * 1000,
WalkingSpeed: 0.8 * 0.001,
CycleSpeed: 4.0 * 0.001,
CarMaxSpeed: 36.0 * 0.001,
CarMinAvgSpeed: 8.0 * 0.001,
MaxWalkingMs: 60 * 1000 * 15,
MaxCyclingMs: 60 * 1000 * 30,
MaxStopsConnectionSeconds: 60 * 1000 * 5,
}
type RoutingData struct {
MaxTripDayLength uint32 `json:"maxTripDayLength"` // number of days to go backwards in time (for trips that end after midnight or multiple days later than the start)
Services []*Service `json:"services"`
Routes []*Route `json:"routes"`
StopToRoutes [][]StopRoutePair `json:"stopToRoutes"`
Trips []*Trip `json:"trips"`
StreetGraph [][]Arc `json:"streetGraph"`
Reorders map[uint64][]uint32 `json:"reorders"`
// for reconstructing journeys after routing
Vertices []Vertex `json:"vertices"`
StopsIndex map[string]uint64 `json:"stopsIndex"` // gtfs stop id -> vertex index
NodesIndex map[int64]uint64 `json:"nodesIndex"` // csv vertex id -> vertex index
GtfsRouteIndex []uint32 `json:"gtfsRouteIndex"` // route index -> gtfs route index
RouteInformation []*RouteInformation `json:"routeInformation"`
TripInformation []*TripInformation `json:"tripInformation"`
TripToRoute []uint32 `json:"tripToRoute"` // trip index -> route index
// for finding vertices by location. points are GeoPoint
WalkableVertexTree *kdtree.KDTree `json:"-"`
CycleableVertexTree *kdtree.KDTree `json:"-"`
CarableVertexTree *kdtree.KDTree `json:"-"`
}
func (r *RoutingData) PrintStats() {
fmt.Println("vertices", len(r.Vertices))
fmt.Println("routes", len(r.Routes))
fmt.Println("trips", len(r.Trips))
fmt.Println("transfer graph", len(r.StreetGraph))
fmt.Println("stop to routes", len(r.StopToRoutes))
fmt.Println("reorders", len(r.Reorders))
fmt.Println("services", len(r.Services))
fmt.Println("max trip day length", r.MaxTripDayLength)
}
func (r *RoutingData) RebuildVertexTree() {
verticesAsPoints := make([]*GeoPoint, len(r.Vertices))
for i, v := range r.Vertices {
verticesAsPoints[i] = &GeoPoint{
Latitude: v.Latitude,
Longitude: v.Longitude,
VertKey: uint64(i),
CanBeReachedBy: 0,
}
}
for origin, arcs := range r.StreetGraph {
for _, arc := range arcs {
supportedVehicles := uint8(0)
if arc.WalkDistance > 0 {
supportedVehicles |= 1 << VehicleTypeWalking
}
if arc.CycleDistance > 0 {
supportedVehicles |= 1 << VehicleTypeBicycle
}
if arc.CarDistance > 0 {
supportedVehicles |= 1 << VehicleTypeCar
}
verticesAsPoints[origin].CanBeStartedBy |= supportedVehicles
verticesAsPoints[arc.Target].CanBeReachedBy |= supportedVehicles
}
}
walkable := make([]kdtree.Point, 0)
cycleable := make([]kdtree.Point, 0)
carable := make([]kdtree.Point, 0)
for _, v := range verticesAsPoints {
if v.CanBeReachedBy&(1<<VehicleTypeWalking) > 0 {
walkable = append(walkable, v)
}
if v.CanBeReachedBy&(1<<VehicleTypeBicycle) > 0 {
cycleable = append(cycleable, v)
}
if v.CanBeReachedBy&(1<<VehicleTypeCar) > 0 {
carable = append(carable, v)
}
}
r.WalkableVertexTree = kdtree.New(walkable)
r.CycleableVertexTree = kdtree.New(cycleable)
r.CarableVertexTree = kdtree.New(carable)
}
type StopContext struct {
Id string
Name string
}
type Vertex struct {
Longitude float64
Latitude float64
Stop *StopContext
}
func (v Vertex) Dimensions() int {
return 2
}
func (v Vertex) Dimension(i int) float64 {
switch i {
case 0:
return v.Latitude
case 1:
return v.Longitude
default:
panic("invalid dimension")
}
}
type GeoPoint struct {
Latitude float64
Longitude float64
VertKey uint64
CanBeStartedBy uint8 // bitmask of vehicles that can start at this point
CanBeReachedBy uint8 // bitmask of vehicles that can reach this point
}
func (s *GeoPoint) Dimensions() int {
return 2
}
func (s *GeoPoint) Dimension(i int) float64 {
switch i {
case 0:
return s.Latitude
case 1:
return s.Longitude
default:
panic("invalid dimension")
}
}
type Stopover struct {
Arrival uint32 // ms time since start of day
Departure uint32 // ms time since start of day
}
func (s Stopover) ArrivalAtDay(day uint64) uint64 {
return uint64(s.Arrival) + day*uint64(DayInMs)
}
func (s Stopover) DepartureAtDay(day uint64) uint64 {
return uint64(s.Departure) + day*uint64(DayInMs)
}
type Route struct {
Stops []uint64
Trips []uint32
}
type StopRoutePair struct {
Route uint32
StopKeyInTrip uint32
}
type Trip struct {
Service uint32
StopTimes []Stopover
}
type Arc struct {
Target uint64
WalkDistance uint32 // in ms
CycleDistance uint32 // in ms
CarDistance uint32 // in ms
}
type Service struct {
Weekdays uint8 // bitfield, 1 << 0 = monday, 1 << 6 = sunday
StartDay uint32 // day relative to PivotDate
EndDay uint32 // day relative to PivotDate
AddedExceptions []uint32 // unix days
RemovedExceptions []uint32 // unix days
}
type RouteInformation struct {
ShortName string
RouteId string
}
type TripInformation struct {
Headsign string
TripId string
}