libgd-gis 0.2.4 → 0.2.5
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/README.md +12 -1
- data/lib/gd/gis/crs_normalizer.rb +57 -0
- data/lib/gd/gis/feature.rb +3 -2
- data/lib/gd/gis/input/detector.rb +34 -0
- 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/layer_geojson.rb +53 -3
- data/lib/gd/gis/map.rb +17 -8
- data/lib/gd/gis/ontology.rb +26 -0
- data/lib/gd/gis/ontology.yml +23 -0
- metadata +9 -2
- data/lib/gd/gis/dump.sh +0 -19
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 15adf406fc3424953ad3ac2fcf5d05bfab4d02268619793fabc2bc5ed5ec67f7
|
|
4
|
+
data.tar.gz: 3a073e0eab8c647fb9a142e5675e1bb138c58a68cb0f31fb03e09f063f848f7d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 17a1eebdd7c9a4c1db7ffdff96965b61e5f0ac37548ea9955ed19dbc0812ac723f5be2a7ab203f26135aefeef2d39f44eff60ba0265bb868a379d5ab86a541ad
|
|
7
|
+
data.tar.gz: 0dd61743522c231ebf7df34c6c6a4da6dffc3c42fb539d5020a17f3a70c1a3ab5cc3fb78d6529f620fc5323a39cf2c02cd0097a3abc9e2f846a1a8f799727b2b
|
data/README.md
CHANGED
|
@@ -29,10 +29,15 @@
|
|
|
29
29
|
</p>
|
|
30
30
|
|
|
31
31
|

|
|
32
|
+
[](https://www.codacy.com/app/libgd-gis/libgd-gis?utm_source=github.com&utm_medium=referral&utm_content=libgd-gis/libgd-gis&utm_campaign=Badge_Grade)
|
|
33
|
+
[](https://coveralls.io/github/libgd-gis/libgd-gis?branch=master)
|
|
34
|
+
[](https://rubygems.org/gems/libgd-gis)
|
|
35
|
+
|
|
32
36
|
|
|
33
37
|
| Examples | Examples | Examples |
|
|
34
38
|
| :----: | :----: | :--: |
|
|
35
|
-
| <img src="examples/
|
|
39
|
+
| <img src="docs/examples/parana.png" height="250"> | <img src="docs/examples/nyc.png" height="250"> | <img src="docs/examples/paris.png" height="250"> |
|
|
40
|
+
| <img src="examples/nyc/nyc.png" height="250"> | <img src="docs/examples/tokyo_solarized.png" height="250"> | <img src="examples/parana/parana.png" height="250"> |
|
|
36
41
|
| <img src="docs/examples/america.png" height="250"> | <img src="docs/examples/argentina_museum.png" height="250"> | <img src="docs/examples/museos_parana.png" height="250"> |
|
|
37
42
|
| <img src="docs/examples/asia.png" height="250"> | <img src="docs/examples/europe.png" height="250"> | <img src="docs/examples/icecream_parana.png" height="250"> |
|
|
38
43
|
| <img src="docs/examples/argentina_cities.png" height="250"> | <img src="docs/examples/tanzania_hydro.png" height="250"> | <img src="docs/examples/parana_polygon.png" height="250"> |
|
|
@@ -40,6 +45,12 @@
|
|
|
40
45
|
|
|
41
46
|
---
|
|
42
47
|
|
|
48
|
+
> **libgd-gis is evolving very fast**, so some examples may temporarily stop working.
|
|
49
|
+
> Please report issues or ask for help — feedback is very welcome.
|
|
50
|
+
> https://github.com/ggerman/libgd-gis/issues or ggerman@gmail.com
|
|
51
|
+
|
|
52
|
+
--
|
|
53
|
+
|
|
43
54
|
## A geospatial raster engine for Ruby.
|
|
44
55
|
|
|
45
56
|
libgd-gis allows Ruby to render real maps, GeoJSON layers, vector features, and geospatial tiles using a native raster backend powered by **libgd**.
|
|
@@ -0,0 +1,57 @@
|
|
|
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
|
data/lib/gd/gis/feature.rb
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
module GD
|
|
2
2
|
module GIS
|
|
3
3
|
class Feature
|
|
4
|
-
attr_reader :geometry, :properties
|
|
4
|
+
attr_reader :geometry, :properties, :layer
|
|
5
5
|
|
|
6
|
-
def initialize(geometry, properties)
|
|
6
|
+
def initialize(geometry, properties, layer = nil)
|
|
7
7
|
@geometry = geometry
|
|
8
8
|
@properties = properties || {}
|
|
9
|
+
@layer = layer
|
|
9
10
|
end
|
|
10
11
|
|
|
11
12
|
# -------------------------------------------------
|
|
@@ -0,0 +1,34 @@
|
|
|
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
ADDED
|
File without changes
|
data/lib/gd/gis/layer_geojson.rb
CHANGED
|
@@ -1,16 +1,66 @@
|
|
|
1
1
|
require "json"
|
|
2
2
|
require_relative "feature"
|
|
3
|
+
require_relative "crs_normalizer"
|
|
4
|
+
require_relative "ontology"
|
|
3
5
|
|
|
4
6
|
module GD
|
|
5
7
|
module GIS
|
|
6
8
|
class LayerGeoJSON
|
|
9
|
+
|
|
7
10
|
def self.load(path)
|
|
8
11
|
data = JSON.parse(File.read(path))
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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)
|
|
12
25
|
end
|
|
13
26
|
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
|
+
|
|
14
64
|
end
|
|
15
65
|
end
|
|
16
66
|
end
|
data/lib/gd/gis/map.rb
CHANGED
|
@@ -47,18 +47,27 @@ module GD
|
|
|
47
47
|
features = LayerGeoJSON.load(path)
|
|
48
48
|
|
|
49
49
|
features.each do |feature|
|
|
50
|
-
|
|
51
|
-
|
|
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
|
+
|
|
52
60
|
@layers[:water] << [kind, feature]
|
|
53
61
|
|
|
54
|
-
|
|
55
|
-
|
|
62
|
+
when :roads
|
|
63
|
+
# map to style categories if you want later
|
|
64
|
+
@layers[:street] << feature
|
|
56
65
|
|
|
57
|
-
|
|
58
|
-
@layers[:
|
|
66
|
+
when :parks
|
|
67
|
+
@layers[:park] << feature
|
|
59
68
|
|
|
60
|
-
|
|
61
|
-
|
|
69
|
+
else
|
|
70
|
+
# ignore unclassified for now
|
|
62
71
|
end
|
|
63
72
|
end
|
|
64
73
|
end
|
|
@@ -0,0 +1,26 @@
|
|
|
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
|
|
@@ -0,0 +1,23 @@
|
|
|
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
|
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.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Germán Alberto Giménez Silva
|
|
@@ -41,14 +41,21 @@ 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/
|
|
44
|
+
- lib/gd/gis/crs_normalizer.rb
|
|
45
45
|
- lib/gd/gis/feature.rb
|
|
46
46
|
- 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
|
|
47
52
|
- lib/gd/gis/layer_geojson.rb
|
|
48
53
|
- lib/gd/gis/layer_lines.rb
|
|
49
54
|
- lib/gd/gis/layer_points.rb
|
|
50
55
|
- lib/gd/gis/layer_polygons.rb
|
|
51
56
|
- lib/gd/gis/map.rb
|
|
57
|
+
- lib/gd/gis/ontology.rb
|
|
58
|
+
- lib/gd/gis/ontology.yml
|
|
52
59
|
- lib/gd/gis/projection.rb
|
|
53
60
|
- lib/gd/gis/style.rb
|
|
54
61
|
- lib/gd/gis/style/dark.rb
|
data/lib/gd/gis/dump.sh
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
|
|
3
|
-
set -e
|
|
4
|
-
|
|
5
|
-
OUT="all_ruby_sources.txt"
|
|
6
|
-
> "$OUT"
|
|
7
|
-
|
|
8
|
-
echo "### Ruby sources dump ($(date))" >> "$OUT"
|
|
9
|
-
echo >> "$OUT"
|
|
10
|
-
|
|
11
|
-
find . -type f -name "*.rb" | sort | while read -r file; do
|
|
12
|
-
echo "===== FILE: $file =====" >> "$OUT"
|
|
13
|
-
echo >> "$OUT"
|
|
14
|
-
cat "$file" >> "$OUT"
|
|
15
|
-
echo >> "$OUT"
|
|
16
|
-
echo >> "$OUT"
|
|
17
|
-
done
|
|
18
|
-
|
|
19
|
-
echo "Wrote $OUT"
|