schleyfox-rgeo 0.2.5
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.
- data/History.rdoc +199 -0
- data/README.rdoc +172 -0
- data/Spatial_Programming_With_RGeo.rdoc +440 -0
- data/Version +1 -0
- data/ext/geos_c_impl/extconf.rb +84 -0
- data/ext/geos_c_impl/factory.c +468 -0
- data/ext/geos_c_impl/factory.h +224 -0
- data/ext/geos_c_impl/geometry.c +705 -0
- data/ext/geos_c_impl/geometry.h +55 -0
- data/ext/geos_c_impl/geometry_collection.c +482 -0
- data/ext/geos_c_impl/geometry_collection.h +69 -0
- data/ext/geos_c_impl/line_string.c +509 -0
- data/ext/geos_c_impl/line_string.h +64 -0
- data/ext/geos_c_impl/main.c +70 -0
- data/ext/geos_c_impl/point.c +193 -0
- data/ext/geos_c_impl/point.h +62 -0
- data/ext/geos_c_impl/polygon.c +265 -0
- data/ext/geos_c_impl/polygon.h +66 -0
- data/ext/geos_c_impl/preface.h +50 -0
- data/ext/proj4_c_impl/extconf.rb +88 -0
- data/ext/proj4_c_impl/main.c +271 -0
- data/lib/rgeo.rb +124 -0
- data/lib/rgeo/cartesian.rb +60 -0
- data/lib/rgeo/cartesian/analysis.rb +118 -0
- data/lib/rgeo/cartesian/bounding_box.rb +337 -0
- data/lib/rgeo/cartesian/calculations.rb +161 -0
- data/lib/rgeo/cartesian/factory.rb +209 -0
- data/lib/rgeo/cartesian/feature_classes.rb +173 -0
- data/lib/rgeo/cartesian/feature_methods.rb +106 -0
- data/lib/rgeo/cartesian/interface.rb +150 -0
- data/lib/rgeo/coord_sys.rb +79 -0
- data/lib/rgeo/coord_sys/cs/entities.rb +1524 -0
- data/lib/rgeo/coord_sys/cs/factories.rb +208 -0
- data/lib/rgeo/coord_sys/cs/wkt_parser.rb +308 -0
- data/lib/rgeo/coord_sys/proj4.rb +312 -0
- data/lib/rgeo/coord_sys/srs_database/active_record_table.rb +194 -0
- data/lib/rgeo/coord_sys/srs_database/interface.rb +165 -0
- data/lib/rgeo/coord_sys/srs_database/proj4_data.rb +188 -0
- data/lib/rgeo/coord_sys/srs_database/sr_org.rb +108 -0
- data/lib/rgeo/coord_sys/srs_database/url_reader.rb +108 -0
- data/lib/rgeo/error.rb +63 -0
- data/lib/rgeo/feature.rb +88 -0
- data/lib/rgeo/feature/curve.rb +156 -0
- data/lib/rgeo/feature/factory.rb +332 -0
- data/lib/rgeo/feature/factory_generator.rb +138 -0
- data/lib/rgeo/feature/geometry.rb +614 -0
- data/lib/rgeo/feature/geometry_collection.rb +129 -0
- data/lib/rgeo/feature/line.rb +66 -0
- data/lib/rgeo/feature/line_string.rb +102 -0
- data/lib/rgeo/feature/linear_ring.rb +66 -0
- data/lib/rgeo/feature/multi_curve.rb +113 -0
- data/lib/rgeo/feature/multi_line_string.rb +66 -0
- data/lib/rgeo/feature/multi_point.rb +73 -0
- data/lib/rgeo/feature/multi_polygon.rb +97 -0
- data/lib/rgeo/feature/multi_surface.rb +116 -0
- data/lib/rgeo/feature/point.rb +120 -0
- data/lib/rgeo/feature/polygon.rb +141 -0
- data/lib/rgeo/feature/surface.rb +122 -0
- data/lib/rgeo/feature/types.rb +305 -0
- data/lib/rgeo/geographic.rb +75 -0
- data/lib/rgeo/geographic/factory.rb +287 -0
- data/lib/rgeo/geographic/interface.rb +410 -0
- data/lib/rgeo/geographic/proj4_projector.rb +98 -0
- data/lib/rgeo/geographic/projected_feature_classes.rb +213 -0
- data/lib/rgeo/geographic/projected_feature_methods.rb +228 -0
- data/lib/rgeo/geographic/projected_window.rb +467 -0
- data/lib/rgeo/geographic/simple_mercator_projector.rb +157 -0
- data/lib/rgeo/geographic/spherical_feature_classes.rb +212 -0
- data/lib/rgeo/geographic/spherical_feature_methods.rb +97 -0
- data/lib/rgeo/geographic/spherical_math.rb +206 -0
- data/lib/rgeo/geos.rb +72 -0
- data/lib/rgeo/geos/factory.rb +301 -0
- data/lib/rgeo/geos/impl_additions.rb +76 -0
- data/lib/rgeo/geos/interface.rb +139 -0
- data/lib/rgeo/geos/zm_factory.rb +275 -0
- data/lib/rgeo/geos/zm_impl.rb +432 -0
- data/lib/rgeo/impl_helper.rb +53 -0
- data/lib/rgeo/impl_helper/basic_geometry_collection_methods.rb +235 -0
- data/lib/rgeo/impl_helper/basic_geometry_methods.rb +85 -0
- data/lib/rgeo/impl_helper/basic_line_string_methods.rb +197 -0
- data/lib/rgeo/impl_helper/basic_point_methods.rb +138 -0
- data/lib/rgeo/impl_helper/basic_polygon_methods.rb +121 -0
- data/lib/rgeo/impl_helper/math.rb +50 -0
- data/lib/rgeo/version.rb +52 -0
- data/lib/rgeo/wkrep.rb +72 -0
- data/lib/rgeo/wkrep/wkb_generator.rb +267 -0
- data/lib/rgeo/wkrep/wkb_parser.rb +315 -0
- data/lib/rgeo/wkrep/wkt_generator.rb +275 -0
- data/lib/rgeo/wkrep/wkt_parser.rb +496 -0
- data/test/common/geometry_collection_tests.rb +238 -0
- data/test/common/line_string_tests.rb +324 -0
- data/test/common/multi_line_string_tests.rb +209 -0
- data/test/common/multi_point_tests.rb +201 -0
- data/test/common/multi_polygon_tests.rb +208 -0
- data/test/common/point_tests.rb +331 -0
- data/test/common/polygon_tests.rb +232 -0
- data/test/coord_sys/tc_active_record_table.rb +102 -0
- data/test/coord_sys/tc_ogc_cs.rb +356 -0
- data/test/coord_sys/tc_proj4.rb +138 -0
- data/test/coord_sys/tc_proj4_srs_data.rb +76 -0
- data/test/coord_sys/tc_sr_org.rb +70 -0
- data/test/coord_sys/tc_url_reader.rb +82 -0
- data/test/geos/tc_factory.rb +91 -0
- data/test/geos/tc_geometry_collection.rb +62 -0
- data/test/geos/tc_line_string.rb +62 -0
- data/test/geos/tc_misc.rb +72 -0
- data/test/geos/tc_multi_line_string.rb +62 -0
- data/test/geos/tc_multi_point.rb +62 -0
- data/test/geos/tc_multi_polygon.rb +63 -0
- data/test/geos/tc_point.rb +86 -0
- data/test/geos/tc_polygon.rb +86 -0
- data/test/geos/tc_zmfactory.rb +85 -0
- data/test/projected_geographic/tc_geometry_collection.rb +62 -0
- data/test/projected_geographic/tc_line_string.rb +62 -0
- data/test/projected_geographic/tc_multi_line_string.rb +62 -0
- data/test/projected_geographic/tc_multi_point.rb +62 -0
- data/test/projected_geographic/tc_multi_polygon.rb +63 -0
- data/test/projected_geographic/tc_point.rb +93 -0
- data/test/projected_geographic/tc_polygon.rb +62 -0
- data/test/simple_cartesian/tc_calculations.rb +145 -0
- data/test/simple_cartesian/tc_geometry_collection.rb +69 -0
- data/test/simple_cartesian/tc_line_string.rb +70 -0
- data/test/simple_cartesian/tc_multi_line_string.rb +67 -0
- data/test/simple_cartesian/tc_multi_point.rb +67 -0
- data/test/simple_cartesian/tc_multi_polygon.rb +70 -0
- data/test/simple_cartesian/tc_point.rb +91 -0
- data/test/simple_cartesian/tc_polygon.rb +67 -0
- data/test/simple_mercator/tc_geometry_collection.rb +62 -0
- data/test/simple_mercator/tc_line_string.rb +62 -0
- data/test/simple_mercator/tc_multi_line_string.rb +62 -0
- data/test/simple_mercator/tc_multi_point.rb +62 -0
- data/test/simple_mercator/tc_multi_polygon.rb +63 -0
- data/test/simple_mercator/tc_point.rb +93 -0
- data/test/simple_mercator/tc_polygon.rb +62 -0
- data/test/simple_mercator/tc_window.rb +219 -0
- data/test/spherical_geographic/tc_calculations.rb +203 -0
- data/test/spherical_geographic/tc_geometry_collection.rb +70 -0
- data/test/spherical_geographic/tc_line_string.rb +70 -0
- data/test/spherical_geographic/tc_multi_line_string.rb +67 -0
- data/test/spherical_geographic/tc_multi_point.rb +67 -0
- data/test/spherical_geographic/tc_multi_polygon.rb +70 -0
- data/test/spherical_geographic/tc_point.rb +100 -0
- data/test/spherical_geographic/tc_polygon.rb +67 -0
- data/test/tc_cartesian_analysis.rb +107 -0
- data/test/tc_oneoff.rb +63 -0
- data/test/wkrep/tc_wkb_generator.rb +249 -0
- data/test/wkrep/tc_wkb_parser.rb +353 -0
- data/test/wkrep/tc_wkt_generator.rb +362 -0
- data/test/wkrep/tc_wkt_parser.rb +480 -0
- metadata +267 -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 Feature
|
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 (or === operator) defined in the Type module.
|
79
|
+
|
80
|
+
module Polygon
|
81
|
+
|
82
|
+
extend Type
|
83
|
+
|
84
|
+
include Surface
|
85
|
+
include ::Enumerable
|
86
|
+
|
87
|
+
|
88
|
+
# === SFS 1.1 Description
|
89
|
+
#
|
90
|
+
# Returns the exterior ring of this Polygon.
|
91
|
+
#
|
92
|
+
# === Notes
|
93
|
+
#
|
94
|
+
# Returns an object that supports the LinearRing interface.
|
95
|
+
|
96
|
+
def exterior_ring
|
97
|
+
raise Error::UnsupportedOperation, "Method Polygon#exterior_ring not defined."
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
# === SFS 1.1 Description
|
102
|
+
#
|
103
|
+
# Returns the number of interiorRings in this Polygon.
|
104
|
+
#
|
105
|
+
# === Notes
|
106
|
+
#
|
107
|
+
# Returns an integer.
|
108
|
+
|
109
|
+
def num_interior_rings
|
110
|
+
raise Error::UnsupportedOperation, "Method Polygon#num_interior_rings not defined."
|
111
|
+
end
|
112
|
+
|
113
|
+
|
114
|
+
# === SFS 1.1 Description
|
115
|
+
#
|
116
|
+
# Returns the Nth interiorRing for this Polygon as a LineString.
|
117
|
+
#
|
118
|
+
# === Notes
|
119
|
+
#
|
120
|
+
# Returns an object that supports the LinearRing interface, or nil
|
121
|
+
# if the given n is out of range.
|
122
|
+
|
123
|
+
def interior_ring_n(n_)
|
124
|
+
raise Error::UnsupportedOperation, "Method Polygon#interior_ring_n not defined."
|
125
|
+
end
|
126
|
+
|
127
|
+
|
128
|
+
# Returns the interior rings as a (possibly empty) array of objects
|
129
|
+
# that support the LinearRing interface.
|
130
|
+
|
131
|
+
def interior_rings
|
132
|
+
raise Error::UnsupportedOperation, "Method Polygon#interior_rings not defined."
|
133
|
+
end
|
134
|
+
|
135
|
+
|
136
|
+
end
|
137
|
+
|
138
|
+
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
@@ -0,0 +1,122 @@
|
|
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 Feature
|
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 (or === operator) defined in the Type module.
|
66
|
+
#
|
67
|
+
# Some implementations may support higher dimensional points.
|
68
|
+
|
69
|
+
module Surface
|
70
|
+
|
71
|
+
extend Type
|
72
|
+
|
73
|
+
include Geometry
|
74
|
+
|
75
|
+
|
76
|
+
# === SFS 1.1 Description
|
77
|
+
#
|
78
|
+
# The area of this Surface, as measured in the spatial reference
|
79
|
+
# system of this Surface.
|
80
|
+
#
|
81
|
+
# === Notes
|
82
|
+
#
|
83
|
+
# Returns a floating-point scalar value.
|
84
|
+
|
85
|
+
def area
|
86
|
+
raise Error::UnsupportedOperation, "Method Surface#area not defined."
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
# === SFS 1.1 Description
|
91
|
+
#
|
92
|
+
# The mathematical centroid for this Surface as a Point. The result
|
93
|
+
# is not guaranteed to be on this Surface.
|
94
|
+
#
|
95
|
+
# === Notes
|
96
|
+
#
|
97
|
+
# Returns an object that supports the Point interface.
|
98
|
+
|
99
|
+
def centroid
|
100
|
+
raise Error::UnsupportedOperation, "Method Surface#centroid not defined."
|
101
|
+
end
|
102
|
+
|
103
|
+
|
104
|
+
# === SFS 1.1 Description
|
105
|
+
#
|
106
|
+
# A Point guaranteed to be on this Surface.
|
107
|
+
#
|
108
|
+
# === Notes
|
109
|
+
#
|
110
|
+
# Returns an object that supports the Point interface.
|
111
|
+
|
112
|
+
def point_on_surface
|
113
|
+
raise Error::UnsupportedOperation, "Method Surface#point_on_surface not defined."
|
114
|
+
end
|
115
|
+
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
@@ -0,0 +1,305 @@
|
|
1
|
+
# -----------------------------------------------------------------------------
|
2
|
+
#
|
3
|
+
# Feature type management and casting
|
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 Feature
|
40
|
+
|
41
|
+
|
42
|
+
# All geometry implementations MUST include this submodule.
|
43
|
+
# This serves as a marker that may be used to test an object for
|
44
|
+
# feature-ness.
|
45
|
+
|
46
|
+
module Instance
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
# These methods are available as module methods (not instance methods)
|
51
|
+
# of the various feature types.
|
52
|
+
# For example, you may determine whether a feature object is a
|
53
|
+
# point by calling:
|
54
|
+
#
|
55
|
+
# ::RGeo::Feature::Point.check_type(object)
|
56
|
+
#
|
57
|
+
# A corresponding === operator is provided so you can use the type
|
58
|
+
# modules in a case-when clause.
|
59
|
+
#
|
60
|
+
# You may also use the presence of this module to determine whether
|
61
|
+
# a particular object is a feature type:
|
62
|
+
#
|
63
|
+
# object.kind_of?(::RGeo::Feature::Type)
|
64
|
+
|
65
|
+
module Type
|
66
|
+
|
67
|
+
|
68
|
+
# Deprecated alias for RGeo::Feature::Instance
|
69
|
+
Instance = Feature::Instance
|
70
|
+
|
71
|
+
|
72
|
+
# Returns true if the given object is this type or a subtype
|
73
|
+
# thereof, or if it is a feature object whose geometry_type is
|
74
|
+
# this type or a subtype thereof.
|
75
|
+
#
|
76
|
+
# Note that feature objects need not actually include this module.
|
77
|
+
|
78
|
+
def check_type(rhs_)
|
79
|
+
rhs_ = rhs_.geometry_type if rhs_.kind_of?(Feature::Instance)
|
80
|
+
rhs_.kind_of?(Type) && (rhs_ == self || rhs_.include?(self))
|
81
|
+
end
|
82
|
+
alias_method :===, :check_type
|
83
|
+
|
84
|
+
|
85
|
+
# Returns true if this type is the same type or a subtype of the
|
86
|
+
# given type.
|
87
|
+
|
88
|
+
def subtype_of?(type_)
|
89
|
+
self == type_ || self.include?(type_)
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
# Returns the OpenGIS type name of this type.
|
94
|
+
|
95
|
+
def type_name
|
96
|
+
self.name.sub('RGeo::Feature::', '')
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
class << self
|
104
|
+
|
105
|
+
|
106
|
+
# Cast the given object according to the given parameters, if
|
107
|
+
# possible, and return the resulting object. If the requested cast
|
108
|
+
# is not possible, nil is returned.
|
109
|
+
#
|
110
|
+
# Parameters may be provided as a hash, or as separate arguments.
|
111
|
+
# Hash keys are as follows:
|
112
|
+
#
|
113
|
+
# [<tt>:factory</tt>]
|
114
|
+
# Set the factory to the given factory. If this argument is not
|
115
|
+
# given, the original object's factory is kept.
|
116
|
+
# [<tt>:type</tt>]
|
117
|
+
# Cast to the given type, which must be a module in the
|
118
|
+
# RGeo::Feature namespace. If this argument is not given, the
|
119
|
+
# result keeps the same type as the original.
|
120
|
+
# [<tt>:project</tt>]
|
121
|
+
# If this is set to true, and both the original and new factories
|
122
|
+
# support proj4 projections, then the cast will also cause the
|
123
|
+
# coordinates to be transformed between those two projections.
|
124
|
+
# If set to false, the coordinates are not modified. Default is
|
125
|
+
# false.
|
126
|
+
# [<tt>:keep_subtype</tt>]
|
127
|
+
# Value must be a boolean indicating whether to keep the subtype
|
128
|
+
# of the original. If set to false, casting to a particular type
|
129
|
+
# always casts strictly to that type, even if the old type is a
|
130
|
+
# subtype of the new type. If set to true, the cast retains the
|
131
|
+
# subtype in that case. For example, casting a LinearRing to a
|
132
|
+
# LineString will normally yield a LineString, even though
|
133
|
+
# LinearRing is already a more specific subtype. If you set this
|
134
|
+
# value to true, the casted object will remain a LinearRing.
|
135
|
+
# Default is false.
|
136
|
+
# [<tt>:force_new</tt>]
|
137
|
+
# Always return a newly-created object, even if neither the type
|
138
|
+
# nor factory is modified. Normally, if this is set to false, and
|
139
|
+
# a cast is not set to modify either the factory or type, the
|
140
|
+
# original object itself is returned. Setting this flag to true
|
141
|
+
# causes cast to return a clone in that case. Default is false.
|
142
|
+
#
|
143
|
+
# You may also pass the new factory, the new type, and the flags
|
144
|
+
# as separate arguments. In this case, the flag names must be
|
145
|
+
# passed as symbols, and their effect is the same as setting their
|
146
|
+
# values to true. You can even combine separate arguments and hash
|
147
|
+
# arguments. For example, the following three calls are equivalent:
|
148
|
+
#
|
149
|
+
# Feature.cast(geom, :type => Feature::Point, :project => true)
|
150
|
+
# Feature.cast(geom, Feature::Point, :project => true)
|
151
|
+
# Feature.cast(geom, Feature::Point, :project)
|
152
|
+
#
|
153
|
+
# RGeo provides a default casting algorithm. Individual feature
|
154
|
+
# implementation factories may override this and customize the
|
155
|
+
# casting behavior by defining the override_cast method. See
|
156
|
+
# ::RGeo::Feature::Factory#override_cast for more details.
|
157
|
+
|
158
|
+
def cast(obj_, *params_)
|
159
|
+
# Interpret params
|
160
|
+
factory_ = obj_.factory
|
161
|
+
type_ = obj_.geometry_type
|
162
|
+
opts_ = {}
|
163
|
+
params_.each do |param_|
|
164
|
+
case param_
|
165
|
+
when Factory::Instance
|
166
|
+
opts_[:factory] = param_
|
167
|
+
when Type
|
168
|
+
opts_[:type] = param_
|
169
|
+
when ::Symbol
|
170
|
+
opts_[param_] = true
|
171
|
+
when ::Hash
|
172
|
+
opts_.merge!(param_)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
force_new_ = opts_[:force_new]
|
176
|
+
keep_subtype_ = opts_[:keep_subtype]
|
177
|
+
project_ = opts_[:project]
|
178
|
+
nfactory_ = opts_.delete(:factory) || factory_
|
179
|
+
ntype_ = opts_.delete(:type) || type_
|
180
|
+
|
181
|
+
# Let the factory override
|
182
|
+
if nfactory_.respond_to?(:override_cast)
|
183
|
+
override_ = nfactory_.override_cast(obj_, ntype_, opts_)
|
184
|
+
return override_ unless override_ == false
|
185
|
+
end
|
186
|
+
|
187
|
+
# Default algorithm
|
188
|
+
ntype_ = type_ if keep_subtype_ && type_.include?(ntype_)
|
189
|
+
if ntype_ == type_
|
190
|
+
# Types are the same
|
191
|
+
if nfactory_ == factory_
|
192
|
+
force_new_ ? obj_.dup : obj_
|
193
|
+
else
|
194
|
+
if type_ == Point
|
195
|
+
proj_ = nproj_ = nil
|
196
|
+
if project_
|
197
|
+
proj_ = factory_.proj4
|
198
|
+
nproj_ = nfactory_.proj4
|
199
|
+
end
|
200
|
+
hasz_ = factory_.property(:has_z_coordinate)
|
201
|
+
nhasz_ = nfactory_.property(:has_z_coordinate)
|
202
|
+
if proj_ && nproj_
|
203
|
+
coords_ = CoordSys::Proj4.transform_coords(proj_, nproj_, obj_.x, obj_.y, hasz_ ? obj_.z : nil)
|
204
|
+
coords_ << (hasz_ ? obj_.z : 0.0) if nhasz_ && coords_.size < 3
|
205
|
+
else
|
206
|
+
coords_ = [obj_.x, obj_.y]
|
207
|
+
coords_ << (hasz_ ? obj_.z : 0.0) if nhasz_
|
208
|
+
end
|
209
|
+
coords_ << (factory_.property(:has_m_coordinate) ? obj_.m : 0.0) if nfactory_.property(:has_m_coordinate)
|
210
|
+
nfactory_.point(*coords_)
|
211
|
+
elsif type_ == Line
|
212
|
+
nfactory_.line(cast(obj_.start_point, nfactory_, opts_), cast(obj_.end_point, nfactory_, opts_))
|
213
|
+
elsif type_ == LinearRing
|
214
|
+
nfactory_.linear_ring(obj_.points.map{ |p_| cast(p_, nfactory_, opts_) })
|
215
|
+
elsif type_ == LineString
|
216
|
+
nfactory_.line_string(obj_.points.map{ |p_| cast(p_, nfactory_, opts_) })
|
217
|
+
elsif type_ == Polygon
|
218
|
+
nfactory_.polygon(cast(obj_.exterior_ring, nfactory_, opts_),
|
219
|
+
obj_.interior_rings.map{ |r_| cast(r_, nfactory_, opts_) })
|
220
|
+
elsif type_ == MultiPoint
|
221
|
+
nfactory_.multi_point(obj_.map{ |g_| cast(g_, nfactory_, opts_) })
|
222
|
+
elsif type_ == MultiLineString
|
223
|
+
nfactory_.multi_line_string(obj_.map{ |g_| cast(g_, nfactory_, opts_) })
|
224
|
+
elsif type_ == MultiPolygon
|
225
|
+
nfactory_.multi_polygon(obj_.map{ |g_| cast(g_, nfactory_, opts_) })
|
226
|
+
elsif type_ == GeometryCollection
|
227
|
+
nfactory_.collection(obj_.map{ |g_| cast(g_, nfactory_, opts_) })
|
228
|
+
else
|
229
|
+
nil
|
230
|
+
end
|
231
|
+
end
|
232
|
+
else
|
233
|
+
# Types are different
|
234
|
+
if ntype_ == Point && (type_ == MultiPoint || type_ == GeometryCollection) ||
|
235
|
+
(ntype_ == Line || ntype_ == LineString || ntype_ == LinearRing) && (type_ == MultiLineString || type_ == GeometryCollection) ||
|
236
|
+
ntype_ == Polygon && (type_ == MultiPolygon || type_ == GeometryCollection)
|
237
|
+
then
|
238
|
+
if obj_.num_geometries == 1
|
239
|
+
cast(obj_.geometry_n(0), nfactory_, ntype_, opts_)
|
240
|
+
else
|
241
|
+
nil
|
242
|
+
end
|
243
|
+
elsif ntype_ == Point
|
244
|
+
nil
|
245
|
+
elsif ntype_ == Line
|
246
|
+
if type_ == LineString && obj_.num_points == 2
|
247
|
+
nfactory_.line(cast(obj_.point_n(0), nfactory_, opts_), cast(obj_.point_n(1), nfactory_, opts_))
|
248
|
+
else
|
249
|
+
nil
|
250
|
+
end
|
251
|
+
elsif ntype_ == LinearRing
|
252
|
+
if type_ == LineString
|
253
|
+
nfactory_.linear_ring(obj_.points.map{ |p_| cast(p_, nfactory_, opts_) })
|
254
|
+
else
|
255
|
+
nil
|
256
|
+
end
|
257
|
+
elsif ntype_ == LineString
|
258
|
+
if type_ == Line || type_ == LinearRing
|
259
|
+
nfactory_.line_string(obj_.points.map{ |p_| cast(p_, nfactory_, opts_) })
|
260
|
+
else
|
261
|
+
nil
|
262
|
+
end
|
263
|
+
elsif ntype_ == MultiPoint
|
264
|
+
if type_ == Point
|
265
|
+
nfactory_.multi_point([cast(obj_, nfactory_, opts_)])
|
266
|
+
elsif type_ == GeometryCollection
|
267
|
+
nfactory_.multi_point(obj_.map{ |g_| cast(p_, nfactory_, opts_) })
|
268
|
+
else
|
269
|
+
nil
|
270
|
+
end
|
271
|
+
elsif ntype_ == MultiLineString
|
272
|
+
if type_ == Line || type_ == LinearRing || type_ == LineString
|
273
|
+
nfactory_.multi_line_string([cast(obj_, nfactory_, opts_)])
|
274
|
+
elsif type_ == GeometryCollection
|
275
|
+
nfactory_.multi_line_string(obj_.map{ |g_| cast(p_, nfactory_, opts_) })
|
276
|
+
else
|
277
|
+
nil
|
278
|
+
end
|
279
|
+
elsif ntype_ == MultiPolygon
|
280
|
+
if type_ == Polygon
|
281
|
+
nfactory_.multi_polygon([cast(obj_, nfactory_, opts_)])
|
282
|
+
elsif type_ == GeometryCollection
|
283
|
+
nfactory_.multi_polygon(obj_.map{ |g_| cast(p_, nfactory_, opts_) })
|
284
|
+
else
|
285
|
+
nil
|
286
|
+
end
|
287
|
+
elsif ntype_ == GeometryCollection
|
288
|
+
if type_ == MultiPoint || type_ == MultiLineString || type_ == MultiPolygon
|
289
|
+
nfactory_.collection(obj_.map{ |g_| cast(p_, nfactory_, opts_) })
|
290
|
+
else
|
291
|
+
nfactory_.collection([cast(obj_, nfactory_, opts_)])
|
292
|
+
end
|
293
|
+
else
|
294
|
+
nil
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
|
300
|
+
end
|
301
|
+
|
302
|
+
|
303
|
+
end
|
304
|
+
|
305
|
+
end
|