underpass 0.0.6 → 0.9.0

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.
@@ -12,8 +12,8 @@ module Underpass
12
12
  # Used to generate the version string
13
13
  module VERSION
14
14
  MAJOR = 0
15
- MINOR = 0
16
- PATCH = 6
15
+ MINOR = 9
16
+ PATCH = 0
17
17
 
18
18
  STRING = [MAJOR, MINOR, PATCH].join('.')
19
19
  end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Underpass
4
+ # Chains way node sequences that share endpoints into complete rings.
5
+ #
6
+ # Used internally by {Shape.multipolygon_from_relation} to merge multiple
7
+ # way segments into closed linear rings.
8
+ class WayChain
9
+ # @api private
10
+ MERGE_STRATEGIES = [
11
+ ->(cur, seq) { cur.last == seq.first ? cur + seq[1..] : nil },
12
+ ->(cur, seq) { cur.last == seq.last ? cur + seq.reverse[1..] : nil },
13
+ ->(cur, seq) { cur.first == seq.last ? seq + cur[1..] : nil },
14
+ ->(cur, seq) { cur.first == seq.first ? seq.reverse + cur[1..] : nil }
15
+ ].freeze
16
+
17
+ # Creates a new WayChain from way IDs and a way lookup table.
18
+ #
19
+ # @param way_ids [Array<Integer>] IDs of the ways to chain
20
+ # @param ways [Hash{Integer => Hash}] way lookup table
21
+ def initialize(way_ids, ways)
22
+ @sequences = way_ids.filter_map do |way_id|
23
+ way = ways[way_id]
24
+ next unless way
25
+
26
+ way[:nodes].dup
27
+ end
28
+ end
29
+
30
+ # Merges node sequences that share endpoints into continuous rings.
31
+ #
32
+ # @return [Array<Array<Integer>>] the merged node ID sequences
33
+ def merged_sequences
34
+ return @sequences if @sequences.empty?
35
+
36
+ remaining = @sequences.dup
37
+ current = remaining.shift
38
+ current, remaining = merge_all(current, remaining)
39
+ [current, *remaining]
40
+ end
41
+
42
+ private
43
+
44
+ def merge_all(current, remaining)
45
+ until remaining.empty?
46
+ found = find_connection(current, remaining)
47
+ break unless found
48
+
49
+ remaining.delete(found[:seq])
50
+ current = found[:merged]
51
+ end
52
+ [current, remaining]
53
+ end
54
+
55
+ def find_connection(current, sequences)
56
+ sequences.each do |seq|
57
+ merged = try_merge(current, seq)
58
+ return { seq: seq, merged: merged } if merged
59
+ end
60
+ nil
61
+ end
62
+
63
+ def try_merge(current, seq)
64
+ MERGE_STRATEGIES.each do |strategy|
65
+ result = strategy.call(current, seq)
66
+ return result if result
67
+ end
68
+ nil
69
+ end
70
+ end
71
+ end
data/lib/underpass.rb CHANGED
@@ -3,26 +3,72 @@
3
3
  require 'rgeo'
4
4
  require 'json'
5
5
 
6
- require 'underpass/ql/ql'
6
+ require 'underpass/cache'
7
+ require 'underpass/configuration'
8
+ require 'underpass/errors'
9
+ require 'underpass/client'
10
+ require 'underpass/feature'
11
+ require 'underpass/filter'
12
+ require 'underpass/geo_json'
13
+ require 'underpass/matcher'
14
+ require 'underpass/shape'
15
+ require 'underpass/way_chain'
16
+ require 'underpass/ql/bounding_box'
17
+ require 'underpass/ql/builder'
18
+ require 'underpass/ql/query'
19
+ require 'underpass/ql/query_analyzer'
20
+ require 'underpass/ql/request'
21
+ require 'underpass/ql/response'
7
22
 
8
23
  # Underpass is a library that makes it easy to query the Overpass API
9
- # and translate its responses into RGeo objects
24
+ # and translate its responses into RGeo objects.
25
+ #
26
+ # @example Quick start
27
+ # wkt = 'POLYGON ((23.669 47.65, 23.725 47.65, 23.725 47.674, 23.669 47.674, 23.669 47.65))'
28
+ # bbox = RGeo::Geographic.spherical_factory.parse_wkt(wkt)
29
+ # query = 'way["heritage:operator"="lmi"];'
30
+ # features = Underpass::QL::Query.perform(bbox, query)
31
+ #
32
+ # @example Configure the API endpoint
33
+ # Underpass.configure do |config|
34
+ # config.api_endpoint = 'https://overpass.kumi.systems/api/interpreter'
35
+ # config.timeout = 30
36
+ # end
10
37
  module Underpass
11
- end
38
+ class << self
39
+ # @return [Cache, nil] the cache instance used for storing API responses
40
+ attr_accessor :cache
12
41
 
13
- # Example usage
14
- #
15
- # require 'underpass'
16
- # wkt = <<-WKT
17
- # POLYGON ((
18
- # 23.669 47.65,
19
- # 23.725 47.65,
20
- # 23.725 47.674,
21
- # 23.669 47.674,
22
- # 23.669 47.65
23
- # ))
24
- # WKT
25
- # f = RGeo::Geographic.spherical_factory
26
- # bbox = f.parse_wkt(wkt)
27
- # op_query = 'way["heritage:operator"="lmi"]["ref:ro:lmi"="MM-II-m-B-04508"];'
28
- # Underpass::QL::Query.perform(bbox, op_query)
42
+ # @return [Configuration] the current configuration
43
+ attr_writer :configuration
44
+
45
+ # Returns the current configuration, initializing a default one if needed.
46
+ #
47
+ # @return [Configuration] the current configuration
48
+ def configuration
49
+ @configuration ||= Configuration.new
50
+ end
51
+
52
+ # Yields the current configuration for modification.
53
+ #
54
+ # @yield [config] the current configuration
55
+ # @yieldparam config [Configuration] the configuration instance
56
+ # @return [void]
57
+ #
58
+ # @example
59
+ # Underpass.configure do |config|
60
+ # config.api_endpoint = 'https://overpass.kumi.systems/api/interpreter'
61
+ # config.timeout = 30
62
+ # end
63
+ def configure
64
+ yield(configuration)
65
+ end
66
+
67
+ # Resets the configuration to default values.
68
+ #
69
+ # @return [Configuration] a new default configuration
70
+ def reset_configuration!
71
+ @configuration = Configuration.new
72
+ end
73
+ end
74
+ end
metadata CHANGED
@@ -1,69 +1,42 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: underpass
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Janos Rusiczki
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2019-04-14 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: rgeo
15
14
  requirement: !ruby/object:Gem::Requirement
16
15
  requirements:
17
- - - ">="
18
- - !ruby/object:Gem::Version
19
- version: 2.0.0
20
16
  - - "~>"
21
17
  - !ruby/object:Gem::Version
22
- version: '2.0'
18
+ version: '3.1'
23
19
  type: :runtime
24
20
  prerelease: false
25
21
  version_requirements: !ruby/object:Gem::Requirement
26
22
  requirements:
27
- - - ">="
28
- - !ruby/object:Gem::Version
29
- version: 2.0.0
30
23
  - - "~>"
31
24
  - !ruby/object:Gem::Version
32
- version: '2.0'
25
+ version: '3.1'
33
26
  - !ruby/object:Gem::Dependency
34
- name: rspec
27
+ name: rgeo-geojson
35
28
  requirement: !ruby/object:Gem::Requirement
36
29
  requirements:
37
- - - ">="
38
- - !ruby/object:Gem::Version
39
- version: 3.8.0
40
30
  - - "~>"
41
31
  - !ruby/object:Gem::Version
42
- version: '3.8'
43
- type: :development
44
- prerelease: false
45
- version_requirements: !ruby/object:Gem::Requirement
46
- requirements:
47
- - - ">="
48
- - !ruby/object:Gem::Version
49
- version: 3.8.0
50
- - - "~>"
51
- - !ruby/object:Gem::Version
52
- version: '3.8'
53
- - !ruby/object:Gem::Dependency
54
- name: simplecov
55
- requirement: !ruby/object:Gem::Requirement
56
- requirements:
57
- - - "~>"
58
- - !ruby/object:Gem::Version
59
- version: 0.16.0
60
- type: :development
32
+ version: '2.2'
33
+ type: :runtime
61
34
  prerelease: false
62
35
  version_requirements: !ruby/object:Gem::Requirement
63
36
  requirements:
64
37
  - - "~>"
65
38
  - !ruby/object:Gem::Version
66
- version: 0.16.0
39
+ version: '2.2'
67
40
  description: " A library that makes it easy to query the Overpass API and translate
68
41
  its responses into RGeo objects\n"
69
42
  email: janos.rusiczki@gmail.com
@@ -74,20 +47,31 @@ files:
74
47
  - LICENSE
75
48
  - README.md
76
49
  - lib/underpass.rb
50
+ - lib/underpass/cache.rb
51
+ - lib/underpass/client.rb
52
+ - lib/underpass/configuration.rb
53
+ - lib/underpass/errors.rb
54
+ - lib/underpass/feature.rb
55
+ - lib/underpass/filter.rb
56
+ - lib/underpass/geo_json.rb
57
+ - lib/underpass/matcher.rb
77
58
  - lib/underpass/ql/bounding_box.rb
78
- - lib/underpass/ql/parser.rb
79
- - lib/underpass/ql/ql.rb
59
+ - lib/underpass/ql/builder.rb
80
60
  - lib/underpass/ql/query.rb
61
+ - lib/underpass/ql/query_analyzer.rb
81
62
  - lib/underpass/ql/request.rb
82
- - lib/underpass/ql/shape.rb
63
+ - lib/underpass/ql/response.rb
64
+ - lib/underpass/shape.rb
83
65
  - lib/underpass/version.rb
66
+ - lib/underpass/way_chain.rb
84
67
  homepage: http://github.com/haiafara/underpass
85
68
  licenses:
86
69
  - MIT
87
70
  metadata:
88
71
  source_code_uri: http://github.com/haiafara/underpass
89
72
  bug_tracker_uri: http://github.com/haiafara/underpass/issues
90
- post_install_message:
73
+ documentation_uri: https://haiafara.github.io/underpass
74
+ rubygems_mfa_required: 'true'
91
75
  rdoc_options: []
92
76
  require_paths:
93
77
  - lib
@@ -95,15 +79,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
95
79
  requirements:
96
80
  - - ">="
97
81
  - !ruby/object:Gem::Version
98
- version: 2.3.0
82
+ version: 3.4.0
99
83
  required_rubygems_version: !ruby/object:Gem::Requirement
100
84
  requirements:
101
85
  - - ">="
102
86
  - !ruby/object:Gem::Version
103
87
  version: '0'
104
88
  requirements: []
105
- rubygems_version: 3.0.1
106
- signing_key:
89
+ rubygems_version: 3.6.9
107
90
  specification_version: 4
108
91
  summary: A library that translates Overpass API responses into RGeo objects
109
92
  test_files: []
@@ -1,56 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Underpass
4
- module QL
5
- # Deals with parsing the API request response into easily digestable objects
6
- # which are then returned as matches
7
- class Parser
8
- def initialize(response)
9
- @response = response
10
- @matches = []
11
- end
12
-
13
- def parse
14
- parsed_json = JSON.parse(@response.body, symbolize_names: true)
15
- elements = parsed_json[:elements]
16
-
17
- @nodes = extract_indexed_nodes(elements)
18
- @ways = extract_indexed_ways(elements)
19
-
20
- self
21
- end
22
-
23
- def matches
24
- @nodes.each_value do |node|
25
- @matches << point_from_node(node) if node.key?(:tags)
26
- end
27
-
28
- @ways.each_value do |way|
29
- @matches << polygon_from_way(way, @nodes) if way.key?(:tags)
30
- end
31
-
32
- @matches
33
- end
34
-
35
- private
36
-
37
- def point_from_node(node)
38
- Underpass::QL::Shape.point_from_node(node)
39
- end
40
-
41
- def polygon_from_way(way, nodes)
42
- Underpass::QL::Shape.polygon_from_way(way, nodes)
43
- end
44
-
45
- def extract_indexed_nodes(elements)
46
- nodes = elements.select { |e| e[:type] == 'node' }
47
- nodes.map { |e| [e[:id], e] }.to_h
48
- end
49
-
50
- def extract_indexed_ways(elements)
51
- ways = elements.select { |e| e[:type] == 'way' }
52
- ways.map { |e| [e[:id], e] }.to_h
53
- end
54
- end
55
- end
56
- end
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'underpass/ql/bounding_box'
4
- require 'underpass/ql/shape'
5
- require 'underpass/ql/request'
6
- require 'underpass/ql/parser'
7
- require 'underpass/ql/query'
8
-
9
- module Underpass
10
- # Provides the means to work with Overpass by using the
11
- # Overpass Query Language (QL). Overpass also provides an XML based
12
- # query language but we're not interested in that
13
- module QL
14
- end
15
- end
@@ -1,35 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Underpass
4
- module QL
5
- # Contains factories for various RGeo shapes from ways and nodes parsed
6
- # with the Parser class
7
- class Shape
8
- def self.polygon_from_way(way, nodes)
9
- f = RGeo::Geographic.spherical_factory(srid: 4326)
10
- f.polygon(line_string_from_way(way, nodes))
11
- end
12
-
13
- def self.line_string_from_way(way, nodes)
14
- f = RGeo::Geographic.spherical_factory(srid: 4326)
15
- f.line_string(
16
- way[:nodes].map do |n|
17
- f.point(nodes[n][:lon], nodes[n][:lat])
18
- end
19
- )
20
- end
21
-
22
- def self.point_from_node(node)
23
- f = RGeo::Geographic.spherical_factory(srid: 4326)
24
- f.point(node[:lon], node[:lat])
25
- end
26
-
27
- # There should be some sort of 'decorator' to return an object
28
- # with the shape and a copy of the tags as
29
- # {
30
- # tags: way[:tags],
31
- # shape: shape
32
- # }
33
- end
34
- end
35
- end