libgd-gis 0.2.5 → 0.2.6

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: 3c36a99210906574c046daffe2120213b027d92fdd22dec0b27861df22f88029
4
+ data.tar.gz: bd991fd3290c3bfb82f5640dad84c8e6486368285539774eed1b942acd7848b6
5
5
  SHA512:
6
- metadata.gz: 17a1eebdd7c9a4c1db7ffdff96965b61e5f0ac37548ea9955ed19dbc0812ac723f5be2a7ab203f26135aefeef2d39f44eff60ba0265bb868a379d5ab86a541ad
7
- data.tar.gz: 0dd61743522c231ebf7df34c6c6a4da6dffc3c42fb539d5020a17f3a70c1a3ab5cc3fb78d6529f620fc5323a39cf2c02cd0097a3abc9e2f846a1a8f799727b2b
6
+ metadata.gz: 6bed27a3930a9512b0f5fff46fdfe2f76fe76932ddf263cc2d219cdaafd754d5161ede878f1b0d929e5a7b00b9c4b546c6905d9ee27d9bc478d5e7914ebc1784
7
+ data.tar.gz: ee203f7b9dc6f0a2669bbbedcde1e6fe31678c3a847c79a14d975c75cee1cc0a7f2784398acbef9b821943cce9124bdb5b41f0194070ff020fa39824f699a56a
@@ -1,12 +1,11 @@
1
1
  module GD
2
2
  module GIS
3
3
  class Feature
4
- attr_reader :geometry, :properties, :layer
4
+ attr_reader :geometry, :properties
5
5
 
6
- def initialize(geometry, properties, layer = nil)
6
+ def initialize(geometry, properties)
7
7
  @geometry = geometry
8
8
  @properties = properties || {}
9
- @layer = layer
10
9
  end
11
10
 
12
11
  # -------------------------------------------------
@@ -1,66 +1,16 @@
1
1
  require "json"
2
2
  require_relative "feature"
3
- require_relative "crs_normalizer"
4
- require_relative "ontology"
5
3
 
6
4
  module GD
7
5
  module GIS
8
6
  class LayerGeoJSON
9
-
10
7
  def self.load(path)
11
8
  data = JSON.parse(File.read(path))
12
-
13
- # 1) Detect CRS
14
- crs_name = data["crs"]&.dig("properties", "name")
15
- normalizer = CRS::Normalizer.new(crs_name)
16
-
17
- # 2) Load ontology
18
- ontology = Ontology.new
19
-
20
- # 3) Normalize geometries + classify
21
- data["features"].map do |f|
22
- normalize_geometry!(f["geometry"], normalizer)
23
- layer = ontology.classify(f["properties"] || {})
24
- Feature.new(f["geometry"], f["properties"], layer)
9
+ features = data["features"]
10
+ features.map do |f|
11
+ Feature.new(f["geometry"], f["properties"])
25
12
  end
26
13
  end
27
-
28
- # --------------------------------------------
29
- # CRS normalization (2D + 3D safe)
30
- # --------------------------------------------
31
- def self.normalize_geometry!(geometry, normalizer)
32
- case geometry["type"]
33
-
34
- when "Point"
35
- geometry["coordinates"] =
36
- normalizer.normalize(geometry["coordinates"])
37
-
38
- when "LineString"
39
- geometry["coordinates"] =
40
- geometry["coordinates"].map { |c| normalizer.normalize(c) }
41
-
42
- when "MultiLineString"
43
- geometry["coordinates"] =
44
- geometry["coordinates"].map do |line|
45
- line.map { |c| normalizer.normalize(c) }
46
- end
47
-
48
- when "Polygon"
49
- geometry["coordinates"] =
50
- geometry["coordinates"].map do |ring|
51
- ring.map { |c| normalizer.normalize(c) }
52
- end
53
-
54
- when "MultiPolygon"
55
- geometry["coordinates"] =
56
- geometry["coordinates"].map do |poly|
57
- poly.map do |ring|
58
- ring.map { |c| normalizer.normalize(c) }
59
- end
60
- end
61
- end
62
- end
63
-
64
14
  end
65
15
  end
66
16
  end
data/lib/gd/gis/map.rb CHANGED
@@ -47,27 +47,18 @@ module GD
47
47
  features = LayerGeoJSON.load(path)
48
48
 
49
49
  features.each do |feature|
50
- case feature.layer
51
- when :water
52
- # optional: detect river vs canal from properties
53
- kind =
54
- case (feature.properties["objeto"] || feature.properties["waterway"]).to_s.downcase
55
- when /river|río/ then :river
56
- when /stream|arroyo/ then :stream
57
- else :minor
58
- end
59
-
50
+ if Classifier.water?(feature)
51
+ kind = Classifier.water_kind(feature)
60
52
  @layers[:water] << [kind, feature]
61
53
 
62
- when :roads
63
- # map to style categories if you want later
64
- @layers[:street] << feature
65
-
66
- when :parks
54
+ elsif Classifier.park?(feature)
67
55
  @layers[:park] << feature
68
56
 
69
- else
70
- # ignore unclassified for now
57
+ elsif Classifier.rail?(feature)
58
+ @layers[:rail] << feature
59
+
60
+ elsif type = Classifier.road(feature)
61
+ @layers[type] << feature
71
62
  end
72
63
  end
73
64
  end
@@ -80,8 +71,30 @@ module GD
80
71
  @points_layers << GD::GIS::PointsLayer.new(data, **opts)
81
72
  end
82
73
 
83
- def add_lines(features, **opts)
84
- @lines_layers << GD::GIS::LinesLayer.new(features, **opts)
74
+ def add_line(coords, **opts)
75
+ feature = {
76
+ "type" => "Feature",
77
+ "geometry" => {
78
+ "type" => "LineString",
79
+ "coordinates" => coords
80
+ },
81
+ "properties" => {}
82
+ }
83
+
84
+ add_lines([feature], **opts)
85
+ end
86
+
87
+ def add_multiline(lines, **opts)
88
+ feature = {
89
+ "type" => "Feature",
90
+ "geometry" => {
91
+ "type" => "MultiLineString",
92
+ "coordinates" => lines
93
+ },
94
+ "properties" => []
95
+ }
96
+
97
+ add_lines([feature], **opts)
85
98
  end
86
99
 
87
100
  def add_polygons(polygons, **opts)
@@ -194,6 +207,17 @@ module GD
194
207
  end
195
208
  end
196
209
 
210
+ private
211
+
212
+ def add_lines(features, **opts)
213
+ stroke = opts.delete(:color) || opts.delete(:stroke)
214
+ width = opts.delete(:width) || opts.delete(:stroke_width)
215
+
216
+ raise ArgumentError, "missing :color or :stroke" unless stroke
217
+ raise ArgumentError, "missing :width" unless width
218
+
219
+ @lines_layers << GD::GIS::LinesLayer.new(features, :stroke => stroke, :width => width)
220
+ end
197
221
 
198
222
  end
199
223
  end
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.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Germán Alberto Giménez Silva
@@ -41,21 +41,13 @@ files:
41
41
  - lib/gd/gis.rb
42
42
  - lib/gd/gis/basemap.rb
43
43
  - lib/gd/gis/classifier.rb
44
- - lib/gd/gis/crs_normalizer.rb
45
44
  - lib/gd/gis/feature.rb
46
45
  - lib/gd/gis/geometry.rb
47
- - lib/gd/gis/input.rb
48
- - lib/gd/gis/input/detector.rb
49
- - lib/gd/gis/input/geojson.rb
50
- - lib/gd/gis/input/kml.rb
51
- - lib/gd/gis/input/shapefile.rb
52
46
  - lib/gd/gis/layer_geojson.rb
53
47
  - lib/gd/gis/layer_lines.rb
54
48
  - lib/gd/gis/layer_points.rb
55
49
  - lib/gd/gis/layer_polygons.rb
56
50
  - lib/gd/gis/map.rb
57
- - lib/gd/gis/ontology.rb
58
- - lib/gd/gis/ontology.yml
59
51
  - lib/gd/gis/projection.rb
60
52
  - lib/gd/gis/style.rb
61
53
  - lib/gd/gis/style/dark.rb
@@ -1,57 +0,0 @@
1
- module GD
2
- module GIS
3
- module CRS
4
- CRS84 = "urn:ogc:def:crs:OGC:1.3:CRS84"
5
- EPSG4326 = "EPSG:4326"
6
- EPSG3857 = "EPSG:3857"
7
-
8
- class Normalizer
9
- def initialize(crs)
10
- @crs = normalize_name(crs)
11
- end
12
-
13
- # Accepts:
14
- # normalize(lon,lat)
15
- # normalize(lon,lat,z)
16
- # normalize([lon,lat])
17
- # normalize([lon,lat,z])
18
- def normalize(*args)
19
- lon, lat = args.flatten
20
- return nil if lon.nil? || lat.nil?
21
-
22
- lon = lon.to_f
23
- lat = lat.to_f
24
-
25
- case @crs
26
- when CRS84, nil
27
- [lon, lat]
28
-
29
- when EPSG4326
30
- # axis order lat,lon → lon,lat
31
- [lat, lon]
32
-
33
- when EPSG3857
34
- mercator_to_wgs84(lon, lat)
35
-
36
- else
37
- [lon, lat]
38
- end
39
- end
40
-
41
- private
42
-
43
- def normalize_name(name)
44
- return nil if name.nil?
45
- name.to_s.strip
46
- end
47
-
48
- def mercator_to_wgs84(x, y)
49
- r = 6378137.0
50
- lon = (x / r) * 180.0 / Math::PI
51
- lat = (2 * Math.atan(Math.exp(y / r)) - Math::PI / 2) * 180.0 / Math::PI
52
- [lon, lat]
53
- end
54
- end
55
- end
56
- end
57
- end
@@ -1,34 +0,0 @@
1
- module GD
2
- module GIS
3
- module Input
4
- module Detector
5
- def self.detect(path)
6
- return :geojson if geojson?(path)
7
- return :kml if kml?(path)
8
- return :shapefile if shapefile?(path)
9
- return :osm_pbf if pbf?(path)
10
- :unknown
11
- end
12
-
13
- def self.geojson?(path)
14
- File.open(path) do |f|
15
- head = f.read(2048)
16
- head.include?('"FeatureCollection"') || head.include?('"GeometryCollection"')
17
- end
18
- end
19
-
20
- def self.kml?(path)
21
- File.open(path) { |f| f.read(512).include?("<kml") }
22
- end
23
-
24
- def self.shapefile?(path)
25
- File.open(path, "rb") { |f| f.read(4) == "\x00\x00\x27\x0A" }
26
- end
27
-
28
- def self.pbf?(path)
29
- File.open(path, "rb") { |f| f.read(2) == "\x1f\x8b" }
30
- end
31
- end
32
- end
33
- end
34
- end
File without changes
File without changes
File without changes
data/lib/gd/gis/input.rb DELETED
File without changes
@@ -1,26 +0,0 @@
1
- require "yaml"
2
-
3
- module GD
4
- module GIS
5
- class Ontology
6
- def initialize(path = nil)
7
- path ||= File.expand_path("ontology.yml", __dir__)
8
- @rules = YAML.load_file(path)
9
- end
10
-
11
- def classify(properties)
12
- @rules.each do |layer, sources|
13
- sources.each do |source, rules|
14
- rules.each do |key, values|
15
- v = (properties[key.to_s] || properties[key.to_sym]).to_s.strip.downcase
16
- values = values.map { |x| x.to_s.downcase }
17
-
18
- return layer.to_sym if values.any? { |x| v.include?(x) }
19
- end
20
- end
21
- end
22
- nil
23
- end
24
- end
25
- end
26
- end
@@ -1,23 +0,0 @@
1
- water:
2
- ign:
3
- objeto:
4
- - canal
5
- - río
6
- - arroyo
7
- - embalse
8
- - laguna
9
- - dique
10
- - represa
11
- gna:
12
- - canal
13
- - río
14
- - arroyo
15
- - embalse
16
- - laguna
17
-
18
- natural_earth:
19
- featurecla:
20
- - river
21
- - lake
22
- - reservoir
23
- - riverbank