active_road 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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