libgd-gis 0.3.0 → 0.3.1
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/lib/gd/gis/font_helper.rb +59 -0
- data/lib/gd/gis/layer_points.rb +3 -2
- data/lib/gd/gis/map.rb +48 -17
- data/lib/gd/gis/ontology.yml +1 -2
- data/lib/gd/gis/style.rb +11 -1
- data/lib/test.rb +4 -0
- metadata +6 -35
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: adcbc0b0d92182bc12b431152cb1f79b202786ef999e3571f42c9ec27e999561
|
|
4
|
+
data.tar.gz: 50cb494d8e9b2fdf94f9ac126c22f14cb39335c4f1d0289df554f88159b5d389
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 704ce58b27ab6ea1096390ad63daa926627f8b4d6b2a7613a0517949129d66850bac74f7860d090b4fd3a8aeb2c1ec58148b6cddce35e6e5a5d90d72e866e2e9
|
|
7
|
+
data.tar.gz: eb62734dbf1d2168918e958ac4a432ea621eb263c9c17e1f36dad7f9f008e9a3e4499eaa3767daad5f8291017c2d316731cab2c3df3873c47c99c251c7d7ba69
|
data/lib/gd/gis/font_helper.rb
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
module GD
|
|
2
2
|
module GIS
|
|
3
|
+
# Provides helper methods for discovering and selecting font files
|
|
4
|
+
# available on the local system.
|
|
5
|
+
#
|
|
6
|
+
# This module is primarily used to supply font paths to text-rendering
|
|
7
|
+
# components (such as PointsLayer labels) in environments where font
|
|
8
|
+
# availability is system-dependent.
|
|
9
|
+
#
|
|
10
|
+
# Font discovery is performed by scanning a set of well-known directories
|
|
11
|
+
# for TrueType and OpenType font files. The results are cached for the
|
|
12
|
+
# lifetime of the process.
|
|
13
|
+
#
|
|
14
|
+
# Supported font formats:
|
|
15
|
+
# - TrueType (.ttf)
|
|
16
|
+
# - OpenType (.otf)
|
|
17
|
+
# - TrueType Collection (.ttc)
|
|
18
|
+
#
|
|
19
|
+
# @example Select a random system font
|
|
20
|
+
# font_path = GD::GIS::FontHelper.random
|
|
21
|
+
#
|
|
22
|
+
# @example Find a font by name fragment
|
|
23
|
+
# font_path = GD::GIS::FontHelper.find("Noto")
|
|
24
|
+
#
|
|
25
|
+
# @note
|
|
26
|
+
# This helper does not validate glyph coverage (e.g. CJK support).
|
|
27
|
+
# It only locates font files present on the system.
|
|
3
28
|
module FontHelper
|
|
4
29
|
PATHS = [
|
|
5
30
|
"/usr/share/fonts",
|
|
@@ -9,6 +34,16 @@ module GD
|
|
|
9
34
|
|
|
10
35
|
EXTENSIONS = %w[ttf otf ttc].freeze
|
|
11
36
|
|
|
37
|
+
# Returns the list of all font files discovered on the system.
|
|
38
|
+
#
|
|
39
|
+
# The search is performed once and cached. Subsequent calls return
|
|
40
|
+
# the cached result.
|
|
41
|
+
#
|
|
42
|
+
# Font files are discovered by recursively scanning the directories
|
|
43
|
+
# defined in {PATHS} for files matching the extensions in {EXTENSIONS}.
|
|
44
|
+
#
|
|
45
|
+
# @return [Array<String>]
|
|
46
|
+
# An array of absolute file paths to font files.
|
|
12
47
|
def self.all
|
|
13
48
|
@all ||= PATHS.flat_map do |path|
|
|
14
49
|
next [] unless Dir.exist?(path)
|
|
@@ -19,10 +54,34 @@ module GD
|
|
|
19
54
|
end.compact.uniq
|
|
20
55
|
end
|
|
21
56
|
|
|
57
|
+
# Returns a randomly selected font file from the system.
|
|
58
|
+
#
|
|
59
|
+
# This is primarily intended as a fallback mechanism when no explicit
|
|
60
|
+
# font is configured by the caller.
|
|
61
|
+
#
|
|
62
|
+
# @return [String]
|
|
63
|
+
# Absolute path to a font file.
|
|
64
|
+
#
|
|
65
|
+
# @raise [RuntimeError]
|
|
66
|
+
# If no font files are found on the system.
|
|
67
|
+
#
|
|
68
|
+
# @note
|
|
69
|
+
# The selected font is not guaranteed to support any particular
|
|
70
|
+
# character set.
|
|
22
71
|
def self.random
|
|
23
72
|
all.sample or raise "GD::GIS::FontHelper: no fonts found on system"
|
|
24
73
|
end
|
|
25
74
|
|
|
75
|
+
# Finds a font file whose filename includes the given name fragment.
|
|
76
|
+
#
|
|
77
|
+
# The match is case-insensitive and performed against the basename
|
|
78
|
+
# of each discovered font file.
|
|
79
|
+
#
|
|
80
|
+
# @param name [String]
|
|
81
|
+
# A substring to search for in font filenames (e.g. "Noto", "DejaVu").
|
|
82
|
+
#
|
|
83
|
+
# @return [String, nil]
|
|
84
|
+
# The path to the first matching font file, or nil if no match is found.
|
|
26
85
|
def self.find(name)
|
|
27
86
|
all.find do |f|
|
|
28
87
|
File.basename(f).downcase.include?(name.downcase)
|
data/lib/gd/gis/layer_points.rb
CHANGED
|
@@ -54,7 +54,8 @@ module GD
|
|
|
54
54
|
@label = label
|
|
55
55
|
@font = font
|
|
56
56
|
@size = size
|
|
57
|
-
@
|
|
57
|
+
@r, @g, @b, @a = color
|
|
58
|
+
@a = 0 if @a.nil?
|
|
58
59
|
|
|
59
60
|
@icon.alpha_blending = true
|
|
60
61
|
@icon.save_alpha = true
|
|
@@ -116,7 +117,7 @@ module GD
|
|
|
116
117
|
x: x + (w / 2) + 4,
|
|
117
118
|
y: y + (font_h / 2),
|
|
118
119
|
size: @size,
|
|
119
|
-
color: @
|
|
120
|
+
color: GD::Color.rgba(@r, @g, @b, @a),
|
|
120
121
|
font: @font)
|
|
121
122
|
end
|
|
122
123
|
end
|
data/lib/gd/gis/map.rb
CHANGED
|
@@ -113,6 +113,7 @@ module GD
|
|
|
113
113
|
primary: [],
|
|
114
114
|
secondary: [],
|
|
115
115
|
street: [],
|
|
116
|
+
track: [],
|
|
116
117
|
minor: [],
|
|
117
118
|
rail: [],
|
|
118
119
|
water: [],
|
|
@@ -155,7 +156,37 @@ module GD
|
|
|
155
156
|
end
|
|
156
157
|
end
|
|
157
158
|
|
|
159
|
+
# Creates a single text label for a named linear feature (LineString or
|
|
160
|
+
# MultiLineString), avoiding duplicate labels for the same named entity.
|
|
161
|
+
#
|
|
162
|
+
# Many datasets (especially OSM) split a single logical entity
|
|
163
|
+
# (rivers, streets, railways, etc.) into multiple line features that
|
|
164
|
+
# all share the same name. This method ensures that:
|
|
165
|
+
#
|
|
166
|
+
# - Only one label is created per unique entity name
|
|
167
|
+
# - The label is placed on a representative segment of the geometry
|
|
168
|
+
# - The logic is independent of the feature's semantic layer (water, road, rail)
|
|
169
|
+
#
|
|
170
|
+
# Labels are rendered using a PointsLayer because libgd-gis does not
|
|
171
|
+
# support text rendering directly on line geometries.
|
|
172
|
+
#
|
|
173
|
+
# The label position is chosen as the midpoint of the line coordinates.
|
|
174
|
+
# This is a simple heuristic that provides a reasonable placement without
|
|
175
|
+
# requiring geometry merging or topological analysis.
|
|
176
|
+
#
|
|
177
|
+
# @param feature [GD::GIS::Feature]
|
|
178
|
+
# A feature with a linear geometry and a "name" property.
|
|
179
|
+
#
|
|
180
|
+
# @return [void]
|
|
181
|
+
# Adds a PointsLayer to @points_layers if a label is created.
|
|
182
|
+
#
|
|
183
|
+
# @note
|
|
184
|
+
# This method must be called during feature loading (add_geojson),
|
|
185
|
+
# before rendering. It intentionally does not depend on map style
|
|
186
|
+
# configuration, which is applied later during rendering.
|
|
158
187
|
def maybe_create_line_label(feature)
|
|
188
|
+
return true if @style.global[:label] == false || @style.global[:label].nil?
|
|
189
|
+
|
|
159
190
|
geom = feature.geometry
|
|
160
191
|
return unless LINE_GEOMS.include?(geom["type"])
|
|
161
192
|
|
|
@@ -171,17 +202,15 @@ module GD
|
|
|
171
202
|
|
|
172
203
|
lon, lat = coords[coords.size / 2]
|
|
173
204
|
|
|
174
|
-
puts @style
|
|
175
|
-
|
|
176
205
|
@points_layers << GD::GIS::PointsLayer.new(
|
|
177
206
|
[feature],
|
|
178
207
|
lon: ->(_) { lon },
|
|
179
208
|
lat: ->(_) { lat },
|
|
180
|
-
|
|
209
|
+
icon: @style.global[:label][:icon],
|
|
181
210
|
label: ->(_) { name },
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
211
|
+
font: @style.global[:label][:font] || GD::GIS::FontHelper.random,
|
|
212
|
+
size: @style.global[:label][:size] || (6..20).to_a.sample,
|
|
213
|
+
color: @style.global[:label][:color] || GD::GIS::ColorHelpers.random_rgba
|
|
185
214
|
)
|
|
186
215
|
|
|
187
216
|
@used_labels[key] = true
|
|
@@ -207,7 +236,7 @@ module GD
|
|
|
207
236
|
kind =
|
|
208
237
|
case (feature.properties["objeto"] || feature.properties["waterway"]).to_s.downcase
|
|
209
238
|
when /river|río|canal/ then :river
|
|
210
|
-
when /stream|arroyo/
|
|
239
|
+
when /stream|arroyo/ then :stream
|
|
211
240
|
else :minor
|
|
212
241
|
end
|
|
213
242
|
|
|
@@ -220,9 +249,7 @@ module GD
|
|
|
220
249
|
@layers[:park] << feature
|
|
221
250
|
|
|
222
251
|
when :track
|
|
223
|
-
|
|
224
|
-
@layers[:minor] << feature
|
|
225
|
-
# o @layers[:street] << feature
|
|
252
|
+
@layers[:track] << feature
|
|
226
253
|
else
|
|
227
254
|
geom_type = feature.geometry["type"]
|
|
228
255
|
|
|
@@ -272,8 +299,8 @@ module GD
|
|
|
272
299
|
# @param data [Enumerable]
|
|
273
300
|
# @param opts [Hash]
|
|
274
301
|
# @return [void]
|
|
275
|
-
def add_points(data, **
|
|
276
|
-
@points_layers << GD::GIS::PointsLayer.new(data, **
|
|
302
|
+
def add_points(data, **)
|
|
303
|
+
@points_layers << GD::GIS::PointsLayer.new(data, **)
|
|
277
304
|
end
|
|
278
305
|
|
|
279
306
|
# Adds a generic lines overlay layer.
|
|
@@ -281,8 +308,8 @@ module GD
|
|
|
281
308
|
# @param features [Array]
|
|
282
309
|
# @param opts [Hash]
|
|
283
310
|
# @return [void]
|
|
284
|
-
def add_lines(features, **
|
|
285
|
-
@lines_layers << GD::GIS::LinesLayer.new(features, **
|
|
311
|
+
def add_lines(features, **)
|
|
312
|
+
@lines_layers << GD::GIS::LinesLayer.new(features, **)
|
|
286
313
|
end
|
|
287
314
|
|
|
288
315
|
# Adds a generic polygons overlay layer.
|
|
@@ -290,8 +317,8 @@ module GD
|
|
|
290
317
|
# @param polygons [Array]
|
|
291
318
|
# @param opts [Hash]
|
|
292
319
|
# @return [void]
|
|
293
|
-
def add_polygons(polygons, **
|
|
294
|
-
@polygons_layers << GD::GIS::PolygonsLayer.new(polygons, **
|
|
320
|
+
def add_polygons(polygons, **)
|
|
321
|
+
@polygons_layers << GD::GIS::PolygonsLayer.new(polygons, **)
|
|
295
322
|
end
|
|
296
323
|
|
|
297
324
|
# Renders the map.
|
|
@@ -438,6 +465,8 @@ module GD
|
|
|
438
465
|
case kind
|
|
439
466
|
when :street, :primary, :motorway, :secondary, :minor
|
|
440
467
|
@style.roads[kind]
|
|
468
|
+
when :track
|
|
469
|
+
@style.track[kind]
|
|
441
470
|
when :rail
|
|
442
471
|
@style.rails
|
|
443
472
|
when :water
|
|
@@ -475,7 +504,9 @@ module GD
|
|
|
475
504
|
if POLY_GEOMS.include?(geom)
|
|
476
505
|
f.draw(@image, projection, nil, nil, style)
|
|
477
506
|
elsif style[:stroke]
|
|
478
|
-
|
|
507
|
+
r, g, b, a = style[:stroke]
|
|
508
|
+
a = 0 if a.nil?
|
|
509
|
+
color = GD::Color.rgba(r, g, b, a)
|
|
479
510
|
|
|
480
511
|
color = GD::GIS::ColorHelpers.random_vivid if @debug
|
|
481
512
|
|
data/lib/gd/gis/ontology.yml
CHANGED
data/lib/gd/gis/style.rb
CHANGED
|
@@ -14,6 +14,9 @@ module GD
|
|
|
14
14
|
# to a {GD::GIS::Map} instance before rendering.
|
|
15
15
|
#
|
|
16
16
|
class Style
|
|
17
|
+
# @return [Hash] global styling rules
|
|
18
|
+
attr_reader :global
|
|
19
|
+
|
|
17
20
|
# @return [Hash] road styling rules
|
|
18
21
|
attr_reader :roads
|
|
19
22
|
|
|
@@ -29,6 +32,9 @@ module GD
|
|
|
29
32
|
# @return [Hash] point styling rules
|
|
30
33
|
attr_reader :points
|
|
31
34
|
|
|
35
|
+
# @return [Hash] track styling rules
|
|
36
|
+
attr_reader :track
|
|
37
|
+
|
|
32
38
|
# @return [Array<Symbol>] drawing order of semantic layers
|
|
33
39
|
attr_reader :order
|
|
34
40
|
|
|
@@ -36,13 +42,15 @@ module GD
|
|
|
36
42
|
#
|
|
37
43
|
# @param definition [Hash]
|
|
38
44
|
# style definition with optional sections:
|
|
39
|
-
# :roads, :rails, :water, :parks, :points, :order
|
|
45
|
+
# :global, :roads, :rails, :water, :parks, :points, :order, :track
|
|
40
46
|
def initialize(definition)
|
|
47
|
+
@global = definition[:global] || {}
|
|
41
48
|
@roads = definition[:roads] || {}
|
|
42
49
|
@rails = definition[:rails] || {}
|
|
43
50
|
@water = definition[:water] || {}
|
|
44
51
|
@parks = definition[:parks] || {}
|
|
45
52
|
@points = definition[:points] || {}
|
|
53
|
+
@track = definition[:track] || {}
|
|
46
54
|
@order = definition[:order] || []
|
|
47
55
|
end
|
|
48
56
|
|
|
@@ -70,8 +78,10 @@ module GD
|
|
|
70
78
|
data = deep_symbolize(data)
|
|
71
79
|
|
|
72
80
|
new(
|
|
81
|
+
global: data[:global],
|
|
73
82
|
roads: data[:roads],
|
|
74
83
|
rails: data[:rail] || data[:rails],
|
|
84
|
+
track: data[:track],
|
|
75
85
|
water: data[:water],
|
|
76
86
|
parks: data[:park] || data[:parks],
|
|
77
87
|
points: data[:points],
|
data/lib/test.rb
ADDED
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: libgd-gis
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Germán Alberto Giménez Silva
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: ruby-libgd
|
|
@@ -30,34 +29,6 @@ dependencies:
|
|
|
30
29
|
- - ">="
|
|
31
30
|
- !ruby/object:Gem::Version
|
|
32
31
|
version: 0.2.3
|
|
33
|
-
- !ruby/object:Gem::Dependency
|
|
34
|
-
name: rubocop
|
|
35
|
-
requirement: !ruby/object:Gem::Requirement
|
|
36
|
-
requirements:
|
|
37
|
-
- - "~>"
|
|
38
|
-
- !ruby/object:Gem::Version
|
|
39
|
-
version: '1.60'
|
|
40
|
-
type: :development
|
|
41
|
-
prerelease: false
|
|
42
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
43
|
-
requirements:
|
|
44
|
-
- - "~>"
|
|
45
|
-
- !ruby/object:Gem::Version
|
|
46
|
-
version: '1.60'
|
|
47
|
-
- !ruby/object:Gem::Dependency
|
|
48
|
-
name: rubocop-performance
|
|
49
|
-
requirement: !ruby/object:Gem::Requirement
|
|
50
|
-
requirements:
|
|
51
|
-
- - "~>"
|
|
52
|
-
- !ruby/object:Gem::Version
|
|
53
|
-
version: '1.20'
|
|
54
|
-
type: :development
|
|
55
|
-
prerelease: false
|
|
56
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
57
|
-
requirements:
|
|
58
|
-
- - "~>"
|
|
59
|
-
- !ruby/object:Gem::Version
|
|
60
|
-
version: '1.20'
|
|
61
32
|
description: A native GIS raster engine for Ruby built on libgd. Render maps, GeoJSON,
|
|
62
33
|
heatmaps and tiles.
|
|
63
34
|
email:
|
|
@@ -86,11 +57,12 @@ files:
|
|
|
86
57
|
- lib/gd/gis/projection.rb
|
|
87
58
|
- lib/gd/gis/style.rb
|
|
88
59
|
- lib/libgd_gis.rb
|
|
60
|
+
- lib/test.rb
|
|
89
61
|
homepage: https://github.com/ggerman/libgd-gis
|
|
90
62
|
licenses:
|
|
91
63
|
- MIT
|
|
92
|
-
metadata:
|
|
93
|
-
|
|
64
|
+
metadata:
|
|
65
|
+
rubygems_mfa_required: 'true'
|
|
94
66
|
rdoc_options: []
|
|
95
67
|
require_paths:
|
|
96
68
|
- lib
|
|
@@ -105,8 +77,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
105
77
|
- !ruby/object:Gem::Version
|
|
106
78
|
version: '0'
|
|
107
79
|
requirements: []
|
|
108
|
-
rubygems_version:
|
|
109
|
-
signing_key:
|
|
80
|
+
rubygems_version: 4.0.4
|
|
110
81
|
specification_version: 4
|
|
111
82
|
summary: Geospatial raster rendering for Ruby using libgd
|
|
112
83
|
test_files: []
|