map_view 0.0.1a → 0.1.1.pre.alpha
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 +4 -4
- data/README.md +0 -188
- data/Rakefile +7 -0
- data/app/controllers/map_view/maps_controller.rb +20 -0
- data/config/initializers/map_view.rb +4 -0
- data/config/routes.rb +4 -0
- data/lib/generators/map_view/install_generator.rb +65 -0
- data/lib/generators/map_view/templates/default_styles.yml +45 -0
- data/lib/generators/map_view/templates/initializer.rb +14 -0
- data/lib/generators/map_view/templates/maps_controller.rb +15 -0
- data/lib/map_view/config.rb +67 -0
- data/lib/map_view/engine.rb +39 -0
- data/lib/map_view/version.rb +4 -0
- data/lib/map_view/view_helper.rb +116 -0
- data/lib/map_view.rb +24 -0
- metadata +83 -39
- data/lib/gd/gis/basemap.rb +0 -178
- data/lib/gd/gis/classifier.rb +0 -57
- data/lib/gd/gis/color_helpers.rb +0 -65
- data/lib/gd/gis/crs_normalizer.rb +0 -57
- data/lib/gd/gis/feature.rb +0 -153
- data/lib/gd/gis/geometry.rb +0 -235
- data/lib/gd/gis/input/detector.rb +0 -34
- data/lib/gd/gis/layer_geojson.rb +0 -66
- data/lib/gd/gis/layer_lines.rb +0 -44
- data/lib/gd/gis/layer_points.rb +0 -78
- data/lib/gd/gis/layer_polygons.rb +0 -54
- data/lib/gd/gis/map.rb +0 -370
- data/lib/gd/gis/middleware.rb +0 -89
- data/lib/gd/gis/ontology.rb +0 -26
- data/lib/gd/gis/ontology.yml +0 -28
- data/lib/gd/gis/projection.rb +0 -39
- data/lib/gd/gis/style.rb +0 -45
- data/lib/gd/gis.rb +0 -15
- data/lib/libgd_gis.rb +0 -44
- /data/{lib/gd/gis/input/geojson.rb → MIT-LICENSE} +0 -0
- /data/{lib/gd/gis/input/kml.rb → app/assets/stylesheets/map_view.css} +0 -0
- /data/{lib/gd/gis/input/shapefile.rb → app/views/map_view/_map.html.erb} +0 -0
metadata
CHANGED
|
@@ -1,69 +1,113 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: map_view
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.1.1.pre.alpha
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
|
-
- Germán Alberto
|
|
7
|
+
- Giménez Silva Germán Alberto
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-04-08 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
|
-
name:
|
|
14
|
+
name: rails
|
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
|
16
16
|
requirements:
|
|
17
|
-
- - "
|
|
17
|
+
- - ">="
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: 0
|
|
19
|
+
version: '6.0'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
20
24
|
- - ">="
|
|
21
25
|
- !ruby/object:Gem::Version
|
|
22
|
-
version: 0
|
|
26
|
+
version: '6.0'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: libgd-gis
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: 0.4.5
|
|
23
34
|
type: :runtime
|
|
24
35
|
prerelease: false
|
|
25
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
26
37
|
requirements:
|
|
27
38
|
- - "~>"
|
|
28
39
|
- !ruby/object:Gem::Version
|
|
29
|
-
version: 0.
|
|
30
|
-
|
|
40
|
+
version: 0.4.5
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: rspec
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '3.0'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
31
53
|
- !ruby/object:Gem::Version
|
|
32
|
-
version: 0
|
|
33
|
-
|
|
34
|
-
|
|
54
|
+
version: '3.0'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: rake
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - "~>"
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '13.0'
|
|
62
|
+
type: :development
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - "~>"
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '13.0'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: pry
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - "~>"
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '0.14'
|
|
76
|
+
type: :development
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - "~>"
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '0.14'
|
|
83
|
+
description: Simple Rails integration for libgd-gis. Provides view helpers to render
|
|
84
|
+
maps from GeoJSON data.
|
|
35
85
|
email:
|
|
36
86
|
- ggerman@gmail.com
|
|
37
87
|
executables: []
|
|
38
88
|
extensions: []
|
|
39
89
|
extra_rdoc_files: []
|
|
40
90
|
files:
|
|
91
|
+
- MIT-LICENSE
|
|
41
92
|
- README.md
|
|
42
|
-
-
|
|
43
|
-
-
|
|
44
|
-
-
|
|
45
|
-
-
|
|
46
|
-
-
|
|
47
|
-
-
|
|
48
|
-
- lib/
|
|
49
|
-
- lib/
|
|
50
|
-
- lib/
|
|
51
|
-
- lib/
|
|
52
|
-
- lib/
|
|
53
|
-
- lib/
|
|
54
|
-
- lib/
|
|
55
|
-
- lib/
|
|
56
|
-
- lib/
|
|
57
|
-
|
|
58
|
-
- lib/gd/gis/middleware.rb
|
|
59
|
-
- lib/gd/gis/ontology.rb
|
|
60
|
-
- lib/gd/gis/ontology.yml
|
|
61
|
-
- lib/gd/gis/projection.rb
|
|
62
|
-
- lib/gd/gis/style.rb
|
|
63
|
-
- lib/libgd_gis.rb
|
|
64
|
-
homepage: https://github.com/ggerman/libgd-gis
|
|
93
|
+
- Rakefile
|
|
94
|
+
- app/assets/stylesheets/map_view.css
|
|
95
|
+
- app/controllers/map_view/maps_controller.rb
|
|
96
|
+
- app/views/map_view/_map.html.erb
|
|
97
|
+
- config/initializers/map_view.rb
|
|
98
|
+
- config/routes.rb
|
|
99
|
+
- lib/generators/map_view/install_generator.rb
|
|
100
|
+
- lib/generators/map_view/templates/default_styles.yml
|
|
101
|
+
- lib/generators/map_view/templates/initializer.rb
|
|
102
|
+
- lib/generators/map_view/templates/maps_controller.rb
|
|
103
|
+
- lib/map_view.rb
|
|
104
|
+
- lib/map_view/config.rb
|
|
105
|
+
- lib/map_view/engine.rb
|
|
106
|
+
- lib/map_view/version.rb
|
|
107
|
+
- lib/map_view/view_helper.rb
|
|
108
|
+
homepage: https://github.com/ggerman/map_view
|
|
65
109
|
licenses:
|
|
66
|
-
-
|
|
110
|
+
- Commercial
|
|
67
111
|
metadata: {}
|
|
68
112
|
post_install_message:
|
|
69
113
|
rdoc_options: []
|
|
@@ -73,15 +117,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
73
117
|
requirements:
|
|
74
118
|
- - ">="
|
|
75
119
|
- !ruby/object:Gem::Version
|
|
76
|
-
version: '
|
|
120
|
+
version: '0'
|
|
77
121
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
78
122
|
requirements:
|
|
79
123
|
- - ">="
|
|
80
124
|
- !ruby/object:Gem::Version
|
|
81
125
|
version: '0'
|
|
82
126
|
requirements: []
|
|
83
|
-
rubygems_version: 3.5.
|
|
127
|
+
rubygems_version: 3.5.3
|
|
84
128
|
signing_key:
|
|
85
129
|
specification_version: 4
|
|
86
|
-
summary:
|
|
130
|
+
summary: Rails view helper for GD::GIS maps
|
|
87
131
|
test_files: []
|
data/lib/gd/gis/basemap.rb
DELETED
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
require "net/http"
|
|
2
|
-
require "fileutils"
|
|
3
|
-
|
|
4
|
-
module GD
|
|
5
|
-
module GIS
|
|
6
|
-
class Basemap
|
|
7
|
-
TILE_SIZE = 256
|
|
8
|
-
attr_reader :origin_x, :origin_y
|
|
9
|
-
|
|
10
|
-
def initialize(zoom, bbox, provider=:carto_light)
|
|
11
|
-
@zoom = zoom
|
|
12
|
-
@bbox = bbox
|
|
13
|
-
@provider = provider
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def url(z, x, y, style = :osm)
|
|
17
|
-
case style
|
|
18
|
-
|
|
19
|
-
# ==============================
|
|
20
|
-
# OpenStreetMap
|
|
21
|
-
# ==============================
|
|
22
|
-
when :osm
|
|
23
|
-
"https://tile.openstreetmap.org/#{z}/#{x}/#{y}.png"
|
|
24
|
-
|
|
25
|
-
when :osm_hot
|
|
26
|
-
"https://tile.openstreetmap.fr/hot/#{z}/#{x}/#{y}.png"
|
|
27
|
-
|
|
28
|
-
when :osm_fr
|
|
29
|
-
"https://a.tile.openstreetmap.fr/osmfr/#{z}/#{x}/#{y}.png"
|
|
30
|
-
|
|
31
|
-
# ==============================
|
|
32
|
-
# CARTO
|
|
33
|
-
# ==============================
|
|
34
|
-
when :carto_light
|
|
35
|
-
"https://a.basemaps.cartocdn.com/light_all/#{z}/#{x}/#{y}.png"
|
|
36
|
-
|
|
37
|
-
when :carto_light_nolabels
|
|
38
|
-
"https://a.basemaps.cartocdn.com/light_nolabels/#{z}/#{x}/#{y}.png"
|
|
39
|
-
|
|
40
|
-
when :carto_dark
|
|
41
|
-
"https://a.basemaps.cartocdn.com/dark_all/#{z}/#{x}/#{y}.png"
|
|
42
|
-
|
|
43
|
-
when :carto_dark_nolabels
|
|
44
|
-
"https://a.basemaps.cartocdn.com/dark_nolabels/#{z}/#{x}/#{y}.png"
|
|
45
|
-
|
|
46
|
-
# ==============================
|
|
47
|
-
# ESRI / ArcGIS (Satellite, terrain, hybrid)
|
|
48
|
-
# ==============================
|
|
49
|
-
when :esri_satellite
|
|
50
|
-
"https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/#{z}/#{y}/#{x}"
|
|
51
|
-
|
|
52
|
-
when :esri_streets
|
|
53
|
-
"https://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/#{z}/#{y}/#{x}"
|
|
54
|
-
|
|
55
|
-
when :esri_terrain
|
|
56
|
-
"https://services.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer/tile/#{z}/#{y}/#{x}"
|
|
57
|
-
|
|
58
|
-
when :esri_hybrid
|
|
59
|
-
"https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/#{z}/#{y}/#{x}"
|
|
60
|
-
|
|
61
|
-
# ==============================
|
|
62
|
-
# STAMEN 503
|
|
63
|
-
# ==============================
|
|
64
|
-
when :stamen_toner
|
|
65
|
-
"https://stamen-tiles.a.ssl.fastly.net/toner/#{z}/#{x}/#{y}.png"
|
|
66
|
-
|
|
67
|
-
when :stamen_toner_lite
|
|
68
|
-
"https://stamen-tiles.a.ssl.fastly.net/toner-lite/#{z}/#{x}/#{y}.png"
|
|
69
|
-
|
|
70
|
-
when :stamen_terrain
|
|
71
|
-
"https://stamen-tiles.a.ssl.fastly.net/terrain/#{z}/#{x}/#{y}.png"
|
|
72
|
-
|
|
73
|
-
when :stamen_watercolor
|
|
74
|
-
"https://stamen-tiles.a.ssl.fastly.net/watercolor/#{z}/#{x}/#{y}.jpg"
|
|
75
|
-
|
|
76
|
-
# ==============================
|
|
77
|
-
# OpenTopoMap
|
|
78
|
-
# ==============================
|
|
79
|
-
when :topo
|
|
80
|
-
"https://a.tile.opentopomap.org/#{z}/#{x}/#{y}.png"
|
|
81
|
-
|
|
82
|
-
# ==============================
|
|
83
|
-
# Wikimedia 403
|
|
84
|
-
# ==============================
|
|
85
|
-
when :wikimedia
|
|
86
|
-
"https://maps.wikimedia.org/osm-intl/#{z}/#{x}/#{y}.png"
|
|
87
|
-
|
|
88
|
-
# ==============================
|
|
89
|
-
# OpenRailwayMap
|
|
90
|
-
# ==============================
|
|
91
|
-
when :railway
|
|
92
|
-
"https://tiles.openrailwaymap.org/standard/#{z}/#{x}/#{y}.png"
|
|
93
|
-
|
|
94
|
-
# ==============================
|
|
95
|
-
# CyclOSM
|
|
96
|
-
# ==============================
|
|
97
|
-
when :cyclosm
|
|
98
|
-
"https://a.tile-cyclosm.openstreetmap.fr/cyclosm/#{z}/#{x}/#{y}.png"
|
|
99
|
-
|
|
100
|
-
else
|
|
101
|
-
raise "Unknown basemap style: #{style}"
|
|
102
|
-
end
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
def lon2tile(lon)
|
|
106
|
-
((lon + 180.0) / 360.0 * (2 ** @zoom)).floor
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
def lat2tile(lat)
|
|
110
|
-
rad = lat * Math::PI / 180
|
|
111
|
-
((1 - Math.log(Math.tan(rad) + 1 / Math.cos(rad)) / Math::PI) / 2 * (2 ** @zoom)).floor
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
def fetch_tiles
|
|
115
|
-
west, south, east, north = @bbox
|
|
116
|
-
|
|
117
|
-
x_min = lon2tile(west)
|
|
118
|
-
x_max = lon2tile(east)
|
|
119
|
-
y_min = lat2tile(north)
|
|
120
|
-
y_max = lat2tile(south)
|
|
121
|
-
|
|
122
|
-
@x_min = x_min
|
|
123
|
-
@y_min = y_min
|
|
124
|
-
|
|
125
|
-
@origin_x = x_min * TILE_SIZE
|
|
126
|
-
@origin_y = y_min * TILE_SIZE
|
|
127
|
-
|
|
128
|
-
FileUtils.mkdir_p("tmp/tiles")
|
|
129
|
-
|
|
130
|
-
tiles = []
|
|
131
|
-
|
|
132
|
-
(x_min..x_max).each do |x|
|
|
133
|
-
(y_min..y_max).each do |y|
|
|
134
|
-
path = nil
|
|
135
|
-
|
|
136
|
-
unless File.exist?("tmp/tiles/#{@provider}_#{@zoom}_#{x}_#{y}.png") ||
|
|
137
|
-
File.exist?("tmp/tiles/#{@provider}_#{@zoom}_#{x}_#{y}.jpg")
|
|
138
|
-
|
|
139
|
-
uri = URI(url(@zoom, x, y, @provider))
|
|
140
|
-
|
|
141
|
-
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
|
|
142
|
-
req = Net::HTTP::Get.new(uri)
|
|
143
|
-
req["User-Agent"] = "libgd-gis/0.1 (Ruby)"
|
|
144
|
-
|
|
145
|
-
res = http.request(req)
|
|
146
|
-
raise "Tile fetch failed #{res.code}" unless res.code == "200"
|
|
147
|
-
|
|
148
|
-
content_type = res["content-type"]
|
|
149
|
-
|
|
150
|
-
ext =
|
|
151
|
-
if content_type&.include?("png")
|
|
152
|
-
"png"
|
|
153
|
-
elsif content_type&.include?("jpeg") || content_type&.include?("jpg")
|
|
154
|
-
"jpg"
|
|
155
|
-
else
|
|
156
|
-
raise "Unsupported tile type: #{content_type}"
|
|
157
|
-
end
|
|
158
|
-
|
|
159
|
-
path = "tmp/tiles/#{@provider}_#{@zoom}_#{x}_#{y}.#{ext}"
|
|
160
|
-
File.binwrite(path, res.body)
|
|
161
|
-
end
|
|
162
|
-
else
|
|
163
|
-
if File.exist?("tmp/tiles/#{@provider}_#{@zoom}_#{x}_#{y}.png")
|
|
164
|
-
path = "tmp/tiles/#{@provider}_#{@zoom}_#{x}_#{y}.png"
|
|
165
|
-
else
|
|
166
|
-
path = "tmp/tiles/#{@provider}_#{@zoom}_#{x}_#{y}.jpg"
|
|
167
|
-
end
|
|
168
|
-
end
|
|
169
|
-
|
|
170
|
-
tiles << [x,y,path]
|
|
171
|
-
end
|
|
172
|
-
end
|
|
173
|
-
|
|
174
|
-
[tiles, x_min, y_min]
|
|
175
|
-
end
|
|
176
|
-
end
|
|
177
|
-
end
|
|
178
|
-
end
|
data/lib/gd/gis/classifier.rb
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
module GD
|
|
2
|
-
module GIS
|
|
3
|
-
class Classifier
|
|
4
|
-
def self.road(feature)
|
|
5
|
-
tags = feature.properties || {}
|
|
6
|
-
|
|
7
|
-
case tags["highway"]
|
|
8
|
-
when "motorway", "trunk"
|
|
9
|
-
:motorway
|
|
10
|
-
when "primary", "primary_link"
|
|
11
|
-
:primary
|
|
12
|
-
when "secondary", "secondary_link"
|
|
13
|
-
:secondary
|
|
14
|
-
when "tertiary"
|
|
15
|
-
:street
|
|
16
|
-
when "residential", "living_street"
|
|
17
|
-
:street
|
|
18
|
-
when "service", "track"
|
|
19
|
-
:minor
|
|
20
|
-
else
|
|
21
|
-
nil
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def self.water?(feature)
|
|
26
|
-
p = feature.properties
|
|
27
|
-
|
|
28
|
-
p["waterway"] ||
|
|
29
|
-
p["natural"] == "water" ||
|
|
30
|
-
p["fclass"] == "river" ||
|
|
31
|
-
p["fclass"] == "stream"
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def self.rail?(feature)
|
|
35
|
-
tags = feature.properties || {}
|
|
36
|
-
tags["railway"]
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def self.park?(feature)
|
|
40
|
-
tags = feature.properties || {}
|
|
41
|
-
%w[park recreation_ground garden].include?(tags["leisure"]) ||
|
|
42
|
-
%w[park grass forest].include?(tags["landuse"])
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def self.water_kind(feature)
|
|
46
|
-
p = feature.properties
|
|
47
|
-
|
|
48
|
-
case p["waterway"] || p["fclass"]
|
|
49
|
-
when "river" then :river
|
|
50
|
-
when "stream" then :stream
|
|
51
|
-
else :minor
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
end
|
data/lib/gd/gis/color_helpers.rb
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
module GD
|
|
2
|
-
module GIS
|
|
3
|
-
module ColorHelpers
|
|
4
|
-
# --------------------------------------------------
|
|
5
|
-
# Random RGB color
|
|
6
|
-
# --------------------------------------------------
|
|
7
|
-
def self.random_rgb(min: 0, max: 255)
|
|
8
|
-
GD::Color.rgb(
|
|
9
|
-
rand(min..max),
|
|
10
|
-
rand(min..max),
|
|
11
|
-
rand(min..max)
|
|
12
|
-
)
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
# --------------------------------------------------
|
|
16
|
-
# Random RGBA color
|
|
17
|
-
# --------------------------------------------------
|
|
18
|
-
def self.random_rgba(min: 0, max: 255, alpha: nil)
|
|
19
|
-
GD::Color.rgba(
|
|
20
|
-
rand(min..max),
|
|
21
|
-
rand(min..max),
|
|
22
|
-
rand(min..max),
|
|
23
|
-
alpha || rand(50..255)
|
|
24
|
-
)
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
# --------------------------------------------------
|
|
28
|
-
# Random vivid color (avoid gray/mud)
|
|
29
|
-
# --------------------------------------------------
|
|
30
|
-
def self.random_vivid
|
|
31
|
-
h = rand
|
|
32
|
-
s = rand(0.6..1.0)
|
|
33
|
-
v = rand(0.7..1.0)
|
|
34
|
-
|
|
35
|
-
r, g, b = hsv_to_rgb(h, s, v)
|
|
36
|
-
GD::Color.rgb(r, g, b)
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
# --------------------------------------------------
|
|
40
|
-
# HSV → RGB
|
|
41
|
-
# --------------------------------------------------
|
|
42
|
-
def self.hsv_to_rgb(h, s, v)
|
|
43
|
-
i = (h * 6).floor
|
|
44
|
-
f = h * 6 - i
|
|
45
|
-
p = v * (1 - s)
|
|
46
|
-
q = v * (1 - f * s)
|
|
47
|
-
t = v * (1 - (1 - f) * s)
|
|
48
|
-
|
|
49
|
-
r, g, b =
|
|
50
|
-
case i % 6
|
|
51
|
-
when 0 then [v, t, p]
|
|
52
|
-
when 1 then [q, v, p]
|
|
53
|
-
when 2 then [p, v, t]
|
|
54
|
-
when 3 then [p, q, v]
|
|
55
|
-
when 4 then [t, p, v]
|
|
56
|
-
when 5 then [v, p, q]
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
[(r * 255).to_i, (g * 255).to_i, (b * 255).to_i]
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
module GD
|
|
2
|
-
module GIS
|
|
3
|
-
module CRS
|
|
4
|
-
CRS84 = "urn:ogc:def:crs:OGC:1.3:CRS84"
|
|
5
|
-
EPSG4326 = "EPSG:4326"
|
|
6
|
-
EPSG3857 = "EPSG:3857"
|
|
7
|
-
|
|
8
|
-
class Normalizer
|
|
9
|
-
def initialize(crs)
|
|
10
|
-
@crs = normalize_name(crs)
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
# Accepts:
|
|
14
|
-
# normalize(lon,lat)
|
|
15
|
-
# normalize(lon,lat,z)
|
|
16
|
-
# normalize([lon,lat])
|
|
17
|
-
# normalize([lon,lat,z])
|
|
18
|
-
def normalize(*args)
|
|
19
|
-
lon, lat = args.flatten
|
|
20
|
-
return nil if lon.nil? || lat.nil?
|
|
21
|
-
|
|
22
|
-
lon = lon.to_f
|
|
23
|
-
lat = lat.to_f
|
|
24
|
-
|
|
25
|
-
case @crs
|
|
26
|
-
when CRS84, nil
|
|
27
|
-
[lon, lat]
|
|
28
|
-
|
|
29
|
-
when EPSG4326
|
|
30
|
-
# axis order lat,lon → lon,lat
|
|
31
|
-
[lat, lon]
|
|
32
|
-
|
|
33
|
-
when EPSG3857
|
|
34
|
-
mercator_to_wgs84(lon, lat)
|
|
35
|
-
|
|
36
|
-
else
|
|
37
|
-
[lon, lat]
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
private
|
|
42
|
-
|
|
43
|
-
def normalize_name(name)
|
|
44
|
-
return nil if name.nil?
|
|
45
|
-
name.to_s.strip
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
def mercator_to_wgs84(x, y)
|
|
49
|
-
r = 6378137.0
|
|
50
|
-
lon = (x / r) * 180.0 / Math::PI
|
|
51
|
-
lat = (2 * Math.atan(Math.exp(y / r)) - Math::PI / 2) * 180.0 / Math::PI
|
|
52
|
-
[lon, lat]
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
end
|
data/lib/gd/gis/feature.rb
DELETED
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
module GD
|
|
2
|
-
module GIS
|
|
3
|
-
class Feature
|
|
4
|
-
attr_reader :geometry, :properties, :layer
|
|
5
|
-
|
|
6
|
-
def initialize(geometry, properties, layer = nil)
|
|
7
|
-
@geometry = geometry
|
|
8
|
-
@properties = properties || {}
|
|
9
|
-
@layer = layer
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
# -------------------------------------------------
|
|
13
|
-
# Main draw entry point
|
|
14
|
-
# -------------------------------------------------
|
|
15
|
-
def draw(img, projection, color, width, layer = nil)
|
|
16
|
-
case geometry["type"]
|
|
17
|
-
when "Polygon"
|
|
18
|
-
if layer == :water
|
|
19
|
-
draw_polygon_outline(img, projection, geometry["coordinates"], color, width)
|
|
20
|
-
elsif layer.is_a?(Hash)
|
|
21
|
-
draw_polygon_styled(img, projection, geometry["coordinates"], layer)
|
|
22
|
-
else
|
|
23
|
-
draw_polygon(img, projection, geometry["coordinates"], color)
|
|
24
|
-
end
|
|
25
|
-
when "MultiPolygon"
|
|
26
|
-
geometry["coordinates"].each do |poly|
|
|
27
|
-
if layer == :water
|
|
28
|
-
draw_polygon_outline(img, projection, poly, color, width)
|
|
29
|
-
elsif layer.is_a?(Hash)
|
|
30
|
-
draw_polygon_styled(img, projection, poly, layer)
|
|
31
|
-
else
|
|
32
|
-
draw_polygon(img, projection, poly, color)
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
when "LineString", "MultiLineString"
|
|
36
|
-
draw_lines(img, projection, geometry["coordinates"], color, width)
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
# -------------------------------------------------
|
|
41
|
-
# Styled polygon rendering (fill + stroke)
|
|
42
|
-
# -------------------------------------------------
|
|
43
|
-
def draw_polygon_styled(img, projection, rings, style)
|
|
44
|
-
fill = style[:fill] ? GD::Color.rgb(*style[:fill]) : nil
|
|
45
|
-
stroke = style[:stroke] ? GD::Color.rgb(*style[:stroke]) : nil
|
|
46
|
-
|
|
47
|
-
rings.each do |ring|
|
|
48
|
-
pts = ring.map do |lon,lat|
|
|
49
|
-
x,y = projection.call(lon,lat)
|
|
50
|
-
next if x.nil? || y.nil?
|
|
51
|
-
[x.to_i, y.to_i]
|
|
52
|
-
end.compact
|
|
53
|
-
|
|
54
|
-
pts = pts.chunk_while { |a,b| a == b }.map(&:first)
|
|
55
|
-
next if pts.length < 3
|
|
56
|
-
|
|
57
|
-
img.filled_polygon(pts, fill) if fill
|
|
58
|
-
|
|
59
|
-
if stroke
|
|
60
|
-
pts.each_cons(2) { |a,b| img.line(a[0],a[1], b[0],b[1], stroke) }
|
|
61
|
-
img.line(pts.last[0], pts.last[1], pts.first[0], pts.first[1], stroke)
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
# -------------------------------------------------
|
|
67
|
-
# Polygon outline (used for water)
|
|
68
|
-
# -------------------------------------------------
|
|
69
|
-
def draw_polygon_outline(img, projection, rings, color, width)
|
|
70
|
-
return if color.nil?
|
|
71
|
-
|
|
72
|
-
rings.each do |ring|
|
|
73
|
-
pts = ring.map do |lon, lat|
|
|
74
|
-
x, y = projection.call(lon, lat)
|
|
75
|
-
[x.to_i, y.to_i] if x && y
|
|
76
|
-
end.compact
|
|
77
|
-
|
|
78
|
-
next if pts.size < 2
|
|
79
|
-
|
|
80
|
-
img.lines(pts, color, width)
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
# -------------------------------------------------
|
|
85
|
-
# Legacy filled polygon (single color)
|
|
86
|
-
# -------------------------------------------------
|
|
87
|
-
def draw_polygon(img, projection, rings, color)
|
|
88
|
-
return if color.nil?
|
|
89
|
-
|
|
90
|
-
rings.each do |ring|
|
|
91
|
-
pts = ring.map do |lon,lat|
|
|
92
|
-
x,y = projection.call(lon,lat)
|
|
93
|
-
next if x.nil? || y.nil?
|
|
94
|
-
[x.to_i, y.to_i]
|
|
95
|
-
end.compact
|
|
96
|
-
|
|
97
|
-
pts = pts.chunk_while { |a,b| a == b }.map(&:first)
|
|
98
|
-
next if pts.length < 3
|
|
99
|
-
|
|
100
|
-
img.filled_polygon(pts, color)
|
|
101
|
-
end
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
# -------------------------------------------------
|
|
105
|
-
# Lines
|
|
106
|
-
# -------------------------------------------------
|
|
107
|
-
def draw_lines(img, projection, coords, color, width)
|
|
108
|
-
return if color.nil?
|
|
109
|
-
|
|
110
|
-
if coords.first.is_a?(Array) && coords.first.first.is_a?(Array)
|
|
111
|
-
coords.each { |line| draw_line(img, projection, line, color, width) }
|
|
112
|
-
else
|
|
113
|
-
draw_line(img, projection, coords, color, width)
|
|
114
|
-
end
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
def draw_line(img, projection, coords, color, width)
|
|
118
|
-
return if color.nil?
|
|
119
|
-
|
|
120
|
-
coords.each_cons(2) do |(lon1,lat1),(lon2,lat2)|
|
|
121
|
-
x1,y1 = projection.call(lon1,lat1)
|
|
122
|
-
x2,y2 = projection.call(lon2,lat2)
|
|
123
|
-
img.line(x1, y1, x2, y2, color, thickness: width)
|
|
124
|
-
end
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
# -------------------------------------------------
|
|
128
|
-
# Metadata helpers
|
|
129
|
-
# -------------------------------------------------
|
|
130
|
-
def label
|
|
131
|
-
properties["name:ja"] || properties["name"]
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
def centroid
|
|
135
|
-
pts = []
|
|
136
|
-
|
|
137
|
-
case geometry["type"]
|
|
138
|
-
when "LineString"
|
|
139
|
-
pts = geometry["coordinates"]
|
|
140
|
-
when "MultiLineString"
|
|
141
|
-
pts = geometry["coordinates"].flatten(1)
|
|
142
|
-
end
|
|
143
|
-
|
|
144
|
-
return nil if pts.empty?
|
|
145
|
-
|
|
146
|
-
lon = pts.map(&:first).sum / pts.size
|
|
147
|
-
lat = pts.map(&:last).sum / pts.size
|
|
148
|
-
|
|
149
|
-
[lon, lat]
|
|
150
|
-
end
|
|
151
|
-
end
|
|
152
|
-
end
|
|
153
|
-
end
|