mapwkt 1.0.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.
@@ -0,0 +1,140 @@
1
+ # encoding: UTF-8
2
+
3
+ class MapWKT::Map
4
+ def center
5
+ return @center if @center
6
+ return if self.overlays.empty?
7
+
8
+ n, s, e, w = nil
9
+
10
+ self.overlays.each do |o|
11
+ n = o.center.y if !n || o.center.y > n
12
+ s = o.center.y if !s || o.center.y < s
13
+ e = o.center.x if !e || o.center.x > e
14
+ w = o.center.x if !w || o.center.x < w
15
+ end
16
+
17
+ x = (e + w) / 2
18
+ y = (n + s) / 2
19
+
20
+ @center = MapWKT::Geometry::Point.new(y, x)
21
+ end
22
+
23
+ def center= (center)
24
+ return unless MapWKT::Geometry::Point === center
25
+ @center = center
26
+ end
27
+
28
+ def id
29
+ @id
30
+ end
31
+
32
+ def id= (id)
33
+ return unless id
34
+ raise(ArgumentError, "invalid HTML id: #{id.to_json}") unless id =~ /^[a-zA-Z][\w\d.:-]*$/
35
+ @id = id
36
+ end
37
+
38
+ def initialize (arg = {})
39
+ @overlays = []
40
+
41
+ self.options = case arg
42
+ when String then { id: arg }
43
+ when Hash then arg
44
+ else {}
45
+ end
46
+ end
47
+
48
+ def js_initialize
49
+ "mapwkt_#{self.object_id}_initialize()"
50
+ end
51
+
52
+ def js_output (arg = {})
53
+ self.options = case arg
54
+ when String then { id: arg }
55
+ when Hash then arg
56
+ else {}
57
+ end
58
+
59
+ raise(ArgumentError, "HMTL id is required") unless self.id
60
+
61
+ <<-JAVASCRIPT.gsub('new google.maps.LatLng','new p')
62
+ function mapwkt_#{self.object_id}_initialize ()
63
+ {
64
+ var p = google.maps.LatLng
65
+ var element = document.getElementById('#{self.id}')
66
+ var options = { center: new google.maps.LatLng(#{self.center.latitude_f},#{self.center.longitude_f}), mapTypeId: google.maps.MapTypeId.#{self.map_type_id}, zoom: #{self.zoom} }
67
+ var map = new google.maps.Map(element, options)
68
+ #{self.overlays.map {|obj| obj.js_output('map') }.join("\n ")}
69
+ }
70
+ JAVASCRIPT
71
+ end
72
+
73
+ def map_type_id
74
+ @map_type_id ||= 'ROADMAP'
75
+ end
76
+
77
+ def map_type_id= (map_type_id)
78
+ return unless map_type_id
79
+ @map_type_id = ([map_type_id.to_s.upcase] & %w:HYBRID ROADMAP SATELLITE TERRAIN:).first || 'ROADMAP'
80
+ end
81
+
82
+ def options
83
+ {
84
+ center: self.center,
85
+ id: self.id,
86
+ map_type_id: self.map_type_id,
87
+ zoom: self.zoom
88
+ }
89
+ end
90
+
91
+ def options= (options)
92
+ options.symbolize_keys!
93
+ self.center = options[:center] || self.center
94
+ self.id = options[:id] || self.id
95
+ self.map_type_id = options[:map_type_id] || options[:mapTypeId] || self.map_type_id
96
+ self.zoom = options[:zoom] || self.zoom || 10
97
+ end
98
+
99
+ def overlays
100
+ self.refresh!
101
+ @overlays
102
+ end
103
+
104
+ def refresh!
105
+ return self if @refreshed
106
+ @refreshed = true
107
+
108
+ self.overlays.select! {|p| MapWKT::Overlay === p }
109
+ self
110
+ end
111
+
112
+ def zoom
113
+ @zoom ||= 10
114
+ end
115
+
116
+ def zoom= (zoom)
117
+ return unless zoom
118
+ @zoom = [0,[zoom.to_i, 25].min].max
119
+ end
120
+
121
+ def << (obj)
122
+ overlays = case obj
123
+ when MapWKT::Geometry then [MapWKT::Overlay.new(obj)]
124
+ when MapWKT::Overlay then [obj]
125
+ else
126
+ raise(TypeError, "method `wkt' is not defined for #{obj.inspect}") unless obj.respond_to?(:wkt)
127
+
128
+ MapWKT::Geometry.parse_wkt(obj.wkt).map do |g|
129
+ {
130
+ MapWKT::Geometry::Point => MapWKT::Overlay::Marker,
131
+ MapWKT::Geometry::LineString => MapWKT::Overlay::Polyline,
132
+ MapWKT::Geometry::Polygon => MapWKT::Overlay::Polygon
133
+ }[g.class].new(g, obj)
134
+ end
135
+ end
136
+
137
+ self.overlays.push(*overlays)
138
+ self
139
+ end
140
+ end
@@ -0,0 +1,7 @@
1
+ # encoding: UTF-8
2
+
3
+ class MapWKT::Overlay::Marker < MapWKT::Overlay
4
+ def js_output (map_name = nil)
5
+ "new google.maps.Marker({#{" map: #{map_name}," if map_name} position: new google.maps.LatLng(#{self.geometry.latitude_f},#{self.geometry.longitude_f}) })"
6
+ end
7
+ end
@@ -0,0 +1,20 @@
1
+ # encoding: UTF-8
2
+
3
+ class MapWKT::Overlay
4
+ def center
5
+ self.geometry.center
6
+ end
7
+
8
+ def geometry
9
+ @geometry
10
+ end
11
+
12
+ def initialize (geometry, source)
13
+ @geometry = geometry
14
+ @source = source
15
+ end
16
+
17
+ def source
18
+ @source
19
+ end
20
+ end
@@ -0,0 +1,12 @@
1
+ # encoding: UTF-8
2
+
3
+ class MapWKT::Overlay::Polygon < MapWKT::Overlay
4
+ def js_output (map_name = nil)
5
+ paths = [self.geometry.perimeter, *self.geometry.lacunae].map do |g|
6
+ points = [*g.points, g.points.first]
7
+ "[#{points.map {|p| "new google.maps.LatLng(#{p.latitude_f},#{p.longitude_f})" }.join(?,)}]"
8
+ end.join(?,)
9
+
10
+ "new google.maps.Polygon({#{" map: #{map_name}," if map_name} paths: [#{paths}] })"
11
+ end
12
+ end
@@ -0,0 +1,10 @@
1
+ # encoding: UTF-8
2
+
3
+ class MapWKT::Overlay::Polyline < MapWKT::Overlay
4
+ def js_output (map_name = nil)
5
+ points = self.geometry.open? ? self.geometry.points : [*self.geometry.points, self.geometry.points.first]
6
+ path = "[#{points.map {|p| "new google.maps.LatLng(#{p.latitude_f},#{p.longitude_f})" }.join(?,)}]"
7
+
8
+ "new google.maps.Polyline({#{" map: #{map_name}," if map_name} path: #{path} })"
9
+ end
10
+ end
@@ -0,0 +1,77 @@
1
+ # encoding: UTF-8
2
+
3
+ class MapWKT::Geometry
4
+ def self.parse_wkt (wkt_string)
5
+ # Remove extraneous whitespace.
6
+ s = wkt_string.to_s.upcase.strip.gsub(/\s*([),(])\s*/,'\1').gsub(/\s+/,' ')
7
+
8
+ case s
9
+ when /^POINT\(([\d\s.-]*?)\)$/
10
+ x, y = self.parse_x_y $1
11
+ [MapWKT::Geometry::Point.new(y,x)]
12
+
13
+ when /^LINESTRING\(([\d\s,.-]*?)\)$/
14
+ points = self.parse_points $1
15
+ [MapWKT::Geometry::LineString.new(*points)]
16
+
17
+ when /^POLYGON\((\([\d\s,.-]*?\)(?:,\([\d\s,.-]*?\))*)\)$/
18
+ perimeter, lacunae = self.parse_linestrings $1
19
+ [MapWKT::Geometry::Polygon.new(perimeter, *lacunae)]
20
+
21
+ when /^MULTIPOINT\(([\d\s,.-]*?)\)$/
22
+ self.parse_points $1
23
+
24
+ when /^MULTIPOINT\((\([\d\s,.-]*?\)(?:,\([\d\s,.-]*?\))*)\)$/
25
+ points_string = $1.gsub(/[()]/,'')
26
+ self.parse_points(points_string)
27
+
28
+ when /^MULTILINESTRING\((\([\d\s,.-]*?\)(?:,\([\d\s,.-]*?\))*)\)$/
29
+ self.parse_linestrings $1
30
+
31
+ when /^MULTIPOLYGON\((\(\([\d\s,.-]*?\)(?:,\([\d\s,.-]*?\))*\)(?:,\(\([\d\s,.-]*?\)(?:,\([\d\s,.-]*?\))*\))*)\)$/
32
+ self.parse_polygons $1
33
+
34
+ when /^GEOMETRYCOLLECTION\((.*?)\)$/
35
+ wkt_strings = $1.scan(/([A-Z]+\(.*?\))(?=,[A-Z]|$)/).flatten
36
+ wkt_strings.map {|wkt_string| self.parse_wkt(wkt_string) }.flatten
37
+
38
+ else
39
+ raise SyntaxError
40
+ end
41
+
42
+ rescue SyntaxError
43
+ raise SyntaxError, "not a valid WKT string: #{wkt_string.inspect}"
44
+ end
45
+
46
+ def self.parse_polygons (polygons_string)
47
+ # Create Polygons from each "((x y, …), (x y, …))" in the polygons string.
48
+ polygons_string.scan(/\((\(.*?\))\)/).flatten.map do |linestrings_string|
49
+ perimeter, lacunae = self.parse_linestrings(linestrings_string)
50
+ MapWKT::Geometry::Polygon.new(perimeter, *lacunae)
51
+ end
52
+ end
53
+
54
+ def self.parse_linestrings (linestrings_string)
55
+ # Create LineStrings from each "(x y, …)" in the linestrings string.
56
+ linestrings_string.scan(/\((.*?)\)/).flatten.map do |points_string|
57
+ points = self.parse_points(points_string)
58
+ MapWKT::Geometry::LineString.new(*points)
59
+ end
60
+ end
61
+
62
+ def self.parse_points (points_string)
63
+ # Create Points from each "x y" in the points string.
64
+ points_string.split(?,).map do |x_y_string|
65
+ x, y = self.parse_x_y(x_y_string)
66
+ MapWKT::Geometry::Point.new(y,x)
67
+ end
68
+ end
69
+
70
+ def self.parse_x_y (x_y_string)
71
+ # Check the string.
72
+ raise SyntaxError unless x_y_string =~ /^(-?\d+(?:\.\d+)?)\s(-?\d+(?:\.\d+)?)$/
73
+
74
+ # Return the x and y values.
75
+ [$1, $2].map(&:to_f)
76
+ end
77
+ end
@@ -0,0 +1,97 @@
1
+ # encoding: UTF-8
2
+
3
+ class MapWKT::Geometry::LineString < MapWKT::Geometry
4
+ # Returns a Point midway between the N/S- & E/W-most Points in the LineString.
5
+ def center
6
+ return if self.points.empty?
7
+ n, s, e, w = nil
8
+
9
+ self.points.each do |p|
10
+ n = p.y if !n || p.y > n
11
+ s = p.y if !s || p.y < s
12
+ e = p.x if !e || p.x > e
13
+ w = p.x if !w || p.x < w
14
+ end
15
+
16
+ x = (e + w) / 2
17
+ y = (n + s) / 2
18
+
19
+ Point.new(y, x)
20
+ end
21
+
22
+ # Returns this LineString after closing its endpoints.
23
+ def close!
24
+ self.refresh! unless @refreshed
25
+ @closed = true
26
+ self
27
+ end
28
+
29
+ # Returns true if this LineString is closed, false otherwise.
30
+ def closed?
31
+ self.refresh!
32
+ @closed ||= false
33
+ end
34
+
35
+ # Returns a new LineString with the same geographic Points as this LineString.
36
+ def dup
37
+ points = self.points.map(&:dup)
38
+ LineString(*points).tap {|ls| ls.close! if self.closed? }
39
+ end
40
+
41
+ # Returns a new LineString containing the given Points.
42
+ def initialize (*points)
43
+ @points = points
44
+ self.refresh!
45
+ end
46
+
47
+ # Returns false if this LineString is closed, true otherwise.
48
+ def open?
49
+ !self.closed?
50
+ end
51
+
52
+ # Returns this LineString after opening its endpoints.
53
+ def open!
54
+ self.refresh!
55
+ @closed = false
56
+ self
57
+ end
58
+
59
+ # Returns the array of Points in this LineString.
60
+ def points
61
+ self.refresh!
62
+ @points
63
+ end
64
+
65
+ # Removes any non-Point objects from this LineString's #points array. If the
66
+ # first Point has been added to the end of the #points array, closes the
67
+ # LineString and removes the Point. Returns this LineString.
68
+ def refresh!
69
+ return self if @refreshed
70
+ @refreshed = true
71
+
72
+ self.points.select! {|p| MapWKT::Geometry::Point === p }
73
+
74
+ while (self.points.many?) && (self.points.last == self.points.first)
75
+ self.points.pop
76
+ @closed = true
77
+ end
78
+
79
+ self
80
+ end
81
+
82
+ # Returns a string representation of this LineString. ⤿ indicates an open
83
+ # LineString, while ⟲ indicates a closed LineString.
84
+ def to_s
85
+ points = self.points.join(", ")
86
+ marker = self.closed? ? ?⟲ : ?⤿
87
+
88
+ "#{marker} #{points} #{marker} "
89
+ end
90
+
91
+ # Returns this LineString's WKT representation, with latitudes and longitudes
92
+ # rounded to 7 decimal places.
93
+ def wkt
94
+ points = self.open? ? self.points : [*self.points, self.points.first]
95
+ "LINESTRING(#{points.map {|p| "#{p.longitude_f} #{p.latitude_f}" }.join(", ")})"
96
+ end
97
+ end
@@ -0,0 +1,123 @@
1
+ # encoding: UTF-8
2
+
3
+ class MapWKT::Geometry::Point < MapWKT::Geometry
4
+ # Returns a new Point with the same latitude and longitude as this Point.
5
+ def center
6
+ self.dup
7
+ end
8
+
9
+ # Returns true if this Point lies in the eastern hemisphere, false otherwise.
10
+ def east?
11
+ self.longitude > 0
12
+ end
13
+
14
+ # Returns true if this Point lies on the equator, false otherwise.
15
+ def equator?
16
+ self.latitude == 0
17
+ end
18
+
19
+ # Returns a new MapWKT::Geometry::Point with latitude and longitude normalized
20
+ # to fit within the range [-90,90] for latitude and (-180,180] for longitude.
21
+ def initialize (φ, λ)
22
+ # Check arguments.
23
+ if [φ, λ].all? {|arg| arg.respond_to?(:to_f) }
24
+ φ = φ.to_f
25
+ λ = λ.to_f
26
+ else
27
+ raise ArgumentError, "expected (latitude, longitude), got (#{φ.inspect}, #{λ.inspect})"
28
+ end
29
+
30
+ # Normalize latitude (-90..90) and longitude (-179..180).
31
+ λ += 180 * (((φ / 90 + 1).floor / 2) % 2)
32
+ @y = 90 - (((90 + φ) % 360) - 180).abs
33
+ @x = self.pole? ? 0 : (λ - 180) % -360 + 180
34
+ end
35
+
36
+ # Returns this Point's latitude as a float, rounded to 7 decimal places.
37
+ def latitude
38
+ self.y.round(7)
39
+ end
40
+
41
+ # Returns this Point's latitude as a string, rounded to 7 decimal places.
42
+ def latitude_f
43
+ sprintf("%.7f", self.latitude).gsub(/\.?0*$/,'')
44
+ end
45
+
46
+ # Returns this Point's latitude in degrees N/S, rounded to 7 decimal places.
47
+ def latitude_°
48
+ φ = self.latitude
49
+ direction = (φ == 0) ? "" : (φ > 0) ? "N" : "S"
50
+
51
+ sprintf("%.7f°%s", φ.abs, direction).gsub(/\.?0*(?=°)/,'')
52
+ end
53
+
54
+ # Returns this Point's longitude as a float, rounded to 7 decimal places.
55
+ def longitude
56
+ self.x.round(7)
57
+ end
58
+
59
+ # Returns this Point's longitude as a string, rounded to 7 decimal places.
60
+ def longitude_f
61
+ sprintf("%.7f", self.longitude).gsub(/\.?0*$/,'')
62
+ end
63
+
64
+ # Returns this Point's longitude in degrees E/W, rounded to 7 decimal places.
65
+ def longitude_°
66
+ λ = self.longitude
67
+ direction = [0, 180].include?(λ) ? "" : (λ > 0) ? "E" : "W"
68
+
69
+ sprintf("%.7f°%s", λ.abs, direction).gsub(/\.?0*(?=°)/,'')
70
+ end
71
+
72
+ # Returns 1 if this Point is the north pole, -1 if it is the south pole, or nil
73
+ # if it is neither.
74
+ def pole?
75
+ return 1 if self.north_pole?
76
+ return -1 if self.south_pole?
77
+ end
78
+
79
+ # Returns true if this Point is the north pole.
80
+ def north_pole?
81
+ self.latitude == 90
82
+ end
83
+
84
+ # Returns true if this Point is the south pole.
85
+ def south_pole?
86
+ self.latitude == -90
87
+ end
88
+
89
+ # Returns a string representation of this Point.
90
+ def to_s
91
+ "#{self.latitude_°} #{self.longitude_°}"
92
+ end
93
+
94
+ # Returns true if this Point lies in the western hemisphere, false otherwise.
95
+ def west?
96
+ self.longitude < 0
97
+ end
98
+
99
+ # Returns this Point's WKT representation, rounded to 7 decimal places.
100
+ def wkt
101
+ "POINT(#{self.longitude_f} #{self.latitude_f})"
102
+ end
103
+
104
+ # Returns this Point's longitude as a float.
105
+ def x
106
+ @x
107
+ end
108
+
109
+ # Returns this Point's latitude as a float.
110
+ def y
111
+ @y
112
+ end
113
+
114
+ # Returns true if this Point matches the other Point, within 7 decimal places.
115
+ def == (other)
116
+ [self.latitude, self.longitude] == [other.latitude, other.longitude]
117
+ end
118
+
119
+ # Returns true if this Point matches the other Point exactly.
120
+ def === (other)
121
+ [self.x, self.y] == [other.x, other.y]
122
+ end
123
+ end
@@ -0,0 +1,42 @@
1
+ # encoding: UTF-8
2
+
3
+ class MapWKT::Geometry::Polygon < MapWKT::Geometry
4
+ # Returns a Point midway between the N/S- & E/W-most Points in the perimeter.
5
+ def center
6
+ self.perimeter.center
7
+ end
8
+
9
+ # Returns a new MapWKT::Geometry::Polygon with the given outer perimeter and
10
+ # internal lacunae. If the given LineStrings were unclosed, closes them for
11
+ # use in the Polygon, but leaves the original LineStrings unchanged.
12
+ def initialize (perimeter, *lacunae)
13
+ @perimeter = perimeter.dup.close!
14
+ @lacunae = lacunae.map {|lacuna| lacuna.dup.close! }
15
+ end
16
+
17
+ # Returns an array of LineStrings representing the geographical areas treated
18
+ # as lacunae in this Polygon's enclosed area. Does not return the objects
19
+ # themselves, nor the actual array containing them.
20
+ def lacunae
21
+ @lacunae.map(&:dup)
22
+ end
23
+
24
+ # Returns a LineString representing the geographical area treated as the
25
+ # outer perimeter of this Polygon's enclosed area. Does not return the actual
26
+ # LineString object used in this Polygon.
27
+ def perimeter
28
+ @perimeter.dup
29
+ end
30
+
31
+ # Returns a string representation of this Polygon. ⭓ indicates the perimeter
32
+ # LineString, while ⬠ indicates a lacuna LineString.
33
+ def to_s
34
+ "⭓ #{@perimeter.points.join(", ")} ⭓#{@lacunae.map {|lacuna| " | ⬠ #{lacuna.points.join(", ")} ⬠" }.join} "
35
+ end
36
+
37
+ # Returns this Polygon's WKT representation, with latitudes and longitudes
38
+ # rounded to 7 decimal places.
39
+ def wkt
40
+ "POLYGON((#{[*@perimeter.points, @perimeter.points.first].map {|p| "#{p.longitude_f} #{p.latitude_f}" }.join(", ")})#{@lacunae.map {|lacuna| ", (#{[*lacuna.points, lacuna.points.first].map {|p| "#{p.longitude_f} #{p.latitude_f}" }.join(", ")})" }.join })"
41
+ end
42
+ end
@@ -0,0 +1,17 @@
1
+ # encoding: UTF-8
2
+
3
+ module MapWKT
4
+ require 'bundler/setup'
5
+ require 'active_support/all'
6
+
7
+ require_relative 'mapwkt/gmap/overlay'
8
+ require_relative 'mapwkt/gmap/map'
9
+ require_relative 'mapwkt/gmap/marker'
10
+ require_relative 'mapwkt/gmap/polygon'
11
+ require_relative 'mapwkt/gmap/polyline'
12
+
13
+ require_relative 'mapwkt/wkt/geometry'
14
+ require_relative 'mapwkt/wkt/line_string'
15
+ require_relative 'mapwkt/wkt/point'
16
+ require_relative 'mapwkt/wkt/polygon'
17
+ end
data/lib/mapwkt.rb ADDED
@@ -0,0 +1,44 @@
1
+ # encoding: UTF-8
2
+
3
+ Geometry = Class.new
4
+ Map = Class.new
5
+ Overlay = Class.new
6
+
7
+ LineString = Class.new(Geometry)
8
+ Point = Class.new(Geometry)
9
+ Polygon = Class.new(Geometry)
10
+
11
+ Marker = Class.new(Overlay)
12
+ PolygonOverlay = Class.new(Overlay)
13
+ Polyline = Class.new(Overlay)
14
+
15
+ # Register the class names in the top-level namespace.
16
+ [
17
+ Geometry, LineString, Map, Marker, Overlay,
18
+ Point, Polygon, PolygonOverlay, Polyline
19
+ ].map(&:name)
20
+
21
+ # Create the namespaced constants pointing to the classes.
22
+ module MapWKT
23
+ Geometry = ::Geometry
24
+ Map = ::Map
25
+ Overlay = ::Overlay
26
+
27
+ class Geometry
28
+ LineString = ::LineString
29
+ Point = ::Point
30
+ Polygon = ::Polygon
31
+ end
32
+
33
+ class Overlay
34
+ Marker = ::Marker
35
+ Polygon = ::PolygonOverlay
36
+ Polyline = ::Polyline
37
+ end
38
+
39
+ require_relative 'mapwkt-safe'
40
+ end
41
+
42
+ def Point (*args) Point.new(*args) end
43
+ def LineString (*args) LineString.new(*args) end
44
+ def Polygon (*args) Polygon.new(*args) end
metadata ADDED
@@ -0,0 +1,56 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mapwkt
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Jesse Sielaff
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-02-11 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: .
15
+ email: jesse.sielaff@gmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - ./lib/mapwkt/gmap/map.rb
21
+ - ./lib/mapwkt/gmap/marker.rb
22
+ - ./lib/mapwkt/gmap/overlay.rb
23
+ - ./lib/mapwkt/gmap/polygon.rb
24
+ - ./lib/mapwkt/gmap/polyline.rb
25
+ - ./lib/mapwkt/wkt/geometry.rb
26
+ - ./lib/mapwkt/wkt/line_string.rb
27
+ - ./lib/mapwkt/wkt/point.rb
28
+ - ./lib/mapwkt/wkt/polygon.rb
29
+ - ./lib/mapwkt-safe.rb
30
+ - ./lib/mapwkt.rb
31
+ homepage:
32
+ licenses: []
33
+ post_install_message:
34
+ rdoc_options: []
35
+ require_paths:
36
+ - lib
37
+ required_ruby_version: !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
40
+ - - ! '>='
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ required_rubygems_version: !ruby/object:Gem::Requirement
44
+ none: false
45
+ requirements:
46
+ - - ! '>='
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ requirements: []
50
+ rubyforge_project:
51
+ rubygems_version: 1.8.23
52
+ signing_key:
53
+ specification_version: 3
54
+ summary: An object library for converting Ruby objects with WKT to JavaScript for
55
+ Google Maps.
56
+ test_files: []