rgeo 0.1.10
Sign up to get free protection for your applications and to get access to all the features.
- data/History.rdoc +22 -0
- data/README.rdoc +124 -0
- data/Version +1 -0
- data/ext/geos_c_impl/extconf.rb +72 -0
- data/ext/geos_c_impl/factory.c +468 -0
- data/ext/geos_c_impl/factory.h +217 -0
- data/ext/geos_c_impl/geometry.c +644 -0
- data/ext/geos_c_impl/geometry.h +65 -0
- data/ext/geos_c_impl/geometry_collection.c +580 -0
- data/ext/geos_c_impl/geometry_collection.h +79 -0
- data/ext/geos_c_impl/globals.h +58 -0
- data/ext/geos_c_impl/line_string.c +468 -0
- data/ext/geos_c_impl/line_string.h +74 -0
- data/ext/geos_c_impl/main.c +65 -0
- data/ext/geos_c_impl/point.c +201 -0
- data/ext/geos_c_impl/point.h +77 -0
- data/ext/geos_c_impl/polygon.c +259 -0
- data/ext/geos_c_impl/polygon.h +76 -0
- data/ext/geos_c_impl/preface.h +42 -0
- data/lib/rgeo.rb +68 -0
- data/lib/rgeo/errors.rb +59 -0
- data/lib/rgeo/features.rb +89 -0
- data/lib/rgeo/features/curve.rb +155 -0
- data/lib/rgeo/features/factory.rb +191 -0
- data/lib/rgeo/features/geometry.rb +560 -0
- data/lib/rgeo/features/geometry_collection.rb +118 -0
- data/lib/rgeo/features/line.rb +65 -0
- data/lib/rgeo/features/line_string.rb +101 -0
- data/lib/rgeo/features/linear_ring.rb +65 -0
- data/lib/rgeo/features/multi_curve.rb +112 -0
- data/lib/rgeo/features/multi_line_string.rb +65 -0
- data/lib/rgeo/features/multi_point.rb +72 -0
- data/lib/rgeo/features/multi_polygon.rb +96 -0
- data/lib/rgeo/features/multi_surface.rb +115 -0
- data/lib/rgeo/features/point.rb +97 -0
- data/lib/rgeo/features/polygon.rb +141 -0
- data/lib/rgeo/features/surface.rb +121 -0
- data/lib/rgeo/geo_json.rb +58 -0
- data/lib/rgeo/geo_json/coder.rb +305 -0
- data/lib/rgeo/geo_json/entities.rb +284 -0
- data/lib/rgeo/geo_json/interface.rb +95 -0
- data/lib/rgeo/geography.rb +75 -0
- data/lib/rgeo/geography/common/geometry_collection_methods.rb +206 -0
- data/lib/rgeo/geography/common/geometry_methods.rb +92 -0
- data/lib/rgeo/geography/common/helper.rb +102 -0
- data/lib/rgeo/geography/common/line_string_methods.rb +187 -0
- data/lib/rgeo/geography/common/point_methods.rb +149 -0
- data/lib/rgeo/geography/common/polygon_methods.rb +122 -0
- data/lib/rgeo/geography/factories.rb +136 -0
- data/lib/rgeo/geography/factory.rb +246 -0
- data/lib/rgeo/geography/projected_window.rb +467 -0
- data/lib/rgeo/geography/simple_mercator/feature_classes.rb +320 -0
- data/lib/rgeo/geography/simple_mercator/feature_methods.rb +291 -0
- data/lib/rgeo/geography/simple_mercator/projector.rb +116 -0
- data/lib/rgeo/geography/simple_spherical/calculations.rb +70 -0
- data/lib/rgeo/geography/simple_spherical/geometry_collection_impl.rb +66 -0
- data/lib/rgeo/geography/simple_spherical/geometry_methods.rb +59 -0
- data/lib/rgeo/geography/simple_spherical/line_string_impl.rb +104 -0
- data/lib/rgeo/geography/simple_spherical/multi_line_string_impl.rb +67 -0
- data/lib/rgeo/geography/simple_spherical/multi_point_impl.rb +67 -0
- data/lib/rgeo/geography/simple_spherical/multi_polygon_impl.rb +67 -0
- data/lib/rgeo/geography/simple_spherical/point_impl.rb +85 -0
- data/lib/rgeo/geography/simple_spherical/polygon_impl.rb +66 -0
- data/lib/rgeo/geos.rb +72 -0
- data/lib/rgeo/geos/factory.rb +260 -0
- data/lib/rgeo/geos/impl_additions.rb +57 -0
- data/lib/rgeo/geos/interface.rb +74 -0
- data/lib/rgeo/version.rb +52 -0
- data/tests/geos/tc_factory.rb +91 -0
- data/tests/geos/tc_geometry_collection.rb +226 -0
- data/tests/geos/tc_line_string.rb +310 -0
- data/tests/geos/tc_misc.rb +72 -0
- data/tests/geos/tc_multi_line_string.rb +211 -0
- data/tests/geos/tc_multi_point.rb +202 -0
- data/tests/geos/tc_multi_polygon.rb +210 -0
- data/tests/geos/tc_point.rb +305 -0
- data/tests/geos/tc_polygon.rb +240 -0
- data/tests/simple_mercator/tc_point.rb +303 -0
- data/tests/simple_mercator/tc_window.rb +219 -0
- data/tests/tc_geojson.rb +230 -0
- data/tests/tc_oneoff.rb +61 -0
- metadata +162 -0
@@ -0,0 +1,141 @@
|
|
1
|
+
# -----------------------------------------------------------------------------
|
2
|
+
#
|
3
|
+
# Polygon feature interface
|
4
|
+
#
|
5
|
+
# -----------------------------------------------------------------------------
|
6
|
+
# Copyright 2010 Daniel Azuma
|
7
|
+
#
|
8
|
+
# All rights reserved.
|
9
|
+
#
|
10
|
+
# Redistribution and use in source and binary forms, with or without
|
11
|
+
# modification, are permitted provided that the following conditions are met:
|
12
|
+
#
|
13
|
+
# * Redistributions of source code must retain the above copyright notice,
|
14
|
+
# this list of conditions and the following disclaimer.
|
15
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
16
|
+
# this list of conditions and the following disclaimer in the documentation
|
17
|
+
# and/or other materials provided with the distribution.
|
18
|
+
# * Neither the name of the copyright holder, nor the names of any other
|
19
|
+
# contributors to this software, may be used to endorse or promote products
|
20
|
+
# derived from this software without specific prior written permission.
|
21
|
+
#
|
22
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
23
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
24
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
25
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
26
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
27
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
28
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
29
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
30
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
31
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
32
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
33
|
+
# -----------------------------------------------------------------------------
|
34
|
+
;
|
35
|
+
|
36
|
+
|
37
|
+
module RGeo
|
38
|
+
|
39
|
+
module Features
|
40
|
+
|
41
|
+
|
42
|
+
# == SFS 1.1 Description
|
43
|
+
#
|
44
|
+
# A Polygon is a planar Surface defined by 1 exterior boundary and 0 or
|
45
|
+
# more interior boundaries. Each interior boundary defines a hole in
|
46
|
+
# the Polygon.
|
47
|
+
#
|
48
|
+
# The assertions for Polygons (the rules that define valid Polygons)
|
49
|
+
# are as follows:
|
50
|
+
#
|
51
|
+
# (a) Polygons are topologically closed;
|
52
|
+
#
|
53
|
+
# (b) The boundary of a Polygon consists of a set of LinearRings that
|
54
|
+
# make up its exterior and interior boundaries;
|
55
|
+
#
|
56
|
+
# (c) No two Rings in the boundary cross and the Rings in the boundary
|
57
|
+
# of a Polygon may intersect at a Point but only as a tangent;
|
58
|
+
#
|
59
|
+
# (d) A Polygon may not have cut lines, spikes or punctures;
|
60
|
+
#
|
61
|
+
# (e) The interior of every Polygon is a connected point set;
|
62
|
+
#
|
63
|
+
# (f) The exterior of a Polygon with 1 or more holes is not connected.
|
64
|
+
# Each hole defines a connected component of the exterior.
|
65
|
+
#
|
66
|
+
# In the above assertions, interior, closure and exterior have the
|
67
|
+
# standard topological definitions. The combination of (a) and (c) make
|
68
|
+
# a Polygon a regular closed Point set.
|
69
|
+
#
|
70
|
+
# Polygons are simple geometric objects.
|
71
|
+
#
|
72
|
+
# == Notes
|
73
|
+
#
|
74
|
+
# Polygon is defined as a module and is provided primarily
|
75
|
+
# for the sake of documentation. Implementations need not necessarily
|
76
|
+
# include this module itself. Therefore, you should not depend on the
|
77
|
+
# kind_of? method to check type. Instead, use the provided check_type
|
78
|
+
# class method. A corresponding === operator is also provided to
|
79
|
+
# to support case-when constructs.
|
80
|
+
|
81
|
+
module Polygon
|
82
|
+
|
83
|
+
include Surface
|
84
|
+
include ::Enumerable
|
85
|
+
|
86
|
+
|
87
|
+
# === SFS 1.1 Description
|
88
|
+
#
|
89
|
+
# Returns the exterior ring of this Polygon.
|
90
|
+
#
|
91
|
+
# === Notes
|
92
|
+
#
|
93
|
+
# Returns an object that supports the LinearRing interface.
|
94
|
+
|
95
|
+
def exterior_ring
|
96
|
+
raise Errors::MethodUnimplemented
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
# === SFS 1.1 Description
|
101
|
+
#
|
102
|
+
# Returns the number of interiorRings in this Polygon.
|
103
|
+
#
|
104
|
+
# === Notes
|
105
|
+
#
|
106
|
+
# Returns an integer.
|
107
|
+
|
108
|
+
def num_interior_rings
|
109
|
+
raise Errors::MethodUnimplemented
|
110
|
+
end
|
111
|
+
|
112
|
+
|
113
|
+
# === SFS 1.1 Description
|
114
|
+
#
|
115
|
+
# Returns the Nth interiorRing for this Polygon as a LineString.
|
116
|
+
#
|
117
|
+
# === Notes
|
118
|
+
#
|
119
|
+
# Returns an object that supports the LineString interface, or nil
|
120
|
+
# if the given n is out of range.
|
121
|
+
|
122
|
+
def interior_ring_n(n_)
|
123
|
+
raise Errors::MethodUnimplemented
|
124
|
+
end
|
125
|
+
|
126
|
+
|
127
|
+
# Returns the interior rings as a (possibly empty) array of objects
|
128
|
+
# that support the LinearRing interface.
|
129
|
+
|
130
|
+
def interior_rings
|
131
|
+
raise Errors::MethodUnimplemented
|
132
|
+
end
|
133
|
+
|
134
|
+
|
135
|
+
|
136
|
+
end
|
137
|
+
|
138
|
+
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
# -----------------------------------------------------------------------------
|
2
|
+
#
|
3
|
+
# Surface feature interface
|
4
|
+
#
|
5
|
+
# -----------------------------------------------------------------------------
|
6
|
+
# Copyright 2010 Daniel Azuma
|
7
|
+
#
|
8
|
+
# All rights reserved.
|
9
|
+
#
|
10
|
+
# Redistribution and use in source and binary forms, with or without
|
11
|
+
# modification, are permitted provided that the following conditions are met:
|
12
|
+
#
|
13
|
+
# * Redistributions of source code must retain the above copyright notice,
|
14
|
+
# this list of conditions and the following disclaimer.
|
15
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
16
|
+
# this list of conditions and the following disclaimer in the documentation
|
17
|
+
# and/or other materials provided with the distribution.
|
18
|
+
# * Neither the name of the copyright holder, nor the names of any other
|
19
|
+
# contributors to this software, may be used to endorse or promote products
|
20
|
+
# derived from this software without specific prior written permission.
|
21
|
+
#
|
22
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
23
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
24
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
25
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
26
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
27
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
28
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
29
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
30
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
31
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
32
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
33
|
+
# -----------------------------------------------------------------------------
|
34
|
+
;
|
35
|
+
|
36
|
+
|
37
|
+
module RGeo
|
38
|
+
|
39
|
+
module Features
|
40
|
+
|
41
|
+
|
42
|
+
# == SFS 1.1 Description
|
43
|
+
#
|
44
|
+
# A Surface is a 2-dimensional geometric object.
|
45
|
+
#
|
46
|
+
# A simple Surface consists of a single "patch" that is associated with
|
47
|
+
# one "exterior boundary" and 0 or more "interior" boundaries. Simple
|
48
|
+
# Surfaces in 3-dimensional space are isomorphic to planar Surfaces.
|
49
|
+
# Polyhedral Surfaces are formed by "stitching" together simple
|
50
|
+
# Surfaces along their boundaries, polyhedral Surfaces in 3-dimensional
|
51
|
+
# space may not be planar as a whole.
|
52
|
+
#
|
53
|
+
# The boundary of a simple Surface is the set of closed Curves
|
54
|
+
# corresponding to its "exterior" and "interior" boundaries.
|
55
|
+
#
|
56
|
+
# The only instantiable subclass of Surface defined in this
|
57
|
+
# specification, Polygon, is a simple Surface that is planar.
|
58
|
+
#
|
59
|
+
# == Notes
|
60
|
+
#
|
61
|
+
# Surface is defined as a module and is provided primarily
|
62
|
+
# for the sake of documentation. Implementations need not necessarily
|
63
|
+
# include this module itself. Therefore, you should not depend on the
|
64
|
+
# kind_of? method to check type. Instead, use the provided check_type
|
65
|
+
# class method. A corresponding === operator is also provided to
|
66
|
+
# to support case-when constructs.
|
67
|
+
#
|
68
|
+
# Some implementations may support higher dimensional points.
|
69
|
+
|
70
|
+
module Surface
|
71
|
+
|
72
|
+
include Geometry
|
73
|
+
|
74
|
+
|
75
|
+
# === SFS 1.1 Description
|
76
|
+
#
|
77
|
+
# The area of this Surface, as measured in the spatial reference
|
78
|
+
# system of this Surface.
|
79
|
+
#
|
80
|
+
# === Notes
|
81
|
+
#
|
82
|
+
# Returns a floating-point scalar value.
|
83
|
+
|
84
|
+
def area
|
85
|
+
raise Errors::MethodUnimplemented
|
86
|
+
end
|
87
|
+
|
88
|
+
|
89
|
+
# === SFS 1.1 Description
|
90
|
+
#
|
91
|
+
# The mathematical centroid for this Surface as a Point. The result
|
92
|
+
# is not guaranteed to be on this Surface.
|
93
|
+
#
|
94
|
+
# === Notes
|
95
|
+
#
|
96
|
+
# Returns an object that supports the Point interface.
|
97
|
+
|
98
|
+
def centroid
|
99
|
+
raise Errors::MethodUnimplemented
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
# === SFS 1.1 Description
|
104
|
+
#
|
105
|
+
# A Point guaranteed to be on this Surface.
|
106
|
+
#
|
107
|
+
# === Notes
|
108
|
+
#
|
109
|
+
# Returns an object that supports the Point interface.
|
110
|
+
|
111
|
+
def point_on_surface
|
112
|
+
raise Errors::MethodUnimplemented
|
113
|
+
end
|
114
|
+
|
115
|
+
|
116
|
+
end
|
117
|
+
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# -----------------------------------------------------------------------------
|
2
|
+
#
|
3
|
+
# GeoJSON implementation for RGeo
|
4
|
+
#
|
5
|
+
# -----------------------------------------------------------------------------
|
6
|
+
# Copyright 2010 Daniel Azuma
|
7
|
+
#
|
8
|
+
# All rights reserved.
|
9
|
+
#
|
10
|
+
# Redistribution and use in source and binary forms, with or without
|
11
|
+
# modification, are permitted provided that the following conditions are met:
|
12
|
+
#
|
13
|
+
# * Redistributions of source code must retain the above copyright notice,
|
14
|
+
# this list of conditions and the following disclaimer.
|
15
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
16
|
+
# this list of conditions and the following disclaimer in the documentation
|
17
|
+
# and/or other materials provided with the distribution.
|
18
|
+
# * Neither the name of the copyright holder, nor the names of any other
|
19
|
+
# contributors to this software, may be used to endorse or promote products
|
20
|
+
# derived from this software without specific prior written permission.
|
21
|
+
#
|
22
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
23
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
24
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
25
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
26
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
27
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
28
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
29
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
30
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
31
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
32
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
33
|
+
# -----------------------------------------------------------------------------
|
34
|
+
;
|
35
|
+
|
36
|
+
|
37
|
+
module RGeo
|
38
|
+
|
39
|
+
|
40
|
+
# This is a namespace for a set of tools that provide GeoJSON encoding.
|
41
|
+
# See http://geojson.org/ for more information about this specification.
|
42
|
+
|
43
|
+
module GeoJSON
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
# Dependency source files.
|
51
|
+
paths_ = [
|
52
|
+
'features',
|
53
|
+
'geo_json/entities',
|
54
|
+
'geo_json/coder',
|
55
|
+
'geo_json/interface',
|
56
|
+
]
|
57
|
+
|
58
|
+
paths_.each{ |path_| require "rgeo/#{path_}" }
|
@@ -0,0 +1,305 @@
|
|
1
|
+
# -----------------------------------------------------------------------------
|
2
|
+
#
|
3
|
+
# GeoJSON encoder object
|
4
|
+
#
|
5
|
+
# -----------------------------------------------------------------------------
|
6
|
+
# Copyright 2010 Daniel Azuma
|
7
|
+
#
|
8
|
+
# All rights reserved.
|
9
|
+
#
|
10
|
+
# Redistribution and use in source and binary forms, with or without
|
11
|
+
# modification, are permitted provided that the following conditions are met:
|
12
|
+
#
|
13
|
+
# * Redistributions of source code must retain the above copyright notice,
|
14
|
+
# this list of conditions and the following disclaimer.
|
15
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
16
|
+
# this list of conditions and the following disclaimer in the documentation
|
17
|
+
# and/or other materials provided with the distribution.
|
18
|
+
# * Neither the name of the copyright holder, nor the names of any other
|
19
|
+
# contributors to this software, may be used to endorse or promote products
|
20
|
+
# derived from this software without specific prior written permission.
|
21
|
+
#
|
22
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
23
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
24
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
25
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
26
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
27
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
28
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
29
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
30
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
31
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
32
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
33
|
+
# -----------------------------------------------------------------------------
|
34
|
+
;
|
35
|
+
|
36
|
+
|
37
|
+
require 'json'
|
38
|
+
|
39
|
+
|
40
|
+
module RGeo
|
41
|
+
|
42
|
+
module GeoJSON
|
43
|
+
|
44
|
+
|
45
|
+
# This object encapsulates encoding and decoding settings (principally
|
46
|
+
# the RGeo::Features::Factory and the RGeo::GeoJSON::EntityFactory to
|
47
|
+
# be used) so that you can encode and decode without specifying those
|
48
|
+
# settings every time.
|
49
|
+
|
50
|
+
class Coder
|
51
|
+
|
52
|
+
|
53
|
+
# Create a new coder settings object. The geo factory is passed as
|
54
|
+
# a required argument. The entity factory is optional. To provide
|
55
|
+
# one, pass an option with key <tt>:entity_factory</tt>. It defaults
|
56
|
+
# to the default RGeo::GeoJSON::EntityFactory, which generates
|
57
|
+
# objects of type RGeo::GeoJSON::Feature or RGeo::GeoJSON::FeatureCollection.
|
58
|
+
|
59
|
+
def initialize(geo_factory_, opts_={})
|
60
|
+
@geo_factory = geo_factory_
|
61
|
+
@entity_factory = opts_[:entity_factory] || EntityFactory.instance
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
# Encode the given object as GeoJSON. The object may be one of the
|
66
|
+
# geometry objects specified in RGeo::Features, or an appropriate
|
67
|
+
# GeoJSON wrapper entity supported by this coder's entity factory.
|
68
|
+
|
69
|
+
def encode(object_)
|
70
|
+
if @entity_factory.is_feature_collection?(object_)
|
71
|
+
{
|
72
|
+
'type' => 'FeatureCollection',
|
73
|
+
'features' => @entity_factory.map_feature_collection(object_){ |f_| _encode_feature(f_) },
|
74
|
+
}
|
75
|
+
elsif @entity_factory.is_feature?(object_)
|
76
|
+
_encode_feature(object_)
|
77
|
+
else
|
78
|
+
_encode_geometry(object_)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
# Decode an object from GeoJSON. The input may be a JSON hash, a
|
84
|
+
# String, or an IO object from which to read the JSON string.
|
85
|
+
|
86
|
+
def decode(input_)
|
87
|
+
if input_.kind_of?(::IO)
|
88
|
+
input_ = input_.read rescue nil
|
89
|
+
end
|
90
|
+
if input_.kind_of?(::String)
|
91
|
+
input_ = ::JSON.parse(input_) rescue nil
|
92
|
+
end
|
93
|
+
unless input_.kind_of?(::Hash)
|
94
|
+
return nil
|
95
|
+
end
|
96
|
+
case input_['type']
|
97
|
+
when 'FeatureCollection'
|
98
|
+
features_ = input_['features']
|
99
|
+
features_ = [] unless features_.kind_of?(::Array)
|
100
|
+
decoded_features_ = []
|
101
|
+
features_.each do |f_|
|
102
|
+
if f_['type'] == 'Feature'
|
103
|
+
decoded_features_ << _decode_feature(f_)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
@entity_factory.feature_collection(decoded_features_)
|
107
|
+
when 'Feature'
|
108
|
+
_decode_feature(input_)
|
109
|
+
else
|
110
|
+
_decode_geometry(input_)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
|
115
|
+
# Returns the RGeo::Features::Factory used to generate geometry objects.
|
116
|
+
|
117
|
+
def geo_factory
|
118
|
+
@geo_factory
|
119
|
+
end
|
120
|
+
|
121
|
+
|
122
|
+
# Returns the RGeo::GeoJSON::EntityFactory used to generate GeoJSON
|
123
|
+
# wrapper entities.
|
124
|
+
|
125
|
+
def entity_factory
|
126
|
+
@entity_factory
|
127
|
+
end
|
128
|
+
|
129
|
+
|
130
|
+
def _encode_feature(object_) # :nodoc:
|
131
|
+
json_ = {
|
132
|
+
'type' => 'Feature',
|
133
|
+
'geometry' => _encode_geometry(@entity_factory.get_feature_geometry(object_)),
|
134
|
+
'properties' => @entity_factory.get_feature_properties(object_).dup,
|
135
|
+
}
|
136
|
+
id_ = @entity_factory.get_feature_id(object_)
|
137
|
+
json_['id'] = id_ if id_
|
138
|
+
json_
|
139
|
+
end
|
140
|
+
|
141
|
+
|
142
|
+
def _encode_geometry(object_) # :nodoc:
|
143
|
+
case object_
|
144
|
+
when Features::Point
|
145
|
+
{
|
146
|
+
'type' => 'Point',
|
147
|
+
'coordinates' => [object_.x, object_.y],
|
148
|
+
}
|
149
|
+
when Features::LineString
|
150
|
+
{
|
151
|
+
'type' => 'LineString',
|
152
|
+
'coordinates' => object_.points.map{ |p_| [p_.x, p_.y] },
|
153
|
+
}
|
154
|
+
when Features::Polygon
|
155
|
+
{
|
156
|
+
'type' => 'Polygon',
|
157
|
+
'coordinates' => [object_.exterior_ring.points.map{ |p_| [p_.x, p_.y] }] + object_.interior_rings.map{ |r_| r_.points.map{ |p_| [p_.x, p_.y] } }
|
158
|
+
}
|
159
|
+
when Features::MultiPoint
|
160
|
+
{
|
161
|
+
'type' => 'MultiPoint',
|
162
|
+
'coordinates' => object_.map{ |p_| [p_.x, p_.y] },
|
163
|
+
}
|
164
|
+
when Features::MultiLineString
|
165
|
+
{
|
166
|
+
'type' => 'MultiLineString',
|
167
|
+
'coordinates' => object_.map{ |ls_| ls_.points.map{ |p_| [p_.x, p_.y] } },
|
168
|
+
}
|
169
|
+
when Features::MultiPolygon
|
170
|
+
{
|
171
|
+
'type' => 'MultiPolygon',
|
172
|
+
'coordinates' => object_.map{ |poly_| [poly_.exterior_ring.points.map{ |p_| [p_.x, p_.y] }] + poly_.interior_rings.map{ |r_| r_.points.map{ |p_| [p_.x, p_.y] } } },
|
173
|
+
}
|
174
|
+
when Features::GeometryCollection
|
175
|
+
{
|
176
|
+
'type' => 'GeometryCollection',
|
177
|
+
'geometries' => object_.map{ |geom_| _encode_geometry(geom_) },
|
178
|
+
}
|
179
|
+
else
|
180
|
+
nil
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
|
185
|
+
def _decode_feature(input_) # :nodoc:
|
186
|
+
geometry_ = _decode_geometry(input_['geometry'])
|
187
|
+
if geometry_
|
188
|
+
@entity_factory.feature(geometry_, input_['id'], input_['properties'])
|
189
|
+
else
|
190
|
+
nil
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
|
195
|
+
def _decode_geometry(input_) # :nodoc:
|
196
|
+
case input_['type']
|
197
|
+
when 'GeometryCollection'
|
198
|
+
_decode_geometry_collection(input_)
|
199
|
+
when 'Point'
|
200
|
+
_decode_point_coords(input_['coordinates'])
|
201
|
+
when 'LineString'
|
202
|
+
_decode_line_string_coords(input_['coordinates'])
|
203
|
+
when 'Polygon'
|
204
|
+
_decode_polygon_coords(input_['coordinates'])
|
205
|
+
when 'MultiPoint'
|
206
|
+
_decode_multi_point_coords(input_['coordinates'])
|
207
|
+
when 'MultiLineString'
|
208
|
+
_decode_multi_line_string_coords(input_['coordinates'])
|
209
|
+
when 'MultiPolygon'
|
210
|
+
_decode_multi_polygon_coords(input_['coordinates'])
|
211
|
+
else
|
212
|
+
nil
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
|
217
|
+
def _decode_geometry_collection(input_) # :nodoc:
|
218
|
+
geometries_ = input_['geometries']
|
219
|
+
geometries_ = [] unless geometries_.kind_of?(::Array)
|
220
|
+
decoded_geometries_ = []
|
221
|
+
geometries_.each do |g_|
|
222
|
+
g_ = _decode_geometry(g_)
|
223
|
+
decoded_geometries_ << g_ if g_
|
224
|
+
end
|
225
|
+
@geo_factory.collection(decoded_geometries_)
|
226
|
+
end
|
227
|
+
|
228
|
+
|
229
|
+
def _decode_point_coords(point_coords_) # :nodoc:
|
230
|
+
return nil unless point_coords_.kind_of?(::Array)
|
231
|
+
@geo_factory.point(point_coords_[0].to_f, point_coords_[1].to_f) rescue nil
|
232
|
+
end
|
233
|
+
|
234
|
+
|
235
|
+
def _decode_line_string_coords(line_coords_) # :nodoc:
|
236
|
+
return nil unless line_coords_.kind_of?(::Array)
|
237
|
+
points_ = []
|
238
|
+
line_coords_.each do |point_coords_|
|
239
|
+
point_ = _decode_point_coords(point_coords_)
|
240
|
+
points_ << point_ if point_
|
241
|
+
end
|
242
|
+
@geo_factory.line_string(points_)
|
243
|
+
end
|
244
|
+
|
245
|
+
|
246
|
+
def _decode_polygon_coords(poly_coords_) # :nodoc:
|
247
|
+
return nil unless poly_coords_.kind_of?(::Array)
|
248
|
+
rings_ = []
|
249
|
+
poly_coords_.each do |ring_coords_|
|
250
|
+
return nil unless ring_coords_.kind_of?(::Array)
|
251
|
+
points_ = []
|
252
|
+
ring_coords_.each do |point_coords_|
|
253
|
+
point_ = _decode_point_coords(point_coords_)
|
254
|
+
points_ << point_ if point_
|
255
|
+
end
|
256
|
+
ring_ = @geo_factory.linear_ring(points_)
|
257
|
+
rings_ << ring_ if ring_
|
258
|
+
end
|
259
|
+
if rings_.size == 0
|
260
|
+
nil
|
261
|
+
else
|
262
|
+
@geo_factory.polygon(rings_[0], rings_[1..-1])
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
|
267
|
+
def _decode_multi_point_coords(multi_point_coords_) # :nodoc:
|
268
|
+
return nil unless multi_point_coords_.kind_of?(::Array)
|
269
|
+
points_ = []
|
270
|
+
multi_point_coords_.each do |point_coords_|
|
271
|
+
point_ = _decode_point_coords(point_coords_)
|
272
|
+
points_ << point_ if point_
|
273
|
+
end
|
274
|
+
@geo_factory.multi_point(points_)
|
275
|
+
end
|
276
|
+
|
277
|
+
|
278
|
+
def _decode_multi_line_string_coords(multi_line_coords_) # :nodoc:
|
279
|
+
return nil unless multi_line_coords_.kind_of?(::Array)
|
280
|
+
lines_ = []
|
281
|
+
multi_line_coords_.each do |line_coords_|
|
282
|
+
line_ = _decode_line_string_coords(line_coords_)
|
283
|
+
lines_ << line_ if line_
|
284
|
+
end
|
285
|
+
@geo_factory.multi_line_string(lines_)
|
286
|
+
end
|
287
|
+
|
288
|
+
|
289
|
+
def _decode_multi_polygon_coords(multi_polygon_coords_) # :nodoc:
|
290
|
+
return nil unless multi_polygon_coords_.kind_of?(::Array)
|
291
|
+
polygons_ = []
|
292
|
+
multi_polygon_coords_.each do |poly_coords_|
|
293
|
+
poly_ = _decode_polygon_coords(poly_coords_)
|
294
|
+
polygons_ << poly_ if poly_
|
295
|
+
end
|
296
|
+
@geo_factory.multi_polygon(polygons_)
|
297
|
+
end
|
298
|
+
|
299
|
+
|
300
|
+
end
|
301
|
+
|
302
|
+
|
303
|
+
end
|
304
|
+
|
305
|
+
end
|