overture_maps 0.1.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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +29 -0
- data/LICENSE.txt +21 -0
- data/README.md +416 -0
- data/app/controllers/overture_maps/application_controller.rb +28 -0
- data/app/controllers/overture_maps/attribution_controller.rb +15 -0
- data/app/controllers/overture_maps/features_controller.rb +125 -0
- data/app/controllers/overture_maps/search_controller.rb +31 -0
- data/app/controllers/overture_maps/tiles_controller.rb +85 -0
- data/config/routes.rb +13 -0
- data/exe/overture-maps-mcp +6 -0
- data/lib/generators/overture_maps/address_generator.rb +19 -0
- data/lib/generators/overture_maps/base_features_generator.rb +19 -0
- data/lib/generators/overture_maps/base_generator.rb +22 -0
- data/lib/generators/overture_maps/building_generator.rb +19 -0
- data/lib/generators/overture_maps/division_generator.rb +19 -0
- data/lib/generators/overture_maps/install_generator.rb +42 -0
- data/lib/generators/overture_maps/place_generator.rb +19 -0
- data/lib/generators/overture_maps/transportation_generator.rb +20 -0
- data/lib/generators/templates/address_migration.rb.tt +25 -0
- data/lib/generators/templates/address_model.rb.tt +4 -0
- data/lib/generators/templates/base_feature_model.rb.tt +4 -0
- data/lib/generators/templates/base_features_migration.rb.tt +27 -0
- data/lib/generators/templates/building_migration.rb.tt +24 -0
- data/lib/generators/templates/building_model.rb.tt +4 -0
- data/lib/generators/templates/category_migration.rb.tt +15 -0
- data/lib/generators/templates/category_model.rb.tt +4 -0
- data/lib/generators/templates/connector_model.rb.tt +4 -0
- data/lib/generators/templates/division_migration.rb.tt +31 -0
- data/lib/generators/templates/division_model.rb.tt +4 -0
- data/lib/generators/templates/imported_areas_migration.rb.tt +20 -0
- data/lib/generators/templates/place_migration.rb.tt +30 -0
- data/lib/generators/templates/place_model.rb.tt +4 -0
- data/lib/generators/templates/postgis_migration.rb.tt +5 -0
- data/lib/generators/templates/segment_model.rb.tt +4 -0
- data/lib/generators/templates/transportation_migration.rb.tt +38 -0
- data/lib/overture_maps/attribution.rb +66 -0
- data/lib/overture_maps/bounding_box.rb +80 -0
- data/lib/overture_maps/changelog.rb +70 -0
- data/lib/overture_maps/configuration.rb +43 -0
- data/lib/overture_maps/database.rb +74 -0
- data/lib/overture_maps/division_search.rb +44 -0
- data/lib/overture_maps/engine.rb +32 -0
- data/lib/overture_maps/geometry_parser.rb +41 -0
- data/lib/overture_maps/gers.rb +30 -0
- data/lib/overture_maps/import/downloader.rb +248 -0
- data/lib/overture_maps/import/location_based_runner.rb +176 -0
- data/lib/overture_maps/import/parquet_reader.rb +32 -0
- data/lib/overture_maps/import/record_mapper.rb +182 -0
- data/lib/overture_maps/import/runner.rb +125 -0
- data/lib/overture_maps/import.rb +27 -0
- data/lib/overture_maps/mcp_server.rb +222 -0
- data/lib/overture_maps/models/address.rb +32 -0
- data/lib/overture_maps/models/base.rb +39 -0
- data/lib/overture_maps/models/base_feature.rb +31 -0
- data/lib/overture_maps/models/building.rb +35 -0
- data/lib/overture_maps/models/category.rb +32 -0
- data/lib/overture_maps/models/connector.rb +11 -0
- data/lib/overture_maps/models/division.rb +43 -0
- data/lib/overture_maps/models/imported_area.rb +42 -0
- data/lib/overture_maps/models/place.rb +43 -0
- data/lib/overture_maps/models/segment.rb +22 -0
- data/lib/overture_maps/models.rb +25 -0
- data/lib/overture_maps/query.rb +168 -0
- data/lib/overture_maps/query_engine.rb +268 -0
- data/lib/overture_maps/releases.rb +74 -0
- data/lib/overture_maps/storage.rb +121 -0
- data/lib/overture_maps/syncer.rb +99 -0
- data/lib/overture_maps/util.rb +30 -0
- data/lib/overture_maps/version.rb +3 -0
- data/lib/overture_maps.rb +42 -0
- data/lib/tasks/overture_maps.rake +554 -0
- metadata +301 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module OvertureMaps
|
|
4
|
+
# Brings imported areas up to a newer Overture release without full
|
|
5
|
+
# reloads. For each tracked area (see Models::ImportedArea):
|
|
6
|
+
#
|
|
7
|
+
# 1. When every intermediate release's changelog is known, delete the ids
|
|
8
|
+
# marked `removed` in each step (bbox-scoped), then re-extract and
|
|
9
|
+
# upsert the area at the target release — upserts cover `added` and
|
|
10
|
+
# `data_changed`, deletions cover `removed`.
|
|
11
|
+
# 2. When the chain is incomplete (the area's release is no longer in the
|
|
12
|
+
# catalog), fall back to a full refresh: delete the area's rows and
|
|
13
|
+
# re-import.
|
|
14
|
+
#
|
|
15
|
+
# Overlapping areas sharing a table converge once all areas are synced to
|
|
16
|
+
# the same target.
|
|
17
|
+
class Syncer
|
|
18
|
+
Result = Struct.new(:area, :status, :removed, :imported, :errors, :message, keyword_init: true)
|
|
19
|
+
|
|
20
|
+
DELETE_BATCH_SIZE = 1000
|
|
21
|
+
|
|
22
|
+
def initialize(target_release: nil)
|
|
23
|
+
@target = Releases.validate!(target_release || Releases.current)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
attr_reader :target
|
|
27
|
+
|
|
28
|
+
def sync_all
|
|
29
|
+
Models::ImportedArea.find_each.map { |area| sync_area(area) }
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def sync_area(area)
|
|
33
|
+
return Result.new(area: area, status: :up_to_date, removed: 0, imported: 0, errors: 0) if area.release == target
|
|
34
|
+
|
|
35
|
+
model = area.model_class
|
|
36
|
+
bbox = area.to_bounding_box
|
|
37
|
+
steps = releases_between(area.release, target)
|
|
38
|
+
|
|
39
|
+
if steps
|
|
40
|
+
removed = delete_removed(area, model, bbox, steps)
|
|
41
|
+
runner = reimport(area, model, bbox)
|
|
42
|
+
finalize(area, runner)
|
|
43
|
+
Result.new(area: area, status: :synced, removed: removed,
|
|
44
|
+
imported: runner.imported_count, errors: runner.error_count)
|
|
45
|
+
else
|
|
46
|
+
purged = purge_area(model, bbox)
|
|
47
|
+
runner = reimport(area, model, bbox)
|
|
48
|
+
finalize(area, runner)
|
|
49
|
+
Result.new(area: area, status: :refreshed, removed: purged,
|
|
50
|
+
imported: runner.imported_count, errors: runner.error_count,
|
|
51
|
+
message: "changelog chain from #{area.release} unavailable; did a full refresh")
|
|
52
|
+
end
|
|
53
|
+
rescue StandardError => e
|
|
54
|
+
Result.new(area: area, status: :failed, removed: 0, imported: 0, errors: 1, message: e.message)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# The releases after `from` up to and including `to`, oldest first, or
|
|
58
|
+
# nil when the chain can't be established from the known release list.
|
|
59
|
+
def releases_between(from, to)
|
|
60
|
+
known = Releases.all.sort
|
|
61
|
+
from_idx = known.index(from)
|
|
62
|
+
to_idx = known.index(to)
|
|
63
|
+
return nil if from_idx.nil? || to_idx.nil? || to_idx <= from_idx
|
|
64
|
+
|
|
65
|
+
known[(from_idx + 1)..to_idx]
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
private
|
|
69
|
+
|
|
70
|
+
def delete_removed(area, model, bbox, steps)
|
|
71
|
+
total = 0
|
|
72
|
+
steps.each do |release|
|
|
73
|
+
ids = Changelog.removed_ids(theme: area.theme, type: area.feature_type,
|
|
74
|
+
release: release, bbox: bbox)
|
|
75
|
+
ids.each_slice(DELETE_BATCH_SIZE) do |slice|
|
|
76
|
+
total += model.where(id: slice).delete_all
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
total
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def purge_area(model, bbox)
|
|
83
|
+
model.within_bounds(bbox.min_lat, bbox.min_lng, bbox.max_lat, bbox.max_lng).delete_all
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def reimport(area, model, bbox)
|
|
87
|
+
Import::LocationBasedRunner.new(
|
|
88
|
+
theme: area.theme,
|
|
89
|
+
location: bbox,
|
|
90
|
+
models: { area.feature_type => model },
|
|
91
|
+
release: target
|
|
92
|
+
).run
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def finalize(area, runner)
|
|
96
|
+
area.update!(release: target, records_count: runner.imported_count)
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module OvertureMaps
|
|
4
|
+
module Util
|
|
5
|
+
module_function
|
|
6
|
+
|
|
7
|
+
def format_size(bytes)
|
|
8
|
+
if bytes >= 1_073_741_824
|
|
9
|
+
"#{(bytes / 1_073_741_824.0).round(2)} GB"
|
|
10
|
+
elsif bytes >= 1_048_576
|
|
11
|
+
"#{(bytes / 1_048_576.0).round(2)} MB"
|
|
12
|
+
elsif bytes >= 1024
|
|
13
|
+
"#{(bytes / 1024.0).round(2)} KB"
|
|
14
|
+
else
|
|
15
|
+
"#{bytes} bytes"
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Approximate area of a bounding box in km².
|
|
20
|
+
def bbox_area_km2(bbox)
|
|
21
|
+
lat_center = (bbox.min_lat + bbox.max_lat) / 2.0
|
|
22
|
+
km_per_deg_lat = 111.0
|
|
23
|
+
km_per_deg_lng = 111.0 * Math.cos(lat_center * Math::PI / 180.0)
|
|
24
|
+
|
|
25
|
+
width_km = (bbox.max_lng - bbox.min_lng) * km_per_deg_lng
|
|
26
|
+
height_km = (bbox.max_lat - bbox.min_lat) * km_per_deg_lat
|
|
27
|
+
(width_km * height_km).abs.round(2)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module OvertureMaps
|
|
4
|
+
class Error < StandardError; end
|
|
5
|
+
class ConfigurationError < Error; end
|
|
6
|
+
class CancelledError < Error; end
|
|
7
|
+
|
|
8
|
+
class << self
|
|
9
|
+
def configure
|
|
10
|
+
yield(configuration)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def configuration
|
|
14
|
+
@configuration ||= Configuration.new
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def reset
|
|
18
|
+
@configuration = nil
|
|
19
|
+
Releases.reset!
|
|
20
|
+
QueryEngine.reset!
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
require "overture_maps/version"
|
|
26
|
+
require "overture_maps/configuration"
|
|
27
|
+
require "overture_maps/util"
|
|
28
|
+
require "overture_maps/bounding_box"
|
|
29
|
+
require "overture_maps/storage"
|
|
30
|
+
require "overture_maps/releases"
|
|
31
|
+
require "overture_maps/query_engine"
|
|
32
|
+
require "overture_maps/database"
|
|
33
|
+
require "overture_maps/geometry_parser"
|
|
34
|
+
require "overture_maps/models"
|
|
35
|
+
require "overture_maps/division_search"
|
|
36
|
+
require "overture_maps/import"
|
|
37
|
+
require "overture_maps/query"
|
|
38
|
+
require "overture_maps/gers"
|
|
39
|
+
require "overture_maps/changelog"
|
|
40
|
+
require "overture_maps/syncer"
|
|
41
|
+
require "overture_maps/attribution"
|
|
42
|
+
require "overture_maps/engine" if defined?(Rails::Railtie)
|