libgd-gis 0.4.2 → 0.4.4

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: fa4dd3c210385e6b89998eeccbc88c4e82d5c45b6081be260b98843b4bd01124
4
- data.tar.gz: c0e6f00da6d017e7d30f8ccc6c14b4a16ee3a5e7799d5cbf8c4a4b72b137bde6
3
+ metadata.gz: 12f001e0a04fd6daa74954df04a6e9a7fb0c96125dcc4abc9d86ad47e2b88c7f
4
+ data.tar.gz: 691682c8ba0207ab1e57f6e47b42aca5f352e99674090b0fb88082d9a01252b1
5
5
  SHA512:
6
- metadata.gz: fd5c30cbcdae3f214a9f0fb9605edd1244ca161774fc6e60fabcff70688b9b3712bc7444be326fd88c5517d470bfa8c06d8bc0522ca470edc86e5608235a26e9
7
- data.tar.gz: 1cfd799c2c1abfb457ad761de7b293a97b5f880ddd55cd4e02298820c91f344977ee176abf8d7da9b77594247a1c8c1a1f34db951f69f15ff00ed7748d3c4da5
6
+ metadata.gz: 7c211ae32a88b7c012ac235a4d00cf03b195074ebfd9a8140f2661368e0515125366e81c576f2d7e277eb38ab56f20e44c484fac8fcf44fb3ce44053d627e146
7
+ data.tar.gz: 245b629a1c2729a7e43d09a47c9e5833e3032699ca4d2b80479d19b9dfc44f4d14eb16261d2c0a113794ffea3e1eff029aa9cb1ed314e9e6f887c5fa16de28d9
data/README.md CHANGED
@@ -27,7 +27,6 @@
27
27
  <p align="right">
28
28
  <img src="docs/images/logo-gis.png" width="160" />
29
29
  </p>
30
-
31
30
  ![CI](https://github.com/ggerman/libgd-gis/actions/workflows/ci.yml/badge.svg)
32
31
  [![Codacy Badge](https://api.codacy.com/project/badge/Grade/6bc3e7d6118d47e6959b16690b815909)](https://www.codacy.com/app/libgd-gis/libgd-gis?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=libgd-gis/libgd-gis&amp;utm_campaign=Badge_Grade)
33
32
  [![Test Coverage](https://coveralls.io/repos/githublibgd-gis/libgd-gis/badge.svg?branch=master)](https://coveralls.io/github/libgd-gis/libgd-gis?branch=master)
@@ -35,16 +34,46 @@
35
34
 
36
35
  ---
37
36
 
38
- **libgd-gis** is a lightweight Ruby GIS rendering library built on top of **GD**.
39
- It renders geographic data (GeoJSON, points, lines, polygons) into raster images using Web Mercator tiles and a simple, explicit rendering pipeline.
37
+ **libgd-gis** is a A native map rendering engine for Ruby built on **libgd**.
38
+
39
+ It allows developers to generate maps, tiles, and heatmaps directly from GeoJSON using the libgd raster engine — without external services.
40
+
41
+ ---
42
+
43
+ ## Use Cases
44
+
45
+ libgd-gis is useful for:
40
46
 
41
- This library is designed for **map visualization**, not for spatial analysis.
47
+ - Generating static maps for Rails applications
48
+ - Rendering GeoJSON data to PNG images
49
+ - Creating heatmaps and geographic visualizations
50
+ - Building internal dashboards with map outputs
51
+ - Self-hosted alternatives to static map APIs
42
52
 
43
53
  ---
44
54
 
55
+ ## Example
56
+
57
+ ```ruby
58
+ map = GD::GIS::Map.new(width: 800, height: 600)
59
+
60
+ map.add_geojson("countries.geojson")
61
+ map.add_point(lat: -34.6, lon: -58.4)
62
+ map.render
63
+
64
+ map.save("map.png")
65
+ ```
66
+
67
+ ![](examples/parana/parana.png)
68
+
69
+ ---
70
+
71
+ > 🆕 **Update:** Style is no longer mandatory. Maps now render out-of-the-box using a built-in default style.
72
+
73
+ ---
45
74
  ## Features
46
75
 
47
- - Web Mercator tile rendering (OSM, CARTO, ESRI, Stamen, etc.)
76
+ - Web Mercator map and tile rendering (OSM, CARTO, ESRI, Stamen, etc.)
48
77
  - CRS normalization (CRS84, EPSG:4326, EPSG:3857, Gauss–Krüger Argentina)
49
78
  - Layered rendering pipeline
50
79
  - YAML-based styling
@@ -54,20 +83,6 @@ This library is designed for **map visualization**, not for spatial analysis.
54
83
 
55
84
  ---
56
85
 
57
- ## Non-Goals
58
-
59
- libgd-gis intentionally does **not** aim to be:
60
-
61
- - a spatial analysis engine
62
- - a replacement for PostGIS / GEOS
63
- - a full map server
64
- - a vector tile generator
65
-
66
- If you need projections beyond Web Mercator or topological correctness,
67
- use a full GIS stack.
68
-
69
- ---
70
-
71
86
  ## Installation
72
87
 
73
88
  Add to your Gemfile:
@@ -124,19 +139,6 @@ map.save("map.png")
124
139
 
125
140
  ---
126
141
 
127
- ## Styles Are Mandatory
128
-
129
- libgd-gis requires an explicit **style definition** in order to render a map.
130
-
131
- A `GD::GIS::Map` instance **will not render without a style**, and calling
132
- `map.render` before assigning one will raise an error.
133
-
134
- This is intentional.
135
-
136
- Styles define how semantic layers (roads, water, parks, points, etc.) are mapped
137
- to visual properties such as colors, stroke widths, fills, and drawing order.
138
- No implicit or default styling is applied.
139
-
140
142
  ### Example:
141
143
 
142
144
  ```ruby
@@ -201,6 +203,39 @@ order:
201
203
  This design ensures predictable rendering and makes all visual decisions explicit
202
204
  and reproducible.
203
205
 
206
+ ![](examples/paris/paris.png)
207
+
208
+
209
+ ---
210
+
211
+
212
+ ## Named geographic extents
213
+
214
+ LibGD-GIS includes a global dataset of predefined geographic areas.
215
+ You can use them directly as the `bbox` parameter.
216
+
217
+ ![](examples/legend/example_parana_polaroid.png)
218
+
219
+ ### Example
220
+
221
+ ```ruby
222
+ map = GD::GIS::Map.new(
223
+ bbox: :argentina,
224
+ zoom: 5,
225
+ width: 800,
226
+ height: 600,
227
+ basemap: :osm
228
+ )
229
+ ```
230
+ You can also use continents or regions:
231
+
232
+ ```
233
+ bbox: :world
234
+ bbox: :europe
235
+ bbox: :south_america
236
+ bbox: :north_america
237
+ bbox: :asia
238
+ ```
204
239
 
205
240
  ---
206
241
 
@@ -1,5 +1,20 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module GD
2
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])
3
18
  module BBoxResolver
4
19
  def self.resolve(bbox)
5
20
  case bbox
@@ -12,16 +27,16 @@ module GD
12
27
 
13
28
  else
14
29
  raise ArgumentError,
15
- "bbox must be Symbol, String or [min_lng, min_lat, max_lng, max_lat]"
30
+ "bbox must be Symbol, String or [min_lng, min_lat, max_lng, max_lat]"
16
31
  end
17
32
  end
18
33
 
19
34
  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
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]"
24
39
  end
25
40
  end
26
41
  end
27
- end
42
+ end
@@ -1,7 +1,24 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "json"
2
4
 
3
5
  module GD
4
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.
5
22
  module Extents
6
23
  DATA_PATH = File.expand_path(
7
24
  "data/extents_global.json",
@@ -31,9 +48,10 @@ module GD
31
48
 
32
49
  def load_data!
33
50
  return if @extents
51
+
34
52
  @extents = JSON.parse(File.read(DATA_PATH))
35
53
  end
36
54
  end
37
55
  end
38
56
  end
39
- end
57
+ end
data/lib/gd/gis/map.rb CHANGED
@@ -132,9 +132,6 @@ module GD
132
132
  @lines_layers = []
133
133
  @polygons_layers = []
134
134
 
135
- # 7. Style
136
- @style = nil
137
-
138
135
  @debug = false
139
136
  @used_labels = {}
140
137
  @count = 1
@@ -190,6 +187,7 @@ module GD
190
187
  # before rendering. It intentionally does not depend on map style
191
188
  # configuration, which is applied later during rendering.
192
189
  def maybe_create_line_label(feature)
190
+ @style ||= GD::GIS::Style.default
193
191
  return true if @style.global[:label] == false || @style.global[:label].nil?
194
192
 
195
193
  geom = feature.geometry
@@ -215,7 +213,8 @@ module GD
215
213
  label: ->(_) { name },
216
214
  font: @style.global[:label][:font] || GD::GIS::FontHelper.random,
217
215
  size: @style.global[:label][:size] || (6..20).to_a.sample,
218
- 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
219
218
  )
220
219
 
221
220
  @used_labels[key] = true
@@ -237,6 +236,7 @@ module GD
237
236
  end
238
237
 
239
238
  def draw_legend
239
+ @style ||= GD::GIS::Style.default
240
240
  return unless @legend
241
241
  return unless @image
242
242
  return unless @style
@@ -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,6 +483,8 @@ 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
490
  lon: ->(r) { r[:lon] },
@@ -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
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: {
131
+ color: [229, 231, 235],
132
+ font: GD::GIS::FontHelper.find("DejaVuSans"),
133
+ size: 12
134
+ }
135
+ },
136
+
137
+ roads: {
138
+ roads: {
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: {
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,12 +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
35
  require_relative "gis/extents"
36
36
  require_relative "gis/bbox_resolver"
37
-
38
37
  require_relative "gis/feature"
39
38
  require_relative "gis/map"
40
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.2
4
+ version: 0.4.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Germán Alberto Giménez Silva