libgd-gis 0.3.1 → 0.3.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 +4 -4
- data/lib/gd/gis/layer_points.rb +100 -15
- data/lib/gd/gis/map.rb +10 -6
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e54f40ea70b79fc866db311f7ac994ca267483f62de518b2f6f4f5989957f5e6
|
|
4
|
+
data.tar.gz: c8825bd11685f5a0254bd5fdaa5b654cee53dff608a990ac91bc4bacfcba4f31
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7bf12c61f036e85b93aa1b7617fb2aa63f9c0fb788f3ad53e1bf313259b5847658e3c1c1cf2682227fdc9d542cabf86489cb94d9a79c5cf15949519dfe08be69
|
|
7
|
+
data.tar.gz: bdc13c7e7aa1e99f4328c3ea69699b4e8f548ea5aeb975b317a81fe136d8dc94b1e64655987f51a0fcf4db0af030ffd8e5a125ae8cd3191a34c8814575cffa0e
|
data/lib/gd/gis/layer_points.rb
CHANGED
|
@@ -38,17 +38,25 @@ module GD
|
|
|
38
38
|
label: nil,
|
|
39
39
|
font: nil,
|
|
40
40
|
size: 12,
|
|
41
|
-
color: [0, 0, 0]
|
|
41
|
+
color: [0, 0, 0],
|
|
42
|
+
font_color: nil,
|
|
43
|
+
count: 0
|
|
42
44
|
)
|
|
43
45
|
@data = data
|
|
44
46
|
@lon = lon
|
|
45
47
|
@lat = lat
|
|
48
|
+
@color = color
|
|
46
49
|
|
|
47
50
|
if icon.is_a?(Array) || icon.nil?
|
|
48
51
|
fill, stroke = icon || [GD::GIS::ColorHelpers.random_rgb, GD::GIS::ColorHelpers.random_rgb]
|
|
49
52
|
@icon = build_default_marker(fill, stroke)
|
|
53
|
+
elsif icon == "numeric" || icon == "alphabetic"
|
|
54
|
+
@icon = icon
|
|
55
|
+
@font_color = font_color
|
|
50
56
|
else
|
|
51
57
|
@icon = GD::Image.open(icon)
|
|
58
|
+
@icon.alpha_blending = true
|
|
59
|
+
@icon.save_alpha = true
|
|
52
60
|
end
|
|
53
61
|
|
|
54
62
|
@label = label
|
|
@@ -56,9 +64,8 @@ module GD
|
|
|
56
64
|
@size = size
|
|
57
65
|
@r, @g, @b, @a = color
|
|
58
66
|
@a = 0 if @a.nil?
|
|
67
|
+
@count = count
|
|
59
68
|
|
|
60
|
-
@icon.alpha_blending = true
|
|
61
|
-
@icon.save_alpha = true
|
|
62
69
|
end
|
|
63
70
|
|
|
64
71
|
# Builds a default circular marker icon.
|
|
@@ -93,8 +100,22 @@ module GD
|
|
|
93
100
|
#
|
|
94
101
|
# @return [void]
|
|
95
102
|
def render!(img, projector)
|
|
96
|
-
|
|
97
|
-
|
|
103
|
+
|
|
104
|
+
case @icon
|
|
105
|
+
when "numeric"
|
|
106
|
+
value = @count
|
|
107
|
+
when "alphabetic"
|
|
108
|
+
value = (@count + 96).chr
|
|
109
|
+
else
|
|
110
|
+
value = "*"
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
if @icon.is_a?(GD::Image)
|
|
114
|
+
w = @icon.width
|
|
115
|
+
h = @icon.height
|
|
116
|
+
else
|
|
117
|
+
w = radius_from_text(img, value, font: @font, size: @size) * 2
|
|
118
|
+
end
|
|
98
119
|
|
|
99
120
|
@data.each do |row|
|
|
100
121
|
lon = @lon.call(row)
|
|
@@ -102,25 +123,89 @@ module GD
|
|
|
102
123
|
|
|
103
124
|
x, y = projector.call(lon, lat)
|
|
104
125
|
|
|
105
|
-
# icono
|
|
106
|
-
img.copy(@icon, x - (w / 2), y - (h / 2), 0, 0, w, h)
|
|
107
|
-
|
|
108
|
-
# etiqueta opcional
|
|
109
126
|
next unless @label && @font
|
|
110
127
|
|
|
111
128
|
text = @label.call(row)
|
|
112
129
|
next if text.nil? || text.strip.empty?
|
|
113
|
-
|
|
114
130
|
font_h = @size * 1.1
|
|
115
131
|
|
|
132
|
+
if @icon == "numeric" || @icon == "alphabetic"
|
|
133
|
+
|
|
134
|
+
draw_symbol_circle!(
|
|
135
|
+
img: img,
|
|
136
|
+
x: x,
|
|
137
|
+
y: y,
|
|
138
|
+
symbol: value,
|
|
139
|
+
radius: 12,
|
|
140
|
+
bg_color: @color,
|
|
141
|
+
font_color: @font_color,
|
|
142
|
+
font: @font,
|
|
143
|
+
font_size: @size
|
|
144
|
+
)
|
|
145
|
+
else
|
|
146
|
+
img.copy(@icon, x - (w / 2), y - (h / 2), 0, 0, w, h)
|
|
147
|
+
end
|
|
148
|
+
|
|
116
149
|
img.text(text,
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
150
|
+
x: x + (w / 2) + 4,
|
|
151
|
+
y: y + (font_h / 2),
|
|
152
|
+
size: @size,
|
|
153
|
+
color: GD::Color.rgba(@r, @g, @b, @a),
|
|
154
|
+
font: @font)
|
|
122
155
|
end
|
|
123
156
|
end
|
|
157
|
+
|
|
158
|
+
# Draws a filled circle (bullet) with a centered numeric label.
|
|
159
|
+
#
|
|
160
|
+
# - x, y: circle center in pixels
|
|
161
|
+
# - y for text() is BASELINE (not top). We compute baseline to center the text.
|
|
162
|
+
def draw_symbol_circle!(img:, x:, y:, symbol:, radius:, bg_color:, font_color:, font:, font_size:, angle: 0.0)
|
|
163
|
+
diameter = radius_from_text(img, symbol, font: font, size: font_size) * 2
|
|
164
|
+
|
|
165
|
+
# 1) Bullet background
|
|
166
|
+
img.filled_ellipse(x, y, diameter, diameter, bg_color)
|
|
167
|
+
|
|
168
|
+
# 2) Measure text in pixels (matches rendering)
|
|
169
|
+
text = symbol.to_s
|
|
170
|
+
w, h = img.text_bbox(text, font: font, size: font_size, angle: angle)
|
|
171
|
+
|
|
172
|
+
# 3) Compute centered position:
|
|
173
|
+
# text() uses baseline Y, so:
|
|
174
|
+
# top_y = y - h/2
|
|
175
|
+
# baseline = top_y + h = y + h/2
|
|
176
|
+
text_x = (x - (w / 2.0)).round
|
|
177
|
+
text_y = (y + (h / 2.0)).round
|
|
178
|
+
|
|
179
|
+
# 4) Draw number
|
|
180
|
+
img.text(
|
|
181
|
+
text,
|
|
182
|
+
x: text_x,
|
|
183
|
+
y: text_y,
|
|
184
|
+
font: font,
|
|
185
|
+
size: font_size,
|
|
186
|
+
color: font_color
|
|
187
|
+
)
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
# Calculates a circle radius that fully contains the rendered text.
|
|
191
|
+
#
|
|
192
|
+
# img : GD::Image
|
|
193
|
+
# text : String (number, letters, etc.)
|
|
194
|
+
# font : path to .ttf
|
|
195
|
+
# size : font size in points
|
|
196
|
+
# padding : extra pixels around text (visual breathing room)
|
|
197
|
+
#
|
|
198
|
+
def radius_from_text(img, text, font:, size:, padding: 4)
|
|
199
|
+
w, h = img.text_bbox(
|
|
200
|
+
text.to_s,
|
|
201
|
+
font: font,
|
|
202
|
+
size: size
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
# Use the larger dimension to ensure the text fits
|
|
206
|
+
(([w, h].max / 2.0).ceil) + padding
|
|
207
|
+
end
|
|
208
|
+
|
|
124
209
|
end
|
|
125
210
|
end
|
|
126
211
|
end
|
data/lib/gd/gis/map.rb
CHANGED
|
@@ -133,6 +133,7 @@ module GD
|
|
|
133
133
|
|
|
134
134
|
@debug = false
|
|
135
135
|
@used_labels = {}
|
|
136
|
+
@count = 1
|
|
136
137
|
end
|
|
137
138
|
|
|
138
139
|
# Returns all features belonging to a given semantic layer.
|
|
@@ -258,20 +259,20 @@ module GD
|
|
|
258
259
|
warn "Style error: missing 'points' section"
|
|
259
260
|
end
|
|
260
261
|
|
|
261
|
-
font =
|
|
262
|
+
font = @style.points[:font] || begin
|
|
262
263
|
warn "[libgd-gis] points.font not defined in style, using random system font"
|
|
263
264
|
GD::GIS::FontHelper.random
|
|
264
265
|
end
|
|
265
266
|
|
|
266
|
-
size =
|
|
267
|
+
size = @style.points[:size] || begin
|
|
267
268
|
warn "[libgd-gis] points.font size not defined in style, using random system font size"
|
|
268
269
|
(6..14).to_a.sample
|
|
269
270
|
end
|
|
270
271
|
|
|
271
|
-
|
|
272
|
-
|
|
272
|
+
color = @style.points[:color] ? @style.normalize_color(@style.points[:color]) : GD::GIS::ColorHelpers.random_vivid
|
|
273
|
+
font_color = @style.points[:font_color] ? @style.normalize_color(@style.points[:font_color]) : [250, 250, 250, 0]
|
|
273
274
|
|
|
274
|
-
icon = if
|
|
275
|
+
icon = if @style.points.key?(:icon_fill) && @style.points.key?(:icon_stroke)
|
|
275
276
|
[points_style[:icon_stroke],
|
|
276
277
|
points_style[:icon_stroke]]
|
|
277
278
|
end
|
|
@@ -285,8 +286,11 @@ module GD
|
|
|
285
286
|
label: ->(f) { f.properties["name"] },
|
|
286
287
|
font: font,
|
|
287
288
|
size: size,
|
|
288
|
-
color: color
|
|
289
|
+
color: color,
|
|
290
|
+
font_color: font_color,
|
|
291
|
+
count: @count
|
|
289
292
|
)
|
|
293
|
+
@count += 1
|
|
290
294
|
elsif LINE_GEOMS.include?(geom_type)
|
|
291
295
|
@layers[:minor] << feature
|
|
292
296
|
end
|