libgd-gis 0.2.5 → 0.2.7.pre.alpha.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 15adf406fc3424953ad3ac2fcf5d05bfab4d02268619793fabc2bc5ed5ec67f7
4
- data.tar.gz: 3a073e0eab8c647fb9a142e5675e1bb138c58a68cb0f31fb03e09f063f848f7d
3
+ metadata.gz: 6559ec92e07ae18e0a783d5d822c676437c68896928d7e2a59143ffd0ef9bb7e
4
+ data.tar.gz: d1d343b32dbef5a5093746577db4b61d678a27d42949737079f3ba8e4c840a9a
5
5
  SHA512:
6
- metadata.gz: 17a1eebdd7c9a4c1db7ffdff96965b61e5f0ac37548ea9955ed19dbc0812ac723f5be2a7ab203f26135aefeef2d39f44eff60ba0265bb868a379d5ab86a541ad
7
- data.tar.gz: 0dd61743522c231ebf7df34c6c6a4da6dffc3c42fb539d5020a17f3a70c1a3ab5cc3fb78d6529f620fc5323a39cf2c02cd0097a3abc9e2f846a1a8f799727b2b
6
+ metadata.gz: 40cdba7a5707db6afde50b1358e6ae65eb936e34880d4ba2d593acfa72945cb09dc25661bab3dfdf7eefc6ea7f260171f9c38bc396dbeb2c42c83fc573964bd7
7
+ data.tar.gz: ac76fd31a7b28acae6067ed56ed4783d2dabb97992d19c841af25459204caf9e3180cd5bea9e74b9de8c583741ab187044ccbdcabd45ce1b2523438faf5c1b5b
@@ -1,6 +1,8 @@
1
1
  module GD
2
2
  module GIS
3
3
  class PointsLayer
4
+ attr_accessor :data, :size
5
+
4
6
  def initialize(data, lon:, lat:, icon:, label: nil, font: nil, size: 12, color: [0,0,0])
5
7
  @data = data
6
8
  @lon = lon
@@ -15,6 +17,7 @@ module GD
15
17
  @label = label
16
18
  @font = font
17
19
  @size = size
20
+ @data = data
18
21
  @color = color
19
22
 
20
23
  @icon.alpha_blending = true
data/lib/gd/gis/map.rb CHANGED
@@ -36,6 +36,10 @@ module GD
36
36
  @lines_layers = []
37
37
  @polygons_layers = []
38
38
 
39
+ @dynamic_points = []
40
+ @dynamic_lines = []
41
+ @dynamic_polys = []
42
+
39
43
  @style = nil
40
44
  end
41
45
 
@@ -77,11 +81,35 @@ module GD
77
81
  # -----------------------------------
78
82
 
79
83
  def add_points(data, **opts)
80
- @points_layers << GD::GIS::PointsLayer.new(data, **opts)
84
+ layer = GD::GIS::PointsLayer.new(data, **opts)
85
+ @points_layers << layer
86
+ layer
81
87
  end
82
88
 
83
- def add_lines(features, **opts)
84
- @lines_layers << GD::GIS::LinesLayer.new(features, **opts)
89
+ def add_line(coords, **opts)
90
+ feature = {
91
+ "type" => "Feature",
92
+ "geometry" => {
93
+ "type" => "LineString",
94
+ "coordinates" => coords
95
+ },
96
+ "properties" => {}
97
+ }
98
+
99
+ add_lines([feature], **opts)
100
+ end
101
+
102
+ def add_multiline(lines, **opts)
103
+ feature = {
104
+ "type" => "Feature",
105
+ "geometry" => {
106
+ "type" => "MultiLineString",
107
+ "coordinates" => lines
108
+ },
109
+ "properties" => []
110
+ }
111
+
112
+ add_lines([feature], **opts)
85
113
  end
86
114
 
87
115
  def add_polygons(polygons, **opts)
@@ -123,20 +151,26 @@ module GD
123
151
  )
124
152
  end
125
153
 
126
- projection = lambda do |lon, lat|
154
+ @projection = lambda do |lon, lat|
127
155
  x, y = GD::GIS::Projection.lonlat_to_global_px(lon, lat, @zoom)
128
156
  [(x - origin_x).round, (y - origin_y).round]
129
157
  end
130
158
 
131
159
  # 1️⃣ Semantic GeoJSON layers (this is what was working)
132
160
  @style.order.each do |kind|
133
- draw_layer(kind, projection)
161
+ draw_layer(kind, @projection)
134
162
  end
135
163
 
136
164
  # 2️⃣ Generic overlays
137
- @polygons_layers.each { |l| l.render!(@image, projection) }
138
- @lines_layers.each { |l| l.render!(@image, projection) }
139
- @points_layers.each { |l| l.render!(@image, projection) }
165
+ @polygons_layers.each { |l| l.render!(@image, @projection) }
166
+ @lines_layers.each { |l| l.render!(@image, @projection) }
167
+ @points_layers.each { |l| l.render!(@image, @projection) }
168
+
169
+ @dynamic_polys.each { |l| l.render!(@image, @projection) }
170
+ @dynamic_lines.each { |l| l.render!(@image, @projection) }
171
+ @dynamic_points.each { |l| l.render!(@image, @projection) }
172
+
173
+ @image
140
174
  end
141
175
 
142
176
  def save(path)
@@ -173,7 +207,7 @@ module GD
173
207
 
174
208
  if style[:stroke]
175
209
  color = GD::Color.rgb(*style[:stroke])
176
- f.draw(@image, projection, color, width, :water)
210
+ f.draw(@image, @projection, color, width, :water)
177
211
  end
178
212
 
179
213
  else
@@ -182,18 +216,67 @@ module GD
182
216
 
183
217
  if geom == "Polygon" || geom == "MultiPolygon"
184
218
  # THIS is the critical fix
185
- f.draw(@image, projection, nil, nil, style)
219
+ f.draw(@image, @projection, nil, nil, style)
186
220
  else
187
221
  if style[:stroke]
188
222
  color = GD::Color.rgb(*style[:stroke])
189
223
  width = style[:stroke_width] || 1
190
- f.draw(@image, projection, color, width)
224
+ f.draw(@image, @projection, color, width)
191
225
  end
192
226
  end
193
227
  end
194
228
  end
195
229
  end
196
230
 
231
+ def clear_dynamic_layers
232
+ @dynamic_points.clear
233
+ @dynamic_lines.clear
234
+ @dynamic_polys.clear
235
+ end
236
+
237
+ def add_dynamic_point(data, **opts)
238
+ @dynamic_points << GD::GIS::PointsLayer.new(data, **opts)
239
+ end
240
+
241
+ def add_dynamic_line(coords, **opts)
242
+ feature = {
243
+ "type" => "Feature",
244
+ "geometry" => {
245
+ "type" => "LineString",
246
+ "coordinates" => coords
247
+ },
248
+ "properties" => {}
249
+ }
250
+ @dynamic_lines << GD::GIS::LinesLayer.new([feature], **opts)
251
+ end
252
+
253
+ def render_base
254
+ render
255
+ @base_image = @image
256
+ end
257
+
258
+ def render_with_base
259
+ img = GD::Image.new(@base_image.width, @base_image.height)
260
+ img.copy(@base_image, 0,0, 0,0, @base_image.width, @base_image.height)
261
+
262
+ @points_layers.each { |l| l.render!(img, @projection) }
263
+ @lines_layers.each { |l| l.render!(img, @projection) }
264
+ @polygons_layers.each{ |l| l.render!(img, @projection) }
265
+
266
+ img
267
+ end
268
+
269
+ private
270
+
271
+ def add_lines(features, **opts)
272
+ stroke = opts.delete(:color) || opts.delete(:stroke)
273
+ width = opts.delete(:width) || opts.delete(:stroke_width)
274
+
275
+ raise ArgumentError, "missing :color or :stroke" unless stroke
276
+ raise ArgumentError, "missing :width" unless width
277
+
278
+ @lines_layers << GD::GIS::LinesLayer.new(features, :stroke => stroke, :width => width)
279
+ end
197
280
 
198
281
  end
199
282
  end
@@ -1,3 +1,7 @@
1
+ # ============================================================
2
+ # WATER
3
+ # ============================================================
4
+
1
5
  water:
2
6
  ign:
3
7
  objeto:
@@ -21,3 +25,243 @@ water:
21
25
  - lake
22
26
  - reservoir
23
27
  - riverbank
28
+
29
+ osm:
30
+ waterway:
31
+ - river
32
+ - stream
33
+ - canal
34
+ - drain
35
+ - ditch
36
+ natural:
37
+ - water
38
+ - lake
39
+ - reservoir
40
+ - wetland
41
+ - bay
42
+ - strait
43
+
44
+ # ============================================================
45
+ # ROADS
46
+ # ============================================================
47
+
48
+ roads:
49
+ ign:
50
+ objeto:
51
+ - autopista
52
+ - ruta
53
+ - camino
54
+ - calle
55
+ - avenida
56
+
57
+ natural_earth:
58
+ featurecla:
59
+ - road
60
+ - highway
61
+
62
+ osm:
63
+ highway:
64
+ - motorway
65
+ - motorway_link
66
+ - trunk
67
+ - trunk_link
68
+ - primary
69
+ - primary_link
70
+ - secondary
71
+ - secondary_link
72
+ - tertiary
73
+ - tertiary_link
74
+ - residential
75
+ - unclassified
76
+ - service
77
+ - living_street
78
+ - pedestrian
79
+ - road
80
+ - busway
81
+ - track
82
+
83
+ # ============================================================
84
+ # RAIL
85
+ # ============================================================
86
+
87
+ rail:
88
+ osm:
89
+ railway:
90
+ - rail
91
+ - subway
92
+ - light_rail
93
+ - tram
94
+ - monorail
95
+ - funicular
96
+
97
+ # ============================================================
98
+ # PARKS & GREEN
99
+ # ============================================================
100
+
101
+ park:
102
+ ign:
103
+ objeto:
104
+ - parque
105
+ - plaza
106
+ - reserva
107
+
108
+ natural_earth:
109
+ featurecla:
110
+ - park
111
+ - protected_area
112
+
113
+ osm:
114
+ leisure:
115
+ - park
116
+ - garden
117
+ - pitch
118
+ - playground
119
+ - recreation_ground
120
+ - golf_course
121
+ landuse:
122
+ - grass
123
+ - meadow
124
+ - forest
125
+ natural:
126
+ - wood
127
+ - scrub
128
+ - heath
129
+ - grassland
130
+
131
+ # ============================================================
132
+ # BUILDINGS
133
+ # ============================================================
134
+
135
+ buildings:
136
+ ign:
137
+ objeto:
138
+ - edificio
139
+ - hospital
140
+ - escuela
141
+
142
+ osm:
143
+ building:
144
+ - yes
145
+ - residential
146
+ - commercial
147
+ - industrial
148
+ - retail
149
+ - hospital
150
+ - school
151
+ - church
152
+ - cathedral
153
+ - university
154
+ - public
155
+ - civic
156
+ - apartments
157
+
158
+ # ============================================================
159
+ # POI (Points of Interest)
160
+ # ============================================================
161
+
162
+ poi:
163
+ osm:
164
+ amenity:
165
+ - hospital
166
+ - school
167
+ - university
168
+ - cafe
169
+ - restaurant
170
+ - bar
171
+ - pharmacy
172
+ - bank
173
+ - atm
174
+ - police
175
+ - fire_station
176
+ - library
177
+ - cinema
178
+ - theatre
179
+ - post_office
180
+ - fuel
181
+ shop:
182
+ - supermarket
183
+ - bakery
184
+ - convenience
185
+ - clothes
186
+ - mall
187
+ - department_store
188
+ - butcher
189
+ - greengrocer
190
+ - fast_food
191
+
192
+ # ============================================================
193
+ # TRANSPORT
194
+ # ============================================================
195
+
196
+ transport:
197
+ osm:
198
+ aeroway:
199
+ - aerodrome
200
+ - runway
201
+ - taxiway
202
+ - apron
203
+ - terminal
204
+ public_transport:
205
+ - station
206
+ - stop_position
207
+ - platform
208
+
209
+ # ============================================================
210
+ # NATURAL FEATURES
211
+ # ============================================================
212
+
213
+ natural:
214
+ natural_earth:
215
+ featurecla:
216
+ - mountain
217
+ - peak
218
+ - hill
219
+ - volcano
220
+
221
+ osm:
222
+ natural:
223
+ - peak
224
+ - hill
225
+ - volcano
226
+ - ridge
227
+ - cliff
228
+ - dune
229
+
230
+ # ============================================================
231
+ # LANDUSE
232
+ # ============================================================
233
+
234
+ landuse:
235
+ osm:
236
+ landuse:
237
+ - residential
238
+ - commercial
239
+ - industrial
240
+ - retail
241
+ - farmland
242
+ - forest
243
+ - grass
244
+ - meadow
245
+ - quarry
246
+ - cemetery
247
+ - landfill
248
+ - recreation_ground
249
+ roads:
250
+ osm_geofabrik:
251
+ fclass:
252
+ - motorway
253
+ - motorway_link
254
+ - trunk
255
+ - trunk_link
256
+ - primary
257
+ - primary_link
258
+ - secondary
259
+ - secondary_link
260
+ - tertiary
261
+ - tertiary_link
262
+ - residential
263
+ - unclassified
264
+ - service
265
+ - living_street
266
+ - pedestrian
267
+ - road
@@ -0,0 +1,68 @@
1
+ require "json"
2
+
3
+ module GD
4
+ module GIS
5
+ class PathSampler
6
+ def initialize(coords)
7
+ @coords = coords
8
+ @segments = []
9
+ @total = 0.0
10
+
11
+ coords.each_cons(2) do |a,b|
12
+ d = haversine(a[0],a[1], b[0],b[1])
13
+ @segments << [a,b,d]
14
+ @total += d
15
+ end
16
+ end
17
+
18
+ def point_at(t)
19
+ target = t * @total
20
+ acc = 0.0
21
+
22
+ @segments.each do |a,b,d|
23
+ return interpolate(a,b,(target-acc)/d) if acc + d >= target
24
+ acc += d
25
+ end
26
+
27
+ @coords.last
28
+ end
29
+
30
+ def interpolate(a,b,t)
31
+ [
32
+ a[0] + (b[0]-a[0])*t,
33
+ a[1] + (b[1]-a[1])*t
34
+ ]
35
+ end
36
+
37
+ def haversine(lon1,lat1,lon2,lat2)
38
+ r = 6371000
39
+ dlat = (lat2-lat1) * Math::PI/180
40
+ dlon = (lon2-lon1) * Math::PI/180
41
+ a = Math.sin(dlat/2)**2 +
42
+ Math.cos(lat1*Math::PI/180)*Math.cos(lat2*Math::PI/180)*
43
+ Math.sin(dlon/2)**2
44
+ 2 * r * Math.atan2(Math.sqrt(a), Math.sqrt(1-a))
45
+ end
46
+
47
+ def self.from_geojson(path)
48
+ data = JSON.parse(File.read(path))
49
+
50
+ coords =
51
+ if data["features"]
52
+ data["features"][0]["geometry"]["coordinates"]
53
+
54
+ elsif data["paths"]
55
+ data["paths"][0]["points"]["coordinates"]
56
+
57
+ elsif data["routes"]
58
+ data["routes"][0]["geometry"]["coordinates"]
59
+
60
+ else
61
+ raise "Formato de ruta desconocido en #{path}"
62
+ end
63
+
64
+ new(coords)
65
+ end
66
+ end
67
+ end
68
+ end
data/lib/gd/gis.rb CHANGED
@@ -12,3 +12,4 @@ require_relative "gis/layer_points"
12
12
  require_relative "gis/layer_lines"
13
13
  require_relative "gis/layer_polygons"
14
14
  require_relative "gis/layer_geojson"
15
+ require_relative "gis/path_sampler"
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.2.5
4
+ version: 0.2.7.pre.alpha.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Germán Alberto Giménez Silva
@@ -15,20 +15,20 @@ dependencies:
15
15
  requirements:
16
16
  - - "~>"
17
17
  - !ruby/object:Gem::Version
18
- version: 0.2.1
18
+ version: 0.2.3
19
19
  - - ">="
20
20
  - !ruby/object:Gem::Version
21
- version: 0.2.1
21
+ version: 0.2.3
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  requirements:
26
26
  - - "~>"
27
27
  - !ruby/object:Gem::Version
28
- version: 0.2.1
28
+ version: 0.2.3
29
29
  - - ">="
30
30
  - !ruby/object:Gem::Version
31
- version: 0.2.1
31
+ version: 0.2.3
32
32
  description: A native GIS raster engine for Ruby built on libgd. Render maps, GeoJSON,
33
33
  heatmaps and tiles.
34
34
  email:
@@ -56,6 +56,7 @@ files:
56
56
  - lib/gd/gis/map.rb
57
57
  - lib/gd/gis/ontology.rb
58
58
  - lib/gd/gis/ontology.yml
59
+ - lib/gd/gis/path_sampler.rb
59
60
  - lib/gd/gis/projection.rb
60
61
  - lib/gd/gis/style.rb
61
62
  - lib/gd/gis/style/dark.rb
@@ -80,7 +81,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
80
81
  - !ruby/object:Gem::Version
81
82
  version: '0'
82
83
  requirements: []
83
- rubygems_version: 4.0.3
84
+ rubygems_version: 4.0.4
84
85
  specification_version: 4
85
86
  summary: Geospatial raster rendering for Ruby using libgd
86
87
  test_files: []