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
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ YWZlZDYwNDEyOGU0Yjk4OGU5NDU1ZmMxYjA4ZmIzNjk4ODAwZjMxOA==
5
+ data.tar.gz: !binary |-
6
+ MjA5NTk3MTgzMDk1MWJkNWQ3YzNjYzEyMTA3YzZhMGI5YTM1ZDkyOA==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ ZDUxMTViZDcyNGFhZGZkN2JlYjAzMjQ3ZWU0NzI5NWRkZjY5Yzg1M2FlZjQ3
10
+ ZWNlNzg1OGFmYWNjZWZiOThiYjIyYWZlYzVhODFlNDUzZjIyZDMzNmY1NjQx
11
+ MjA4NWFhYjZiZjVlZGM3NjVhOWU1ZWFhNDBkZTk2YmM3YTNmNWQ=
12
+ data.tar.gz: !binary |-
13
+ YzIyYWIyYjY1ZjM2Yjc3NTkyM2ZhODBkYzRkZGFhYzgxYTZhNzQzNjM3Y2M5
14
+ MDgwZDNhMTczZDQ0OWI4MDBmMDQyZGE4MjZhMmU2ODMwNDIzMmNjYWNjMjJk
15
+ OTY3MzZkMDI1YTVkZWNhN2IxMTQ5ODIxZGRlZDI4Njc3YmVkOGE=
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour
@@ -1,8 +1,13 @@
1
1
  language: ruby
2
+ addons:
3
+ postgresql: "9.2"
2
4
  rvm:
3
5
  - 1.9.3
4
- env:
5
- - POSTGIS=1.5
6
+ - 2.0
7
+ notifications:
8
+ recipients:
9
+ - mflorisson@cityway.fr
10
+ - ldonnet@cityway.fr
6
11
  before_install: ./travis/before_install.sh
7
12
  before_script:
8
13
  - ./travis/before_script.sh
data/Gemfile CHANGED
@@ -3,12 +3,18 @@ source "http://rubygems.org"
3
3
  # Specify your gem's dependencies in activeroad.gemspec
4
4
  gemspec
5
5
 
6
- gem 'dr-postgis_adapter', :require => "postgis_adapter"
6
+ gem 'dr-postgis_adapter', :require => 'postgis_adapter'
7
+ gem 'coveralls', require: false
7
8
 
8
9
  group :development do
9
- gem 'rails-erd'
10
+ gem "rails-erd" # Tool to make schema class
10
11
  group :linux do
11
12
  gem 'rb-inotify', :require => RUBY_PLATFORM.include?('linux') && 'rb-inotify'
12
13
  gem 'rb-fsevent', :require => RUBY_PLATFORM.include?('darwin') && 'rb-fsevent'
13
14
  end
14
15
  end
16
+
17
+ group :development, :test do
18
+ gem "ruby-prof"
19
+ gem "bullet"
20
+ end
data/Guardfile CHANGED
@@ -2,8 +2,9 @@ guard 'bundler' do
2
2
  watch('Gemfile')
3
3
  end
4
4
 
5
- guard 'rspec', :version => 2, :notification => false, :bundler => true, :binstubs => false do
5
+ guard 'rspec', :notification => false do
6
6
  watch(%r{^spec/.+_spec\.rb$})
7
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
7
8
  watch('spec/spec_helper.rb') { "spec" }
8
9
 
9
10
  # Rails example
@@ -19,8 +20,3 @@ guard 'rspec', :version => 2, :notification => false, :bundler => true, :binstub
19
20
  watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/requests/#{m[1]}_spec.rb" }
20
21
  end
21
22
 
22
- guard 'migrate' do
23
- watch(%r{^db/migrate/(\d+).+\.rb})
24
- watch('db/seeds.rb')
25
- end
26
-
data/README.md CHANGED
@@ -1,29 +1,89 @@
1
- # ActiveRoad [![Build Status](https://travis-ci.org/dryade/activeroad.png)](http://travis-ci.org/dryade/activeroad?branch=master) [![Dependency Status](https://gemnasium.com/dryade/activeroad.png)](https://gemnasium.com/dryade/activeroad) [![Code Climate](https://codeclimate.com/github/dryade/activeroad.png)](https://codeclimate.com/github/dryade/activeroad)
1
+ # ActiveRoad
2
+ [![Build Status](https://travis-ci.org/cityway-transdev/activeroad.png)](http://travis-ci.org/cityway-transdev/activeroad?branch=master) [![Dependency Status](https://gemnasium.com/cityway-transdev/activeroad.png)](https://gemnasium.com/cityway-transdev/activeroad) [![Code Climate](https://codeclimate.com/github/cityway-transdev/activeroad.png)](https://codeclimate.com/github/cityway-transdev/activeroad) [![Coverage Status](https://img.shields.io/coveralls/cityway-transdev/activeroad.svg)](https://coveralls.io/r/cityway-transdev/activeroad?branch=master)
2
3
 
3
- Rails engine with a model for roads and rails description
4
+ ActiveRoads is a rails engine with a specific models for transport networks. It allows to :
5
+ - import osm ways form openstreetmap datas (PBF file format)
6
+ - make an itinerary research
7
+ The goal of this project is not to make the faster itinerary search engine like [OSRM](http://map.project-osrm.org/) or [OpenTripPlanner](http://www.opentripplanner.org/) but the more flexible because it doesn't need to binarize datas.
4
8
 
5
9
  Requirements
6
10
  ------------
7
11
 
8
- This code has been run and tested on Ruby 1.9.3
12
+ This code has been run and tested on :
13
+ * Ruby 1.9.3 and ruby 2.0
14
+ * Postgresql 9.X
15
+ * Postgis 2.X
16
+
17
+ External Deps
18
+ -------------
19
+ On Debian/Ubuntu/Kubuntu OS :
20
+ ```sh
21
+ sudo apt-get install git postgresql postgis build-essential ruby-dev libproj-dev libgeos-dev libffi-dev zlib1g-dev libxslt1-dev libxml2-dev libbz2-dev libleveldb-dev libsnappy-dev
22
+ ```
9
23
 
10
24
  Installation
11
25
  ------------
12
26
 
13
27
  This package is available in RubyGems and can be installed with:
14
-
15
- gem install active_road
28
+ ```sh
29
+ gem install active_road
30
+ ```
16
31
 
17
32
  More Information
18
33
  ----------------
19
34
 
20
- More information can be found on the [project website on GitHub](http://github.com/dryade/activeroad).
21
- There is extensive usage documentation available [on the wiki](https://github.com/dryade/activeroad/wiki).
35
+ More information can be found on the [project website on GitHub](http://github.com/cityway-transdev/activeroad).
36
+ There is extensive usage documentation available [on the wiki](https://github.com/cityway-transdev/activeroad/wiki).
22
37
 
23
38
  Example Usage
24
39
  ------------
25
40
 
26
- ...
41
+ ### Import OSM ways
42
+
43
+ ```sh
44
+ bundle exec rake "app:active_road:import:osm_pbf_data[/home/user/test.osm.pbf]"
45
+
46
+ ```
47
+
48
+ ### Itinerary research
49
+
50
+ Example of basic finder :
51
+
52
+ Actually we can use only 4 transport modes :
53
+ * car
54
+ * train
55
+ * pedestrian
56
+ * bike
57
+
58
+ ```ruby
59
+ from = GeoRuby::SimpleFeatures::Point.from_x_y(-52.652771, 5.174379)
60
+ to = GeoRuby::SimpleFeatures::Point.from_x_y(-52.323182, 4.941829)
61
+ speed = 4 # In kilometer/hour
62
+ finder = ActiveRoad::ShortestPath::Finder.new(from, to, speed).tap do |finder|
63
+ finder.timeout = 30.seconds
64
+ end
65
+
66
+ # Get geometry
67
+ finder.geometry
68
+
69
+ # Get steps
70
+ finder.paths
71
+ ```
72
+
73
+ For a more complex query, you can use constraints arguments. It's an array of string which
74
+ describes :
75
+ * if we use conditionnal cost for a physical road Ex : ["car"]
76
+ * if we not use a physical road because it contains a specific conditionnal cost Ex : ["~car"]
77
+
78
+ ```ruby
79
+ from = GeoRuby::SimpleFeatures::Point.from_x_y(-52.652771, 5.174379)
80
+ to = GeoRuby::SimpleFeatures::Point.from_x_y(-52.323182, 4.941829)
81
+ speed = 50 # In kilometer/hour
82
+ constraints = ["car"]
83
+ finder = ActiveRoad::ShortestPath::Finder.new(from, to, speed, constraints).tap do |finder|
84
+ finder.timeout = 30.seconds
85
+ end
86
+ ```
27
87
 
28
88
  License
29
89
  -------
@@ -34,4 +94,4 @@ This project is licensed under the MIT license, a copy of which can be found in
34
94
  Support
35
95
  -------
36
96
 
37
- Users looking for support should file an issue on the GitHub issue tracking page (https://github.com/dryade/activeroad/issues), or file a pull request (https://github.com/dryade/activeroad/pulls) if you have a fix available.
97
+ Users looking for support should file an issue on the GitHub issue tracking page (https://github.com/cityway-transdev/activeroad/issues), or file a pull request (https://github.com/cityway-transdev/activeroad/pulls) if you have a fix available.
data/Rakefile CHANGED
@@ -5,13 +5,6 @@ rescue LoadError
5
5
  puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
6
  end
7
7
 
8
- namespace :ci do
9
- task :prepare do
10
- cp "config/database.yml.ci", "config/database.yml"
11
- end
12
- task :build => ["db:migrate", "spec"]
13
- end
14
-
15
8
  begin
16
9
  require 'rdoc/task'
17
10
  rescue LoadError
@@ -44,3 +37,11 @@ RSpec::Core::RakeTask.new(:rcov) do |t|
44
37
  end
45
38
 
46
39
  task :spec => "app:db:test:prepare"
40
+
41
+ namespace :ci do
42
+ task :prepare do
43
+ cp "config/database.yml.ci", "config/database.yml"
44
+ end
45
+ task :build => ["db:migrate", "spec"]
46
+ end
47
+
@@ -7,9 +7,12 @@ Gem::Specification.new do |s|
7
7
  s.version = ActiveRoad::VERSION
8
8
  s.authors = ["Alban Peignier", "Luc Donnet", "Marc Florisson"]
9
9
  s.email = ["alban@tryphon.eu", "luc.donnet@free.fr", "mflorisson@gmail.com"]
10
- s.homepage = ""
11
- s.summary = %q{Rails engine to manage roads and rails model}
12
- s.description = %q{Find street numbers and road ways}
10
+ s.homepage = "https://rubygems.org/gems/active_road"
11
+ s.summary = %q{Rails engine to import openstreetmap datas and make an itinerary research}
12
+ s.description = %q{Import openstreetmap datas and make an itinerary research}
13
+ s.required_ruby_version = '>= 1.9.3'
14
+ s.license = 'MIT'
15
+ #spec.requirements << 'libsnappy-dev, v6.0'
13
16
 
14
17
  s.files = `git ls-files`.split("\n")
15
18
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
@@ -19,20 +22,21 @@ Gem::Specification.new do |s|
19
22
  s.add_development_dependency "guard"
20
23
  s.add_development_dependency "guard-bundler"
21
24
  s.add_development_dependency "guard-rspec"
22
- s.add_development_dependency "guard-migrate"
23
- s.add_development_dependency "factory_girl_rails", "~> 4.2.1"
24
- s.add_development_dependency "rspec-rails", "~> 2.11.4"
25
- s.add_development_dependency 'rails', '~> 3.2.13'
25
+ s.add_development_dependency "factory_girl_rails", ">= 4.2.1"
26
+ s.add_development_dependency "rspec-rails", '~> 3.1.0'
27
+ s.add_development_dependency 'rails', '>=3.1.12'
26
28
 
27
- s.add_dependency 'activerecord'
29
+ s.add_dependency 'activerecord', '3.2.18'
28
30
  s.add_dependency 'activerecord-postgres-hstore'
29
- s.add_dependency 'dr-postgis_adapter', '0.8.1'
30
- s.add_dependency 'sqlite3', '~> 1.3.7'
31
- s.add_dependency 'pg', '~> 0.15.1'
32
- s.add_dependency 'activerecord-import', '~> 0.3.1'
33
- s.add_dependency 'georuby-ext', "0.0.2"
31
+ s.add_dependency 'dr-postgis_adapter', '0.8.4'
32
+ s.add_dependency 'pg', '>= 0.15.1'
33
+ s.add_dependency 'georuby-ext', "0.0.5"
34
34
  s.add_dependency 'nokogiri'
35
35
  s.add_dependency 'saxerator'
36
- s.add_dependency 'shortest_path', '0.0.3'
37
- s.add_dependency 'enumerize', '0.6.1'
36
+ s.add_dependency 'shortest_path', '0.0.4'
37
+ s.add_dependency 'enumerize', '0.7.0'
38
+ s.add_dependency "pbf_parser", '~> 0.0.6'
39
+ s.add_dependency "leveldb-native", '~> 0.6'
40
+ s.add_dependency "snappy"
41
+ s.add_dependency 'postgres-copy', '~> 0.6.O'
38
42
  end
@@ -14,8 +14,8 @@ class ActiveRoad::AccessLink
14
14
 
15
15
  alias_method :to_s, :name
16
16
 
17
- def self.from(location, constraints = {})
18
- ActiveRoad::AccessPoint.from(location, constraints).collect do |access_point|
17
+ def self.from(location)
18
+ ActiveRoad::AccessPoint.from(location).collect do |access_point|
19
19
  new :departure => location, :arrival => access_point
20
20
  end
21
21
  end
@@ -33,8 +33,8 @@ class ActiveRoad::AccessLink
33
33
 
34
34
  delegate :access_to_road?, :to => :arrival
35
35
 
36
- def paths(constraints = {})
37
- arrival.respond_to?(:paths) ? arrival.paths(constraints) : [arrival]
36
+ def paths
37
+ arrival.respond_to?(:paths) ? arrival.paths : [arrival]
38
38
  end
39
39
 
40
40
  def access_to_road?(road)
@@ -13,19 +13,15 @@ class ActiveRoad::AccessPoint
13
13
  end
14
14
 
15
15
  # Find access points from a location
16
- def self.from(location, constraints = {})
17
- physical_roads_filtered = ActiveRoad::PhysicalRoadFilter.new(constraints).filter
18
-
19
- physical_roads_filtered.nearest_to(location, 100).collect do |physical_road|
16
+ def self.from(location)
17
+ ActiveRoad::PhysicalRoad.nearest_to(location).collect do |physical_road|
20
18
  new :location => location, :physical_road => physical_road
21
19
  end
22
20
  end
23
21
 
24
22
  # Find access points to go to a location
25
- def self.to(location, constraints = {})
26
- physical_roads_filtered = ActiveRoad::PhysicalRoadFilter.new(constraints).filter
27
-
28
- physical_roads_filtered.nearest_to(location, 100).collect do |physical_road|
23
+ def self.to(location)
24
+ ActiveRoad::PhysicalRoad.nearest_to(location).collect do |physical_road|
29
25
  new :location => location, :physical_road => physical_road, :exit => true
30
26
  end
31
27
  end
@@ -41,7 +37,7 @@ class ActiveRoad::AccessPoint
41
37
  alias_method :geometry, :point_on_road
42
38
 
43
39
  def access_to_road?(road)
44
- physical_road == road
40
+ physical_road.id == road.id
45
41
  end
46
42
 
47
43
  def name
@@ -0,0 +1,41 @@
1
+ module ActiveRoad
2
+ class Boundary < ActiveRoad::Base
3
+ #set_table_name :boundaries
4
+ attr_accessible :objectid, :geometry, :name, :admin_level, :postal_code, :insee_code
5
+ acts_as_geom :geometry => :multi_polygon
6
+
7
+ # Return linear rings which delimit multi polygon area
8
+ def self.all_uniq_borders
9
+ borders = self.all.collect(&:geometry).collect(&:polygons).flatten(1).collect(&:rings).flatten(1).uniq
10
+ GeoRuby::SimpleFeatures::MultiLineString.from_line_strings(borders)
11
+ end
12
+
13
+ # Return linear rings which delimit multi polygon area
14
+ def borders
15
+ geometry.polygons.collect(&:rings).flatten
16
+ end
17
+
18
+ def intersection(other)
19
+ postgis_calculate(:intersection, [self, other])
20
+ end
21
+
22
+
23
+ def difference(other)
24
+ postgis_calculate(:difference, [self, other])
25
+ end
26
+
27
+ def sym_difference(other)
28
+ postgis_calculate(:symDifference, [self, other])
29
+ end
30
+
31
+ # Contains not take object equals on a boundary border!!
32
+ def self.first_contains(other)
33
+ where("ST_Contains(geometry, ST_GeomFromEWKT(E'#{other.as_hex_ewkb}'))").first
34
+ end
35
+
36
+ def self.all_intersect(other)
37
+ where("ST_Intersects(geometry, ST_GeomFromEWKT(E'#{other.as_hex_ewkb}'))")
38
+ end
39
+
40
+ end
41
+ end
@@ -1,6 +1,4 @@
1
1
  # A junction is a connection between 1 to n physical roads
2
- require "activerecord-postgres-hstore"
3
-
4
2
  module ActiveRoad
5
3
  class Junction < ActiveRoad::Base
6
4
  serialize :tags, ActiveRecord::Coders::Hstore
@@ -11,30 +9,18 @@ module ActiveRoad
11
9
  has_and_belongs_to_many :physical_roads, :class_name => "ActiveRoad::PhysicalRoad",:uniq => true
12
10
  has_many :junction_conditionnal_costs, :class_name => "ActiveRoad::JunctionConditionnalCost"
13
11
 
14
- %w[max_speed, max_slope].each do |key|
15
- attr_accessible key
16
- scope "has_#{key}", lambda { |value| where("properties @> hstore(?, ?)", key, value) }
17
- define_method(key) do
18
- properties && properties[key]
19
- end
20
-
21
- define_method("#{key}=") do |value|
22
- self.properties = (properties || {}).merge(key => value)
23
- end
24
- end
25
-
26
12
  def location_on_road(road)
27
13
  (@location_on_road ||= {})[road.id] ||= road.locate_point(geometry)
28
14
  end
29
15
 
30
- def paths(tags = {})
31
- ActiveRoad::PhysicalRoadFilter.new(tags, physical_roads).filter.includes(:junctions).collect do |physical_road|
16
+ def paths
17
+ physical_roads.includes(:junctions, :physical_road_conditionnal_costs).collect do |physical_road|
32
18
  ActiveRoad::Path.all self, (physical_road.junctions - [self]), physical_road
33
19
  end.flatten
34
20
  end
35
21
 
36
22
  def access_to_road?(road)
37
- physical_roads.include? road
23
+ physical_roads.pluck(:id).include? road.id
38
24
  end
39
25
 
40
26
  def to_geometry
@@ -42,7 +28,7 @@ module ActiveRoad
42
28
  end
43
29
 
44
30
  def to_s
45
- "Junction @#{geometry.to_lat_lng}"
31
+ "Junction @#{geometry.lng},#{geometry.lat}"
46
32
  end
47
33
 
48
34
  def name
@@ -1,5 +1,6 @@
1
1
  module ActiveRoad
2
2
  class JunctionConditionnalCost < ActiveRoad::Base
3
+ attr_accessible :tags, :cost, :start_physical_road, :end_physical_road
3
4
 
4
5
  belongs_to :junction
5
6
  belongs_to :start_physical_road, :class_name => 'ActiveRoad::PhysicalRoad', :foreign_key => 'start_physical_road_id'
@@ -7,6 +8,7 @@ module ActiveRoad
7
8
 
8
9
  validates_presence_of :junction_id
9
10
  validates_presence_of :tags
11
+ validates_uniqueness_of :tags
10
12
  validates_presence_of :cost
11
13
 
12
14
  end
@@ -0,0 +1,5 @@
1
+ module ActiveRoad
2
+ class JunctionsPhysicalRoad < ActiveRoad::Base
3
+
4
+ end
5
+ end
@@ -1,13 +1,14 @@
1
1
  module ActiveRoad
2
2
  class LogicalRoad < ActiveRoad::Base
3
3
  extend ActiveSupport::Memoizable
4
- attr_accessible :objectid, :name
5
-
6
- validates_uniqueness_of :objectid
4
+ attr_accessible :objectid, :name, :boundary_id
7
5
 
8
6
  has_many :physical_roads, :class_name => "ActiveRoad::PhysicalRoad", :inverse_of => :logical_road
9
-
10
7
  has_many :numbers, :through => :physical_roads, :class_name => "ActiveRoad::StreetNumber"
8
+ belongs_to :boundary, :class_name => "ActiveRoad::Boundary"
9
+
10
+ #validates_uniqueness_of :objectid
11
+ #validates :boundary, presence: true
11
12
 
12
13
  def geometry
13
14
  GeoRuby::SimpleFeatures::MultiLineString.from_line_strings physical_roads.map(&:geometry)
@@ -0,0 +1,293 @@
1
+ module ActiveRoad
2
+ module OsmPbfImporter
3
+
4
+ @@relation_required_tags_keys = ["boundary", "admin_level"]
5
+ @@relation_selected_tags_keys = ["boundary", "admin_level", "ref:INSEE", "name", "addr:postcode", "type"]
6
+ mattr_reader :relation_required_tags_keys
7
+ mattr_reader :relation_selected_tags_keys
8
+
9
+ @@way_required_tags_keys = ["highway", "railway", "boundary", "admin_level", "addr:housenumber"]
10
+ @@way_for_physical_road_required_tags_keys = ["highway", "railway"]
11
+ @@way_for_boundary_required_tags_keys = ["boundary", "admin_level"]
12
+ @@way_for_street_number_required_tags_keys = ["addr:housenumber"]
13
+ @@way_selected_tags_keys = [ "name", "maxspeed", "oneway", "boundary", "admin_level", "addr:housenumber" ]
14
+ # Add first_node_id and last_node_id
15
+ @@way_optionnal_tags_keys = ["highway", "maxspeed", "bridge", "tunnel", "toll", "cycleway", "cycleway-right", "cycleway-left", "cycleway-both", "oneway:bicycle", "oneway", "bicycle", "segregated", "foot", "lanes", "lanes:forward", "lanes:forward:bus", "busway:right", "busway:left", "oneway_bus", "boundary", "admin_level", "access", "construction", "junction", "motor_vehicle", "psv", "bus", "addr:city", "addr:country", "addr:state", "addr:street"]
16
+ mattr_reader :way_required_tags_keys
17
+ mattr_reader :way_for_physical_road_required_tags_keys
18
+ mattr_reader :way_for_boundary_required_tags_keys
19
+ mattr_reader :way_for_street_number_required_tags_keys
20
+ mattr_reader :way_selected_tags_keys
21
+ mattr_reader :way_optionnal_tags_keys
22
+
23
+ @@nodes_selected_tags_keys = [ "addr:housenumber", "addr:city", "addr:postcode", "addr:street" ]
24
+ mattr_reader :nodes_selected_tags_keys
25
+
26
+ @@pg_batch_size = 10000 # Not Rails.logger.debug a high value because postgres failed to allocate memory
27
+ mattr_reader :pg_batch_size
28
+
29
+ def self.included(base)
30
+ base.extend(ClassMethods)
31
+ end
32
+
33
+ module ClassMethods
34
+ end
35
+
36
+ def pedestrian?(tags)
37
+ highway_tag_values = %w{pedestrian footway path steps}
38
+ if tags["highway"].present? && highway_tag_values.include?(tags["highway"])
39
+ true
40
+ else
41
+ false
42
+ end
43
+ end
44
+
45
+ # http://wiki.openstreetmap.org/wiki/FR:Cycleway
46
+ # http://wiki.openstreetmap.org/wiki/FR:Bicycle
47
+ def bike?(tags)
48
+ highway_tag_values = %w{cycleway}
49
+ bike_tags_keys = ["cycleway:left", "cycleway:right", "cycleway", "cycleway:left"]
50
+
51
+ if (tags["highway"].present? && highway_tag_values.include?(tags["highway"])) || (bike_tags_keys & tags.keys).present?
52
+ true
53
+ else
54
+ false
55
+ end
56
+ end
57
+
58
+ # http://wiki.openstreetmap.org/wiki/Key:railway
59
+ def train?(tags)
60
+ railway_tag_values = %w{rail tram funicular light_rail subway}
61
+ if tags["railway"].present? && railway_tag_values.include?(tags["railway"])
62
+ true
63
+ else
64
+ false
65
+ end
66
+ end
67
+
68
+ # http://wiki.openstreetmap.org/wiki/FR:France_roads_tagging
69
+ def car?(tags)
70
+ highway_tag_values = %w{motorway trunk trunk_link primary secondary tertiary motorway_link primary_link unclassified service road residential track}
71
+ if tags["highway"].present? && highway_tag_values.include?(tags["highway"])
72
+ true
73
+ else
74
+ false
75
+ end
76
+ end
77
+
78
+ def required_way?(required_tags, tags)
79
+ required_tags.each do |require_tag_key|
80
+ if tags.keys.include?(require_tag_key)
81
+ return true
82
+ end
83
+ end
84
+ return false
85
+ end
86
+
87
+ def required_relation?(tags)
88
+ @@relation_required_tags_keys.each do |require_tag_key|
89
+ if tags.keys.include?(require_tag_key)
90
+ return true
91
+ end
92
+ end
93
+ return false
94
+ end
95
+
96
+ # Return an hash with tag_key => tag_value for osm attributes
97
+ def selected_tags(tags, selected_tags_keys)
98
+ {}.tap do |selected_tags|
99
+ tags.each do |key, value|
100
+ if selected_tags_keys.include?(key)
101
+ selected_tags[key] = value
102
+ end
103
+ end
104
+ end
105
+ end
106
+
107
+ # def extract_tag_value(tag_value)
108
+ # case tag_value
109
+ # when "yes" : 1
110
+ # when "no" : 0
111
+ # when /[0-9].+/i tag_value.to_f
112
+ # else 0
113
+ # end
114
+ # end
115
+
116
+ def physical_road_conditionnal_costs(way)
117
+ [].tap do |prcc|
118
+ prcc << [ "car", Float::MAX] if !way.car
119
+ prcc << [ "pedestrian", Float::MAX] if !way.pedestrian
120
+ prcc << [ "bike", Float::MAX] if !way.bike
121
+ prcc << [ "train", Float::MAX] if !way.train
122
+ end
123
+ end
124
+
125
+ def extract_relation_polygon(outer_geometries, inner_geometries = [])
126
+ outer_rings = join_ways(outer_geometries)
127
+ inner_rings = join_ways(inner_geometries)
128
+
129
+ # TODO : Fix the case where many outer rings with many inner rings
130
+ polygons = [].tap do |polygons|
131
+ outer_rings.each { |outer_ring|
132
+ polygons << GeoRuby::SimpleFeatures::Polygon.from_linear_rings( [outer_ring] + inner_rings )
133
+ }
134
+ end
135
+ end
136
+
137
+ def join_ways(ways)
138
+ closed_ways = []
139
+ endpoints_to_ways = EndpointToWayMap.new
140
+ for way in ways
141
+ if way.closed?
142
+ closed_ways << way
143
+ next
144
+ end
145
+
146
+ # Are there any existing ways we can join this to?
147
+ to_join_to = endpoints_to_ways.get_from_either_end(way)
148
+ if to_join_to.present?
149
+ joined = way
150
+ for existing_way in to_join_to
151
+ joined = join_way(joined, existing_way)
152
+ endpoints_to_ways.remove_way(existing_way)
153
+ if joined.closed?
154
+ closed_ways << joined
155
+ break
156
+ end
157
+ end
158
+
159
+ if !joined.closed?
160
+ endpoints_to_ways.add_way(joined)
161
+ end
162
+ else
163
+ endpoints_to_ways.add_way(way)
164
+ end
165
+ end
166
+
167
+ if endpoints_to_ways.number_of_endpoints != 0
168
+ raise StandardError, "Unclosed boundaries"
169
+ end
170
+
171
+ closed_ways
172
+ end
173
+
174
+ def join_way(way, other)
175
+ if way.closed?
176
+ raise StandardError, "Trying to join a closed way to another"
177
+ end
178
+ if other.closed?
179
+ raise StandardError, "Trying to join a way to a closed way"
180
+ end
181
+
182
+ if way.points.first == other.points.first
183
+ new_points = other.reverse.points[0..-2] + way.points
184
+ elsif way.points.first == other.points.last
185
+ new_points = other.points[0..-2] + way.points
186
+ elsif way.points.last == other.points.first
187
+ new_points = way.points[0..-2] + other.points
188
+ elsif way.points.last == other.points.last
189
+ new_points = way.points[0..-2] + other.reverse.points
190
+ else
191
+ raise StandardError, "Trying to join two ways with no end point in common"
192
+ end
193
+
194
+ GeoRuby::SimpleFeatures::LineString.from_points(new_points)
195
+ end
196
+
197
+ class EndpointToWayMap
198
+ attr_accessor :endpoints
199
+
200
+ def initialize
201
+ @endpoints = {}
202
+ end
203
+
204
+ def add_way(way)
205
+ if get_from_either_end(way).present?
206
+ raise StandardError, "Call to add_way would overwrite existing way(s)"
207
+ end
208
+ self.endpoints[way.points.first] = way
209
+ self.endpoints[way.points.last] = way
210
+ end
211
+
212
+ def remove_way(way)
213
+ endpoints.delete(way.points.first)
214
+ endpoints.delete(way.points.last)
215
+ end
216
+
217
+ def get_from_either_end(way)
218
+ [].tap do |selected_end_points|
219
+ selected_end_points << endpoints[way.points.first] if endpoints.include?(way.points.first)
220
+ selected_end_points << endpoints[way.points.last] if endpoints.include?(way.points.last)
221
+ end
222
+ end
223
+
224
+ def number_of_endpoints
225
+ return endpoints.size
226
+ end
227
+
228
+ end
229
+
230
+ class Node
231
+ attr_accessor :id, :lon, :lat, :ways, :end_of_way, :addr_housenumber, :tags
232
+
233
+ def initialize(id, lon, lat, addr_housenumber = "", ways = [], end_of_way = false, tags = {} )
234
+ @id = id
235
+ @lon = lon
236
+ @lat = lat
237
+ @addr_housenumber = addr_housenumber
238
+ @ways = ways
239
+ @end_of_way = end_of_way
240
+ @tags = tags
241
+ end
242
+
243
+ def add_way(id)
244
+ @ways << id
245
+ end
246
+
247
+ def marshal_dump
248
+ [@id, @lon, @lat, @addr_housenumber, @ways, @end_of_way, @tags]
249
+ end
250
+
251
+ def marshal_load array
252
+ @id, @lon, @lat, @addr_housenumber, @ways, @end_of_way, @tags = array
253
+ end
254
+
255
+ def used?
256
+ ( ways.present? && ways.size > 1 ) || end_of_way
257
+ end
258
+ end
259
+
260
+ class Way
261
+ attr_accessor :id, :nodes, :car, :bike, :train, :pedestrian, :name, :maxspeed, :oneway, :boundary, :admin_level, :addr_housenumber, :options
262
+
263
+ def initialize(id, nodes = [], car = false, bike = false, train = false, pedestrian = false, name = "", maxspeed = 0, oneway = false, boundary = "", admin_level = "", addr_housenumber = "", options = {})
264
+ @id = id
265
+ @nodes = nodes
266
+ @car = car
267
+ @bike = bike
268
+ @train = train
269
+ @pedestrian = pedestrian
270
+ @name = name
271
+ @maxspeed = maxspeed
272
+ @oneway = oneway
273
+ @boundary = boundary
274
+ @admin_level = admin_level
275
+ @addr_housenumber = addr_housenumber
276
+ @options = options
277
+ end
278
+
279
+ def add_node(id)
280
+ @nodes << id
281
+ end
282
+
283
+ def marshal_dump
284
+ [@id, @nodes, @car, @bike, @train, @pedestrian, @name, @maxspeed, @oneway, @boundary, @admin_level, @addr_housenumber, @options]
285
+ end
286
+
287
+ def marshal_load array
288
+ @id, @nodes, @car, @bike, @train, @pedestrian, @name, @maxspeed, @oneway, @boundary, @admin_level, @addr_housenumber, @options = array
289
+ end
290
+ end
291
+
292
+ end
293
+ end