libgd-gis 0.4.1 → 0.4.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ff2a73817209bdd6e71f77b83cd0f7ffaee27327e95c199e01bf9eb879b2ff53
4
- data.tar.gz: d5fe87d75561eba31a1cae4c46902a16dfcd9a70b525f8d6772682f05f1f9c56
3
+ metadata.gz: fa4dd3c210385e6b89998eeccbc88c4e82d5c45b6081be260b98843b4bd01124
4
+ data.tar.gz: c0e6f00da6d017e7d30f8ccc6c14b4a16ee3a5e7799d5cbf8c4a4b72b137bde6
5
5
  SHA512:
6
- metadata.gz: a9e41b51e0e1365eb60905131e2766981de954d74b92b16ba8abb45224e3c6df9215a96628cf23f7c90c6675d2acf98dbafe326c569ee45440dcedd1502f5d7d
7
- data.tar.gz: d2598e4392ee4c400a0cf2982d91916119222f9ec4dd869b4851d0b994a0a241f39ef483e720d66121fd070af3b4ba5c46068d2194d8a09b9ed4b61cfa259192
6
+ metadata.gz: fd5c30cbcdae3f214a9f0fb9605edd1244ca161774fc6e60fabcff70688b9b3712bc7444be326fd88c5517d470bfa8c06d8bc0522ca470edc86e5608235a26e9
7
+ data.tar.gz: 1cfd799c2c1abfb457ad761de7b293a97b5f880ddd55cd4e02298820c91f344977ee176abf8d7da9b77594247a1c8c1a1f34db951f69f15ff00ed7748d3c4da5
@@ -0,0 +1,27 @@
1
+ module GD
2
+ module GIS
3
+ module BBoxResolver
4
+ def self.resolve(bbox)
5
+ case bbox
6
+ when Symbol, String
7
+ Extents.fetch(bbox)
8
+
9
+ when Array
10
+ validate!(bbox)
11
+ bbox.map(&:to_f)
12
+
13
+ else
14
+ raise ArgumentError,
15
+ "bbox must be Symbol, String or [min_lng, min_lat, max_lng, max_lat]"
16
+ end
17
+ end
18
+
19
+ def self.validate!(bbox)
20
+ unless bbox.is_a?(Array) && bbox.size == 4
21
+ raise ArgumentError,
22
+ "bbox must be [min_lng, min_lat, max_lng, max_lat]"
23
+ end
24
+ end
25
+ end
26
+ end
27
+ 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,39 @@
1
+ require "json"
2
+
3
+ module GD
4
+ module GIS
5
+ module Extents
6
+ DATA_PATH = File.expand_path(
7
+ "data/extents_global.json",
8
+ __dir__
9
+ )
10
+
11
+ @extents = nil
12
+
13
+ class << self
14
+ def fetch(name)
15
+ load_data!
16
+ @extents.fetch(name.to_s.downcase) do
17
+ raise ArgumentError, "Unknown extent: #{name}"
18
+ end
19
+ end
20
+
21
+ def [](name)
22
+ fetch(name)
23
+ end
24
+
25
+ def all
26
+ load_data!
27
+ @extents.keys.map(&:to_sym)
28
+ end
29
+
30
+ private
31
+
32
+ def load_data!
33
+ return if @extents
34
+ @extents = JSON.parse(File.read(DATA_PATH))
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -101,16 +101,15 @@ module GD
101
101
  #
102
102
  # @return [void]
103
103
  def render!(img, projector)
104
- value = case @icon
105
- when "numeric"
106
- @symbol
107
- when "alphabetic"
108
- (@symbol + 96).chr
109
- when "symbol"
110
- @symbol
111
- else
112
- @icon
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/libgd/gis/legend.rb
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
@@ -230,6 +231,7 @@ module GD
230
231
 
231
232
  layers.each do |layer|
232
233
  next unless layer.respond_to?(:color)
234
+
233
235
  @legend.add(layer.color, layer.name)
234
236
  end
235
237
  end
@@ -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(
@@ -484,10 +484,10 @@ module GD
484
484
 
485
485
  @points_layers << GD::GIS::PointsLayer.new(
486
486
  [row],
487
- lon: -> r { r[:lon] },
488
- lat: -> r { r[:lat] },
487
+ lon: ->(r) { r[:lon] },
488
+ lat: ->(r) { r[:lat] },
489
489
  icon: icon || @style.point[:icon],
490
- label: label ? -> r { r[:label] } : nil,
490
+ label: label ? ->(r) { r[:label] } : nil,
491
491
  font: font || @style.point[:font],
492
492
  size: size || @style.point[:size],
493
493
  color: color || @style.point[:color],
@@ -585,7 +585,7 @@ module GD
585
585
  @polygons_layers.each { |l| l.render!(@image, projection) }
586
586
  @lines_layers.each { |l| l.render!(@image, projection) }
587
587
  @points_layers.each { |l| l.render!(@image, projection) }
588
-
588
+
589
589
  draw_legend
590
590
  end
591
591
 
@@ -646,7 +646,7 @@ module GD
646
646
  @polygons_layers.each { |l| l.render!(@image, projection) }
647
647
  @lines_layers.each { |l| l.render!(@image, projection) }
648
648
  @points_layers.each { |l| l.render!(@image, projection) }
649
-
649
+
650
650
  draw_legend
651
651
  end
652
652
 
data/lib/gd/gis.rb CHANGED
@@ -32,6 +32,9 @@ require_relative "gis/font_helper"
32
32
  require_relative "gis/style"
33
33
  require_relative "gis/classifier"
34
34
 
35
+ require_relative "gis/extents"
36
+ require_relative "gis/bbox_resolver"
37
+
35
38
  require_relative "gis/feature"
36
39
  require_relative "gis/map"
37
40
  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.1
4
+ version: 0.4.2
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