active_road 0.0.2 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. checksums.yaml +15 -0
  2. data/.rspec +1 -0
  3. data/.travis.yml +7 -2
  4. data/Gemfile +8 -2
  5. data/Guardfile +2 -6
  6. data/README.md +69 -9
  7. data/Rakefile +8 -7
  8. data/active_road.gemspec +19 -15
  9. data/app/models/active_road/access_link.rb +4 -4
  10. data/app/models/active_road/access_point.rb +5 -9
  11. data/app/models/active_road/boundary.rb +41 -0
  12. data/app/models/active_road/junction.rb +4 -18
  13. data/app/models/active_road/junction_conditionnal_cost.rb +2 -0
  14. data/app/models/active_road/junctions_physical_road.rb +5 -0
  15. data/app/models/active_road/logical_road.rb +5 -4
  16. data/app/models/active_road/osm_pbf_importer.rb +293 -0
  17. data/app/models/active_road/osm_pbf_importer_level_db.rb +784 -0
  18. data/app/models/active_road/path.rb +40 -9
  19. data/app/models/active_road/physical_road.rb +22 -27
  20. data/app/models/active_road/physical_road_conditionnal_cost.rb +3 -1
  21. data/app/models/active_road/request_conditionnal_cost_linker.rb +59 -0
  22. data/app/models/active_road/street_number.rb +60 -57
  23. data/app/models/active_road/terra_importer.rb +161 -0
  24. data/db/migrate/20120419093427_add_kind_to_physical_roads.rb +2 -2
  25. data/db/migrate/20140206091734_create_boundaries.rb +16 -0
  26. data/db/migrate/20140210132933_add_attributes_to_physical_road.rb +9 -0
  27. data/db/migrate/20140219095521_add_boundary_id_to_logical_road.rb +5 -0
  28. data/db/migrate/20140228072448_add_boundary_id_to_physical_road.rb +5 -0
  29. data/db/migrate/20140304141150_add_marker_to_physical_road.rb +5 -0
  30. data/db/migrate/20140310083550_add_tags_to_street_number.rb +5 -0
  31. data/db/migrate/20140317153437_add_index_to_conditionnal_costs.rb +6 -0
  32. data/db/migrate/20140602160047_add_physical_road_index_to_junctions_physical_road.rb +5 -0
  33. data/lib/active_road.rb +8 -2
  34. data/lib/active_road/engine.rb +4 -1
  35. data/lib/active_road/shortest_path/finder.rb +37 -46
  36. data/lib/active_road/simulation_tool.rb +73 -0
  37. data/lib/active_road/version.rb +1 -1
  38. data/lib/tasks/activeroad_tasks.rake +88 -4
  39. data/script/benchmark_import_kyotocabinet.rb +148 -0
  40. data/script/benchmark_shortest_path.rb +22 -0
  41. data/script/count_tag_in_osm_data.rb +114 -0
  42. data/script/import-tiger-numbers +3 -3
  43. data/spec/dummy/db/schema.rb +2 -1
  44. data/spec/dummy/db/structure.sql +100 -11
  45. data/spec/factories/boundary.rb +8 -0
  46. data/spec/factories/junction.rb +1 -1
  47. data/spec/factories/physical_road.rb +1 -2
  48. data/spec/fixtures/test.osm +120 -0
  49. data/spec/fixtures/test.osm.bz2 +0 -0
  50. data/spec/fixtures/test.osm.pbf +0 -0
  51. data/spec/lib/active_road/shortest_path/finder_spec.rb +143 -90
  52. data/spec/lib/active_road/shortest_path/performance_finder_spec.rb +59 -0
  53. data/spec/models/active_road/access_point_spec.rb +9 -18
  54. data/spec/models/active_road/junction_conditionnal_cost_spec.rb +4 -4
  55. data/spec/models/active_road/junction_spec.rb +34 -11
  56. data/spec/models/active_road/logical_road_spec.rb +20 -19
  57. data/spec/models/active_road/osm_pbf_importer_level_db_spec.rb +410 -0
  58. data/spec/models/active_road/path_spec.rb +1 -1
  59. data/spec/models/active_road/physical_road_conditionnal_cost_spec.rb +4 -4
  60. data/spec/models/active_road/physical_road_spec.rb +14 -3
  61. data/spec/models/active_road/request_conditionnal_cost_linker_spec.rb +65 -0
  62. data/spec/models/active_road/shared_examples/osm_pbf_importer_spec.rb +148 -0
  63. data/spec/models/active_road/street_number_spec.rb +58 -58
  64. data/spec/models/active_road/terra_importer_spec.rb +140 -0
  65. data/spec/spec_helper.rb +14 -9
  66. data/spec/support/geometry_support.rb +36 -0
  67. data/spec/support/profile.rb +19 -0
  68. data/tmp/performance/.gitignore +0 -0
  69. data/travis/before_install.sh +5 -9
  70. data/travis/before_script.sh +7 -7
  71. metadata +118 -121
  72. data/app/models/active_road/physical_road_filter.rb +0 -41
  73. data/app/models/active_road/terra_import.rb +0 -148
  74. data/spec/models/active_road/physical_road_filter_spec.rb +0 -85
  75. data/spec/models/active_road/terra_import_spec.rb +0 -113
  76. data/spec/support/georuby_ext.rb +0 -15
@@ -19,8 +19,8 @@ class ActiveRoad::Path
19
19
  def locations_on_road
20
20
  [departure, arrival].collect do |endpoint|
21
21
  location =
22
- if GeoRuby::SimpleFeatures::Point === endpoint
23
- road.locate_point endpoint
22
+ if ActiveRoad::AccessPoint === endpoint
23
+ road.locate_point endpoint.geometry
24
24
  else
25
25
  endpoint.location_on_road road
26
26
  end
@@ -45,8 +45,8 @@ class ActiveRoad::Path
45
45
 
46
46
  delegate :access_to_road?, :to => :arrival
47
47
 
48
- def paths(tags = {})
49
- arrival.paths(tags) - [reverse]
48
+ def paths
49
+ arrival.paths - [reverse]
50
50
  end
51
51
 
52
52
  def reverse
@@ -54,11 +54,42 @@ class ActiveRoad::Path
54
54
  end
55
55
 
56
56
  def geometry_without_cache
57
- sorted_locations_on_road = locations_on_road.sort
58
- reverse = (sorted_locations_on_road != locations_on_road)
59
- geometry = road.line_substring *sorted_locations_on_road
60
- geometry = geometry.reverse if reverse
61
- geometry
57
+ # sorted_locations_on_road = locations_on_road.sort
58
+ # reverse = (sorted_locations_on_road != locations_on_road)
59
+ # geometry = road.line_substring(sorted_locations_on_road.first, sorted_locations_on_road.last)
60
+ # geometry = geometry.reverse if reverse
61
+ # geometry
62
+
63
+ points = physical_road.geometry.points
64
+ points_selected = []
65
+
66
+ if ActiveRoad::AccessPoint === departure || ActiveRoad::AccessPoint === arrival
67
+ sorted_locations_on_road = locations_on_road.sort
68
+ reverse = (sorted_locations_on_road != locations_on_road)
69
+
70
+ if sorted_locations_on_road == [0, 1]
71
+ if reverse
72
+ return physical_road.geometry.reverse
73
+ else
74
+ return physical_road.geometry
75
+ end
76
+ end
77
+
78
+ return road.line_substring(sorted_locations_on_road.first, sorted_locations_on_road.last)
79
+ end
80
+
81
+ departure_index = points.index(departure.geometry)
82
+ arrival_index = points.index(arrival.geometry)
83
+
84
+ if departure_index < arrival_index
85
+ points_selected = points[arrival_index..departure_index]
86
+ elsif arrival_index < departure_index
87
+ points_selected = points.reverse![arrival_index..departure_index]
88
+ else
89
+ raise StandardError, "Junction is not on the physical road"
90
+ end
91
+
92
+ GeoRuby::SimpleFeatures::LineString.from_points(points)
62
93
  end
63
94
 
64
95
  def geometry_with_cache
@@ -1,18 +1,14 @@
1
- require "activerecord-postgres-hstore"
2
- require "enumerize"
3
-
1
+ # -*- coding: utf-8 -*-
4
2
  module ActiveRoad
5
3
  class PhysicalRoad < ActiveRoad::Base
6
- extend Enumerize
4
+ extend ::Enumerize
7
5
  extend ActiveModel::Naming
8
6
 
7
+ attr_accessible :objectid, :tags, :geometry, :logical_road_id, :boundary_id, :length_in_meter, :minimum_width, :covering, :transport_mode, :slope, :cant, :physical_road_type
9
8
  serialize :tags, ActiveRecord::Coders::Hstore
10
9
 
11
- attr_accessible :objectid, :tags, :geometry, :logical_road_id, :length_in_meter, :minimum_width, :covering, :transport_mode, :slope, :cant, :physical_road_type
12
-
13
10
  # TODO : Pass covering in array mode???
14
11
  enumerize :covering, :in => [:slippery_gravel, :gravel, :asphalt_road, :asphalt_road_damaged, :pavement, :irregular_pavement, :slippery_pavement]
15
- enumerize :transport_mode, :in => [:pedestrian, :bike]
16
12
 
17
13
  enumerize :minimum_width, :in => [:wide, :enlarged, :narrow, :cramped], :default => :wide
18
14
  enumerize :slope, :in => [:flat, :medium, :significant, :steep], :default => :flat
@@ -23,42 +19,41 @@ module ActiveRoad
23
19
 
24
20
  has_many :numbers, :class_name => "ActiveRoad::StreetNumber", :inverse_of => :physical_road
25
21
  belongs_to :logical_road, :class_name => "ActiveRoad::LogicalRoad"
22
+ belongs_to :boundary, :class_name => "ActiveRoad::Boundary"
26
23
  has_and_belongs_to_many :junctions, :uniq => true
27
24
  has_many :physical_road_conditionnal_costs
28
25
 
29
26
  acts_as_geom :geometry => :line_string
30
- delegate :locate_point, :interpolate_point, :to => :geometry
31
-
32
- before_validation :update_length_in_meter
27
+ delegate :locate_point, :interpolate_point, :length, :to => :geometry
33
28
 
29
+ before_create :update_length_in_meter
30
+ before_update :update_length_in_meter
34
31
  def update_length_in_meter
35
- if ( geometry )
32
+ if geometry.present?
36
33
  spherical_factory = ::RGeo::Geographic.spherical_factory
37
- self.update_attribute :length_in_meter, spherical_factory.line_string(geometry.points.collect(&:to_rgeo)).length
34
+ self.length_in_meter = spherical_factory.line_string(geometry.points.collect(&:to_rgeo)).length
35
+ #self.length_in_meter = length
38
36
  end
39
37
  end
40
38
 
41
- def name
39
+ def street_name
42
40
  logical_road.try(:name) or objectid
43
41
  end
44
42
 
45
- alias_method :to_s, :name
46
-
47
- def self.nearest_to(location, distance = 100)
48
- with_in(location, distance).closest_to(location)
43
+ def intersection(other)
44
+ postgis_calculate(:intersection, [self, other])
49
45
  end
50
46
 
51
- def self.closest_to(location)
52
- location_as_text = location.to_ewkt(false)
53
- order("ST_Distance(geometry, GeomFromText('#{location_as_text}', 4326))")
47
+ def difference(other)
48
+ postgis_calculate(:difference, [self, other])
54
49
  end
55
-
56
- def self.with_in(location, distance = 100)
57
- # FIXME why ST_DWithin doesn't use meters ??
58
- distance = distance / 1000.0
59
-
60
- location_as_text = location.to_ewkt(false)
61
- where "ST_DWithin(ST_GeomFromText(?, 4326), geometry, ?)", location_as_text, distance
50
+
51
+ # distance in srid format 0.001 ~= 111.3 m à l'équateur
52
+ # TODO : Must convert distance in meters => distance in srid
53
+ def self.nearest_to(location, distance = 0.001)
54
+ # FIX Limit to 1 physical roads for perf, must be extended
55
+ pr = all_dwithin(location, distance)
56
+ pr == [] ? [] : [pr.first]
62
57
  end
63
58
 
64
59
  end
@@ -1,6 +1,8 @@
1
1
  module ActiveRoad
2
2
  class PhysicalRoadConditionnalCost < ActiveRoad::Base
3
- belongs_to :physical_road
3
+ attr_accessible :tags, :cost, :physical_road_id
4
+
5
+ belongs_to :physical_road
4
6
 
5
7
  validates_presence_of :physical_road_id
6
8
  validates_presence_of :tags
@@ -0,0 +1,59 @@
1
+ module ActiveRoad
2
+ class RequestConditionnalCostLinker
3
+ attr_accessor :unauthorized_constraints, :authorized_constraints, :constraints
4
+
5
+ def initialize(constraints = [], external_constraints = {})
6
+ @constraints = constraints
7
+ end
8
+
9
+ def unauthorized_constraints
10
+ @unauthorized_constraints ||= [].tap do |unauthorized_constraints|
11
+ constraints.each do |constraint|
12
+ if constraint.start_with?("~")
13
+ unauthorized_constraints << constraint.gsub("~", "")
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+ def authorized_constraints
20
+ @authorized_constraints ||= [].tap do |authorized_constraints|
21
+ constraints.each do |constraint|
22
+ if !constraint.start_with?("~")
23
+ authorized_constraints << constraint
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+ def authorized_constraints_intersection_with?(tags)
30
+ (authorized_constraints & tags == false || authorized_constraints & tags == []) ? false : true
31
+ end
32
+
33
+ def unauthorized_constraints_intersection_with?(tags)
34
+ (unauthorized_constraints & tags == false || unauthorized_constraints & tags == []) ? false : true
35
+ end
36
+
37
+ def linked?(conditionnal_costs_tags)
38
+ authorized_constraints_intersection_with?(conditionnal_costs_tags) || unauthorized_constraints_intersection_with?(conditionnal_costs_tags)
39
+ end
40
+
41
+ def conditionnal_costs_linked(conditionnal_costs)
42
+ conditionnal_costs.where(:tags => authorized_constraints)
43
+ end
44
+
45
+ def conditionnal_costs_sum(conditionnal_costs)
46
+ conditionnal_costs_tags = conditionnal_costs.collect(&:tags)
47
+ if linked?(conditionnal_costs_tags)
48
+ if unauthorized_constraints && unauthorized_constraints_intersection_with?(conditionnal_costs_tags)
49
+ return Float::MAX
50
+ else
51
+ return conditionnal_costs_linked(conditionnal_costs).collect(&:cost).sum
52
+ end
53
+ else
54
+ 0
55
+ end
56
+ end
57
+
58
+ end
59
+ end
@@ -1,81 +1,84 @@
1
- class ActiveRoad::StreetNumber < ActiveRoad::Base
2
- attr_accessible :objectid, :number, :geometry, :physical_road_id, :location_on_road
1
+ module ActiveRoad
2
+ class StreetNumber < ActiveRoad::Base
3
+ serialize :tags, ActiveRecord::Coders::Hstore
4
+ attr_accessible :objectid, :tags, :number, :geometry, :physical_road_id, :location_on_road
3
5
 
4
- validates_uniqueness_of :objectid
5
- validates_presence_of :number, :stored_geometry
6
+ validates_uniqueness_of :objectid
7
+ validates_presence_of :number, :stored_geometry
6
8
 
7
- belongs_to :physical_road, :class_name => "ActiveRoad::PhysicalRoad"
8
- def road
9
- @road or physical_road
10
- end
11
- def road=(road)
12
- @road ||= road
13
- end
9
+ belongs_to :physical_road, :class_name => "ActiveRoad::PhysicalRoad"
10
+ def road
11
+ @road or physical_road
12
+ end
13
+ def road=(road)
14
+ @road ||= road
15
+ end
14
16
 
15
- before_validation :compute_locate_on_road, :on => :create
17
+ #before_validation :compute_locate_on_road, :on => :create
16
18
 
17
- def stored_geometry
18
- read_attribute :geometry
19
- end
19
+ def stored_geometry
20
+ read_attribute :geometry
21
+ end
20
22
 
21
- def geometry
22
- stored_geometry or computed_geometry
23
- end
23
+ def geometry
24
+ stored_geometry or computed_geometry
25
+ end
24
26
 
25
- def computed_geometry
26
- road.at computed_location_on_road
27
- end
27
+ def computed_geometry
28
+ road.at computed_location_on_road
29
+ end
28
30
 
29
- def location_on_road
30
- stored_location_on_road or computed_location_on_road
31
- end
31
+ def location_on_road
32
+ stored_location_on_road or computed_location_on_road
33
+ end
32
34
 
33
- def stored_location_on_road
34
- read_attribute :location_on_road
35
- end
35
+ def stored_location_on_road
36
+ read_attribute :location_on_road
37
+ end
36
38
 
37
- def compute_locate_on_road
38
- if stored_location_on_road.nil? and stored_geometry
39
- self.location_on_road = road.geometry.locate_point(stored_geometry)
39
+ def compute_locate_on_road
40
+ if stored_location_on_road.nil? and stored_geometry
41
+ self.location_on_road = road.geometry.locate_point(stored_geometry)
42
+ end
40
43
  end
41
- end
42
44
 
43
- # TODO rename into estimated_location_on_road
44
- def computed_location_on_road
45
- if previous and self.next
46
- number_ratio = (number.to_i - previous.number.to_i) / (self.next.number.to_i - previous.number.to_i).to_f
47
- previous.location_on_road + number_ratio * (self.next.location_on_road - previous.location_on_road)
45
+ # TODO rename into estimated_location_on_road
46
+ def computed_location_on_road
47
+ if previous and self.next
48
+ number_ratio = (number.to_i - previous.number.to_i) / (self.next.number.to_i - previous.number.to_i).to_f
49
+ previous.location_on_road + number_ratio * (self.next.location_on_road - previous.location_on_road)
50
+ end
48
51
  end
49
- end
50
52
 
51
- def previous
52
- @previous ||= road.numbers.find :first, :conditions => ["number < ?", number], :limit => 1, :order => "number desc"
53
- end
53
+ def previous
54
+ @previous ||= road.numbers.find :first, :conditions => ["number < ?", number], :limit => 1, :order => "number desc"
55
+ end
54
56
 
55
- def next
56
- @next ||= road.numbers.find :first, :conditions => ["number > ?", number], :limit => 1, :order => "number"
57
- end
57
+ def next
58
+ @next ||= road.numbers.find :first, :conditions => ["number > ?", number], :limit => 1, :order => "number"
59
+ end
58
60
 
59
- def number
60
- Number.new read_attribute(:number)
61
- end
61
+ def number
62
+ Number.new read_attribute(:number)
63
+ end
62
64
 
63
- class Number < String
65
+ class Number < String
64
66
 
65
- alias_method :numeric_value, :to_i
67
+ alias_method :numeric_value, :to_i
66
68
 
67
- def suffix
68
- gsub(/^[0-9]+/,'')
69
- end
69
+ def suffix
70
+ gsub(/^[0-9]+/,'')
71
+ end
70
72
 
71
- def +(value)
72
- self.class.new "#{numeric_value+value}#{suffix}"
73
- end
73
+ def +(value)
74
+ self.class.new "#{numeric_value+value}#{suffix}"
75
+ end
76
+
77
+ def -(value)
78
+ self.class.new "#{numeric_value-value}#{suffix}"
79
+ end
74
80
 
75
- def -(value)
76
- self.class.new "#{numeric_value-value}#{suffix}"
77
81
  end
78
82
 
79
83
  end
80
-
81
84
  end
@@ -0,0 +1,161 @@
1
+ # require "kyotocabinet"
2
+
3
+ # module ActiveRoad
4
+ # class TerraImporter
5
+ # #include KyotoCabinet
6
+
7
+ # attr_reader :parser, :database_path, :xml_file
8
+
9
+ # def initialize(xml_file, database_path = "/tmp/terra.kch")
10
+ # @xml_file = xml_file
11
+ # @database_path = database_path
12
+ # end
13
+
14
+ # def parser
15
+ # @parser ||= ::Saxerator.parser(File.new(xml_file))
16
+ # end
17
+
18
+ # def database
19
+ # @database ||= DB::new
20
+ # end
21
+
22
+ # def open_database(path)
23
+ # database.open(path, DB::OWRITER | DB::OCREATE)
24
+ # database.clear
25
+ # end
26
+
27
+ # def close_database
28
+ # database.close
29
+ # end
30
+
31
+ # def physical_road_conditionnal_costs(tags)
32
+ # [].tap do |prcc|
33
+ # tags.each do |tag_key, tag_value|
34
+ # if ["highway", "railway"].include?(tag_key)
35
+ # prcc << ActiveRoad::PhysicalRoadConditionnalCost.new(:tags => "car", :cost => Float::MAX) if !ActiveRoad::OsmXmlImporter.tag_for_car_values.include?(tag_value)
36
+ # prcc << ActiveRoad::PhysicalRoadConditionnalCost.new(:tags => "pedestrian", :cost => Float::MAX) if !ActiveRoad::OsmXmlImporter.tag_for_pedestrian_values.include?(tag_value)
37
+ # prcc << ActiveRoad::PhysicalRoadConditionnalCost.new(:tags => "bike", :cost => Float::MAX) if !ActiveRoad::OsmXmlImporter.tag_for_bike_values.include?(tag_value)
38
+ # prcc << ActiveRoad::PhysicalRoadConditionnalCost.new(:tags => "train", :cost => Float::MAX) if !ActiveRoad::OsmXmlImporter.tag_for_train_values.include?(tag_value)
39
+ # end
40
+ # end
41
+ # end
42
+ # end
43
+
44
+ # def backup_nodes(database)
45
+ # # Save nodes in kyotocabinet database
46
+ # parser.for_tag(:TrajectoryNode).each do |node|
47
+ # ways = node["TrajectoryArcRef"].is_a?(Array) ? node["TrajectoryArcRef"] : [ node["TrajectoryArcRef"] ]
48
+ # database[ node["ObjectId"] ] = Marshal.dump(Node.new(node["ObjectId"], node["Geometry"], ways))
49
+ # end
50
+ # end
51
+
52
+ # def iterate_nodes(database)
53
+ # junctions_values = []
54
+ # junctions_ways = {}
55
+ # # traverse records by iterator
56
+ # database.each { |key, value|
57
+
58
+ # node = Marshal.load(value)
59
+ # geometry = GeoRuby::SimpleFeatures::Geometry.from_ewkt( node.geometry) if( node.geometry )
60
+ # if node.ways.present? # && node.ways.count >= 2 # Take node with at least two ways
61
+ # junctions_values << [ node.id, geometry ]
62
+ # junctions_ways[node.id] = node.ways
63
+ # end
64
+
65
+ # if junctions_values.count == 1000
66
+ # save_junctions(junctions_values, junction_ways)
67
+ # #Reset
68
+ # junctions_values = []
69
+ # junctions_ways = {}
70
+ # end
71
+ # }
72
+ # save_junctions(junctions_values, junctions_ways) if junctions_values.present?
73
+ # end
74
+
75
+ # def save_junctions(junctions_values, junctions_ways)
76
+ # junction_columns = [:objectid, :geometry]
77
+ # # Save junctions in the stack
78
+ # ActiveRoad::Junction.import(junction_columns, junctions_values, :validate => false) if junctions_values.present?
79
+
80
+ # # Link the junction with physical roads
81
+ # junctions_ways.each do |junction_objectid, way_objectids|
82
+ # junction = ActiveRoad::Junction.find_by_objectid(junction_objectid)
83
+
84
+ # physical_roads = ActiveRoad::PhysicalRoad.find_all_by_objectid(way_objectids)
85
+ # junction.physical_roads << physical_roads if physical_roads
86
+ # end
87
+ # end
88
+
89
+ # def import
90
+ # # process the database by iterator
91
+ # DB::process(database_path) { |database|
92
+ # database.clear
93
+ # backup_nodes(database)
94
+
95
+ # physical_roads = []
96
+ # attributes_by_objectid = {}
97
+ # parser.for_tag(:TrajectoryArc).each do |way|
98
+ # geometry = GeoRuby::SimpleFeatures::Geometry.from_ewkt(way["Geometry"]) if way["Geometry"]
99
+ # physical_road = ActiveRoad::PhysicalRoad.new :objectid => way["ObjectId"], :geometry => geometry, :length_in_meter => way["Length"]
100
+
101
+ # physical_roads << physical_road
102
+ # attributes_by_objectid[physical_road.objectid] = [physical_road_conditionnal_costs(way["Tags"])]
103
+
104
+ # if (physical_roads.count == 1000)
105
+ # save_physical_roads_and_children(physical_roads, attributes_by_objectid)
106
+
107
+ # # Reset
108
+ # physical_roads = []
109
+ # attributes_by_objectid = {}
110
+ # end
111
+ # end
112
+
113
+ # save_physical_roads_and_children(physical_roads, attributes_by_objectid) if physical_roads.present?
114
+ # iterate_nodes(database)
115
+ # }
116
+ # end
117
+
118
+ # def save_physical_roads_and_children(physical_roads, attributes_by_objectid = {})
119
+ # # Save physical roads
120
+ # ActiveRoad::PhysicalRoad.import(physical_roads)
121
+
122
+ # # Save physical road conditionnal costs
123
+ # prcc = []
124
+ # attributes_by_objectid.each do |objectid, attributes|
125
+ # pr = ActiveRoad::PhysicalRoad.where(:objectid => objectid).first
126
+
127
+ # physical_road_conditionnal_costs = attributes.first
128
+ # physical_road_conditionnal_costs.each do |physical_road_conditionnal_cost|
129
+ # physical_road_conditionnal_cost.update_attribute :physical_road_id, pr.id
130
+ # prcc << physical_road_conditionnal_cost
131
+ # end
132
+ # end
133
+ # ActiveRoad::PhysicalRoadConditionnalCost.import(prcc)
134
+ # end
135
+
136
+
137
+ # class Node
138
+ # attr_accessor :id, :geometry, :ways, :end_of_way
139
+
140
+ # def initialize(id, geometry, ways = [], end_of_way = false)
141
+ # @id = id
142
+ # @geometry = geometry
143
+ # @ways = ways
144
+ # @end_of_way = end_of_way
145
+ # end
146
+
147
+ # def add_way(id)
148
+ # @ways << id
149
+ # end
150
+
151
+ # def marshal_dump
152
+ # [@id, @geometry, @ways, @end_of_way]
153
+ # end
154
+
155
+ # def marshal_load array
156
+ # @id, @geometry, @ways, @end_of_way = array
157
+ # end
158
+ # end
159
+
160
+ # end
161
+ # end