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
@@ -2,8 +2,8 @@ class AddKindToPhysicalRoads < ActiveRecord::Migration
2
2
  def change
3
3
  add_column :physical_roads, :kind, :string
4
4
 
5
- ActiveRoad::PhysicalRoad.reset_column_information
6
- ActiveRoad::PhysicalRoad.update_all :kind => "road"
5
+ #ActiveRoad::PhysicalRoad.reset_column_information
6
+ #ActiveRoad::PhysicalRoad.update_all :kind => "road"
7
7
 
8
8
  add_index :physical_roads, :kind
9
9
  end
@@ -0,0 +1,16 @@
1
+ class CreateBoundaries < ActiveRecord::Migration
2
+
3
+ def change
4
+ create_table :boundaries do |t|
5
+ t.string :objectid
6
+ t.string :name
7
+ t.integer :admin_level
8
+ t.string :postal_code
9
+ t.string :insee_code
10
+ t.multi_polygon :geometry, :srid => ActiveRoad.srid
11
+ end
12
+
13
+ add_index :boundaries, :geometry, :spatial => true
14
+ end
15
+
16
+ end
@@ -0,0 +1,9 @@
1
+ class AddAttributesToPhysicalRoad < ActiveRecord::Migration
2
+ def change
3
+ add_column :physical_roads, :car, :boolean
4
+ add_column :physical_roads, :bike, :boolean
5
+ add_column :physical_roads, :train, :boolean
6
+ add_column :physical_roads, :pedestrian, :boolean
7
+ add_column :physical_roads, :name, :string
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ class AddBoundaryIdToLogicalRoad < ActiveRecord::Migration
2
+ def change
3
+ add_column :logical_roads, :boundary_id, :integer
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class AddBoundaryIdToPhysicalRoad < ActiveRecord::Migration
2
+ def change
3
+ add_column :physical_roads, :boundary_id, :integer
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class AddMarkerToPhysicalRoad < ActiveRecord::Migration
2
+ def change
3
+ add_column :physical_roads, :marker, :integer, :default => 0
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class AddTagsToStreetNumber < ActiveRecord::Migration
2
+ def change
3
+ add_column :street_numbers, :tags, :hstore
4
+ end
5
+ end
@@ -0,0 +1,6 @@
1
+ class AddIndexToConditionnalCosts < ActiveRecord::Migration
2
+ def change
3
+ add_index :physical_road_conditionnal_costs, :physical_road_id
4
+ add_index :junction_conditionnal_costs, :junction_id
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ class AddPhysicalRoadIndexToJunctionsPhysicalRoad < ActiveRecord::Migration
2
+ def change
3
+ add_index :junctions_physical_roads, [:physical_road_id]
4
+ end
5
+ end
@@ -1,5 +1,13 @@
1
1
  require "active_road/engine"
2
2
  require 'erb'
3
+ require 'saxerator'
4
+ require "activerecord-postgres-hstore"
5
+ require "enumerize"
6
+ require "pbf_parser"
7
+ require "postgis_adapter"
8
+ require "georuby-ext"
9
+ require 'snappy'
10
+ require 'postgres-copy'
3
11
 
4
12
  module ActiveRoad
5
13
 
@@ -15,5 +23,3 @@ end
15
23
 
16
24
  require "active_road/shortest_path"
17
25
  require "active_road/shortest_path/finder"
18
-
19
-
@@ -3,7 +3,10 @@ module ActiveRoad
3
3
  require "active_road/migration"
4
4
 
5
5
  class Engine < ::Rails::Engine
6
-
6
+ config.generators do |g|
7
+ g.test_framework :rspec
8
+ end
9
+
7
10
  initializer "active_road.factories", :after => "factory_girl.set_factory_paths" do
8
11
  FactoryGirl.definition_file_paths << File.expand_path('../../../spec/factories', __FILE__) if defined?(FactoryGirl)
9
12
  end
@@ -17,24 +17,22 @@ require 'shortest_path/finder'
17
17
 
18
18
  class ActiveRoad::ShortestPath::Finder < ShortestPath::Finder
19
19
 
20
- attr_accessor :speed, :physical_road_filter, :follow_way_filter, :user_weights
20
+ attr_accessor :speed, :physical_road_filter, :follow_way_filter, :user_weights, :request_conditionnal_costs_linker, :constraints
21
21
 
22
- def initialize(departure, arrival, speed = 4, constraints = {}, user_weights = {})
22
+ def initialize(departure, arrival, speed = 4, constraints = [], follow_way_filter = {})
23
23
  super departure, arrival
24
24
  @speed = speed * 1000 / 3600 # Convert speed in meter/second
25
- @follow_way_filter, @physical_road_filter = {}, {}
26
- constraints.each do |key, value|
27
- if key == :uphill || key == :downhill || key == :height
28
- @follow_way_filter[key] = value # filter to use with follow_way? method
29
- else
30
- @physical_road_filter[key] = value # filter to use with physical_roads
31
- end
32
- end
33
- @user_weights = user_weights # Not used
25
+ @constraints = constraints
26
+ @follow_way_filter = follow_way_filter
27
+ @steps = 0
28
+ end
29
+
30
+ def request_conditionnal_costs_linker
31
+ @request_conditionnal_costs_linker ||= ActiveRoad::RequestConditionnalCostLinker.new(constraints)
34
32
  end
35
33
 
36
34
  def destination_accesses
37
- @destination_accesses ||= ActiveRoad::AccessPoint.to(destination, physical_road_filter)
35
+ @destination_accesses ||= ActiveRoad::AccessPoint.to(destination)
38
36
  end
39
37
 
40
38
  # Return a time in second from node to destination
@@ -63,23 +61,18 @@ class ActiveRoad::ShortestPath::Finder < ShortestPath::Finder
63
61
  path_weights += path_weight(path.length_in_meter) if path.respond_to?(:length_in_meter)
64
62
 
65
63
  # Add junction weight if it's a junction with a waiting constraint
66
- if path.class != GeoRuby::SimpleFeatures::Point && path.departure.class == ActiveRoad::Junction && path.departure && path.departure.waiting_constraint
64
+ if !(GeoRuby::SimpleFeatures::Point === path) && ActiveRoad::Junction === path.departure && path.departure.waiting_constraint
67
65
  path_weights += path.departure.waiting_constraint
68
66
  end
69
-
70
- # TODO Refactor user weights
71
- # if path.respond_to?(:road) # PhysicalRoad only no AccessLink
72
- # path_tags = path.road.tags
73
-
74
- # user_weights.each do |key, value|
75
- # if path_tags.keys.include? key
76
- # min, max, percentage = value[0], value[1], value[2]
77
- # if min <= path_tags[key].to_i && path_tags[key].to_i <= max
78
- # path_weights += path_weight(path_length, percentage)
79
- # end
80
- # end
81
- # end
82
- # end
67
+
68
+ # Add physical road weight if it's a physical road
69
+ physical_road = path.physical_road if ActiveRoad::Path === path
70
+ physical_road_conditionnal_costs = physical_road.physical_road_conditionnal_costs if physical_road
71
+
72
+ if physical_road && physical_road_conditionnal_costs
73
+ cc_percentage = request_conditionnal_costs_linker.conditionnal_costs_sum(physical_road_conditionnal_costs)
74
+ path_weights += path_weight(path.length_in_meter, cc_percentage) if path.respond_to?(:length_in_meter)
75
+ end
83
76
 
84
77
  path_weights
85
78
  end
@@ -89,15 +82,7 @@ class ActiveRoad::ShortestPath::Finder < ShortestPath::Finder
89
82
  end
90
83
 
91
84
  def geometry
92
- @geometry ||= GeoRuby::SimpleFeatures::LineString.merge path.collect { |n| n.to_geometry }.select { |g| GeoRuby::SimpleFeatures::LineString === g }
93
- end
94
-
95
- # Use to profile code
96
- def self.example
97
- from = (ENV['FROM'] or "30.030238,-90.061541")
98
- to = (ENV['TO'] or "29.991739,-90.06918")
99
-
100
- ActiveRoad::ShortestPath::Finder.new GeoRuby::SimpleFeatures::Point.from_lat_lng(from), GeoRuby::SimpleFeatures::Point.from_lat_lng(to)
85
+ @geometry ||= GeoRuby::SimpleFeatures::LineString.merge path.collect{ |n| n.to_geometry }.select{ |g| GeoRuby::SimpleFeatures::LineString === g }
101
86
  end
102
87
 
103
88
  #-----------------------------------------
@@ -123,7 +108,7 @@ class ActiveRoad::ShortestPath::Finder < ShortestPath::Finder
123
108
  context_downhill = context[:downhill] ? context[:downhill] : 0
124
109
  context_height = context[:height] ? context[:height] : 0
125
110
 
126
- if( node.class == ActiveRoad::Path )
111
+ if( ActiveRoad::Path === node )
127
112
  departure = node.departure
128
113
  physical_road = node.physical_road
129
114
 
@@ -144,28 +129,34 @@ class ActiveRoad::ShortestPath::Finder < ShortestPath::Finder
144
129
  request = request && context[:uphill] <= follow_way_filter[:uphill] if follow_way_filter[:uphill] && context[:uphill].present?
145
130
  request = request && context[:downhill] <= follow_way_filter[:downhill] if follow_way_filter[:downhill] && context[:downhill].present?
146
131
  request = request && context[:height] <= follow_way_filter[:height] if follow_way_filter[:height] && context[:height].present?
147
- request = request && search_heuristic(node) + weight < time_heuristic(source) * 10
132
+ request = request && ( search_heuristic(node) + weight ) < ( time_heuristic(source) * 4 )
148
133
  end
149
134
 
150
- def ways(node, context={})
135
+ def ways(node, context={})
151
136
  paths =
152
137
  if GeoRuby::SimpleFeatures::Point === node
153
- ActiveRoad::AccessLink.from(node, physical_road_filter)
138
+ # Search access to physical roads for departure
139
+ ActiveRoad::AccessLink.from(node)
154
140
  else
155
- node.paths(physical_road_filter)
141
+ node.paths
156
142
  end
157
-
158
- unless GeoRuby::SimpleFeatures::Point === node # For the first point to access physical roads
143
+
144
+ # Search for each node if they have physical roads in common with arrival
145
+ # If true finish the trip and link to arrival
146
+ unless GeoRuby::SimpleFeatures::Point === node
159
147
  destination_accesses.select do |destination_access|
160
- if node.access_to_road?(destination_access.physical_road)
148
+ if node.access_to_road?(destination_access.physical_road) && !(ActiveRoad::AccessPoint === node.arrival)
161
149
  paths << ActiveRoad::Path.new(:departure => node.arrival, :arrival => destination_access, :physical_road => destination_access.physical_road)
162
150
  end
163
151
  end
164
152
  end
165
-
153
+
166
154
  array = paths.collect do |path|
167
155
  [ path, path_weights(path)]
168
- end
156
+ end
157
+
158
+ @steps += 1
159
+
169
160
  Hash[array]
170
161
  end
171
162
 
@@ -0,0 +1,73 @@
1
+ class ActiveRoad::SimulationTool
2
+ def self.sql_insert_junction( x, y)
3
+ x = (( x * 100000 ).to_i)/100000.0
4
+ y = (( y * 100000 ).to_i)/100000.0
5
+ "INSERT INTO junctions (objectid, created_at, updated_at, geometry) values ( '#{x}-#{y}', '2014-03-14 14:32:23.362164', '2014-03-14 14:32:23.362164', ST_geometryFromText('POINT( #{x} #{y})', 4326) );"
6
+ end
7
+ def self.sql_insert_physical_road( x1, y1, x2, y2)
8
+ x2 = (( x2 * 100000 ).to_i)/100000.0
9
+ y2 = (( y2 * 100000 ).to_i)/100000.0
10
+ x1 = (( x1 * 100000 ).to_i)/100000.0
11
+ y1 = (( y1 * 100000 ).to_i)/100000.0
12
+ "INSERT INTO physical_roads (objectid, created_at, updated_at, geometry) values ( '#{x1}-#{y1}-#{x2}-#{y2}', '2014-03-14 14:32:23.362164', '2014-03-14 14:32:23.362164', ST_geometryFromText('LINESTRING( #{x1} #{y1}, #{x2} #{y2})', 4326) );"
13
+ end
14
+ def self.save_simulated_square( size )
15
+ ActiveRoad::PhysicalRoad.connection.execute square_sqls( size ).join("\n")
16
+ ActiveRoad::PhysicalRoad.connection.execute relation_sqls.join("\n")
17
+ end
18
+
19
+
20
+ def self.square_sqls( size)
21
+ result = []
22
+ step = (1.0 / size)
23
+ index_x = 0
24
+ 0.upto( size) do |i_x|
25
+ index_y = 0
26
+ 0.upto( size) do |i_y|
27
+ result << sql_insert_junction( index_x, index_y)
28
+
29
+ if i_y < size
30
+ result << sql_insert_physical_road( index_x, index_y, index_x, index_y+step)
31
+ end
32
+ if i_x < size
33
+ result << sql_insert_physical_road( index_x, index_y, index_x+step, index_y)
34
+ end
35
+ index_y += step
36
+ end
37
+ index_x += step
38
+ end
39
+ result
40
+ end
41
+
42
+
43
+ def self.j_by_objectid
44
+ hash = {}
45
+ ActiveRoad::Junction.all.each do |j|
46
+ hash[ j.objectid ] = j.id
47
+ end
48
+ hash
49
+ end
50
+ def self.pr_by_objectid
51
+ hash = {}
52
+ ActiveRoad::PhysicalRoad.all.each do |pr|
53
+ hash[ pr.objectid ] = pr.id
54
+ end
55
+ hash
56
+ end
57
+ def self.relation_sqls
58
+ result = []
59
+ pr_h = pr_by_objectid
60
+ j_h = j_by_objectid
61
+ pr_h.keys.each do |pr_objectid|
62
+ parts = pr_objectid.split("-")
63
+ j_start_objectid = "#{parts[0]}-#{parts[1]}"
64
+ j_end_objectid = "#{parts[2]}-#{parts[3]}"
65
+
66
+ result << "INSERT INTO junctions_physical_roads ( physical_road_id, junction_id ) values ( #{pr_h[ pr_objectid ]}, #{j_h[ j_start_objectid ]} );"
67
+ result << "INSERT INTO junctions_physical_roads ( physical_road_id, junction_id ) values ( #{pr_h[ pr_objectid ]}, #{j_h[ j_end_objectid ]} );"
68
+ end
69
+ result
70
+ end
71
+
72
+
73
+ end
@@ -1,3 +1,3 @@
1
1
  module ActiveRoad
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -1,4 +1,88 @@
1
- # desc "Explaining what the task does"
2
- # task :activeroad do
3
- # # Task goes here
4
- # end
1
+ # -*- coding: utf-8 -*-
2
+ namespace :active_road do
3
+
4
+ desc 'This rebuilds environment db'
5
+ task :reset => :environment do
6
+ Rake::Task["db:drop"].invoke
7
+ Rake::Task["db:create"].invoke
8
+ Rake::Task["db:migrate"].invoke
9
+ end
10
+
11
+ namespace :import do
12
+
13
+ # bundle exec rake "app:active_road:import:osm_pbf_data[/home/user/test.osm.pbf, true]"
14
+ desc "Import osm data from a pbf file"
15
+ task :osm_pbf_data, [:file, :split_ways] => [:environment] do |task, args|
16
+ begin
17
+ puts "Import data from osm pbf file #{args.file} and with split_ways #{args.split_ways} with LevelDB"
18
+ raise "You should provide a valid osm file" if args.file.blank?
19
+ split_ways = args.split_ways == "true" ? true : false
20
+ ActiveRoad::OsmPbfImporterLevelDb.new(args.file, split_ways).import
21
+ puts "Completed import successfully."
22
+ rescue => e
23
+ puts("Failed to import osm data : " + e.message)
24
+ puts e.backtrace.join("\n")
25
+ end
26
+ end
27
+
28
+ desc "Import terra data from a terra file"
29
+ task :terra_data, [:file] => [:environment] do |task, args|
30
+ begin
31
+ puts "Import data from terra file #{args.file}"
32
+ raise "You should provide a valid osm file" if args.file.blank?
33
+ start = Time.now
34
+ ActiveRoad::TerraImporter.new(args.file).import
35
+ #puts "OSM import finished in #{(Time.now - start).strftime('%H:%M:%S')} seconds"
36
+ puts "Completed import successfully."
37
+ rescue => e
38
+ puts("Failed to import terra data : " + e.message)
39
+ puts e.backtrace.join("\n")
40
+ end
41
+ end
42
+
43
+ end
44
+
45
+ task :itinerary, [:from, :to, :speed, :constraints] => [:environment] do |task, args|
46
+ puts "Search an itinerary"
47
+ raise "You should provide arguments" if args.from.blank? || args.to.blank? || args.speed.blank?
48
+ start = Time.now
49
+ begin
50
+ finder = ActiveRoad::ShortestPath::Finder.new(args.from, args.to, args.speed, args.constraints).tap do |finder|
51
+ finder.timeout = 30.seconds
52
+ end
53
+ puts "Itinerary in json : #{finder.to_json}"
54
+ rescue => e
55
+ puts("Failed to find an itinerary : " + e.message)
56
+ end
57
+ puts "Itinerary research finished in #{(Time.now - start)} seconds"
58
+ end
59
+
60
+ # nammespace :install do
61
+ # task :dependencies do
62
+ # end
63
+
64
+ # task :kyotocabinet, [:file] => [:environment] do |task, args|
65
+ # sudo apt-get install -qq libgeos-dev libproj-dev postgresql-9.1-postgis liblzo2-dev liblzma-dev zlib1g-dev build-essential
66
+
67
+ # # Se placer dans le dossier /tmp
68
+ # cd /tmp
69
+
70
+ # # Installer kyotocabinet
71
+ # wget http://fallabs.com/kyotocabinet/pkg/kyotocabinet-1.2.76.tar.gz
72
+ # tar xzf kyotocabinet-1.2.76.tar.gz
73
+ # cd kyotocabinet-1.2.76
74
+ # ./configure –enable-zlib –enable-lzo –enable-lzma --prefix=/usr && make
75
+ # sudo make install
76
+
77
+ # # Installer les bindings ruby pour kyotocabinet
78
+ # cd /tmp
79
+ # wget http://fallabs.com/kyotocabinet/rubypkg/kyotocabinet-ruby-1.32.tar.gz
80
+ # tar xzf kyotocabinet-ruby-1.32.tar.gz
81
+ # cd kyotocabinet-ruby-1.32
82
+ # ruby extconf.rb
83
+ # make
84
+ # sudo make install
85
+ # end
86
+ # end
87
+
88
+ end
@@ -0,0 +1,148 @@
1
+ require 'kyotocabinet'
2
+ include KyotoCabinet
3
+
4
+ class Node
5
+ attr_accessor :id, :lon, :lat, :ways, :end_of_way
6
+
7
+ def initialize(id, lon, lat, ways = [], end_of_way = false)
8
+ @id = id
9
+ @lon = lon
10
+ @lat = lat
11
+ @ways = ways
12
+ @end_of_way = end_of_way
13
+ end
14
+
15
+ def add_way(id)
16
+ @ways << id
17
+ end
18
+
19
+ def marshal_dump
20
+ [@id, @lon, @lat, @ways, @end_of_way]
21
+ end
22
+
23
+ def marshal_load array
24
+ @id, @lon, @lat, @ways, @end_of_way = array
25
+ end
26
+ end
27
+
28
+ class KCImport
29
+
30
+ def initialize(rnum, database_path = "/tmp/test.kch", options = "")
31
+ @rnum = rnum
32
+ @database_path = database_path
33
+ @options = options
34
+ end
35
+
36
+ # def database
37
+ # @database = DB::new
38
+ # end
39
+
40
+ def memoryusage()
41
+ rss = -1
42
+ file = open('/proc/self/status')
43
+ file.each do |line|
44
+ if line =~ /^VmRSS:/
45
+ line.gsub!(/.*:\s*(\d+).*/, '\1')
46
+ rss = line.to_i / 1024.0
47
+ break
48
+ end
49
+ end
50
+ return rss
51
+ end
52
+
53
+ def import
54
+ DB::process(@database_path + @options, DB::OWRITER | DB::OCREATE | DB::OTRUNCATE) { |database|
55
+
56
+ #GC.start
57
+ musage = memoryusage
58
+ stime = Time.now
59
+
60
+ (0...@rnum).each do |i|
61
+ i_s = i.to_s
62
+ key = i_s
63
+ value = Marshal.dump(Node.new(i_s, rand, rand))
64
+ database[key] = value
65
+ end
66
+
67
+ etime = Time.now
68
+ #GC.start
69
+
70
+ printf("Count: %d\n", database.count)
71
+ printf("Time: %.3f sec.\n", etime - stime)
72
+ printf("Usage: %.3f MB\n", memoryusage - musage)
73
+
74
+ }
75
+ end
76
+
77
+ def import_and_update
78
+ DB::process(@database_path + @options, DB::OWRITER | DB::OCREATE | DB::OTRUNCATE) { |database|
79
+
80
+ #GC.start
81
+ musage = memoryusage
82
+ stime = Time.now
83
+
84
+ (0...@rnum).each do |i|
85
+ i_s = i.to_s
86
+ key = i_s
87
+ value = Marshal.dump(Node.new(i_s, rand, rand))
88
+ database[key] = value
89
+ end
90
+
91
+ database.transaction {
92
+ (0...4000000).each do |way|
93
+ update_node_with_way(way, database)
94
+ end
95
+ }
96
+
97
+ etime = Time.now
98
+ #GC.start
99
+
100
+ printf("Count: %d\n", database.count)
101
+ printf("Time: %.3f sec.\n", etime - stime)
102
+ printf("Usage: %.3f MB\n", memoryusage - musage)
103
+
104
+ }
105
+ end
106
+
107
+ def update_node_with_way(way, database)
108
+ way_id = way.to_s
109
+ nodes = [rand(6000000), rand(6000000), rand(6000000), rand(6000000), rand(6000000), rand(6000000), rand(6000000)]
110
+
111
+ # Take only the first and the last node => the end of physical roads
112
+ node_ids = nodes.collect(&:to_s)
113
+
114
+ # Update node data with way id
115
+ database.accept_bulk(node_ids) { |key, value|
116
+ node = Marshal.load(value)
117
+ node.add_way(way_id)
118
+ node.end_of_way = true if [nodes.first.to_s, nodes.last.to_s].include?(node.id)
119
+ Marshal.dump(node)
120
+ }
121
+ end
122
+
123
+ end
124
+
125
+ rnum = 6000000
126
+ if ARGV.length > 0
127
+ rnum = ARGV[0].to_i
128
+ end
129
+
130
+ # if ARGV.length > 1
131
+ # database_path = ARGV[1]
132
+ # end
133
+
134
+ # import in KC without options
135
+ puts "Import without options"
136
+ KCImport.new(rnum, "/home/luc/import_without_options.kch").import
137
+
138
+ # import in KC with options apow=8, opts=l, bnum=2000000 and msiz=50000000
139
+ puts "\nImport with options apow=8, opts=l, bnum=2000000 and msiz=50000000"
140
+ KCImport.new(rnum, "/home/luc/import_with_options.kch", "#apow=8#opts=l#bnum=2000000#msiz=50000000").import
141
+
142
+ # import in KC without options
143
+ puts "\nImport and update without options"
144
+ KCImport.new(rnum, "/home/luc/import_without_options.kch").import_and_update
145
+
146
+ # import in KC with options apow=8, opts=l, bnum=2000000 and msiz=50000000
147
+ # puts "\nImport and update with options apow=8, opts=l, bnum=2000000 and msiz=50000000"
148
+ # KCImport.new(rnum, "/home/luc/import_with_options.kch", "#apow=8#opts=l#bnum=2000000#msiz=50000000").import_and_update