diff options
| author | Teddy Wing | 2018-03-23 12:26:04 +0100 | 
|---|---|---|
| committer | Teddy Wing | 2018-03-27 16:46:18 +0200 | 
| commit | 4bc33f14a148feb4056db1a2839303b07c67a6b3 (patch) | |
| tree | 7e0c057da62ed5efb6d2376bd1e45726b2a79e25 /lib | |
| parent | d3ab2606ffd3dcb94a27d7b4e7c899f1238d3a53 (diff) | |
| download | chouette-core-4bc33f14a148feb4056db1a2839303b07c67a6b3.tar.bz2 | |
Add `TomTom::Matrix`
A new component to the `TomTom` module that asks TomTom's Matrix API
endpoint
(https://developer.tomtom.com/online-routing/online-routing-documentation/matrix-routing)
to compute `WayCost`s. The matrix API will give us all costs between
each pair of coordinates. This will enable us to provide costs for any
combination of points in a journey pattern.
Given a list of `WayCost`s, it will send all points from those costs to
the matrix API and return a list of all non-zero `WayCost`s between all
pairs of coordinates.
`points_from_way_costs()` extracts unique coordinates from the
`WayCost`s.
`points_as_params()` builds a list of points in the format expected by
the matrix API.
The response from the matrix API is formatted as a two-dimensional array
consisting of rows and columns that pair each "origin" point with each
"destination" point. We loop through this matrix and construct new
`WayCost` objects for each pair of coordinates.
At the moment, I haven't figured out how I want to save `WayCost` IDs
when creating the new pairs. Leaving that for later.
Refs #6222
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/tom_tom.rb | 4 | ||||
| -rw-r--r-- | lib/tom_tom/matrix.rb | 89 | 
2 files changed, 93 insertions, 0 deletions
| diff --git a/lib/tom_tom.rb b/lib/tom_tom.rb index a1a2bda43..fcebcc7ac 100644 --- a/lib/tom_tom.rb +++ b/lib/tom_tom.rb @@ -19,4 +19,8 @@ module TomTom    def self.batch(way_costs)      TomTom::Batch.new(@connection).batch(way_costs)    end + +  def self.matrix(way_costs) +    TomTom::Matrix.new(@connection).matrix(way_costs) +  end  end diff --git a/lib/tom_tom/matrix.rb b/lib/tom_tom/matrix.rb new file mode 100644 index 000000000..985055dae --- /dev/null +++ b/lib/tom_tom/matrix.rb @@ -0,0 +1,89 @@ +module TomTom +  class Matrix +    def initialize(connection) +      @connection = connection +    end + +    def matrix(way_costs) +      points = points_from_way_costs(way_costs) +      points = points_as_params(points) + +      response = @connection.post do |req| +        req.url '/routing/1/matrix/json' +        req.headers['Content-Type'] = 'application/json' + +        req.params[:routeType] = 'shortest' +        req.params[:travelMode] = 'bus' + +        req.body = { +          origins: points, +          destinations: points +        }.to_json +      end + +      extract_costs_to_way_costs!( +        way_costs, +        points, +        JSON.parse(response.body) +      ) +    end + +    def points_from_way_costs(way_costs) +      points = Set.new + +      way_costs.each do |way_cost| +        points.add(way_cost.departure) +        points.add(way_cost.arrival) +      end + +      points +    end + +    def points_as_params(points) +      points.map do |latlng| +        { +          point: { +            latitude: latlng.lat, +            longitude: latlng.lng +          } +        } +      end +    end + +    # TODO: We actually need to create new WayCost objects to hold the new dot connections given to us by the matrix API. +    def extract_costs_to_way_costs!(way_costs, points, matrix_json) +      way_costs = [] + +      # `row` and `column` order is the same as `points` +      matrix_json['matrix'].each_with_index do |row, row_i| +        row.each_with_index do |column, column_i| +          next if column['statusCode'] != 200 + +          distance = column['response']['routeSummary']['lengthInMeters'] + +          # Ignore costs between a point and itself (e.g. from A to A) +          next if distance == 0 + +          departure = points[row_i] +          arrival = points[column_i] + +          way_costs << WayCost.new( +            departure: Geokit::LatLng.new( +              departure[:point][:latitude], +              departure[:point][:longitude] +            ), +            arrival: Geokit::LatLng.new( +              arrival[:point][:latitude], +              arrival[:point][:longitude] +            ), +            distance: distance, +            time: column['response']['routeSummary']['travelTimeInSeconds'] +            # id: 'TODO: figure out how to add combined stop IDs' +          ) +        end +      end + +      way_costs +    end +  end +end | 
