Skip to content

Commit

Permalink
Merge branch 'dev' into feat/fix_#363_partition_resolution_time
Browse files Browse the repository at this point in the history
  • Loading branch information
senhalil authored Feb 3, 2022
2 parents c2e4828 + 6448ae1 commit c46d760
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 23 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
- The resolution method called through `cluster_threshold` now use VROOM instead of `sim_annealing` gem [#321](https://github.com/Mapotempo/optimizer-api/pull/321)
- Reduce consequently the time to separate independent vrps.This change reduces also the memory usage. [#321](https://github.com/Mapotempo/optimizer-api/pull/321)
- The internal solution object now use a single model for all the resolution methods. This improve the consistency and the completness of the solutions returned. [#321](https://github.com/Mapotempo/optimizer-api/pull/321)
- Geojson object colors are now related to vehicle partition if defined [#338](https://github.com/Mapotempo/optimizer-api/pull/338)

### Removed

Expand Down
48 changes: 25 additions & 23 deletions lib/output_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -319,16 +319,22 @@ def self.generate_geometry(result_object)

geojson = {}

geojson[:partitions] = generate_partitions_geometry(solution) if expected_geometry.include?(:partitions)
geojson[:points] = generate_points_geometry(solution)
geojson[:polylines] = generate_polylines_geometry(solution) if expected_geometry.include?(:polylines) && ENV['OPTIM_GENERATE_GEOJSON_POLYLINES']
# if there is vehicle partition, the geojson object colors will be based on vehicle indices
vehicle_color_indices = solution[:routes]&.map&.with_index{ |route, index|
[route[:original_vehicle_id], index]
}&.to_h

geojson[:partitions] = generate_partitions_geometry(solution, vehicle_color_indices) if expected_geometry.include?(:partitions)
geojson[:points] = generate_points_geometry(solution, vehicle_color_indices)
geojson[:polylines] = generate_polylines_geometry(solution, vehicle_color_indices) if expected_geometry.include?(:polylines) && ENV['OPTIM_GENERATE_GEOJSON_POLYLINES']

geojson
}
end

private

def self.generate_partitions_geometry(result)
def self.generate_partitions_geometry(result, vehicle_color_indices)
activities = result[:routes].flat_map{ |r|
r[:activities].select{ |a| a[:type] != 'depot' && a[:type] != 'rest' }
}
Expand All @@ -340,12 +346,12 @@ def self.generate_partitions_geometry(result)
return unless has_vehicle_partition || has_work_day_partition

partitions = {}
partitions[:vehicle] = draw_cluster(elements, :vehicle) if has_vehicle_partition
partitions[:work_day] = draw_cluster(elements, :work_day) if has_work_day_partition
partitions[:vehicle] = draw_cluster(elements, vehicle_color_indices, :vehicle) if has_vehicle_partition
partitions[:work_day] = draw_cluster(elements, vehicle_color_indices, :work_day) if has_work_day_partition
partitions
end

def self.draw_cluster(elements, entity)
def self.draw_cluster(elements, vehicle_color_indices, entity)
polygons = elements.group_by{ |element|
entity == :vehicle ?
[element[:detail][:internal_skills].find{ |sk| sk.to_s.start_with?('vehicle_partition_') }] :
Expand All @@ -354,7 +360,8 @@ def self.draw_cluster(elements, entity)
}.collect.with_index{ |data, cluster_index|
cluster_name, partition_items = data
skills_properties = compute_skills_properties(data)
collect_basic_hulls(partition_items.collect{ |item| item[:detail] }, entity, cluster_index, cluster_name, skills_properties)
color_index = skills_properties[:vehicle] ? vehicle_color_indices[skills_properties[:vehicle]] : cluster_index
collect_basic_hulls(partition_items.collect{ |item| item[:detail] }, entity, color_index, cluster_name, skills_properties)
}

{
Expand All @@ -375,16 +382,8 @@ def self.compute_skills_properties(data)
sk_properties
end

def self.compute_color(elements, entity, index)
if entity == :vehicle
@colors[index % @colors.size]
elsif entity == :work_day
day = elements.first[:internal_skills].find{ |skill| skill.start_with?('work_day_partition_') }.split('_').last
index = OptimizerWrapper::WEEKDAYS.find_index(day.to_sym)
@colors[index]
else
@colors[index % 7]
end
def self.compute_color(_elements, _entity, index)
@colors[index % @colors.size]
end

def self.collect_basic_hulls(elements, entity, cluster_index, cluster_name, skills_properties)
Expand Down Expand Up @@ -416,7 +415,7 @@ def self.collect_basic_hulls(elements, entity, cluster_index, cluster_name, skil
}
end

def self.generate_points_geometry(result)
def self.generate_points_geometry(result, vehicle_color_indices)
return nil unless (result[:unassigned].empty? || result[:unassigned].any?{ |un| un[:detail][:lat] }) &&
(result[:routes].all?{ |r| r[:activities].empty? } ||
result[:routes].any?{ |r| r[:activities].any?{ |a| a[:detail] && a[:detail][:lat] } })
Expand All @@ -440,7 +439,7 @@ def self.generate_points_geometry(result)
}

result[:routes].each{ |r|
color = compute_color([], nil, r[:day] || 0)
color = compute_color([], nil, vehicle_color_indices[r[:original_vehicle_id]] || r[:day] || 0)
r[:activities].each{ |a|
next unless mission_types.include?(a[:type].to_sym)

Expand All @@ -466,21 +465,24 @@ def self.generate_points_geometry(result)
}
end

def self.generate_polylines_geometry(result)
def self.generate_polylines_geometry(result, vehicle_color_indices)
polylines = []

result[:routes].each_with_index{ |route, route_index|
next unless route[:geometry]

color = route[:day] ? compute_color([], nil, route[:day]) : compute_color([], :vehicle, route_index)
color = route[:original_vehicle_id] && compute_color([], nil, vehicle_color_indices[route[:original_vehicle_id]]) ||
route[:day] && compute_color([], nil, route[:day]) ||
compute_color([], :vehicle, route_index)
week_day = route[:day] && { work_day: OptimizerWrapper::WEEKDAYS[route[:day] % 7] } || {}
polylines << {
type: 'Feature',
properties: {
color: color,
name: "#{route[:original_vehicle_id]}#{route[:day] ? '' : ", day #{route[:day]} route"}",
vehicle: route[:original_vehicle_id],
day: route[:day]
},
}.merge(week_day),
geometry: {
type: 'LineString',
coordinates: route[:geometry].flatten(1)
Expand Down

0 comments on commit c46d760

Please sign in to comment.