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 +4 -4
- data/lib/gd/gis/feature.rb +2 -3
- data/lib/gd/gis/layer_geojson.rb +3 -53
- data/lib/gd/gis/map.rb +43 -19
- metadata +1 -9
- data/lib/gd/gis/crs_normalizer.rb +0 -57
- data/lib/gd/gis/input/detector.rb +0 -34
- data/lib/gd/gis/input/geojson.rb +0 -0
- data/lib/gd/gis/input/kml.rb +0 -0
- data/lib/gd/gis/input/shapefile.rb +0 -0
- data/lib/gd/gis/input.rb +0 -0
- data/lib/gd/gis/ontology.rb +0 -26
- data/lib/gd/gis/ontology.yml +0 -23
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3c36a99210906574c046daffe2120213b027d92fdd22dec0b27861df22f88029
|
|
4
|
+
data.tar.gz: bd991fd3290c3bfb82f5640dad84c8e6486368285539774eed1b942acd7848b6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6bed27a3930a9512b0f5fff46fdfe2f76fe76932ddf263cc2d219cdaafd754d5161ede878f1b0d929e5a7b00b9c4b546c6905d9ee27d9bc478d5e7914ebc1784
|
|
7
|
+
data.tar.gz: ee203f7b9dc6f0a2669bbbedcde1e6fe31678c3a847c79a14d975c75cee1cc0a7f2784398acbef9b821943cce9124bdb5b41f0194070ff020fa39824f699a56a
|
data/lib/gd/gis/feature.rb
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
module GD
|
|
2
2
|
module GIS
|
|
3
3
|
class Feature
|
|
4
|
-
attr_reader :geometry, :properties
|
|
4
|
+
attr_reader :geometry, :properties
|
|
5
5
|
|
|
6
|
-
def initialize(geometry, properties
|
|
6
|
+
def initialize(geometry, properties)
|
|
7
7
|
@geometry = geometry
|
|
8
8
|
@properties = properties || {}
|
|
9
|
-
@layer = layer
|
|
10
9
|
end
|
|
11
10
|
|
|
12
11
|
# -------------------------------------------------
|
data/lib/gd/gis/layer_geojson.rb
CHANGED
|
@@ -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
|
-
|
|
14
|
-
|
|
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
|
-
|
|
51
|
-
|
|
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
|
-
|
|
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
|
-
|
|
70
|
-
|
|
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
|
|
84
|
-
|
|
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.
|
|
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
|
data/lib/gd/gis/input/geojson.rb
DELETED
|
File without changes
|
data/lib/gd/gis/input/kml.rb
DELETED
|
File without changes
|
|
File without changes
|
data/lib/gd/gis/input.rb
DELETED
|
File without changes
|
data/lib/gd/gis/ontology.rb
DELETED
|
@@ -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
|
data/lib/gd/gis/ontology.yml
DELETED
|
@@ -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
|