libgd-gis 0.4.1 → 0.4.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 +4 -4
- data/README.md +29 -0
- data/lib/gd/gis/bbox_resolver.rb +42 -0
- data/lib/gd/gis/data/extents_global.json +95 -0
- data/lib/gd/gis/extents.rb +57 -0
- data/lib/gd/gis/layer_points.rb +10 -11
- data/lib/gd/gis/legend.rb +19 -1
- data/lib/gd/gis/map.rb +23 -16
- data/lib/gd/gis/style.rb +74 -0
- data/lib/gd/gis.rb +3 -1
- metadata +4 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8fdfcd8c25a4c2d5be9f69153957d4d3c5fbd2b82e26167554be17c7e0ff058c
|
|
4
|
+
data.tar.gz: 9b5b504f06e11d6a0ac465747237e8832986234bee3ded81f0360a5c6749d29f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7ded6603953b5144db8794841f6c898aea15819960b8d1a3b89c46e7122e74bf7c0e344814a983d5fbede7f4472080dc39ea360743d6d73d24c82d31371e5dcc
|
|
7
|
+
data.tar.gz: 2a2b7f255b78b338e128d9a2a0bd293db0936da7a30cfdb94e710c541251937c798504b9f5c20fd5ccabb8845c10fc29a47878d886a723e0a66f3ce25effd4aa
|
data/README.md
CHANGED
|
@@ -202,6 +202,35 @@ This design ensures predictable rendering and makes all visual decisions explici
|
|
|
202
202
|
and reproducible.
|
|
203
203
|
|
|
204
204
|
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
## Named geographic extents
|
|
209
|
+
|
|
210
|
+
LibGD-GIS includes a global dataset of predefined geographic areas.
|
|
211
|
+
You can use them directly as the `bbox` parameter.
|
|
212
|
+
|
|
213
|
+
### Example
|
|
214
|
+
|
|
215
|
+
```ruby
|
|
216
|
+
map = GD::GIS::Map.new(
|
|
217
|
+
bbox: :argentina,
|
|
218
|
+
zoom: 5,
|
|
219
|
+
width: 800,
|
|
220
|
+
height: 600,
|
|
221
|
+
basemap: :osm
|
|
222
|
+
)
|
|
223
|
+
```
|
|
224
|
+
You can also use continents or regions:
|
|
225
|
+
|
|
226
|
+
```
|
|
227
|
+
bbox: :world
|
|
228
|
+
bbox: :europe
|
|
229
|
+
bbox: :south_america
|
|
230
|
+
bbox: :north_america
|
|
231
|
+
bbox: :asia
|
|
232
|
+
```
|
|
233
|
+
|
|
205
234
|
---
|
|
206
235
|
|
|
207
236
|
## CRS Support
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module GD
|
|
4
|
+
module GIS
|
|
5
|
+
# Resolves bounding box inputs into a normalized WGS84 bbox array.
|
|
6
|
+
#
|
|
7
|
+
# Accepts:
|
|
8
|
+
# - Symbol or String referencing a named extent (e.g. :world, :argentina)
|
|
9
|
+
# - Array in the form [min_lng, min_lat, max_lng, max_lat]
|
|
10
|
+
#
|
|
11
|
+
# Returns a 4-element array of Float values.
|
|
12
|
+
#
|
|
13
|
+
# @example Using a named extent
|
|
14
|
+
# BBoxResolver.resolve(:europe)
|
|
15
|
+
#
|
|
16
|
+
# @example Using a raw bbox
|
|
17
|
+
# BBoxResolver.resolve([-10, 35, 5, 45])
|
|
18
|
+
module BBoxResolver
|
|
19
|
+
def self.resolve(bbox)
|
|
20
|
+
case bbox
|
|
21
|
+
when Symbol, String
|
|
22
|
+
Extents.fetch(bbox)
|
|
23
|
+
|
|
24
|
+
when Array
|
|
25
|
+
validate!(bbox)
|
|
26
|
+
bbox.map(&:to_f)
|
|
27
|
+
|
|
28
|
+
else
|
|
29
|
+
raise ArgumentError,
|
|
30
|
+
"bbox must be Symbol, String or [min_lng, min_lat, max_lng, max_lat]"
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def self.validate!(bbox)
|
|
35
|
+
return if bbox.is_a?(Array) && bbox.size == 4
|
|
36
|
+
|
|
37
|
+
raise ArgumentError,
|
|
38
|
+
"bbox must be [min_lng, min_lat, max_lng, max_lat]"
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
{
|
|
2
|
+
"world": [-180.0, -90.0, 180.0, 90.0],
|
|
3
|
+
|
|
4
|
+
"northern_hemisphere": [-180.0, 0.0, 180.0, 90.0],
|
|
5
|
+
"southern_hemisphere": [-180.0, -90.0, 180.0, 0.0],
|
|
6
|
+
"eastern_hemisphere": [0.0, -90.0, 180.0, 90.0],
|
|
7
|
+
"western_hemisphere": [-180.0, -90.0, 0.0, 90.0],
|
|
8
|
+
|
|
9
|
+
"africa": [-25.0, -35.0, 51.0, 38.0],
|
|
10
|
+
"antarctica": [-180.0, -90.0, 180.0, -60.0],
|
|
11
|
+
"asia": [26.0, -11.0, 169.0, 78.0],
|
|
12
|
+
"europe": [-31.0, 34.0, 39.0, 72.0],
|
|
13
|
+
"north_america": [-168.0, 7.0, -52.0, 83.0],
|
|
14
|
+
"south_america": [-82.0, -56.0, -34.0, 13.0],
|
|
15
|
+
"oceania": [110.0, -50.0, 180.0, 0.0],
|
|
16
|
+
|
|
17
|
+
"argentina": [-73.6, -55.1, -53.6, -21.7],
|
|
18
|
+
"bolivia": [-69.7, -22.9, -57.5, -9.7],
|
|
19
|
+
"brazil": [-74.0, -34.0, -34.0, 5.3],
|
|
20
|
+
"chile": [-75.6, -56.0, -66.4, -17.5],
|
|
21
|
+
"colombia": [-79.0, -4.2, -66.9, 13.5],
|
|
22
|
+
"ecuador": [-81.0, -5.0, -75.0, 1.5],
|
|
23
|
+
"guyana": [-61.4, 1.2, -56.5, 8.6],
|
|
24
|
+
"paraguay": [-62.6, -27.6, -54.3, -19.3],
|
|
25
|
+
"peru": [-81.4, -18.4, -68.7, -0.0],
|
|
26
|
+
"suriname": [-58.1, 1.8, -53.9, 6.0],
|
|
27
|
+
"uruguay": [-58.4, -35.0, -53.1, -30.1],
|
|
28
|
+
"venezuela": [-73.4, 0.6, -59.8, 12.2],
|
|
29
|
+
|
|
30
|
+
"canada": [-141.0, 41.0, -52.6, 83.1],
|
|
31
|
+
"united_states": [-125.0, 24.0, -66.9, 49.4],
|
|
32
|
+
"mexico": [-118.4, 14.5, -86.7, 32.7],
|
|
33
|
+
"greenland": [-73.0, 59.8, -12.2, 83.6],
|
|
34
|
+
|
|
35
|
+
"iceland": [-24.5, 63.3, -13.5, 66.6],
|
|
36
|
+
"ireland": [-10.5, 51.4, -6.0, 55.5],
|
|
37
|
+
"united_kingdom": [-8.6, 49.8, 1.8, 60.9],
|
|
38
|
+
"portugal": [-9.6, 36.9, -6.2, 42.2],
|
|
39
|
+
"spain": [-9.5, 35.9, 3.3, 43.8],
|
|
40
|
+
"france": [-5.2, 41.3, 9.6, 51.1],
|
|
41
|
+
"belgium": [2.5, 49.5, 6.4, 51.5],
|
|
42
|
+
"netherlands": [3.3, 50.7, 7.2, 53.7],
|
|
43
|
+
"germany": [5.9, 47.3, 15.0, 55.1],
|
|
44
|
+
"switzerland": [5.9, 45.8, 10.5, 47.8],
|
|
45
|
+
"italy": [6.6, 36.6, 18.5, 47.1],
|
|
46
|
+
"austria": [9.5, 46.4, 17.2, 49.0],
|
|
47
|
+
"poland": [14.1, 49.0, 24.1, 54.8],
|
|
48
|
+
"czechia": [12.1, 48.5, 18.9, 51.1],
|
|
49
|
+
"hungary": [16.1, 45.7, 22.9, 48.6],
|
|
50
|
+
"greece": [19.4, 34.8, 28.2, 41.8],
|
|
51
|
+
"norway": [4.9, 58.0, 31.3, 71.2],
|
|
52
|
+
"sweden": [11.1, 55.3, 24.2, 69.1],
|
|
53
|
+
"finland": [20.6, 59.8, 31.6, 70.1],
|
|
54
|
+
"denmark": [8.0, 54.5, 12.7, 57.8],
|
|
55
|
+
|
|
56
|
+
"turkey": [26.0, 36.0, 45.0, 42.1],
|
|
57
|
+
"russia": [19.0, 41.0, 180.0, 82.0],
|
|
58
|
+
|
|
59
|
+
"saudi_arabia": [34.5, 16.3, 55.7, 32.2],
|
|
60
|
+
"iran": [44.0, 25.0, 63.3, 39.8],
|
|
61
|
+
"iraq": [38.8, 29.0, 48.6, 37.4],
|
|
62
|
+
"israel": [34.2, 29.5, 35.9, 33.3],
|
|
63
|
+
"jordan": [34.9, 29.2, 39.3, 33.4],
|
|
64
|
+
"syria": [35.7, 32.3, 42.4, 37.3],
|
|
65
|
+
|
|
66
|
+
"india": [68.1, 6.5, 97.4, 35.5],
|
|
67
|
+
"pakistan": [60.9, 23.7, 77.8, 37.1],
|
|
68
|
+
"bangladesh": [88.0, 20.7, 92.7, 26.6],
|
|
69
|
+
"china": [73.5, 18.1, 135.1, 53.6],
|
|
70
|
+
"mongolia": [87.7, 41.6, 119.9, 52.1],
|
|
71
|
+
"japan": [129.4, 31.0, 145.8, 45.5],
|
|
72
|
+
"south_korea": [125.0, 33.1, 131.9, 38.6],
|
|
73
|
+
"north_korea": [124.0, 37.7, 130.7, 43.0],
|
|
74
|
+
|
|
75
|
+
"thailand": [97.3, 5.6, 105.6, 20.5],
|
|
76
|
+
"vietnam": [102.1, 8.2, 109.5, 23.4],
|
|
77
|
+
"malaysia": [99.6, 0.8, 119.3, 7.4],
|
|
78
|
+
"indonesia": [95.0, -11.0, 141.0, 6.0],
|
|
79
|
+
"philippines": [116.9, 4.6, 126.6, 21.2],
|
|
80
|
+
|
|
81
|
+
"egypt": [24.7, 22.0, 36.9, 31.7],
|
|
82
|
+
"libya": [9.3, 19.5, 25.1, 33.2],
|
|
83
|
+
"algeria": [-8.7, 19.0, 12.0, 37.1],
|
|
84
|
+
"morocco": [-13.2, 27.7, -1.0, 35.9],
|
|
85
|
+
"tunisia": [7.5, 30.2, 11.6, 37.3],
|
|
86
|
+
|
|
87
|
+
"nigeria": [2.7, 4.2, 14.7, 13.9],
|
|
88
|
+
"ethiopia": [32.9, 3.4, 47.9, 14.9],
|
|
89
|
+
"kenya": [33.9, -4.7, 41.9, 5.0],
|
|
90
|
+
"south_africa": [16.4, -34.8, 32.9, -22.1],
|
|
91
|
+
|
|
92
|
+
"australia": [112.9, -43.7, 153.6, -10.7],
|
|
93
|
+
"new_zealand": [166.4, -47.3, 178.6, -34.4],
|
|
94
|
+
"papua_new_guinea": [140.8, -11.7, 156.0, -1.4]
|
|
95
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
|
|
5
|
+
module GD
|
|
6
|
+
module GIS
|
|
7
|
+
# Provides access to predefined geographic extents loaded from
|
|
8
|
+
# a JSON dataset.
|
|
9
|
+
#
|
|
10
|
+
# Extents are WGS84 bounding boxes defined as:
|
|
11
|
+
# [min_lng, min_lat, max_lng, max_lat]
|
|
12
|
+
#
|
|
13
|
+
# Supports lookup by symbolic name.
|
|
14
|
+
#
|
|
15
|
+
# @example Fetch extent
|
|
16
|
+
# Extents.fetch(:world)
|
|
17
|
+
#
|
|
18
|
+
# @example Using bracket syntax
|
|
19
|
+
# Extents[:argentina]
|
|
20
|
+
#
|
|
21
|
+
# @note Bounding boxes are approximate and intended for visualization.
|
|
22
|
+
module Extents
|
|
23
|
+
DATA_PATH = File.expand_path(
|
|
24
|
+
"data/extents_global.json",
|
|
25
|
+
__dir__
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
@extents = nil
|
|
29
|
+
|
|
30
|
+
class << self
|
|
31
|
+
def fetch(name)
|
|
32
|
+
load_data!
|
|
33
|
+
@extents.fetch(name.to_s.downcase) do
|
|
34
|
+
raise ArgumentError, "Unknown extent: #{name}"
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def [](name)
|
|
39
|
+
fetch(name)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def all
|
|
43
|
+
load_data!
|
|
44
|
+
@extents.keys.map(&:to_sym)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
def load_data!
|
|
50
|
+
return if @extents
|
|
51
|
+
|
|
52
|
+
@extents = JSON.parse(File.read(DATA_PATH))
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
data/lib/gd/gis/layer_points.rb
CHANGED
|
@@ -101,16 +101,15 @@ module GD
|
|
|
101
101
|
#
|
|
102
102
|
# @return [void]
|
|
103
103
|
def render!(img, projector)
|
|
104
|
-
value =
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
end
|
|
104
|
+
value =
|
|
105
|
+
case @icon
|
|
106
|
+
when "numeric", "symbol"
|
|
107
|
+
@symbol
|
|
108
|
+
when "alphabetic"
|
|
109
|
+
(@symbol + 96).chr
|
|
110
|
+
else
|
|
111
|
+
@icon
|
|
112
|
+
end
|
|
114
113
|
|
|
115
114
|
if @icon.is_a?(GD::Image)
|
|
116
115
|
w = @icon.width
|
|
@@ -176,7 +175,7 @@ module GD
|
|
|
176
175
|
# baseline = top_y + h = y + h/2
|
|
177
176
|
text_x = (x - (w / 2.0)).round
|
|
178
177
|
text_y = (y + (h / 2.0)).round
|
|
179
|
-
|
|
178
|
+
|
|
180
179
|
# 4) Draw number
|
|
181
180
|
img.text(
|
|
182
181
|
text,
|
data/lib/gd/gis/legend.rb
CHANGED
|
@@ -1,9 +1,27 @@
|
|
|
1
|
-
# lib/
|
|
1
|
+
# lib/gd/gis/legend.rb
|
|
2
2
|
|
|
3
3
|
module GD
|
|
4
4
|
module GIS
|
|
5
5
|
LegendItem = Struct.new(:color, :label)
|
|
6
6
|
|
|
7
|
+
# Represents a map legend rendered as part of the final image.
|
|
8
|
+
#
|
|
9
|
+
# A Legend provides visual context for map elements by associating
|
|
10
|
+
# colors or symbols with human-readable labels.
|
|
11
|
+
#
|
|
12
|
+
# Legends are rendered server-side and embedded directly into the
|
|
13
|
+
# resulting map image, allowing the map to be self-explanatory
|
|
14
|
+
# without relying on external UI components.
|
|
15
|
+
#
|
|
16
|
+
# A Legend is typically created and configured via {Map#legend}
|
|
17
|
+
# and rendered automatically during the map rendering pipeline.
|
|
18
|
+
#
|
|
19
|
+
# @example Creating a legend
|
|
20
|
+
# map.legend do |l|
|
|
21
|
+
# l.add [76, 175, 80, 0], "Delivered"
|
|
22
|
+
# l.add [255, 193, 7, 0], "In transit"
|
|
23
|
+
# l.add [244, 67, 54, 0], "Delayed"
|
|
24
|
+
#
|
|
7
25
|
class Legend
|
|
8
26
|
attr_reader :items, :position
|
|
9
27
|
|
data/lib/gd/gis/map.rb
CHANGED
|
@@ -43,8 +43,6 @@ module GD
|
|
|
43
43
|
# @return [Boolean] enables debug rendering
|
|
44
44
|
attr_reader :debug
|
|
45
45
|
|
|
46
|
-
attr_reader :legend
|
|
47
|
-
|
|
48
46
|
# Creates a new map.
|
|
49
47
|
#
|
|
50
48
|
# @param bbox [Array<Float>]
|
|
@@ -72,6 +70,9 @@ module GD
|
|
|
72
70
|
crs: nil,
|
|
73
71
|
fitted_bbox: false
|
|
74
72
|
)
|
|
73
|
+
# resolve symbolic bbox
|
|
74
|
+
bbox = GD::GIS::BBoxResolver.resolve(bbox)
|
|
75
|
+
|
|
75
76
|
# 1. Basic input validation
|
|
76
77
|
raise ArgumentError, "bbox must be [min_lng, min_lat, max_lng, max_lat]" unless
|
|
77
78
|
bbox.is_a?(Array) && bbox.size == 4
|
|
@@ -131,9 +132,6 @@ module GD
|
|
|
131
132
|
@lines_layers = []
|
|
132
133
|
@polygons_layers = []
|
|
133
134
|
|
|
134
|
-
# 7. Style
|
|
135
|
-
@style = nil
|
|
136
|
-
|
|
137
135
|
@debug = false
|
|
138
136
|
@used_labels = {}
|
|
139
137
|
@count = 1
|
|
@@ -189,6 +187,7 @@ module GD
|
|
|
189
187
|
# before rendering. It intentionally does not depend on map style
|
|
190
188
|
# configuration, which is applied later during rendering.
|
|
191
189
|
def maybe_create_line_label(feature)
|
|
190
|
+
@style ||= GD::GIS::Style.default
|
|
192
191
|
return true if @style.global[:label] == false || @style.global[:label].nil?
|
|
193
192
|
|
|
194
193
|
geom = feature.geometry
|
|
@@ -214,7 +213,8 @@ module GD
|
|
|
214
213
|
label: ->(_) { name },
|
|
215
214
|
font: @style.global[:label][:font] || GD::GIS::FontHelper.random,
|
|
216
215
|
size: @style.global[:label][:size] || (6..20).to_a.sample,
|
|
217
|
-
color: @style.global[:label][:color] || GD::GIS::ColorHelpers.random_rgba
|
|
216
|
+
color: @style.global[:label][:color] || GD::GIS::ColorHelpers.random_rgba,
|
|
217
|
+
font_color: @style.global[:label][:color] || GD::GIS::ColorHelpers.random_rgba
|
|
218
218
|
)
|
|
219
219
|
|
|
220
220
|
@used_labels[key] = true
|
|
@@ -230,11 +230,13 @@ module GD
|
|
|
230
230
|
|
|
231
231
|
layers.each do |layer|
|
|
232
232
|
next unless layer.respond_to?(:color)
|
|
233
|
+
|
|
233
234
|
@legend.add(layer.color, layer.name)
|
|
234
235
|
end
|
|
235
236
|
end
|
|
236
237
|
|
|
237
238
|
def draw_legend
|
|
239
|
+
@style ||= GD::GIS::Style.default
|
|
238
240
|
return unless @legend
|
|
239
241
|
return unless @image
|
|
240
242
|
return unless @style
|
|
@@ -272,8 +274,8 @@ module GD
|
|
|
272
274
|
w
|
|
273
275
|
end
|
|
274
276
|
|
|
275
|
-
width = (text_widths.max || 0) + box_size + padding * 3
|
|
276
|
-
height = @legend.items.size * line_height + padding * 2
|
|
277
|
+
width = (text_widths.max || 0) + box_size + (padding * 3)
|
|
278
|
+
height = (@legend.items.size * line_height) + (padding * 2)
|
|
277
279
|
|
|
278
280
|
# --- position --------------------------------------------
|
|
279
281
|
|
|
@@ -285,8 +287,6 @@ module GD
|
|
|
285
287
|
[margin, @image.height - height - margin]
|
|
286
288
|
when :top_right
|
|
287
289
|
[@image.width - width - margin, margin]
|
|
288
|
-
when :top_left
|
|
289
|
-
[margin, margin]
|
|
290
290
|
else
|
|
291
291
|
[margin, margin]
|
|
292
292
|
end
|
|
@@ -302,7 +302,7 @@ module GD
|
|
|
302
302
|
# --- items -----------------------------------------------
|
|
303
303
|
|
|
304
304
|
@legend.items.each_with_index do |item, idx|
|
|
305
|
-
iy = y + padding + idx * line_height
|
|
305
|
+
iy = y + padding + (idx * line_height)
|
|
306
306
|
|
|
307
307
|
# color box
|
|
308
308
|
@image.filled_rectangle(
|
|
@@ -335,6 +335,7 @@ module GD
|
|
|
335
335
|
# @param path [String] path to GeoJSON file
|
|
336
336
|
# @return [void]
|
|
337
337
|
def add_geojson(path)
|
|
338
|
+
@style ||= GD::GIS::Style.default
|
|
338
339
|
features = LayerGeoJSON.load(path)
|
|
339
340
|
|
|
340
341
|
features.each do |feature|
|
|
@@ -482,12 +483,14 @@ module GD
|
|
|
482
483
|
label: label
|
|
483
484
|
}
|
|
484
485
|
|
|
486
|
+
@style ||= GD::GIS::Style.default
|
|
487
|
+
|
|
485
488
|
@points_layers << GD::GIS::PointsLayer.new(
|
|
486
489
|
[row],
|
|
487
|
-
lon: ->
|
|
488
|
-
lat: ->
|
|
490
|
+
lon: ->(r) { r[:lon] },
|
|
491
|
+
lat: ->(r) { r[:lat] },
|
|
489
492
|
icon: icon || @style.point[:icon],
|
|
490
|
-
label: label ? ->
|
|
493
|
+
label: label ? ->(r) { r[:label] } : nil,
|
|
491
494
|
font: font || @style.point[:font],
|
|
492
495
|
size: size || @style.point[:size],
|
|
493
496
|
color: color || @style.point[:color],
|
|
@@ -502,6 +505,7 @@ module GD
|
|
|
502
505
|
# @param opts [Hash]
|
|
503
506
|
# @return [void]
|
|
504
507
|
def add_points(data, **)
|
|
508
|
+
@style ||= GD::GIS::Style.default
|
|
505
509
|
@points_layers << GD::GIS::PointsLayer.new(data, **)
|
|
506
510
|
end
|
|
507
511
|
|
|
@@ -511,6 +515,7 @@ module GD
|
|
|
511
515
|
# @param opts [Hash]
|
|
512
516
|
# @return [void]
|
|
513
517
|
def add_lines(features, **)
|
|
518
|
+
@style ||= GD::GIS::Style.default
|
|
514
519
|
@lines_layers << GD::GIS::LinesLayer.new(features, **)
|
|
515
520
|
end
|
|
516
521
|
|
|
@@ -520,6 +525,7 @@ module GD
|
|
|
520
525
|
# @param opts [Hash]
|
|
521
526
|
# @return [void]
|
|
522
527
|
def add_polygons(polygons, **)
|
|
528
|
+
@style ||= GD::GIS::Style.default
|
|
523
529
|
@polygons_layers << GD::GIS::PolygonsLayer.new(polygons, **)
|
|
524
530
|
end
|
|
525
531
|
|
|
@@ -531,6 +537,7 @@ module GD
|
|
|
531
537
|
# @return [void]
|
|
532
538
|
# @raise [RuntimeError] if style is not set
|
|
533
539
|
def render
|
|
540
|
+
# Style assign DEFAULT Styles
|
|
534
541
|
raise "map.style must be set" unless @style
|
|
535
542
|
|
|
536
543
|
if @width && @height
|
|
@@ -585,7 +592,7 @@ module GD
|
|
|
585
592
|
@polygons_layers.each { |l| l.render!(@image, projection) }
|
|
586
593
|
@lines_layers.each { |l| l.render!(@image, projection) }
|
|
587
594
|
@points_layers.each { |l| l.render!(@image, projection) }
|
|
588
|
-
|
|
595
|
+
|
|
589
596
|
draw_legend
|
|
590
597
|
end
|
|
591
598
|
|
|
@@ -646,7 +653,7 @@ module GD
|
|
|
646
653
|
@polygons_layers.each { |l| l.render!(@image, projection) }
|
|
647
654
|
@lines_layers.each { |l| l.render!(@image, projection) }
|
|
648
655
|
@points_layers.each { |l| l.render!(@image, projection) }
|
|
649
|
-
|
|
656
|
+
|
|
650
657
|
draw_legend
|
|
651
658
|
end
|
|
652
659
|
|
data/lib/gd/gis/style.rb
CHANGED
|
@@ -110,6 +110,80 @@ module GD
|
|
|
110
110
|
end
|
|
111
111
|
end
|
|
112
112
|
|
|
113
|
+
# Returns a built-in default style so Map can render even if no external style is set.
|
|
114
|
+
#
|
|
115
|
+
# @return [Style]
|
|
116
|
+
def self.default
|
|
117
|
+
new({
|
|
118
|
+
global: {
|
|
119
|
+
background: [15, 23, 42],
|
|
120
|
+
font: GD::GIS::FontHelper.find("DejaVuSans"),
|
|
121
|
+
font_color: [243, 244, 246],
|
|
122
|
+
label: {
|
|
123
|
+
color: [229, 231, 235],
|
|
124
|
+
font: GD::GIS::FontHelper.find("DejaVuSans"),
|
|
125
|
+
size: 12
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
|
|
129
|
+
label: {
|
|
130
|
+
label: { # ← envolver
|
|
131
|
+
color: [229, 231, 235],
|
|
132
|
+
font: GD::GIS::FontHelper.find("DejaVuSans"),
|
|
133
|
+
size: 12
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
|
|
137
|
+
roads: {
|
|
138
|
+
roads: { # ← envolver
|
|
139
|
+
color: [229, 231, 235],
|
|
140
|
+
font: GD::GIS::FontHelper.find("DejaVuSans"),
|
|
141
|
+
width: 6
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
|
|
145
|
+
rails: {
|
|
146
|
+
rails: {
|
|
147
|
+
color: [156, 163, 175],
|
|
148
|
+
font: GD::GIS::FontHelper.find("DejaVuSans"),
|
|
149
|
+
width: 5
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
|
|
153
|
+
water: {
|
|
154
|
+
water: {
|
|
155
|
+
color: [59, 130, 246]
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
|
|
159
|
+
parks: {
|
|
160
|
+
parks: {
|
|
161
|
+
color: [34, 197, 94]
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
|
|
165
|
+
points: {
|
|
166
|
+
points: {
|
|
167
|
+
color: [239, 68, 68],
|
|
168
|
+
radius: 4,
|
|
169
|
+
font: GD::GIS::FontHelper.find("DejaVuSans"),
|
|
170
|
+
font_color: [243, 244, 246]
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
|
|
174
|
+
track: {
|
|
175
|
+
track: { # ← CLAVE
|
|
176
|
+
stroke: [0, 85, 127, 250],
|
|
177
|
+
color: [250, 204, 21],
|
|
178
|
+
width: 2,
|
|
179
|
+
font_color: [243, 244, 246]
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
|
|
183
|
+
order: %i[water parks rails roads points track]
|
|
184
|
+
})
|
|
185
|
+
end
|
|
186
|
+
|
|
113
187
|
# Normalizes a color definition into a GD::Color.
|
|
114
188
|
#
|
|
115
189
|
# Accepted formats:
|
data/lib/gd/gis.rb
CHANGED
|
@@ -29,9 +29,11 @@ require "gd"
|
|
|
29
29
|
#
|
|
30
30
|
require_relative "gis/color_helpers"
|
|
31
31
|
require_relative "gis/font_helper"
|
|
32
|
-
require_relative "gis/style"
|
|
33
32
|
require_relative "gis/classifier"
|
|
33
|
+
require_relative "gis/style"
|
|
34
34
|
|
|
35
|
+
require_relative "gis/extents"
|
|
36
|
+
require_relative "gis/bbox_resolver"
|
|
35
37
|
require_relative "gis/feature"
|
|
36
38
|
require_relative "gis/map"
|
|
37
39
|
require_relative "gis/basemap"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: libgd-gis
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.4.
|
|
4
|
+
version: 0.4.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Germán Alberto Giménez Silva
|
|
@@ -40,9 +40,12 @@ files:
|
|
|
40
40
|
- README.md
|
|
41
41
|
- lib/gd/gis.rb
|
|
42
42
|
- lib/gd/gis/basemap.rb
|
|
43
|
+
- lib/gd/gis/bbox_resolver.rb
|
|
43
44
|
- lib/gd/gis/classifier.rb
|
|
44
45
|
- lib/gd/gis/color_helpers.rb
|
|
45
46
|
- lib/gd/gis/crs_normalizer.rb
|
|
47
|
+
- lib/gd/gis/data/extents_global.json
|
|
48
|
+
- lib/gd/gis/extents.rb
|
|
46
49
|
- lib/gd/gis/feature.rb
|
|
47
50
|
- lib/gd/gis/font_helper.rb
|
|
48
51
|
- lib/gd/gis/geometry.rb
|