rgeo 1.1.2 → 2.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.
- checksums.yaml +4 -4
- data/ext/geos_c_impl/extconf.rb +5 -3
- data/ext/geos_c_impl/factory.c +4 -4
- data/ext/geos_c_impl/geometry.c +1 -1
- data/lib/rgeo.rb +2 -4
- data/lib/rgeo/cartesian.rb +6 -16
- data/lib/rgeo/cartesian/analysis.rb +22 -20
- data/lib/rgeo/cartesian/bounding_box.rb +83 -79
- data/lib/rgeo/cartesian/calculations.rb +40 -38
- data/lib/rgeo/cartesian/factory.rb +134 -169
- data/lib/rgeo/cartesian/feature_classes.rb +2 -18
- data/lib/rgeo/cartesian/feature_methods.rb +37 -39
- data/lib/rgeo/cartesian/interface.rb +11 -9
- data/lib/rgeo/coord_sys.rb +9 -8
- data/lib/rgeo/coord_sys/cs/entities.rb +345 -303
- data/lib/rgeo/coord_sys/cs/factories.rb +30 -28
- data/lib/rgeo/coord_sys/cs/wkt_parser.rb +128 -126
- data/lib/rgeo/coord_sys/srs_database/{interface.rb → entry.rb} +26 -32
- data/lib/rgeo/coord_sys/srs_database/sr_org.rb +19 -17
- data/lib/rgeo/coord_sys/srs_database/url_reader.rb +21 -19
- data/lib/rgeo/error.rb +3 -1
- data/lib/rgeo/feature.rb +23 -34
- data/lib/rgeo/feature/curve.rb +2 -0
- data/lib/rgeo/feature/factory.rb +15 -13
- data/lib/rgeo/feature/factory_generator.rb +7 -5
- data/lib/rgeo/feature/geometry.rb +31 -29
- data/lib/rgeo/feature/geometry_collection.rb +6 -4
- data/lib/rgeo/feature/line.rb +2 -0
- data/lib/rgeo/feature/line_string.rb +3 -1
- data/lib/rgeo/feature/linear_ring.rb +2 -0
- data/lib/rgeo/feature/multi_curve.rb +2 -0
- data/lib/rgeo/feature/multi_line_string.rb +2 -0
- data/lib/rgeo/feature/multi_point.rb +2 -0
- data/lib/rgeo/feature/multi_polygon.rb +2 -0
- data/lib/rgeo/feature/multi_surface.rb +2 -0
- data/lib/rgeo/feature/point.rb +2 -0
- data/lib/rgeo/feature/polygon.rb +3 -1
- data/lib/rgeo/feature/surface.rb +2 -0
- data/lib/rgeo/feature/types.rb +107 -103
- data/lib/rgeo/geographic.rb +17 -27
- data/lib/rgeo/geographic/factory.rb +154 -199
- data/lib/rgeo/geographic/interface.rb +141 -137
- data/lib/rgeo/geographic/proj4_projector.rb +28 -23
- data/lib/rgeo/geographic/projected_feature_classes.rb +2 -18
- data/lib/rgeo/geographic/projected_feature_methods.rb +59 -49
- data/lib/rgeo/geographic/projected_window.rb +4 -2
- data/lib/rgeo/geographic/simple_mercator_projector.rb +41 -39
- data/lib/rgeo/geographic/spherical_feature_classes.rb +2 -18
- data/lib/rgeo/geographic/spherical_feature_methods.rb +67 -67
- data/lib/rgeo/geographic/spherical_math.rb +81 -87
- data/lib/rgeo/geos.rb +23 -34
- data/lib/rgeo/geos/capi_factory.rb +106 -135
- data/lib/rgeo/geos/capi_feature_classes.rb +19 -37
- data/lib/rgeo/geos/ffi_factory.rb +276 -297
- data/lib/rgeo/geos/ffi_feature_classes.rb +2 -20
- data/lib/rgeo/geos/ffi_feature_methods.rb +170 -166
- data/lib/rgeo/geos/interface.rb +25 -23
- data/lib/rgeo/geos/utils.rb +47 -39
- data/lib/rgeo/geos/zm_factory.rb +171 -185
- data/lib/rgeo/geos/zm_feature_classes.rb +2 -20
- data/lib/rgeo/geos/zm_feature_methods.rb +76 -72
- data/lib/rgeo/impl_helper.rb +1 -11
- data/lib/rgeo/impl_helper/basic_geometry_collection_methods.rb +72 -75
- data/lib/rgeo/impl_helper/basic_geometry_methods.rb +21 -23
- data/lib/rgeo/impl_helper/basic_line_string_methods.rb +57 -49
- data/lib/rgeo/impl_helper/basic_point_methods.rb +29 -25
- data/lib/rgeo/impl_helper/basic_polygon_methods.rb +31 -27
- data/lib/rgeo/impl_helper/math.rb +2 -0
- data/lib/rgeo/impl_helper/utils.rb +9 -15
- data/lib/rgeo/version.rb +3 -1
- data/lib/rgeo/wkrep.rb +20 -30
- data/lib/rgeo/wkrep/wkb_generator.rb +87 -84
- data/lib/rgeo/wkrep/wkb_parser.rb +93 -93
- data/lib/rgeo/wkrep/wkt_generator.rb +67 -63
- data/lib/rgeo/wkrep/wkt_parser.rb +172 -168
- metadata +17 -32
- data/lib/rgeo/feature/mixins.rb +0 -143
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# -----------------------------------------------------------------------------
|
2
4
|
#
|
3
5
|
# GEOS implementation additions written in Ruby
|
@@ -16,114 +18,94 @@ module RGeo
|
|
16
18
|
# Marshal support
|
17
19
|
|
18
20
|
def marshal_dump # :nodoc:
|
19
|
-
|
20
|
-
[
|
21
|
+
my_factory = factory
|
22
|
+
[my_factory, my_factory.write_for_marshal(self)]
|
21
23
|
end
|
22
24
|
|
23
25
|
def marshal_load(data_) # :nodoc:
|
24
|
-
|
25
|
-
_steal(
|
26
|
+
obj = data_[0].read_for_marshal(data_[1])
|
27
|
+
_steal(obj)
|
26
28
|
end
|
27
29
|
|
28
30
|
# Psych support
|
29
31
|
|
30
|
-
def encode_with(
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
32
|
+
def encode_with(coder) # :nodoc:
|
33
|
+
my_factory = factory
|
34
|
+
coder["factory"] = my_factory
|
35
|
+
str = my_factory.write_for_psych(self)
|
36
|
+
str = str.encode("US-ASCII") if str.respond_to?(:encode)
|
37
|
+
coder["wkt"] = str
|
36
38
|
end
|
37
39
|
|
38
|
-
def init_with(
|
39
|
-
|
40
|
-
_steal(
|
40
|
+
def init_with(coder) # :nodoc:
|
41
|
+
obj = coder["factory"].read_for_psych(coder["wkt"])
|
42
|
+
_steal(obj)
|
41
43
|
end
|
42
44
|
|
43
45
|
def as_text
|
44
|
-
|
45
|
-
|
46
|
-
|
46
|
+
str = _as_text
|
47
|
+
str.force_encoding("US-ASCII") if str.respond_to?(:force_encoding)
|
48
|
+
str
|
47
49
|
end
|
48
50
|
alias to_s as_text
|
49
51
|
end
|
50
52
|
|
51
53
|
module CAPIGeometryCollectionMethods # :nodoc:
|
52
|
-
include
|
54
|
+
include Enumerable
|
53
55
|
end
|
54
56
|
|
55
57
|
class CAPIGeometryImpl # :nodoc:
|
56
58
|
include CAPIGeometryMethods
|
57
|
-
|
58
|
-
Feature::MixinCollection::GLOBAL.for_type(Feature::Geometry).include_in_class(self, true)
|
59
59
|
end
|
60
60
|
|
61
61
|
class CAPIPointImpl # :nodoc:
|
62
62
|
include CAPIGeometryMethods
|
63
63
|
include CAPIPointMethods
|
64
|
-
|
65
|
-
Feature::MixinCollection::GLOBAL.for_type(Feature::Point).include_in_class(self, true)
|
66
64
|
end
|
67
65
|
|
68
66
|
class CAPILineStringImpl # :nodoc:
|
69
67
|
include CAPIGeometryMethods
|
70
68
|
include CAPILineStringMethods
|
71
|
-
|
72
|
-
Feature::MixinCollection::GLOBAL.for_type(Feature::LineString).include_in_class(self, true)
|
73
69
|
end
|
74
70
|
|
75
71
|
class CAPILinearRingImpl # :nodoc:
|
76
72
|
include CAPIGeometryMethods
|
77
73
|
include CAPILineStringMethods
|
78
74
|
include CAPILinearRingMethods
|
79
|
-
|
80
|
-
Feature::MixinCollection::GLOBAL.for_type(Feature::LinearRing).include_in_class(self, true)
|
81
75
|
end
|
82
76
|
|
83
77
|
class CAPILineImpl # :nodoc:
|
84
78
|
include CAPIGeometryMethods
|
85
79
|
include CAPILineStringMethods
|
86
80
|
include CAPILineMethods
|
87
|
-
|
88
|
-
Feature::MixinCollection::GLOBAL.for_type(Feature::Line).include_in_class(self, true)
|
89
81
|
end
|
90
82
|
|
91
83
|
class CAPIPolygonImpl # :nodoc:
|
92
84
|
include CAPIGeometryMethods
|
93
85
|
include CAPIPolygonMethods
|
94
|
-
|
95
|
-
Feature::MixinCollection::GLOBAL.for_type(Feature::Polygon).include_in_class(self, true)
|
96
86
|
end
|
97
87
|
|
98
88
|
class CAPIGeometryCollectionImpl # :nodoc:
|
99
89
|
include CAPIGeometryMethods
|
100
90
|
include CAPIGeometryCollectionMethods
|
101
|
-
|
102
|
-
Feature::MixinCollection::GLOBAL.for_type(Feature::GeometryCollection).include_in_class(self, true)
|
103
91
|
end
|
104
92
|
|
105
93
|
class CAPIMultiPointImpl # :nodoc:
|
106
94
|
include CAPIGeometryMethods
|
107
95
|
include CAPIGeometryCollectionMethods
|
108
96
|
include CAPIMultiPointMethods
|
109
|
-
|
110
|
-
Feature::MixinCollection::GLOBAL.for_type(Feature::MultiPoint).include_in_class(self, true)
|
111
97
|
end
|
112
98
|
|
113
99
|
class CAPIMultiLineStringImpl # :nodoc:
|
114
100
|
include CAPIGeometryMethods
|
115
101
|
include CAPIGeometryCollectionMethods
|
116
102
|
include CAPIMultiLineStringMethods
|
117
|
-
|
118
|
-
Feature::MixinCollection::GLOBAL.for_type(Feature::MultiLineString).include_in_class(self, true)
|
119
103
|
end
|
120
104
|
|
121
105
|
class CAPIMultiPolygonImpl # :nodoc:
|
122
106
|
include CAPIGeometryMethods
|
123
107
|
include CAPIGeometryCollectionMethods
|
124
108
|
include CAPIMultiPolygonMethods
|
125
|
-
|
126
|
-
Feature::MixinCollection::GLOBAL.for_type(Feature::MultiPolygon).include_in_class(self, true)
|
127
109
|
end
|
128
110
|
end
|
129
111
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# -----------------------------------------------------------------------------
|
2
4
|
#
|
3
5
|
# FFI-GEOS factory implementation
|
@@ -10,45 +12,46 @@ module RGeo
|
|
10
12
|
|
11
13
|
class FFIFactory
|
12
14
|
include Feature::Factory::Instance
|
15
|
+
include ImplHelper::Utils
|
13
16
|
|
14
17
|
# Create a new factory. Returns nil if the FFI-GEOS implementation
|
15
18
|
# is not supported.
|
16
19
|
#
|
17
20
|
# See RGeo::Geos.factory for a list of supported options.
|
18
21
|
|
19
|
-
def initialize(
|
22
|
+
def initialize(opts = {})
|
20
23
|
# Main flags
|
21
|
-
@uses_lenient_multi_polygon_assertions =
|
22
|
-
|
23
|
-
@has_z =
|
24
|
-
@has_m =
|
24
|
+
@uses_lenient_multi_polygon_assertions = opts[:uses_lenient_assertions] ||
|
25
|
+
opts[:lenient_multi_polygon_assertions] || opts[:uses_lenient_multi_polygon_assertions]
|
26
|
+
@has_z = opts[:has_z_coordinate] ? true : false
|
27
|
+
@has_m = opts[:has_m_coordinate] ? true : false
|
25
28
|
if @has_z && @has_m
|
26
29
|
raise Error::UnsupportedOperation, "GEOS cannot support both Z and M coordinates at the same time."
|
27
30
|
end
|
28
31
|
@_has_3d = @has_z || @has_m
|
29
|
-
@buffer_resolution =
|
32
|
+
@buffer_resolution = opts[:buffer_resolution].to_i
|
30
33
|
@buffer_resolution = 1 if @buffer_resolution < 1
|
31
|
-
@_auto_prepare =
|
34
|
+
@_auto_prepare = opts[:auto_prepare] == :disabled ? false : true
|
32
35
|
|
33
36
|
# Interpret the generator options
|
34
|
-
wkt_generator_ =
|
37
|
+
wkt_generator_ = opts[:wkt_generator]
|
35
38
|
case wkt_generator_
|
36
39
|
when :geos
|
37
40
|
@wkt_writer = ::Geos::WktWriter.new
|
38
41
|
@wkt_generator = nil
|
39
|
-
when
|
42
|
+
when Hash
|
40
43
|
@wkt_generator = WKRep::WKTGenerator.new(wkt_generator_)
|
41
44
|
@wkt_writer = nil
|
42
45
|
else
|
43
46
|
@wkt_generator = WKRep::WKTGenerator.new(convert_case: :upper)
|
44
47
|
@wkt_writer = nil
|
45
48
|
end
|
46
|
-
wkb_generator_ =
|
49
|
+
wkb_generator_ = opts[:wkb_generator]
|
47
50
|
case wkb_generator_
|
48
51
|
when :geos
|
49
52
|
@wkb_writer = ::Geos::WkbWriter.new
|
50
53
|
@wkb_generator = nil
|
51
|
-
when
|
54
|
+
when Hash
|
52
55
|
@wkb_generator = WKRep::WKBGenerator.new(wkb_generator_)
|
53
56
|
@wkb_writer = nil
|
54
57
|
else
|
@@ -57,53 +60,49 @@ module RGeo
|
|
57
60
|
end
|
58
61
|
|
59
62
|
# Coordinate system (srid, proj4, and coord_sys)
|
60
|
-
@srid =
|
61
|
-
@proj4 =
|
63
|
+
@srid = opts[:srid]
|
64
|
+
@proj4 = opts[:proj4]
|
62
65
|
if @proj4 && CoordSys.check!(:proj4)
|
63
|
-
if @proj4.is_a?(
|
66
|
+
if @proj4.is_a?(String) || @proj4.is_a?(Hash)
|
64
67
|
@proj4 = CoordSys::Proj4.create(@proj4)
|
65
68
|
end
|
66
69
|
else
|
67
70
|
@proj4 = nil
|
68
71
|
end
|
69
|
-
@coord_sys =
|
70
|
-
if @coord_sys.is_a?(
|
71
|
-
@coord_sys =
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
entry_ = db_.get(@srid.to_i)
|
79
|
-
if entry_
|
80
|
-
@proj4 ||= entry_.proj4
|
81
|
-
@coord_sys ||= entry_.coord_sys
|
72
|
+
@coord_sys = opts[:coord_sys]
|
73
|
+
if @coord_sys.is_a?(String)
|
74
|
+
@coord_sys = CoordSys::CS.create_from_wkt(@coord_sys)
|
75
|
+
end
|
76
|
+
if (!@proj4 || !@coord_sys) && @srid && (db = opts[:srs_database])
|
77
|
+
entry = db.get(@srid.to_i)
|
78
|
+
if entry
|
79
|
+
@proj4 ||= entry.proj4
|
80
|
+
@coord_sys ||= entry.coord_sys
|
82
81
|
end
|
83
82
|
end
|
84
83
|
@srid ||= @coord_sys.authority_code if @coord_sys
|
85
84
|
@srid = @srid.to_i
|
86
85
|
|
87
86
|
# Interpret parser options
|
88
|
-
|
89
|
-
case
|
87
|
+
wkt_parser = opts[:wkt_parser]
|
88
|
+
case wkt_parser
|
90
89
|
when :geos
|
91
90
|
@wkt_reader = ::Geos::WktReader.new
|
92
91
|
@wkt_parser = nil
|
93
|
-
when
|
94
|
-
@wkt_parser = WKRep::WKTParser.new(self,
|
92
|
+
when Hash
|
93
|
+
@wkt_parser = WKRep::WKTParser.new(self, wkt_parser)
|
95
94
|
@wkt_reader = nil
|
96
95
|
else
|
97
96
|
@wkt_parser = WKRep::WKTParser.new(self)
|
98
97
|
@wkt_reader = nil
|
99
98
|
end
|
100
|
-
|
101
|
-
case
|
99
|
+
wkb_parser = opts[:wkb_parser]
|
100
|
+
case wkb_parser
|
102
101
|
when :geos
|
103
102
|
@wkb_reader = ::Geos::WkbReader.new
|
104
103
|
@wkb_parser = nil
|
105
|
-
when
|
106
|
-
@wkb_parser = WKRep::WKBParser.new(self,
|
104
|
+
when Hash
|
105
|
+
@wkb_parser = WKRep::WKBParser.new(self, wkb_parser)
|
107
106
|
@wkb_reader = nil
|
108
107
|
else
|
109
108
|
@wkb_parser = WKRep::WKBParser.new(self)
|
@@ -119,12 +118,12 @@ module RGeo
|
|
119
118
|
|
120
119
|
# Factory equivalence test.
|
121
120
|
|
122
|
-
def eql?(
|
123
|
-
|
124
|
-
@has_z ==
|
125
|
-
@has_m ==
|
126
|
-
@buffer_resolution ==
|
127
|
-
@proj4.eql?(
|
121
|
+
def eql?(rhs)
|
122
|
+
rhs.is_a?(self.class) && @srid == rhs.srid &&
|
123
|
+
@has_z == rhs.property(:has_z_coordinate) &&
|
124
|
+
@has_m == rhs.property(:has_m_coordinate) &&
|
125
|
+
@buffer_resolution == rhs.property(:buffer_resolution) &&
|
126
|
+
@proj4.eql?(rhs.proj4)
|
128
127
|
end
|
129
128
|
alias == eql?
|
130
129
|
|
@@ -137,100 +136,100 @@ module RGeo
|
|
137
136
|
# Marshal support
|
138
137
|
|
139
138
|
def marshal_dump # :nodoc:
|
140
|
-
|
139
|
+
hash = {
|
141
140
|
"hasz" => @has_z,
|
142
141
|
"hasm" => @has_m,
|
143
142
|
"srid" => @srid,
|
144
143
|
"bufr" => @buffer_resolution,
|
145
|
-
"wktg" => @wkt_generator.
|
146
|
-
"wkbg" => @wkb_generator.
|
147
|
-
"wktp" => @wkt_parser.
|
148
|
-
"wkbp" => @wkb_parser.
|
144
|
+
"wktg" => @wkt_generator.properties,
|
145
|
+
"wkbg" => @wkb_generator.properties,
|
146
|
+
"wktp" => @wkt_parser.properties,
|
147
|
+
"wkbp" => @wkb_parser.properties,
|
149
148
|
"lmpa" => @uses_lenient_multi_polygon_assertions,
|
150
149
|
"apre" => @_auto_prepare
|
151
150
|
}
|
152
|
-
|
153
|
-
|
154
|
-
|
151
|
+
hash["proj4"] = @proj4.marshal_dump if @proj4
|
152
|
+
hash["cs"] = @coord_sys.to_wkt if @coord_sys
|
153
|
+
hash
|
155
154
|
end
|
156
155
|
|
157
|
-
def marshal_load(
|
158
|
-
if (
|
159
|
-
|
160
|
-
|
156
|
+
def marshal_load(data) # :nodoc:
|
157
|
+
if (proj4_data = data["proj4"]) && CoordSys.check!(:proj4)
|
158
|
+
proj4 = CoordSys::Proj4.allocate
|
159
|
+
proj4.marshal_load(proj4_data)
|
161
160
|
else
|
162
|
-
|
161
|
+
proj4 = nil
|
163
162
|
end
|
164
|
-
if (
|
165
|
-
|
163
|
+
if (coord_sys_data = data["cs"])
|
164
|
+
coord_sys = CoordSys::CS.create_from_wkt(coord_sys_data)
|
166
165
|
else
|
167
|
-
|
166
|
+
coord_sys = nil
|
168
167
|
end
|
169
168
|
initialize(
|
170
|
-
has_z_coordinate:
|
171
|
-
has_m_coordinate:
|
172
|
-
srid:
|
173
|
-
buffer_resolution:
|
174
|
-
wkt_generator:
|
175
|
-
wkb_generator:
|
176
|
-
wkt_parser:
|
177
|
-
wkb_parser:
|
178
|
-
uses_lenient_multi_polygon_assertions:
|
179
|
-
auto_prepare: (
|
180
|
-
proj4:
|
181
|
-
coord_sys:
|
169
|
+
has_z_coordinate: data["hasz"],
|
170
|
+
has_m_coordinate: data["hasm"],
|
171
|
+
srid: data["srid"],
|
172
|
+
buffer_resolution: data["bufr"],
|
173
|
+
wkt_generator: symbolize_hash(data["wktg"]),
|
174
|
+
wkb_generator: symbolize_hash(data["wkbg"]),
|
175
|
+
wkt_parser: symbolize_hash(data["wktp"]),
|
176
|
+
wkb_parser: symbolize_hash(data["wkbp"]),
|
177
|
+
uses_lenient_multi_polygon_assertions: data["lmpa"],
|
178
|
+
auto_prepare: (data["apre"] ? :simple : :disabled),
|
179
|
+
proj4: proj4,
|
180
|
+
coord_sys: coord_sys
|
182
181
|
)
|
183
182
|
end
|
184
183
|
|
185
184
|
# Psych support
|
186
185
|
|
187
|
-
def encode_with(
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
186
|
+
def encode_with(coder) # :nodoc:
|
187
|
+
coder["has_z_coordinate"] = @has_z
|
188
|
+
coder["has_m_coordinate"] = @has_m
|
189
|
+
coder["srid"] = @srid
|
190
|
+
coder["buffer_resolution"] = @buffer_resolution
|
191
|
+
coder["lenient_multi_polygon_assertions"] = @uses_lenient_multi_polygon_assertions
|
192
|
+
coder["wkt_generator"] = @wkt_generator.properties
|
193
|
+
coder["wkb_generator"] = @wkb_generator.properties
|
194
|
+
coder["wkt_parser"] = @wkt_parser.properties
|
195
|
+
coder["wkb_parser"] = @wkb_parser.properties
|
196
|
+
coder["auto_prepare"] = @_auto_prepare ? "simple" : "disabled"
|
198
197
|
if @proj4
|
199
|
-
|
200
|
-
|
198
|
+
str = @proj4.original_str || @proj4.canonical_str
|
199
|
+
coder["proj4"] = @proj4.radians? ? { "proj4" => str, "radians" => true } : str
|
201
200
|
end
|
202
|
-
|
201
|
+
coder["coord_sys"] = @coord_sys.to_wkt if @coord_sys
|
203
202
|
end
|
204
203
|
|
205
|
-
def init_with(
|
206
|
-
if (
|
204
|
+
def init_with(coder) # :nodoc:
|
205
|
+
if (proj4_data = coder["proj4"])
|
207
206
|
CoordSys.check!(:proj4)
|
208
|
-
if
|
209
|
-
|
207
|
+
if proj4_data.is_a?(Hash)
|
208
|
+
proj4 = CoordSys::Proj4.create(proj4_data["proj4"], radians: proj4_data["radians"])
|
210
209
|
else
|
211
|
-
|
210
|
+
proj4 = CoordSys::Proj4.create(proj4_data.to_s)
|
212
211
|
end
|
213
212
|
else
|
214
|
-
|
213
|
+
proj4 = nil
|
215
214
|
end
|
216
|
-
if (
|
217
|
-
|
215
|
+
if (coord_sys_data = coder["cs"])
|
216
|
+
coord_sys = CoordSys::CS.create_from_wkt(coord_sys_data.to_s)
|
218
217
|
else
|
219
|
-
|
218
|
+
coord_sys = nil
|
220
219
|
end
|
221
220
|
initialize(
|
222
|
-
has_z_coordinate:
|
223
|
-
has_m_coordinate:
|
224
|
-
srid:
|
225
|
-
buffer_resolution:
|
226
|
-
wkt_generator:
|
227
|
-
wkb_generator:
|
228
|
-
wkt_parser:
|
229
|
-
wkb_parser:
|
230
|
-
auto_prepare:
|
231
|
-
uses_lenient_multi_polygon_assertions:
|
232
|
-
proj4:
|
233
|
-
coord_sys:
|
221
|
+
has_z_coordinate: coder["has_z_coordinate"],
|
222
|
+
has_m_coordinate: coder["has_m_coordinate"],
|
223
|
+
srid: coder["srid"],
|
224
|
+
buffer_resolution: coder["buffer_resolution"],
|
225
|
+
wkt_generator: symbolize_hash(coder["wkt_generator"]),
|
226
|
+
wkb_generator: symbolize_hash(coder["wkb_generator"]),
|
227
|
+
wkt_parser: symbolize_hash(coder["wkt_parser"]),
|
228
|
+
wkb_parser: symbolize_hash(coder["wkb_parser"]),
|
229
|
+
auto_prepare: coder["auto_prepare"] == "disabled" ? :disabled : :simple,
|
230
|
+
uses_lenient_multi_polygon_assertions: coder["lenient_multi_polygon_assertions"],
|
231
|
+
proj4: proj4,
|
232
|
+
coord_sys: coord_sys
|
234
233
|
)
|
235
234
|
end
|
236
235
|
|
@@ -268,181 +267,170 @@ module RGeo
|
|
268
267
|
end
|
269
268
|
end
|
270
269
|
|
271
|
-
# Create a feature that wraps the given ffi-geos geometry object
|
272
|
-
|
273
|
-
def wrap_fg_geom(fg_geom_)
|
274
|
-
_wrap_fg_geom(fg_geom_, nil)
|
275
|
-
end
|
276
|
-
|
277
270
|
# See RGeo::Feature::Factory#parse_wkt
|
278
271
|
|
279
|
-
def parse_wkt(
|
272
|
+
def parse_wkt(str)
|
280
273
|
if @wkt_reader
|
281
|
-
|
274
|
+
wrap_fg_geom(@wkt_reader.read(str), nil)
|
282
275
|
else
|
283
|
-
@wkt_parser.parse(
|
276
|
+
@wkt_parser.parse(str)
|
284
277
|
end
|
285
278
|
end
|
286
279
|
|
287
280
|
# See RGeo::Feature::Factory#parse_wkb
|
288
281
|
|
289
|
-
def parse_wkb(
|
282
|
+
def parse_wkb(str)
|
290
283
|
if @wkb_reader
|
291
|
-
|
284
|
+
wrap_fg_geom(@wkb_reader.read(str), nil)
|
292
285
|
else
|
293
|
-
@wkb_parser.parse(
|
286
|
+
@wkb_parser.parse(str)
|
294
287
|
end
|
295
288
|
end
|
296
289
|
|
297
290
|
# See RGeo::Feature::Factory#point
|
298
291
|
|
299
|
-
def point(
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
FFIPointImpl.new(self, ::Geos::Utils.create_point(
|
292
|
+
def point(x, y, z = 0)
|
293
|
+
cs = ::Geos::CoordinateSequence.new(1, 3)
|
294
|
+
cs.set_x(0, x)
|
295
|
+
cs.set_y(0, y)
|
296
|
+
cs.set_z(0, z)
|
297
|
+
FFIPointImpl.new(self, ::Geos::Utils.create_point(cs), nil)
|
305
298
|
end
|
306
299
|
|
307
300
|
# See RGeo::Feature::Factory#line_string
|
308
301
|
|
309
|
-
def line_string(
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
302
|
+
def line_string(points)
|
303
|
+
points = points.to_a unless points.is_a?(Array)
|
304
|
+
size = points.size
|
305
|
+
raise(Error::InvalidGeometry, "Must have more than one point") if size == 1
|
306
|
+
cs = ::Geos::CoordinateSequence.new(size, 3)
|
307
|
+
points.each_with_index do |p, i|
|
308
|
+
raise(Error::InvalidGeometry, "Invalid point: #{p}") unless RGeo::Feature::Point.check_type(p)
|
309
|
+
cs.set_x(i, p.x)
|
310
|
+
cs.set_y(i, p.y)
|
318
311
|
if @has_z
|
319
|
-
|
312
|
+
cs.set_z(i, p.z)
|
320
313
|
elsif @has_m
|
321
|
-
|
314
|
+
cs.set_z(i, p.m)
|
322
315
|
end
|
323
316
|
end
|
324
|
-
FFILineStringImpl.new(self, ::Geos::Utils.create_line_string(
|
317
|
+
FFILineStringImpl.new(self, ::Geos::Utils.create_line_string(cs), nil)
|
325
318
|
end
|
326
319
|
|
327
320
|
# See RGeo::Feature::Factory#line
|
328
321
|
|
329
|
-
def line(
|
330
|
-
return
|
331
|
-
RGeo::Feature::Point.check_type(
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
322
|
+
def line(start, stop)
|
323
|
+
return unless RGeo::Feature::Point.check_type(start) &&
|
324
|
+
RGeo::Feature::Point.check_type(stop)
|
325
|
+
cs = ::Geos::CoordinateSequence.new(2, 3)
|
326
|
+
cs.set_x(0, start.x)
|
327
|
+
cs.set_x(1, stop.x)
|
328
|
+
cs.set_y(0, start.y)
|
329
|
+
cs.set_y(1, stop.y)
|
337
330
|
if @has_z
|
338
|
-
|
339
|
-
|
331
|
+
cs.set_z(0, start.z)
|
332
|
+
cs.set_z(1, stop.z)
|
340
333
|
elsif @has_m
|
341
|
-
|
342
|
-
|
334
|
+
cs.set_z(0, start.m)
|
335
|
+
cs.set_z(1, stop.m)
|
343
336
|
end
|
344
|
-
FFILineImpl.new(self, ::Geos::Utils.create_line_string(
|
337
|
+
FFILineImpl.new(self, ::Geos::Utils.create_line_string(cs), nil)
|
345
338
|
end
|
346
339
|
|
347
340
|
# See RGeo::Feature::Factory#linear_ring
|
348
341
|
|
349
|
-
def linear_ring(
|
350
|
-
|
351
|
-
|
352
|
-
|
342
|
+
def linear_ring(points)
|
343
|
+
points = points.to_a unless points.is_a?(Array)
|
344
|
+
fg_geom = create_fg_linear_ring(points)
|
345
|
+
FFILinearRingImpl.new(self, fg_geom, nil)
|
353
346
|
end
|
354
347
|
|
355
348
|
# See RGeo::Feature::Factory#polygon
|
356
349
|
|
357
|
-
def polygon(
|
358
|
-
|
359
|
-
return
|
360
|
-
|
361
|
-
|
362
|
-
return
|
363
|
-
|
364
|
-
end
|
365
|
-
|
366
|
-
|
367
|
-
|
350
|
+
def polygon(outer_ring, inner_rings = nil)
|
351
|
+
inner_rings = inner_rings.to_a unless inner_rings.is_a?(Array)
|
352
|
+
return unless RGeo::Feature::LineString.check_type(outer_ring)
|
353
|
+
outer_ring = create_fg_linear_ring(outer_ring.points)
|
354
|
+
inner_rings = inner_rings.map do |r|
|
355
|
+
return unless RGeo::Feature::LineString.check_type(r)
|
356
|
+
create_fg_linear_ring(r.points)
|
357
|
+
end
|
358
|
+
inner_rings.compact!
|
359
|
+
fg_geom = ::Geos::Utils.create_polygon(outer_ring, *inner_rings)
|
360
|
+
FFIPolygonImpl.new(self, fg_geom, nil)
|
368
361
|
end
|
369
362
|
|
370
363
|
# See RGeo::Feature::Factory#collection
|
371
364
|
|
372
|
-
def collection(
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
if
|
380
|
-
|
381
|
-
|
365
|
+
def collection(elems)
|
366
|
+
elems = elems.to_a unless elems.is_a?(Array)
|
367
|
+
klasses = []
|
368
|
+
my_fg_geoms = []
|
369
|
+
elems.each do |elem|
|
370
|
+
k = elem._klasses if elem.factory.is_a?(FFIFactory)
|
371
|
+
elem = RGeo::Feature.cast(elem, self, :force_new, :keep_subtype)
|
372
|
+
if elem
|
373
|
+
klasses << (k || elem.class)
|
374
|
+
my_fg_geoms << elem.detach_fg_geom
|
382
375
|
end
|
383
376
|
end
|
384
|
-
|
385
|
-
|
386
|
-
fg_geom_ ? FFIGeometryCollectionImpl.new(self, fg_geom_, klasses_) : nil
|
377
|
+
fg_geom = ::Geos::Utils.create_collection(::Geos::GeomTypes::GEOS_GEOMETRYCOLLECTION, my_fg_geoms)
|
378
|
+
FFIGeometryCollectionImpl.new(self, fg_geom, klasses)
|
387
379
|
end
|
388
380
|
|
389
381
|
# See RGeo::Feature::Factory#multi_point
|
390
382
|
|
391
|
-
def multi_point(
|
392
|
-
|
393
|
-
|
394
|
-
|
383
|
+
def multi_point(elems)
|
384
|
+
elems = elems.to_a unless elems.is_a?(Array)
|
385
|
+
elems = elems.map do |elem|
|
386
|
+
elem = RGeo::Feature.cast(elem, self, RGeo::Feature::Point,
|
395
387
|
:force_new, :keep_subtype)
|
396
|
-
return
|
397
|
-
|
388
|
+
return unless elem
|
389
|
+
elem.detach_fg_geom
|
398
390
|
end
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
fg_geom_ ? FFIMultiPointImpl.new(self, fg_geom_, klasses_) : nil
|
391
|
+
klasses = Array.new(elems.size, FFIPointImpl)
|
392
|
+
fg_geom = ::Geos::Utils.create_collection(::Geos::GeomTypes::GEOS_MULTIPOINT, elems)
|
393
|
+
FFIMultiPointImpl.new(self, fg_geom, klasses)
|
403
394
|
end
|
404
395
|
|
405
396
|
# See RGeo::Feature::Factory#multi_line_string
|
406
397
|
|
407
|
-
def multi_line_string(
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
elem_._detach_fg_geom
|
398
|
+
def multi_line_string(elems)
|
399
|
+
elems = elems.to_a unless elems.is_a?(Array)
|
400
|
+
klasses = []
|
401
|
+
elems = elems.map do |elem|
|
402
|
+
elem = RGeo::Feature.cast(elem, self, RGeo::Feature::LineString, :force_new, :keep_subtype)
|
403
|
+
raise(RGeo::Error::InvalidGeometry, "Parse error") unless elem
|
404
|
+
klasses << elem.class
|
405
|
+
elem.detach_fg_geom
|
416
406
|
end
|
417
|
-
|
418
|
-
|
419
|
-
fg_geom_ ? FFIMultiLineStringImpl.new(self, fg_geom_, klasses_) : nil
|
407
|
+
fg_geom = ::Geos::Utils.create_collection(::Geos::GeomTypes::GEOS_MULTILINESTRING, elems)
|
408
|
+
FFIMultiLineStringImpl.new(self, fg_geom, klasses)
|
420
409
|
end
|
421
410
|
|
422
411
|
# See RGeo::Feature::Factory#multi_polygon
|
423
412
|
|
424
|
-
def multi_polygon(
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
elem_._detach_fg_geom
|
413
|
+
def multi_polygon(elems)
|
414
|
+
elems = elems.to_a unless elems.is_a?(Array)
|
415
|
+
elems = elems.map do |elem|
|
416
|
+
elem = RGeo::Feature.cast(elem, self, RGeo::Feature::Polygon, :force_new, :keep_subtype)
|
417
|
+
raise(RGeo::Error::InvalidGeometry, "Could not cast to polygon: #{elem}") unless elem
|
418
|
+
elem.detach_fg_geom
|
431
419
|
end
|
432
420
|
unless @uses_lenient_multi_polygon_assertions
|
433
|
-
(1...
|
434
|
-
(0...
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
421
|
+
(1...elems.size).each do |i|
|
422
|
+
(0...i).each do |j|
|
423
|
+
igeom = elems[i]
|
424
|
+
jgeom = elems[j]
|
425
|
+
if igeom.relate_pattern(jgeom, "2********") || igeom.relate_pattern(jgeom, "****1****")
|
426
|
+
raise(RGeo::Error::InvalidGeometry, "Invalid relate pattern: #{jgeom}")
|
427
|
+
end
|
439
428
|
end
|
440
429
|
end
|
441
430
|
end
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
fg_geom_ ? FFIMultiPolygonImpl.new(self, fg_geom_, klasses_) : nil
|
431
|
+
klasses = Array.new(elems.size, FFIPolygonImpl)
|
432
|
+
fg_geom = ::Geos::Utils.create_collection(::Geos::GeomTypes::GEOS_MULTIPOLYGON, elems)
|
433
|
+
FFIMultiPolygonImpl.new(self, fg_geom, klasses)
|
446
434
|
end
|
447
435
|
|
448
436
|
# See RGeo::Feature::Factory#proj4
|
@@ -455,138 +443,129 @@ module RGeo
|
|
455
443
|
|
456
444
|
# See RGeo::Feature::Factory#override_cast
|
457
445
|
|
458
|
-
def override_cast(
|
446
|
+
def override_cast(original, ntype, flags)
|
459
447
|
false
|
460
448
|
# TODO
|
461
449
|
end
|
462
450
|
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
def _wrap_fg_geom(fg_geom_, klass_) # :nodoc:
|
467
|
-
klasses_ = nil
|
451
|
+
# Create a feature that wraps the given ffi-geos geometry object
|
452
|
+
def wrap_fg_geom(fg_geom, klass = nil)
|
453
|
+
klasses = nil
|
468
454
|
|
469
455
|
# We don't allow "empty" points, so replace such objects with
|
470
456
|
# an empty collection.
|
471
|
-
if
|
472
|
-
|
473
|
-
|
457
|
+
if fg_geom.type_id == ::Geos::GeomTypes::GEOS_POINT && fg_geom.empty?
|
458
|
+
fg_geom = ::Geos::Utils.create_geometry_collection
|
459
|
+
klass = FFIGeometryCollectionImpl
|
474
460
|
end
|
475
461
|
|
476
|
-
unless
|
477
|
-
|
478
|
-
case
|
462
|
+
unless klass.is_a?(::Class)
|
463
|
+
is_collection = false
|
464
|
+
case fg_geom.type_id
|
479
465
|
when ::Geos::GeomTypes::GEOS_POINT
|
480
|
-
|
466
|
+
inferred_klass = FFIPointImpl
|
481
467
|
when ::Geos::GeomTypes::GEOS_MULTIPOINT
|
482
|
-
|
483
|
-
|
468
|
+
inferred_klass = FFIMultiPointImpl
|
469
|
+
is_collection = true
|
484
470
|
when ::Geos::GeomTypes::GEOS_LINESTRING
|
485
|
-
|
471
|
+
inferred_klass = FFILineStringImpl
|
486
472
|
when ::Geos::GeomTypes::GEOS_LINEARRING
|
487
|
-
|
473
|
+
inferred_klass = FFILinearRingImpl
|
488
474
|
when ::Geos::GeomTypes::GEOS_MULTILINESTRING
|
489
|
-
|
490
|
-
|
475
|
+
inferred_klass = FFIMultiLineStringImpl
|
476
|
+
is_collection = true
|
491
477
|
when ::Geos::GeomTypes::GEOS_POLYGON
|
492
|
-
|
478
|
+
inferred_klass = FFIPolygonImpl
|
493
479
|
when ::Geos::GeomTypes::GEOS_MULTIPOLYGON
|
494
|
-
|
495
|
-
|
480
|
+
inferred_klass = FFIMultiPolygonImpl
|
481
|
+
is_collection = true
|
496
482
|
when ::Geos::GeomTypes::GEOS_GEOMETRYCOLLECTION
|
497
|
-
|
498
|
-
|
483
|
+
inferred_klass = FFIGeometryCollectionImpl
|
484
|
+
is_collection = true
|
499
485
|
else
|
500
|
-
|
486
|
+
inferred_klass = FFIGeometryImpl
|
501
487
|
end
|
502
|
-
|
503
|
-
|
488
|
+
klasses = klass if is_collection && klass.is_a?(Array)
|
489
|
+
klass = inferred_klass
|
504
490
|
end
|
505
|
-
|
491
|
+
klass.new(self, fg_geom, klasses)
|
506
492
|
end
|
507
493
|
|
508
|
-
|
509
|
-
|
510
|
-
obj_
|
511
|
-
else
|
512
|
-
obj_ = Feature.cast(obj_, self, type_)
|
513
|
-
end
|
514
|
-
obj_ ? obj_.fg_geom : nil
|
515
|
-
end
|
494
|
+
attr_reader :_has_3d # :nodoc:
|
495
|
+
attr_reader :_auto_prepare # :nodoc:
|
516
496
|
|
517
|
-
def
|
518
|
-
|
519
|
-
|
520
|
-
if size_ > 0 && points_.first != points_.last
|
521
|
-
points_ += [points_.first]
|
522
|
-
size_ += 1
|
523
|
-
end
|
524
|
-
cs_ = ::Geos::CoordinateSequence.new(size_, 3)
|
525
|
-
points_.each_with_index do |p_, i_|
|
526
|
-
return nil unless RGeo::Feature::Point.check_type(p_)
|
527
|
-
cs_.set_x(i_, p_.x)
|
528
|
-
cs_.set_y(i_, p_.y)
|
529
|
-
if @has_z
|
530
|
-
cs_.set_z(i_, p_.z)
|
531
|
-
elsif @has_m
|
532
|
-
cs_.set_z(i_, p_.m)
|
533
|
-
end
|
497
|
+
def convert_to_fg_geometry(obj, type = nil)
|
498
|
+
if type && obj.factory != self
|
499
|
+
obj = Feature.cast(obj, self, type)
|
534
500
|
end
|
535
|
-
|
501
|
+
obj&.fg_geom
|
536
502
|
end
|
537
503
|
|
538
|
-
def
|
504
|
+
def generate_wkt(geom)
|
539
505
|
if @wkt_writer
|
540
|
-
@wkt_writer.write(
|
506
|
+
@wkt_writer.write(geom.fg_geom)
|
541
507
|
else
|
542
|
-
@wkt_generator.generate(
|
508
|
+
@wkt_generator.generate(geom)
|
543
509
|
end
|
544
510
|
end
|
545
511
|
|
546
|
-
def
|
512
|
+
def generate_wkb(geom)
|
547
513
|
if @wkb_writer
|
548
|
-
@wkb_writer.write(
|
514
|
+
@wkb_writer.write(geom.fg_geom)
|
549
515
|
else
|
550
|
-
@wkb_generator.generate(
|
516
|
+
@wkb_generator.generate(geom)
|
551
517
|
end
|
552
518
|
end
|
553
519
|
|
554
|
-
def
|
520
|
+
def write_for_marshal(geom)
|
555
521
|
if Utils.ffi_supports_set_output_dimension || !@_has_3d
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
end
|
560
|
-
@marshal_wkb_writer.write(geom_.fg_geom)
|
522
|
+
wkb_writer = ::Geos::WkbWriter.new
|
523
|
+
wkb_writer.output_dimensions = 3 if @_has_3d
|
524
|
+
wkb_writer.write(geom.fg_geom)
|
561
525
|
else
|
562
|
-
Utils.marshal_wkb_generator.generate(
|
526
|
+
Utils.marshal_wkb_generator.generate(geom)
|
563
527
|
end
|
564
528
|
end
|
565
529
|
|
566
|
-
def
|
567
|
-
|
568
|
-
@marshal_wkb_reader = ::Geos::WkbReader.new
|
569
|
-
end
|
570
|
-
@marshal_wkb_reader.read(str_)
|
530
|
+
def read_for_marshal(str)
|
531
|
+
::Geos::WkbReader.new.read(str)
|
571
532
|
end
|
572
533
|
|
573
|
-
def
|
534
|
+
def write_for_psych(geom)
|
574
535
|
if Utils.ffi_supports_set_output_dimension || !@_has_3d
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
end
|
579
|
-
@psych_wkt_writer.write(geom_.fg_geom)
|
536
|
+
wkt_writer = ::Geos::WktWriter.new
|
537
|
+
wkt_writer.output_dimensions = 3 if @_has_3d
|
538
|
+
wkt_writer.write(geom.fg_geom)
|
580
539
|
else
|
581
|
-
Utils.psych_wkt_generator.generate(
|
540
|
+
Utils.psych_wkt_generator.generate(geom)
|
582
541
|
end
|
583
542
|
end
|
584
543
|
|
585
|
-
def
|
586
|
-
|
587
|
-
|
544
|
+
def read_for_psych(str)
|
545
|
+
::Geos::WktReader.new.read(str)
|
546
|
+
end
|
547
|
+
|
548
|
+
private
|
549
|
+
|
550
|
+
def create_fg_linear_ring(points)
|
551
|
+
size = points.size
|
552
|
+
return if size == 1 || size == 2
|
553
|
+
if size > 0 && points.first != points.last
|
554
|
+
points += [points.first]
|
555
|
+
size += 1
|
556
|
+
end
|
557
|
+
cs = ::Geos::CoordinateSequence.new(size, 3)
|
558
|
+
points.each_with_index do |p, i|
|
559
|
+
return unless RGeo::Feature::Point.check_type(p)
|
560
|
+
cs.set_x(i, p.x)
|
561
|
+
cs.set_y(i, p.y)
|
562
|
+
if @has_z
|
563
|
+
cs.set_z(i, p.z)
|
564
|
+
elsif @has_m
|
565
|
+
cs.set_z(i, p.m)
|
566
|
+
end
|
588
567
|
end
|
589
|
-
|
568
|
+
::Geos::Utils.create_linear_ring(cs)
|
590
569
|
end
|
591
570
|
end
|
592
571
|
end
|