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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 88715c69977bde03e32967c508e4f4a519fecd03
4
- data.tar.gz: e3fc05839b11f705c3e38ddac17bff854fadb179
3
+ metadata.gz: bacfcba592bdf78f9891f8065d8f9e8172fe049c
4
+ data.tar.gz: 9c8baebb11ad0b66b27635bab3c1c2bd918e4902
5
5
  SHA512:
6
- metadata.gz: bc40ce6a147fdfa8e55eb838b6f1f911a68b821b2e59dfda30618c2b2738c9fbbd8048afacc0eacac8c01ad7851e427d678c30cc3108bf7c686e8792d02c5399
7
- data.tar.gz: 069423d4fee2ca209821cae9d2e1d43626e2e90b0dbe66a9edb0c8ee7fb1d1550dc297c338296a2d788fbaa737ce926ef409f7d20ea05ba6359c2429db37a891
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 for [GeoNames](http://www.geonames.org) places.
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
  ![alt tag](https://cloud.githubusercontent.com/assets/6061036/5606205/2216ff3c-9402-11e4-9123-fff91369208e.png)
@@ -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
- You can use the GeoNames API, with the Terragona::API class, or download
28
- a dump, (Terragona::Dump class) and specify the dump file path in opts. The API is faster
29
- but less accurate (max 1000 points per request). The dump is more accurate but much slower (please,
30
- use country dumps, not the world dump: it's to big -~9 million points- and could take lots of time.). For example:
31
- with the API, the Italy polygon is drawn using 1000 points. With the dump, the input is ~95.000 points.
32
- You can use the `max_points` option to limit this number.
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
- default_country Default country.
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.
@@ -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) if not opts[:dont_create_polygons]
16
+ concave_hull = ConcaveHull.new(opts)
16
17
 
17
- names.map{|n|
18
- name = @geonames.search(n)
19
-
20
- if name[:points].count < @minimal_polygon_points
21
- puts "No points for #{n[:name]}"
22
- next
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
- unless opts[:dont_create_polygons]
26
- if concave_hull.perform(name[:points],name[:place_name],name[:place_id])
27
- puts "Polygon created for #{n[:name]}"
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 API < Base
45
- def initialize (options={})
46
- super
47
- @geonames = GeoNames::API.new(options)
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 Dump < Base
78
+
79
+ class CSVParser < Base
52
80
  def initialize (options={})
53
81
  super
54
- @geonames = GeoNames::Dump.new(options)
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
@@ -1,3 +1,3 @@
1
1
  module Terragona
2
- VERSION = "0.1.1"
2
+ VERSION = "0.2.0"
3
3
  end
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.1.1
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-04-16 00:00:00.000000000 Z
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