charta 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,92 @@
1
+ require 'nokogiri'
2
+
3
+ class GmlImport
4
+ def initialize(data)
5
+ @shapes = nil
6
+ @xml = data
7
+ end
8
+
9
+ def valid?
10
+ shapes
11
+ geometries = as_geojson || {}
12
+
13
+ !geometries.empty?
14
+ end
15
+
16
+ def sanitize(xml)
17
+ xml.to_s.split.join(' ')
18
+ end
19
+
20
+ def shapes(options = {})
21
+ options[:to] ||= ''
22
+
23
+ f = sanitize @xml
24
+
25
+ doc = Nokogiri::XML(f) do |config|
26
+ config.options = Nokogiri::XML::ParseOptions::NOBLANKS
27
+ end
28
+
29
+ @shapes = doc.root
30
+
31
+ if options[:to].equal? :xml
32
+ @shapes = @shapes.to_xml
33
+ elsif options[:to].equal? :string
34
+ @shapes = @shapes.to_s
35
+ else
36
+ @shapes
37
+ end
38
+ end
39
+
40
+ def as_geojson
41
+ geojson_features_collection = {}
42
+ geojson_features = []
43
+
44
+ if @shapes.is_a? Nokogiri::XML::Node
45
+
46
+ geojson_features << featurize(@shapes)
47
+
48
+ elsif @shapes.is_a? Nokogiri::XML::NodeSet
49
+
50
+ @shapes.each do |node|
51
+ geojson_features << featurize(node)
52
+ end
53
+
54
+ end
55
+
56
+ geojson_features_collection = {
57
+ type: 'FeatureCollection',
58
+ features: geojson_features
59
+ }
60
+
61
+ geojson_features_collection
62
+ end
63
+
64
+ private
65
+
66
+ def featurize(node)
67
+ if node.element? && node.xpath('.//gml:Polygon')
68
+ geojson_feature = {}
69
+
70
+ geometry = node.xpath('.//gml:Polygon')
71
+ geometry.first['srsName'] = 'EPSG:2154'
72
+
73
+ if ::Charta::GML.valid?(geometry)
74
+
75
+ # properties
76
+ id = (Time.zone.now.to_i.to_s + Time.zone.now.usec.to_s)
77
+
78
+ geojson_feature = {
79
+ type: 'Feature',
80
+ properties: {
81
+ internal_id: id
82
+ }.reject { |_, v| v.nil? },
83
+ geometry: ::Charta.new_geometry(geometry.to_xml, nil, 'gml').transform(:WGS84).to_geojson
84
+ }.reject { |_, v| v.nil? }
85
+
86
+ return geojson_feature
87
+ else
88
+ return false
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,92 @@
1
+ require 'nokogiri'
2
+
3
+ module Charta
4
+ # Represents a Geometry with SRID
5
+ class KML
6
+ attr_reader :srid
7
+
8
+ TAGS = %w[Point LineString Polygon MultiGeometry].freeze
9
+
10
+ def initialize(data, srid = :WGS84)
11
+ @kml = if data.is_a? String
12
+
13
+ Nokogiri::XML(data.to_s.split.join(' ')) do |config|
14
+ config.options = Nokogiri::XML::ParseOptions::NOBLANKS
15
+ end
16
+
17
+ else
18
+ # Nokogiri::XML::Document expected
19
+ data
20
+ end
21
+ @srid = Charta.find_srid(srid)
22
+ end
23
+
24
+ def to_ewkt
25
+ "SRID=#{@srid};" + self.class.document_to_ewkt(@kml)
26
+ end
27
+
28
+ def valid?
29
+ to_ewkt
30
+ true
31
+ # rescue
32
+ # false
33
+ end
34
+
35
+ class << self
36
+ # Test is given data is a valid KML
37
+ def valid?(data, srid = :WGS84)
38
+ new(data, srid).valid?
39
+ # rescue
40
+ # false
41
+ end
42
+
43
+ def object_to_ewkt(fragment)
44
+ send("#{Charta.underscore(fragment.name)}_to_ewkt", fragment)
45
+ end
46
+
47
+ def document_to_ewkt(kml)
48
+ return 'GEOMETRYCOLLECTION EMPTY' if kml.css('Document').nil?
49
+ 'GEOMETRYCOLLECTION(' + kml.css('Placemark').collect do |placemark|
50
+ TAGS.collect do |tag|
51
+ next if placemark.css(tag).empty?
52
+ placemark.css(tag).collect do |fragment|
53
+ object_to_ewkt(fragment)
54
+ end.compact.join(', ')
55
+ end.compact.join(', ')
56
+ end.compact.join(', ') + ')'
57
+ end
58
+ alias geometry_collection_to_ewkt document_to_ewkt
59
+
60
+ def feature_to_ewkt(kml)
61
+ object_to_ewkt(kml)
62
+ end
63
+
64
+ def point_to_ewkt(kml)
65
+ return 'POINT EMPTY' if kml.css('coordinates').nil?
66
+ 'POINT(' + kml.css('coordinates').collect { |coords| coords.content.split ',' }.flatten.join(' ') + ')'
67
+ end
68
+
69
+ def line_string_to_ewkt(kml)
70
+ return 'LINESTRING EMPTY' if kml.css('coordinates').nil?
71
+
72
+ 'LINESTRING(' + kml.css('coordinates').collect { |coords| coords.content.split(/\r\n|\n| /) }.flatten.reject(&:empty?).collect { |c| c.split ',' }.collect { |dimension| %(#{dimension.first} #{dimension[1]}) }.join(', ') + ')'
73
+ end
74
+
75
+ def polygon_to_ewkt(kml)
76
+ return 'POLYGON EMPTY' if kml.css('coordinates').nil?
77
+
78
+ 'POLYGON(' + %w[outerBoundaryIs innerBoundaryIs].collect do |boundary|
79
+ next if kml.css(boundary).empty?
80
+
81
+ kml.css(boundary).collect do |hole|
82
+ '(' + hole.css('coordinates').collect { |coords| coords.content.split(/\r\n|\n| /) }.flatten.reject(&:empty?).collect { |c| c.split ',' }.collect { |dimension| %(#{dimension.first} #{dimension[1]}) }.join(', ') + ')'
83
+ end.join(', ')
84
+ end.compact.join(', ') + ')'
85
+ end
86
+
87
+ def multigeometry_to_ewkt(_kml)
88
+ raise :not_implemented
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,22 @@
1
+ module Charta
2
+ # Represent a Geometry which contains points in a line string.
3
+ class LineString < Geometry
4
+ # Browse each point
5
+ def each_point(&block)
6
+ if block.arity == 1
7
+ points.each(&block)
8
+ elsif block.arity == 2
9
+ points.each_with_index(&block)
10
+ else
11
+ raise 'Cannot browse each point without parameter'
12
+ end
13
+ end
14
+
15
+ def points
16
+ @points ||= feature.points.map do |point|
17
+ generator = RGeo::WKRep::WKTGenerator.new(tag_format: :ewkt, emit_ewkt_srid: true)
18
+ Point.new(generator.generate(point))
19
+ end || []
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,28 @@
1
+ module Charta
2
+ # Represent a Geometry with contains only polygons
3
+ class MultiPolygon < GeometryCollection
4
+ def each_polygon(&block)
5
+ if block.arity == 1
6
+ polygons.each(&block)
7
+ elsif block.arity == 2
8
+ polygons.each_with_index do |polygon, index|
9
+ yield polygon, index + 1
10
+ end
11
+ else
12
+ raise 'Cannot browse each polygon without parameter'
13
+ end
14
+ end
15
+
16
+ # Extract polygons ordered by 'PointOnSurface' position
17
+ def polygons
18
+ unless defined? @polygons
19
+ @polygons = []
20
+ feature.each do |polygon|
21
+ generator = RGeo::WKRep::WKTGenerator.new(tag_format: :ewkt, emit_ewkt_srid: true)
22
+ @polygons << Polygon.new(generator.generate(polygon))
23
+ end
24
+ end
25
+ @polygons
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,14 @@
1
+ module Charta
2
+ # Represent a Point
3
+ class Point < Geometry
4
+ def x
5
+ feature.x
6
+ end
7
+ alias longitude x
8
+
9
+ def y
10
+ feature.y
11
+ end
12
+ alias latitude y
13
+ end
14
+ end
@@ -0,0 +1,12 @@
1
+ module Charta
2
+ # Represent a Geometry with contains only polygons
3
+ class Polygon < Geometry
4
+ def exterior_ring
5
+ unless defined? @exterior_ring
6
+ generator = RGeo::WKRep::WKTGenerator.new(tag_format: :ewkt, emit_ewkt_srid: true)
7
+ @exterior_ring = Charta.new_geometry(generator.generate(feature.exterior_ring))
8
+ end
9
+ @exterior_ring
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,3 @@
1
+ module Charta
2
+ VERSION = '0.1.0'.freeze
3
+ end
@@ -0,0 +1,69 @@
1
+ module RGeo
2
+ module SVG
3
+ class << self
4
+ def encode(feature)
5
+ send('encode_' + Charta.underscore(feature.geometry_type.type_name), feature)
6
+ end
7
+
8
+ protected
9
+
10
+ def encode_point(feature)
11
+ 'M' + coordinates(feature)
12
+ end
13
+
14
+ def encode_multi_point(feature)
15
+ points = []
16
+ feature.each do |point|
17
+ points << encode_point(point)
18
+ end
19
+ points.join(' ')
20
+ end
21
+
22
+ def encode_line_string(feature)
23
+ points = []
24
+ feature.points.each do |point|
25
+ points << coordinates(point)
26
+ end
27
+ 'M' + points.join('L')
28
+ end
29
+
30
+ def encode_multi_line_string(feature)
31
+ line_strings = []
32
+ feature.each do |line_string|
33
+ line_strings << encode_line_string(line_string)
34
+ end
35
+ line_strings.join(' ')
36
+ end
37
+
38
+ def encode_polygon(feature)
39
+ rings = []
40
+ # TODO: Optimize useless last point repetition
41
+ rings << encode_line_string(feature.exterior_ring) + 'Z'
42
+ feature.interior_rings.each do |ring|
43
+ rings << encode_line_string(ring) + 'Z'
44
+ end
45
+ rings.join(' ')
46
+ end
47
+
48
+ def encode_multi_polygon(feature)
49
+ polygons = []
50
+ feature.each do |polygon|
51
+ polygons << encode_polygon(polygon)
52
+ end
53
+ polygons.join(' ')
54
+ end
55
+
56
+ def encode_geometry_collection(feature)
57
+ geometries = []
58
+ feature.each do |geometry|
59
+ geometries << encode(geometry)
60
+ end
61
+ geometries.join(' ')
62
+ end
63
+
64
+ def coordinates(feature)
65
+ feature.x.to_s + ',' + feature.y.to_s
66
+ end
67
+ end
68
+ end
69
+ end
metadata ADDED
@@ -0,0 +1,179 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: charta
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Brice TEXIER
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-07-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: nokogiri
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 1.7.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 1.7.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: rgeo
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.6.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.6.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: json
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 1.8.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 1.8.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: rgeo-geojson
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.4.3
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.4.3
69
+ - !ruby/object:Gem::Dependency
70
+ name: bundler
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.14'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.14'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rake
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '10.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '10.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: minitest
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '5.0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '5.0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: byebug
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description:
126
+ email:
127
+ - brice@ekylibre.com
128
+ executables: []
129
+ extensions: []
130
+ extra_rdoc_files: []
131
+ files:
132
+ - ".gitignore"
133
+ - ".travis.yml"
134
+ - CODE_OF_CONDUCT.md
135
+ - Gemfile
136
+ - LICENSE.txt
137
+ - README.md
138
+ - Rakefile
139
+ - charta.gemspec
140
+ - lib/charta.rb
141
+ - lib/charta/bounding_box.rb
142
+ - lib/charta/geo_json.rb
143
+ - lib/charta/geojson_import.rb
144
+ - lib/charta/geometry.rb
145
+ - lib/charta/geometry_collection.rb
146
+ - lib/charta/gml.rb
147
+ - lib/charta/gml_import.rb
148
+ - lib/charta/kml.rb
149
+ - lib/charta/line_string.rb
150
+ - lib/charta/multi_polygon.rb
151
+ - lib/charta/point.rb
152
+ - lib/charta/polygon.rb
153
+ - lib/charta/version.rb
154
+ - lib/rgeo/svg.rb
155
+ homepage: https://github.com/ekylibre/charta
156
+ licenses:
157
+ - MIT
158
+ metadata: {}
159
+ post_install_message:
160
+ rdoc_options: []
161
+ require_paths:
162
+ - lib
163
+ required_ruby_version: !ruby/object:Gem::Requirement
164
+ requirements:
165
+ - - ">="
166
+ - !ruby/object:Gem::Version
167
+ version: '0'
168
+ required_rubygems_version: !ruby/object:Gem::Requirement
169
+ requirements:
170
+ - - ">="
171
+ - !ruby/object:Gem::Version
172
+ version: '0'
173
+ requirements: []
174
+ rubyforge_project:
175
+ rubygems_version: 2.5.2
176
+ signing_key:
177
+ specification_version: 4
178
+ summary: Simple tool over geos and co
179
+ test_files: []