terragona 0.1.1 → 0.2.0
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 +47 -16
- data/lib/terragona/base.rb +50 -23
- data/lib/terragona/concave_hull.rb +1 -5
- data/lib/terragona/generic.rb +41 -0
- data/lib/terragona/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bacfcba592bdf78f9891f8065d8f9e8172fe049c
|
4
|
+
data.tar.gz: 9c8baebb11ad0b66b27635bab3c1c2bd918e4902
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 21c854dbc451bf049243d910ee0276c4214583a1f97695f81bd7ec522058c53fe0577a284c3fe3f0c7740442f795702181d77acd5f7d9690d3adb90f02a54c3d
|
7
|
+
data.tar.gz: b693d2a52d5481d861fe279b158b41b9d31da88cde5a4155053146d743697c96bcc1f2b1cda3c6c1f949c8d67668cea3685bc3be0ad7d76d7627dbcfbe348fc6
|
data/README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
terragona
|
2
2
|
=========
|
3
3
|
|
4
|
-
Create polygons
|
5
|
-
This means: Create concave polygons using geonames places and store them in a postgres/postgis database.
|
4
|
+
Create polygons from [GeoNames](http://www.geonames.org) places or other sources.
|
5
|
+
This means: Create concave polygons using, i.e., geonames places and store them in a postgres/postgis database.
|
6
6
|
See [ST_Concave_Hull](http://postgis.net/docs/ST_ConcaveHull.html).
|
7
7
|
|
8
8
|

|
@@ -19,17 +19,25 @@ Install
|
|
19
19
|
|
20
20
|
or add `gem 'terragona'` to your Gemfile
|
21
21
|
|
22
|
+
News
|
23
|
+
----
|
24
|
+
|
25
|
+
* Classes API and Dump are now nested inside a `Geonames` class.
|
26
|
+
|
22
27
|
Usage
|
23
28
|
-----
|
24
29
|
|
25
30
|
First, create a db in postgres and install the postgis extension.
|
26
31
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
32
|
+
Right now, as sources you can use:
|
33
|
+
* GeoNames API, with the `Terragona::Geonames::API` class,
|
34
|
+
* A Geonames dump, (`Terragona::Geonames::Dump` class) and specify the dump file path in opts.
|
35
|
+
* A CSV (`Terragona::CSVParser` class) (with headers: `name,x,y`)
|
36
|
+
|
37
|
+
The API is faster but less accurate than the dump (max 1000 points per request).
|
38
|
+
The dump is more accurate but much slower (please, use country dumps, not the world dump: it's to big
|
39
|
+
-~9 million points- and could take lots of time.). For example: with the API, the Italy polygon is drawn
|
40
|
+
using 1000 points. With the dump, the input is ~95.000 points. You can use the `max_points` option to limit this number.
|
33
41
|
|
34
42
|
The slow part of the process is when points are filtered: the ones that are isolated are discarded.
|
35
43
|
This has to be refactored.
|
@@ -46,13 +54,12 @@ opts = {...}
|
|
46
54
|
countries=[{:name=>'Argentina',:fcode=>'PCLI',:country=>'AR'},
|
47
55
|
{:name=>'Uruguay',:fcode=>'PCLI',:country=>'UY'}]
|
48
56
|
|
49
|
-
terragona = Terragona::API.new(opts)
|
57
|
+
terragona = Terragona::Geonames::API.new(opts)
|
50
58
|
terragona.create_polygons_family(countries, 'countries', 'countries_subdivisions')
|
51
59
|
|
52
60
|
```
|
53
61
|
|
54
62
|
With Dump, and using returned children places
|
55
|
-
|
56
63
|
```ruby
|
57
64
|
require 'terragona'
|
58
65
|
|
@@ -67,16 +74,36 @@ opts={
|
|
67
74
|
|
68
75
|
italy=[{:name=>'Italy',:fcode=>'PCLI'}]
|
69
76
|
|
70
|
-
terragona=Terragona::Dump.new(opts)
|
71
|
-
result=terragona.create_polygons_family(italy,'italy','italian_regions')
|
77
|
+
terragona = Terragona::Geonames::Dump.new(opts)
|
78
|
+
result = terragona.create_polygons_family(italy,'italy','italian_regions')
|
72
79
|
|
73
|
-
italian_rest=[]
|
80
|
+
italian_rest = []
|
74
81
|
result.each {|r|
|
75
82
|
italian_rest.concat(r[:children_places])
|
76
83
|
}
|
77
84
|
terragona.create_polygons_family(italian_rest,'province','comuni')
|
78
85
|
```
|
79
86
|
|
87
|
+
With the CSVParser class
|
88
|
+
|
89
|
+
```ruby
|
90
|
+
require 'terragona'
|
91
|
+
|
92
|
+
opts={
|
93
|
+
:target_percent=> 0.85,
|
94
|
+
:max_distance_ratio=>1.6,
|
95
|
+
:db_username=>'mydbuser',
|
96
|
+
:db_password=>'mydbpsswd',
|
97
|
+
:db_name=>'mydb',
|
98
|
+
:csv_filename=>'/path/to/csv/IT.csv'}
|
99
|
+
|
100
|
+
italy=[] #Don't need input but the csv.
|
101
|
+
|
102
|
+
terragona = Terragona::CSVParser.new(opts)
|
103
|
+
terragona.create_polygons_family(italy,'italy','italian_regions')
|
104
|
+
|
105
|
+
```
|
106
|
+
|
80
107
|
Methods
|
81
108
|
-------
|
82
109
|
|
@@ -86,6 +113,9 @@ create_polygons(<array of places>, options)
|
|
86
113
|
create_polygons_family(<array of places>, <first order geometries table name>, <second order geometries table name>, options)
|
87
114
|
```
|
88
115
|
|
116
|
+
Important: **With the CSVParser class the initial array of places is not used**.
|
117
|
+
Terragona tries to create the parent polygon using all points.
|
118
|
+
|
89
119
|
Each place in the array of places is a hash with this keys:
|
90
120
|
|
91
121
|
```
|
@@ -110,10 +140,11 @@ Options
|
|
110
140
|
```
|
111
141
|
dump Only for Dump. Path to dump file.
|
112
142
|
max_points Only for Dump. Max number of points to consider from
|
113
|
-
dump file.
|
114
|
-
|
143
|
+
dump file.
|
144
|
+
csv_filename Only for CSV.
|
145
|
+
default_country Default country. Only for Geonames.
|
115
146
|
geonames_username Only for API. Geonames API username.
|
116
|
-
use_cache Boolean. Default: false.
|
147
|
+
use_cache Boolean. Default: false.
|
117
148
|
cache_expiration_time Default: 7200.
|
118
149
|
projection Default: EPSG 4326 (WGS84).
|
119
150
|
target_percent Require to draw the concave polygons.
|
data/lib/terragona/base.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require_relative './generic'
|
1
2
|
require_relative './geonames'
|
2
3
|
require_relative './concave_hull'
|
3
4
|
require_relative './version'
|
@@ -12,23 +13,20 @@ module Terragona
|
|
12
13
|
def create_polygons(names,options={})
|
13
14
|
opts=@options.merge(options)
|
14
15
|
|
15
|
-
concave_hull = ConcaveHull.new(opts)
|
16
|
+
concave_hull = ConcaveHull.new(opts)
|
16
17
|
|
17
|
-
names.
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
end
|
18
|
+
if (!names or names.empty?) and @input.class == Generic::CSVParser
|
19
|
+
n = {:name => 'CSV'}
|
20
|
+
name = @input.search(n)
|
21
|
+
process_points(n,name,concave_hull,opts)
|
22
|
+
return [name]
|
23
|
+
end
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
end
|
29
|
-
end
|
25
|
+
names.map{|n|
|
26
|
+
name = @input.search(n)
|
27
|
+
next unless process_points(n,name,concave_hull,opts)
|
30
28
|
name
|
31
|
-
}
|
29
|
+
}.compact
|
32
30
|
end
|
33
31
|
|
34
32
|
def create_polygons_family(names,parents_table,children_table,opts={})
|
@@ -39,20 +37,49 @@ module Terragona
|
|
39
37
|
}
|
40
38
|
create_polygons(children,opts.merge({:table => children_table}))
|
41
39
|
end
|
40
|
+
|
41
|
+
private
|
42
|
+
def process_points(n, name, concave_hull, opts)
|
43
|
+
if name[:points].count < @minimal_polygon_points
|
44
|
+
puts "No points for #{n[:name]}"
|
45
|
+
return
|
46
|
+
end
|
47
|
+
|
48
|
+
unless opts[:dont_create_polygons]
|
49
|
+
if concave_hull.perform(name[:points],name[:place_name],name[:place_id])
|
50
|
+
puts "Polygon created for #{n[:name]}"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Thought the polygon might have not been created, we return true
|
55
|
+
# (so we retrieve it's children). The only case where we don't want the children is if
|
56
|
+
# there are no enough points.
|
57
|
+
|
58
|
+
true
|
59
|
+
|
60
|
+
end
|
42
61
|
end
|
43
|
-
|
44
|
-
class
|
45
|
-
|
46
|
-
|
47
|
-
|
62
|
+
|
63
|
+
class Geonames
|
64
|
+
class API < Base
|
65
|
+
def initialize (options={})
|
66
|
+
super
|
67
|
+
@input = GeoNames::API.new(options)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
class Dump < Base
|
72
|
+
def initialize (options={})
|
73
|
+
super
|
74
|
+
@input = GeoNames::Dump.new(options)
|
75
|
+
end
|
48
76
|
end
|
49
77
|
end
|
50
|
-
|
51
|
-
class
|
78
|
+
|
79
|
+
class CSVParser < Base
|
52
80
|
def initialize (options={})
|
53
81
|
super
|
54
|
-
@
|
82
|
+
@input = Generic::CSVParser.new(options)
|
55
83
|
end
|
56
84
|
end
|
57
|
-
|
58
85
|
end
|
@@ -59,10 +59,6 @@ module Terragona
|
|
59
59
|
puts "Error with #{tags}, Id: #{id}, #{count} points."
|
60
60
|
end
|
61
61
|
end
|
62
|
-
|
63
|
-
def drop_points_table(table)
|
64
|
-
@db << "DROP TABLE IF EXISTS #{table};"
|
65
|
-
end
|
66
62
|
|
67
63
|
def filter_points_by_distance(points)
|
68
64
|
random_points = points.count > 200 ? (0..200).map {|e|
|
@@ -92,7 +88,7 @@ module Terragona
|
|
92
88
|
end
|
93
89
|
|
94
90
|
def clean_str(str)
|
95
|
-
str.gsub("'",' ')
|
91
|
+
str.to_s.gsub("'",' ')
|
96
92
|
end
|
97
93
|
end
|
98
94
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'csv'
|
2
|
+
|
3
|
+
module Terragona
|
4
|
+
module Generic
|
5
|
+
class CSVParser
|
6
|
+
def initialize(args = {})
|
7
|
+
filename = args[:csv_filename]
|
8
|
+
|
9
|
+
abort "Missing CSV filename. Aborting." unless filename
|
10
|
+
|
11
|
+
@csv = CSV.table(filename)
|
12
|
+
@id_counter = 0
|
13
|
+
end
|
14
|
+
def search(options = {})
|
15
|
+
@id_counter +=1
|
16
|
+
|
17
|
+
name = options[:name]
|
18
|
+
|
19
|
+
points = []
|
20
|
+
|
21
|
+
if name == 'CSV'
|
22
|
+
children = []
|
23
|
+
|
24
|
+
@csv.each {|p|
|
25
|
+
points.push({:x => p[:x], :y => p[:y]})
|
26
|
+
children.push({:name => p[:name]})
|
27
|
+
}
|
28
|
+
|
29
|
+
children.uniq!
|
30
|
+
|
31
|
+
children_places = (children.count > 1 )? children : []
|
32
|
+
else
|
33
|
+
@csv.select{|row| row[:name] == name}.each {|p| points.push({:x => p[:x], :y => p[:y]})}
|
34
|
+
children_places = []
|
35
|
+
end
|
36
|
+
|
37
|
+
{:children_places=>children_places, :points => points, :place_name=> name, :place_id=>@id_counter}
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/terragona/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: terragona
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bruno Salerno
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-05-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pg
|
@@ -151,6 +151,7 @@ files:
|
|
151
151
|
- lib/terragona.rb
|
152
152
|
- lib/terragona/base.rb
|
153
153
|
- lib/terragona/concave_hull.rb
|
154
|
+
- lib/terragona/generic.rb
|
154
155
|
- lib/terragona/geonames.rb
|
155
156
|
- lib/terragona/version.rb
|
156
157
|
- terragona.gemspec
|