class ActiveRoad::ShortestPath::Finder

Attributes

constraints[RW]
follow_way_filter[RW]
physical_road_filter[RW]
request_conditionnal_costs_linker[RW]
speed[RW]
user_weights[RW]

Public Class Methods

new(departure, arrival, speed = 4, constraints = [], follow_way_filter = {}) click to toggle source
Calls superclass method
# File lib/active_road/shortest_path/finder.rb, line 21
def initialize(departure, arrival, speed = 4, constraints = [], follow_way_filter = {})    
  super departure, arrival
  @speed = speed * 1000 / 3600 # Convert speed in meter/second
  @constraints = constraints
  @follow_way_filter = follow_way_filter
  @steps = 0
end

Public Instance Methods

destination_accesses() click to toggle source
# File lib/active_road/shortest_path/finder.rb, line 33
def destination_accesses 
  @destination_accesses ||= ActiveRoad::AccessPoint.to(destination)
end
distance_heuristic(node) click to toggle source

Return a distance in meter from node to destination

# File lib/active_road/shortest_path/finder.rb, line 48
def distance_heuristic(node)
  if node.respond_to?(:arrival)
    node.arrival.to_geometry.spherical_distance(destination)
  else
    node.to_geometry.spherical_distance(destination)
  end
end
follow_way?(node, destination, weight, context={}) click to toggle source

Follow way depends from uphill, downhill, height and heuristics

# File lib/active_road/shortest_path/finder.rb, line 125
def follow_way?(node, destination, weight, context={})
  # Check that arguments in the context is less  than the object parameters
  request = true
  request = request && context[:uphill] <= follow_way_filter[:uphill] if follow_way_filter[:uphill] && context[:uphill].present?
  request = request && context[:downhill] <= follow_way_filter[:downhill] if follow_way_filter[:downhill] && context[:downhill].present?
  request = request && context[:height] <= follow_way_filter[:height] if follow_way_filter[:height] && context[:height].present?    
  request = request && ( search_heuristic(node) + weight ) < ( time_heuristic(source) * 4 )
end
geometry() click to toggle source
# File lib/active_road/shortest_path/finder.rb, line 83
def geometry
  @geometry ||= GeoRuby::SimpleFeatures::LineString.merge path.collect{ |n| n.to_geometry }.select{ |g| GeoRuby::SimpleFeatures::LineString === g }
end
path_weight( length_in_meter = 0, percentage = 1 ) click to toggle source
# File lib/active_road/shortest_path/finder.rb, line 79
def path_weight( length_in_meter = 0, percentage = 1 )
  (length_in_meter / speed) * percentage
end
path_weights(path) click to toggle source
# File lib/active_road/shortest_path/finder.rb, line 56
def path_weights(path)
  path_weights = 0
  
  # Add path weight
  path_weights += path_weight(path.length_in_meter) if path.respond_to?(:length_in_meter)
  
  # Add junction weight if it's a junction with a waiting constraint
  if !(GeoRuby::SimpleFeatures::Point === path)  && ActiveRoad::Junction === path.departure && path.departure.waiting_constraint
    path_weights += path.departure.waiting_constraint
  end

  # Add physical road weight if it's a physical road
  physical_road = path.physical_road if ActiveRoad::Path === path
  physical_road_conditionnal_costs = physical_road.physical_road_conditionnal_costs if physical_road

  if physical_road && physical_road_conditionnal_costs
    cc_percentage = request_conditionnal_costs_linker.conditionnal_costs_sum(physical_road_conditionnal_costs)
    path_weights += path_weight(path.length_in_meter, cc_percentage) if path.respond_to?(:length_in_meter)
  end
  
  path_weights
end
refresh_context( node, context = {} ) click to toggle source

Update context with uphill, downhill and height TODO : Fix arguments node is not a node but a path a point or an access link!!

# File lib/active_road/shortest_path/finder.rb, line 105
def refresh_context( node, context = {} )
  context_uphill = context[:uphill] ? context[:uphill] : 0
  context_downhill = context[:downhill] ? context[:downhill] : 0
  context_height = context[:height] ? context[:height] : 0

  if( ActiveRoad::Path === node )
    departure = node.departure
    physical_road = node.physical_road            

    node_uphill = ( physical_road && physical_road.uphill) ? physical_road.uphill : 0
    node_downhill = (physical_road && physical_road.downhill) ? physical_road.downhill : 0
    node_height = (departure.class != ActiveRoad::AccessPoint && departure && departure.height) ? departure.height : 0
    
    return { :uphill => (context_uphill + node_uphill), :downhill => (context_downhill + node_downhill), :height => (context_height + node_height) }
  else
    return {:uphill => context_uphill, :downhill => context_downhill, :height => context_height}
  end
end
search_heuristic(node) click to toggle source
# File lib/active_road/shortest_path/finder.rb, line 99
def search_heuristic(node)
  shortest_distances[node] + time_heuristic(node)
end
time_heuristic(node) click to toggle source

Return a time in second from node to destination TODO : Tenir compte de la sinuosité de la route???

# File lib/active_road/shortest_path/finder.rb, line 39
def time_heuristic(node)
  if node.respond_to?(:arrival)
    node.arrival.to_geometry.spherical_distance(destination) / speed
  else
    node.to_geometry.spherical_distance(destination) / speed
  end
end
visit(node) click to toggle source
Calls superclass method
# File lib/active_road/shortest_path/finder.rb, line 95
def visit(node)
  super(respond_to?(:arrival) ? node.arrival : node)
end
visited?(node) click to toggle source
Calls superclass method
# File lib/active_road/shortest_path/finder.rb, line 91
def visited?(node)
  super(respond_to?(:arrival) ? node.arrival : node)
end
ways(node, context={}) click to toggle source
# File lib/active_road/shortest_path/finder.rb, line 134
def ways(node, context={})    
  paths =
    if GeoRuby::SimpleFeatures::Point === node
      # Search access to physical roads for departure
      ActiveRoad::AccessLink.from(node)
    else
      node.paths
    end

  # Search for each node if they have physical roads in common with arrival
  # If true finish the trip and link to arrival
  unless GeoRuby::SimpleFeatures::Point === node 
    destination_accesses.select do |destination_access|
      if node.access_to_road?(destination_access.physical_road) && !(ActiveRoad::AccessPoint === node.arrival)
        paths << ActiveRoad::Path.new(:departure => node.arrival, :arrival => destination_access, :physical_road => destination_access.physical_road)
      end
    end
  end
  
  array = paths.collect do |path|
    [ path, path_weights(path)]
  end       

  @steps += 1
  
  Hash[array]
end