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.
- checksums.yaml +15 -0
- data/.rspec +1 -0
- data/.travis.yml +7 -2
- data/Gemfile +8 -2
- data/Guardfile +2 -6
- data/README.md +69 -9
- data/Rakefile +8 -7
- data/active_road.gemspec +19 -15
- data/app/models/active_road/access_link.rb +4 -4
- data/app/models/active_road/access_point.rb +5 -9
- data/app/models/active_road/boundary.rb +41 -0
- data/app/models/active_road/junction.rb +4 -18
- data/app/models/active_road/junction_conditionnal_cost.rb +2 -0
- data/app/models/active_road/junctions_physical_road.rb +5 -0
- data/app/models/active_road/logical_road.rb +5 -4
- data/app/models/active_road/osm_pbf_importer.rb +293 -0
- data/app/models/active_road/osm_pbf_importer_level_db.rb +784 -0
- data/app/models/active_road/path.rb +40 -9
- data/app/models/active_road/physical_road.rb +22 -27
- data/app/models/active_road/physical_road_conditionnal_cost.rb +3 -1
- data/app/models/active_road/request_conditionnal_cost_linker.rb +59 -0
- data/app/models/active_road/street_number.rb +60 -57
- data/app/models/active_road/terra_importer.rb +161 -0
- data/db/migrate/20120419093427_add_kind_to_physical_roads.rb +2 -2
- data/db/migrate/20140206091734_create_boundaries.rb +16 -0
- data/db/migrate/20140210132933_add_attributes_to_physical_road.rb +9 -0
- data/db/migrate/20140219095521_add_boundary_id_to_logical_road.rb +5 -0
- data/db/migrate/20140228072448_add_boundary_id_to_physical_road.rb +5 -0
- data/db/migrate/20140304141150_add_marker_to_physical_road.rb +5 -0
- data/db/migrate/20140310083550_add_tags_to_street_number.rb +5 -0
- data/db/migrate/20140317153437_add_index_to_conditionnal_costs.rb +6 -0
- data/db/migrate/20140602160047_add_physical_road_index_to_junctions_physical_road.rb +5 -0
- data/lib/active_road.rb +8 -2
- data/lib/active_road/engine.rb +4 -1
- data/lib/active_road/shortest_path/finder.rb +37 -46
- data/lib/active_road/simulation_tool.rb +73 -0
- data/lib/active_road/version.rb +1 -1
- data/lib/tasks/activeroad_tasks.rake +88 -4
- data/script/benchmark_import_kyotocabinet.rb +148 -0
- data/script/benchmark_shortest_path.rb +22 -0
- data/script/count_tag_in_osm_data.rb +114 -0
- data/script/import-tiger-numbers +3 -3
- data/spec/dummy/db/schema.rb +2 -1
- data/spec/dummy/db/structure.sql +100 -11
- data/spec/factories/boundary.rb +8 -0
- data/spec/factories/junction.rb +1 -1
- data/spec/factories/physical_road.rb +1 -2
- data/spec/fixtures/test.osm +120 -0
- data/spec/fixtures/test.osm.bz2 +0 -0
- data/spec/fixtures/test.osm.pbf +0 -0
- data/spec/lib/active_road/shortest_path/finder_spec.rb +143 -90
- data/spec/lib/active_road/shortest_path/performance_finder_spec.rb +59 -0
- data/spec/models/active_road/access_point_spec.rb +9 -18
- data/spec/models/active_road/junction_conditionnal_cost_spec.rb +4 -4
- data/spec/models/active_road/junction_spec.rb +34 -11
- data/spec/models/active_road/logical_road_spec.rb +20 -19
- data/spec/models/active_road/osm_pbf_importer_level_db_spec.rb +410 -0
- data/spec/models/active_road/path_spec.rb +1 -1
- data/spec/models/active_road/physical_road_conditionnal_cost_spec.rb +4 -4
- data/spec/models/active_road/physical_road_spec.rb +14 -3
- data/spec/models/active_road/request_conditionnal_cost_linker_spec.rb +65 -0
- data/spec/models/active_road/shared_examples/osm_pbf_importer_spec.rb +148 -0
- data/spec/models/active_road/street_number_spec.rb +58 -58
- data/spec/models/active_road/terra_importer_spec.rb +140 -0
- data/spec/spec_helper.rb +14 -9
- data/spec/support/geometry_support.rb +36 -0
- data/spec/support/profile.rb +19 -0
- data/tmp/performance/.gitignore +0 -0
- data/travis/before_install.sh +5 -9
- data/travis/before_script.sh +7 -7
- metadata +118 -121
- data/app/models/active_road/physical_road_filter.rb +0 -41
- data/app/models/active_road/terra_import.rb +0 -148
- data/spec/models/active_road/physical_road_filter_spec.rb +0 -85
- data/spec/models/active_road/terra_import_spec.rb +0 -113
- data/spec/support/georuby_ext.rb +0 -15
checksums.yaml
ADDED
@@ -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
|
data/.travis.yml
CHANGED
@@ -1,8 +1,13 @@
|
|
1
1
|
language: ruby
|
2
|
+
addons:
|
3
|
+
postgresql: "9.2"
|
2
4
|
rvm:
|
3
5
|
- 1.9.3
|
4
|
-
|
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 =>
|
6
|
+
gem 'dr-postgis_adapter', :require => 'postgis_adapter'
|
7
|
+
gem 'coveralls', require: false
|
7
8
|
|
8
9
|
group :development do
|
9
|
-
gem
|
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', :
|
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
|
1
|
+
# ActiveRoad
|
2
|
+
[](http://travis-ci.org/cityway-transdev/activeroad?branch=master) [](https://gemnasium.com/cityway-transdev/activeroad) [](https://codeclimate.com/github/cityway-transdev/activeroad) [](https://coveralls.io/r/cityway-transdev/activeroad?branch=master)
|
2
3
|
|
3
|
-
|
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
|
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
|
-
|
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/
|
21
|
-
There is extensive usage documentation available [on the wiki](https://github.com/
|
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/
|
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
|
+
|
data/active_road.gemspec
CHANGED
@@ -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
|
12
|
-
s.description = %q{
|
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 "
|
23
|
-
s.add_development_dependency "
|
24
|
-
s.add_development_dependency
|
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.
|
30
|
-
s.add_dependency '
|
31
|
-
s.add_dependency '
|
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.
|
37
|
-
s.add_dependency 'enumerize', '0.
|
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
|
18
|
-
ActiveRoad::AccessPoint.from(location
|
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
|
37
|
-
arrival.respond_to?(:paths) ? arrival.paths
|
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
|
17
|
-
|
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
|
26
|
-
|
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
|
31
|
-
|
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.
|
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
|
@@ -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
|