rgeo 2.3.1 → 3.0.0.pre.rc.2

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.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +6 -0
  3. data/README.md +11 -10
  4. data/ext/geos_c_impl/analysis.c +8 -6
  5. data/ext/geos_c_impl/analysis.h +1 -3
  6. data/ext/geos_c_impl/errors.c +10 -8
  7. data/ext/geos_c_impl/errors.h +7 -3
  8. data/ext/geos_c_impl/extconf.rb +3 -0
  9. data/ext/geos_c_impl/factory.c +273 -202
  10. data/ext/geos_c_impl/factory.h +51 -63
  11. data/ext/geos_c_impl/geometry.c +124 -22
  12. data/ext/geos_c_impl/geometry.h +8 -3
  13. data/ext/geos_c_impl/geometry_collection.c +81 -185
  14. data/ext/geos_c_impl/geometry_collection.h +1 -14
  15. data/ext/geos_c_impl/globals.c +91 -0
  16. data/ext/geos_c_impl/globals.h +45 -0
  17. data/ext/geos_c_impl/line_string.c +28 -29
  18. data/ext/geos_c_impl/line_string.h +1 -3
  19. data/ext/geos_c_impl/main.c +10 -9
  20. data/ext/geos_c_impl/point.c +9 -8
  21. data/ext/geos_c_impl/point.h +1 -3
  22. data/ext/geos_c_impl/polygon.c +43 -72
  23. data/ext/geos_c_impl/polygon.h +1 -3
  24. data/ext/geos_c_impl/preface.h +12 -0
  25. data/ext/geos_c_impl/ruby_more.c +65 -0
  26. data/ext/geos_c_impl/ruby_more.h +16 -0
  27. data/lib/rgeo/cartesian/calculations.rb +54 -17
  28. data/lib/rgeo/cartesian/factory.rb +6 -14
  29. data/lib/rgeo/cartesian/feature_classes.rb +68 -46
  30. data/lib/rgeo/cartesian/feature_methods.rb +67 -20
  31. data/lib/rgeo/cartesian/interface.rb +0 -36
  32. data/lib/rgeo/cartesian/planar_graph.rb +379 -0
  33. data/lib/rgeo/cartesian/sweepline_intersector.rb +149 -0
  34. data/lib/rgeo/cartesian/valid_op.rb +71 -0
  35. data/lib/rgeo/cartesian.rb +3 -0
  36. data/lib/rgeo/coord_sys/cs/wkt_parser.rb +6 -6
  37. data/lib/rgeo/coord_sys.rb +0 -11
  38. data/lib/rgeo/error.rb +15 -0
  39. data/lib/rgeo/feature/factory_generator.rb +0 -3
  40. data/lib/rgeo/feature/geometry.rb +107 -28
  41. data/lib/rgeo/feature/geometry_collection.rb +13 -5
  42. data/lib/rgeo/feature/line_string.rb +3 -3
  43. data/lib/rgeo/feature/multi_surface.rb +3 -3
  44. data/lib/rgeo/feature/point.rb +4 -4
  45. data/lib/rgeo/feature/surface.rb +3 -3
  46. data/lib/rgeo/geographic/factory.rb +6 -7
  47. data/lib/rgeo/geographic/interface.rb +6 -49
  48. data/lib/rgeo/geographic/proj4_projector.rb +0 -2
  49. data/lib/rgeo/geographic/projected_feature_classes.rb +21 -9
  50. data/lib/rgeo/geographic/projected_feature_methods.rb +67 -28
  51. data/lib/rgeo/geographic/simple_mercator_projector.rb +0 -2
  52. data/lib/rgeo/geographic/spherical_feature_classes.rb +29 -9
  53. data/lib/rgeo/geographic/spherical_feature_methods.rb +79 -2
  54. data/lib/rgeo/geos/capi_factory.rb +21 -38
  55. data/lib/rgeo/geos/capi_feature_classes.rb +54 -11
  56. data/lib/rgeo/geos/ffi_factory.rb +6 -35
  57. data/lib/rgeo/geos/ffi_feature_classes.rb +34 -10
  58. data/lib/rgeo/geos/ffi_feature_methods.rb +39 -5
  59. data/lib/rgeo/geos/interface.rb +0 -24
  60. data/lib/rgeo/geos/zm_factory.rb +0 -19
  61. data/lib/rgeo/geos/zm_feature_methods.rb +16 -0
  62. data/lib/rgeo/geos.rb +6 -3
  63. data/lib/rgeo/impl_helper/basic_geometry_collection_methods.rb +4 -4
  64. data/lib/rgeo/impl_helper/basic_geometry_methods.rb +1 -1
  65. data/lib/rgeo/impl_helper/basic_line_string_methods.rb +15 -19
  66. data/lib/rgeo/impl_helper/basic_point_methods.rb +1 -1
  67. data/lib/rgeo/impl_helper/basic_polygon_methods.rb +1 -1
  68. data/lib/rgeo/impl_helper/valid_op.rb +354 -0
  69. data/lib/rgeo/impl_helper/validity_check.rb +139 -0
  70. data/lib/rgeo/impl_helper.rb +1 -0
  71. data/lib/rgeo/version.rb +1 -1
  72. metadata +45 -9
  73. data/lib/rgeo/coord_sys/srs_database/entry.rb +0 -107
  74. data/lib/rgeo/coord_sys/srs_database/sr_org.rb +0 -64
  75. data/lib/rgeo/coord_sys/srs_database/url_reader.rb +0 -65
@@ -26,7 +26,6 @@ module RGeo
26
26
 
27
27
  # Get flags to pass to the C extension
28
28
  flags = 0
29
- flags |= 1 if opts_[:uses_lenient_assertions] || opts_[:lenient_multi_polygon_assertions] || opts_[:uses_lenient_multi_polygon_assertions]
30
29
  flags |= 2 if opts_[:has_z_coordinate]
31
30
  flags |= 4 if opts_[:has_m_coordinate]
32
31
  if flags & 6 == 6
@@ -72,13 +71,6 @@ module RGeo
72
71
  if coord_sys_.is_a?(String)
73
72
  coord_sys_ = CoordSys::CS.create_from_wkt(coord_sys_)
74
73
  end
75
- if (!proj4_ || !coord_sys_) && srid_ && (db_ = opts_[:srs_database])
76
- entry_ = db_.get(srid_.to_i)
77
- if entry_
78
- proj4_ ||= entry_.proj4
79
- coord_sys_ ||= entry_.coord_sys
80
- end
81
- end
82
74
  srid_ ||= coord_sys_.authority_code if coord_sys_
83
75
 
84
76
  # Create the factory and set instance variables
@@ -137,16 +129,15 @@ module RGeo
137
129
 
138
130
  def marshal_dump # :nodoc:
139
131
  hash_ = {
140
- "hasz" => (_flags & 0x2 != 0),
141
- "hasm" => (_flags & 0x4 != 0),
132
+ "hasz" => supports_z?,
133
+ "hasm" => supports_m?,
142
134
  "srid" => _srid,
143
135
  "bufr" => _buffer_resolution,
144
136
  "wktg" => _wkt_generator ? _wkt_generator.properties : {},
145
137
  "wkbg" => _wkb_generator ? _wkb_generator.properties : {},
146
138
  "wktp" => _wkt_parser ? _wkt_parser.properties : {},
147
139
  "wkbp" => _wkb_parser ? _wkb_parser.properties : {},
148
- "lmpa" => (_flags & 0x1 != 0),
149
- "apre" => ((_flags & 0x8) >> 3)
140
+ "apre" => auto_prepare
150
141
  }
151
142
  if (proj4_ = _proj4)
152
143
  hash_["proj4"] = proj4_.marshal_dump
@@ -179,8 +170,7 @@ module RGeo
179
170
  wkb_generator: symbolize_hash(data_["wkbg"]),
180
171
  wkt_parser: symbolize_hash(data_["wktp"]),
181
172
  wkb_parser: symbolize_hash(data_["wkbp"]),
182
- uses_lenient_multi_polygon_assertions: data_["lmpa"],
183
- auto_prepare: (data_["apre"] == 0 ? :disabled : :simple),
173
+ auto_prepare: data_["apre"],
184
174
  proj4: proj4_,
185
175
  coord_sys: coord_sys_
186
176
  )
@@ -190,16 +180,15 @@ module RGeo
190
180
  # Psych support
191
181
 
192
182
  def encode_with(coder_) # :nodoc:
193
- coder_["has_z_coordinate"] = (_flags & 0x2 != 0)
194
- coder_["has_m_coordinate"] = (_flags & 0x4 != 0)
183
+ coder_["has_z_coordinate"] = supports_z?
184
+ coder_["has_m_coordinate"] = supports_m?
195
185
  coder_["srid"] = _srid
196
186
  coder_["buffer_resolution"] = _buffer_resolution
197
- coder_["lenient_multi_polygon_assertions"] = (_flags & 0x1 != 0)
198
187
  coder_["wkt_generator"] = _wkt_generator ? _wkt_generator.properties : {}
199
188
  coder_["wkb_generator"] = _wkb_generator ? _wkb_generator.properties : {}
200
189
  coder_["wkt_parser"] = _wkt_parser ? _wkt_parser.properties : {}
201
190
  coder_["wkb_parser"] = _wkb_parser ? _wkb_parser.properties : {}
202
- coder_["auto_prepare"] = ((_flags & 0x8) == 0 ? "disabled" : "simple")
191
+ coder_["auto_prepare"] = auto_prepare
203
192
  if (proj4_ = _proj4)
204
193
  str_ = proj4_.original_str || proj4_.canonical_str
205
194
  coder_["proj4"] = proj4_.radians? ? { "proj4" => str_, "radians" => true } : str_
@@ -236,7 +225,6 @@ module RGeo
236
225
  wkt_parser: symbolize_hash(coder_["wkt_parser"]),
237
226
  wkb_parser: symbolize_hash(coder_["wkb_parser"]),
238
227
  auto_prepare: coder_["auto_prepare"] == "disabled" ? :disabled : :simple,
239
- uses_lenient_multi_polygon_assertions: coder_["lenient_multi_polygon_assertions"],
240
228
  proj4: proj4_,
241
229
  coord_sys: coord_sys_
242
230
  )
@@ -256,28 +244,19 @@ module RGeo
256
244
  _buffer_resolution
257
245
  end
258
246
 
259
- # Returns true if this factory is lenient with MultiPolygon assertions
260
-
261
- def lenient_multi_polygon_assertions?
262
- _flags & 0x1 != 0
263
- end
264
-
265
247
  # See RGeo::Feature::Factory#property
266
-
267
248
  def property(name_)
268
249
  case name_
269
250
  when :has_z_coordinate
270
- _flags & 0x2 != 0
251
+ supports_z?
271
252
  when :has_m_coordinate
272
- _flags & 0x4 != 0
253
+ supports_m?
273
254
  when :is_cartesian
274
255
  true
275
- when :uses_lenient_multi_polygon_assertions
276
- _flags & 0x1 != 0
277
256
  when :buffer_resolution
278
257
  _buffer_resolution
279
258
  when :auto_prepare
280
- _flags & 0x8 != 0 ? :simple : :disabled
259
+ prepare_heuristic? ? :simple : :disabled
281
260
  end
282
261
  end
283
262
 
@@ -307,11 +286,11 @@ module RGeo
307
286
 
308
287
  # See RGeo::Feature::Factory#point
309
288
 
310
- def point(x_, y_, *extra_)
311
- if extra_.length > (_flags & 6 == 0 ? 0 : 1)
289
+ def point(x, y, *extra)
290
+ if extra.length > (supports_z_or_m? ? 1 : 0)
312
291
  raise(RGeo::Error::InvalidGeometry, "Parse error")
313
292
  else
314
- CAPIPointImpl.create(self, x_, y_, extra_[0].to_f)
293
+ CAPIPointImpl.create(self, x, y, extra[0].to_f)
315
294
  end
316
295
  end
317
296
 
@@ -398,7 +377,7 @@ module RGeo
398
377
  # Optimization if we're just changing factories, but the
399
378
  # factories are zm-compatible and proj4-compatible.
400
379
  if original.factory != self && ntype == type &&
401
- original.factory._flags & 0x6 == _flags & 0x6 &&
380
+ original.factory._flags & FLAG_SUPPORTS_Z_OR_M == _flags & FLAG_SUPPORTS_Z_OR_M &&
402
381
  (!project || original.factory.proj4 == _proj4)
403
382
  result = original.dup
404
383
  result.factory = self
@@ -406,7 +385,7 @@ module RGeo
406
385
  end
407
386
  # LineString conversion optimization.
408
387
  if (original.factory != self || ntype != type) &&
409
- original.factory._flags & 0x6 == _flags & 0x6 &&
388
+ original.factory._flags & FLAG_SUPPORTS_Z_OR_M == _flags & FLAG_SUPPORTS_Z_OR_M &&
410
389
  (!project || original.factory.proj4 == _proj4) &&
411
390
  type.subtype_of?(Feature::LineString) && ntype.subtype_of?(Feature::LineString)
412
391
  return IMPL_CLASSES[ntype]._copy_from(self, original)
@@ -414,15 +393,19 @@ module RGeo
414
393
  when ZMGeometryMethods
415
394
  # Optimization for just removing a coordinate from an otherwise
416
395
  # compatible factory
417
- if _flags & 0x6 == 0x2 && self == original.factory.z_factory
396
+ if supports_z? && !supports_m? && self == original.factory.z_factory
418
397
  return Feature.cast(original.z_geometry, ntype, flags)
419
- elsif _flags & 0x6 == 0x4 && self == original.factory.m_factory
398
+ elsif supports_m? && !supports_z? && self == original.factory.m_factory
420
399
  return Feature.cast(original.m_geometry, ntype, flags)
421
400
  end
422
401
  end
423
402
  false
424
403
  end
425
404
 
405
+ def auto_prepare # :nodoc:
406
+ prepare_heuristic? ? :simple : :disabled
407
+ end
408
+
426
409
  # :stopdoc:
427
410
 
428
411
  IMPL_CLASSES = {
@@ -6,11 +6,24 @@
6
6
  #
7
7
  # -----------------------------------------------------------------------------
8
8
 
9
+ require_relative "../impl_helper/validity_check"
10
+
9
11
  module RGeo
10
12
  module Geos
11
- module CAPIGeometryMethods # :nodoc:
13
+ module CAPIGeometryMethods
12
14
  include Feature::Instance
13
15
 
16
+ def coordinate_dimension
17
+ dim = 2
18
+ dim += 1 if factory.supports_z?
19
+ dim += 1 if factory.supports_m?
20
+ dim
21
+ end
22
+
23
+ def spatial_dimension
24
+ factory.supports_z? ? 3 : 2
25
+ end
26
+
14
27
  def is_empty? # rubocop:disable Naming/PredicateName
15
28
  warn "The is_empty? method is deprecated, please use the empty? counterpart, will be removed in v3" unless ENV["RGEO_SILENCE_DEPRECATION"]
16
29
  empty?
@@ -21,6 +34,14 @@ module RGeo
21
34
  simple?
22
35
  end
23
36
 
37
+ def is_3d?
38
+ factory.supports_z?
39
+ end
40
+
41
+ def measured?
42
+ factory.supports_m?
43
+ end
44
+
24
45
  def inspect
25
46
  "#<#{self.class}:0x#{object_id.to_s(16)} #{as_text.inspect}>"
26
47
  end
@@ -83,21 +104,29 @@ module RGeo
83
104
  include Enumerable
84
105
  end
85
106
 
86
- class CAPIGeometryImpl # :nodoc:
107
+ class CAPIGeometryImpl
108
+ include Feature::Geometry
109
+ include ImplHelper::ValidityCheck
87
110
  include CAPIGeometryMethods
88
111
  end
89
112
 
90
- class CAPIPointImpl # :nodoc:
113
+ class CAPIPointImpl
114
+ include Feature::Point
115
+ include ImplHelper::ValidityCheck
91
116
  include CAPIGeometryMethods
92
117
  include CAPIPointMethods
93
118
  end
94
119
 
95
- class CAPILineStringImpl # :nodoc:
120
+ class CAPILineStringImpl
121
+ include Feature::LineString
122
+ include ImplHelper::ValidityCheck
96
123
  include CAPIGeometryMethods
97
124
  include CAPILineStringMethods
98
125
  end
99
126
 
100
- class CAPILinearRingImpl # :nodoc:
127
+ class CAPILinearRingImpl
128
+ include Feature::LinearRing
129
+ include ImplHelper::ValidityCheck
101
130
  include CAPIGeometryMethods
102
131
  include CAPILineStringMethods
103
132
  include CAPILinearRingMethods
@@ -107,38 +136,52 @@ module RGeo
107
136
  end
108
137
  end
109
138
 
110
- class CAPILineImpl # :nodoc:
139
+ class CAPILineImpl
140
+ include Feature::Line
141
+ include ImplHelper::ValidityCheck
111
142
  include CAPIGeometryMethods
112
143
  include CAPILineStringMethods
113
144
  include CAPILineMethods
114
145
  end
115
146
 
116
- class CAPIPolygonImpl # :nodoc:
147
+ class CAPIPolygonImpl
148
+ include Feature::Polygon
149
+ include ImplHelper::ValidityCheck
117
150
  include CAPIGeometryMethods
118
151
  include CAPIPolygonMethods
119
152
  end
120
153
 
121
- class CAPIGeometryCollectionImpl # :nodoc:
154
+ class CAPIGeometryCollectionImpl
155
+ include Feature::GeometryCollection
156
+ include ImplHelper::ValidityCheck
122
157
  include CAPIGeometryMethods
123
158
  include CAPIGeometryCollectionMethods
124
159
  end
125
160
 
126
- class CAPIMultiPointImpl # :nodoc:
161
+ class CAPIMultiPointImpl
162
+ include Feature::MultiPoint
163
+ include ImplHelper::ValidityCheck
127
164
  include CAPIGeometryMethods
128
165
  include CAPIGeometryCollectionMethods
129
166
  include CAPIMultiPointMethods
130
167
  end
131
168
 
132
- class CAPIMultiLineStringImpl # :nodoc:
169
+ class CAPIMultiLineStringImpl
170
+ include Feature::MultiLineString
171
+ include ImplHelper::ValidityCheck
133
172
  include CAPIGeometryMethods
134
173
  include CAPIGeometryCollectionMethods
135
174
  include CAPIMultiLineStringMethods
136
175
  end
137
176
 
138
- class CAPIMultiPolygonImpl # :nodoc:
177
+ class CAPIMultiPolygonImpl
178
+ include Feature::MultiPolygon
179
+ include ImplHelper::ValidityCheck
139
180
  include CAPIGeometryMethods
140
181
  include CAPIGeometryCollectionMethods
141
182
  include CAPIMultiPolygonMethods
142
183
  end
184
+
185
+ ImplHelper::ValidityCheck.override_classes
143
186
  end
144
187
  end
@@ -20,14 +20,16 @@ module RGeo
20
20
  # See RGeo::Geos.factory for a list of supported options.
21
21
 
22
22
  def initialize(opts = {})
23
- # Main flags
24
- @uses_lenient_multi_polygon_assertions = opts[:uses_lenient_assertions] ||
25
- opts[:lenient_multi_polygon_assertions] || opts[:uses_lenient_multi_polygon_assertions]
26
23
  @has_z = opts[:has_z_coordinate] ? true : false
27
24
  @has_m = opts[:has_m_coordinate] ? true : false
28
25
  if @has_z && @has_m
29
26
  raise Error::UnsupportedOperation, "GEOS cannot support both Z and M coordinates at the same time."
30
27
  end
28
+ @coordinate_dimension = 2
29
+ @coordinate_dimension += 1 if @has_z
30
+ @coordinate_dimension += 1 if @has_m
31
+ @spatial_dimension = @has_z ? 3 : 2
32
+
31
33
  @_has_3d = @has_z || @has_m
32
34
  @buffer_resolution = opts[:buffer_resolution].to_i
33
35
  @buffer_resolution = 1 if @buffer_resolution < 1
@@ -73,13 +75,6 @@ module RGeo
73
75
  if @coord_sys.is_a?(String)
74
76
  @coord_sys = CoordSys::CS.create_from_wkt(@coord_sys)
75
77
  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
81
- end
82
- end
83
78
  @srid ||= @coord_sys.authority_code if @coord_sys
84
79
  @srid = @srid.to_i
85
80
 
@@ -109,6 +104,7 @@ module RGeo
109
104
  @wkb_reader = nil
110
105
  end
111
106
  end
107
+ attr_reader :coordinate_dimension, :spatial_dimension
112
108
 
113
109
  # Standard object inspection output
114
110
 
@@ -145,7 +141,6 @@ module RGeo
145
141
  "wkbg" => @wkb_generator.properties,
146
142
  "wktp" => @wkt_parser.properties,
147
143
  "wkbp" => @wkb_parser.properties,
148
- "lmpa" => @uses_lenient_multi_polygon_assertions,
149
144
  "apre" => @_auto_prepare
150
145
  }
151
146
  hash["proj4"] = @proj4.marshal_dump if @proj4
@@ -174,7 +169,6 @@ module RGeo
174
169
  wkb_generator: symbolize_hash(data["wkbg"]),
175
170
  wkt_parser: symbolize_hash(data["wktp"]),
176
171
  wkb_parser: symbolize_hash(data["wkbp"]),
177
- uses_lenient_multi_polygon_assertions: data["lmpa"],
178
172
  auto_prepare: (data["apre"] ? :simple : :disabled),
179
173
  proj4: proj4,
180
174
  coord_sys: coord_sys
@@ -188,7 +182,6 @@ module RGeo
188
182
  coder["has_m_coordinate"] = @has_m
189
183
  coder["srid"] = @srid
190
184
  coder["buffer_resolution"] = @buffer_resolution
191
- coder["lenient_multi_polygon_assertions"] = @uses_lenient_multi_polygon_assertions
192
185
  coder["wkt_generator"] = @wkt_generator.properties
193
186
  coder["wkb_generator"] = @wkb_generator.properties
194
187
  coder["wkt_parser"] = @wkt_parser.properties
@@ -227,7 +220,6 @@ module RGeo
227
220
  wkt_parser: symbolize_hash(coder["wkt_parser"]),
228
221
  wkb_parser: symbolize_hash(coder["wkb_parser"]),
229
222
  auto_prepare: coder["auto_prepare"] == "disabled" ? :disabled : :simple,
230
- uses_lenient_multi_polygon_assertions: coder["lenient_multi_polygon_assertions"],
231
223
  proj4: proj4,
232
224
  coord_sys: coord_sys
233
225
  )
@@ -242,14 +234,7 @@ module RGeo
242
234
 
243
235
  attr_reader :buffer_resolution
244
236
 
245
- # Returns true if this factory is lenient with MultiPolygon assertions
246
-
247
- def lenient_multi_polygon_assertions?
248
- @uses_lenient_multi_polygon_assertions
249
- end
250
-
251
237
  # See RGeo::Feature::Factory#property
252
-
253
238
  def property(name_)
254
239
  case name_
255
240
  when :has_z_coordinate
@@ -260,15 +245,12 @@ module RGeo
260
245
  true
261
246
  when :buffer_resolution
262
247
  @buffer_resolution
263
- when :uses_lenient_multi_polygon_assertions
264
- @uses_lenient_multi_polygon_assertions
265
248
  when :auto_prepare
266
249
  @_auto_prepare ? :simple : :disabled
267
250
  end
268
251
  end
269
252
 
270
253
  # See RGeo::Feature::Factory#parse_wkt
271
-
272
254
  def parse_wkt(str)
273
255
  if @wkt_reader
274
256
  wrap_fg_geom(@wkt_reader.read(str), nil)
@@ -417,17 +399,6 @@ module RGeo
417
399
  raise(RGeo::Error::InvalidGeometry, "Could not cast to polygon: #{elem}") unless elem
418
400
  elem.detach_fg_geom
419
401
  end
420
- unless @uses_lenient_multi_polygon_assertions
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
428
- end
429
- end
430
- end
431
402
  klasses = Array.new(elems.size, FFIPolygonImpl)
432
403
  fg_geom = ::Geos::Utils.create_collection(::Geos::GeomTypes::GEOS_MULTIPOLYGON, elems)
433
404
  FFIMultiPolygonImpl.new(self, fg_geom, klasses)
@@ -6,60 +6,84 @@
6
6
  #
7
7
  # -----------------------------------------------------------------------------
8
8
 
9
+ require_relative "../impl_helper/validity_check"
10
+
9
11
  module RGeo
10
12
  module Geos
11
- class FFIGeometryImpl # :nodoc:
13
+ class FFIGeometryImpl
14
+ include Feature::Geometry
15
+ include ImplHelper::ValidityCheck
12
16
  include FFIGeometryMethods
13
17
  end
14
18
 
15
- class FFIPointImpl # :nodoc:
19
+ class FFIPointImpl
20
+ include Feature::Point
21
+ include ImplHelper::ValidityCheck
16
22
  include FFIGeometryMethods
17
23
  include FFIPointMethods
18
24
  end
19
25
 
20
- class FFILineStringImpl # :nodoc:
26
+ class FFILineStringImpl
27
+ include Feature::LineString
28
+ include ImplHelper::ValidityCheck
21
29
  include FFIGeometryMethods
22
30
  include FFILineStringMethods
23
31
  end
24
32
 
25
- class FFILinearRingImpl # :nodoc:
33
+ class FFILinearRingImpl
34
+ include Feature::LinearRing
35
+ include ImplHelper::ValidityCheck
26
36
  include FFIGeometryMethods
27
37
  include FFILineStringMethods
28
38
  include FFILinearRingMethods
29
39
  end
30
40
 
31
- class FFILineImpl # :nodoc:
41
+ class FFILineImpl
42
+ include Feature::Line
43
+ include ImplHelper::ValidityCheck
32
44
  include FFIGeometryMethods
33
45
  include FFILineStringMethods
34
46
  include FFILineMethods
35
47
  end
36
48
 
37
- class FFIPolygonImpl # :nodoc:
49
+ class FFIPolygonImpl
50
+ include Feature::Polygon
51
+ include ImplHelper::ValidityCheck
38
52
  include FFIGeometryMethods
39
53
  include FFIPolygonMethods
40
54
  end
41
55
 
42
- class FFIGeometryCollectionImpl # :nodoc:
56
+ class FFIGeometryCollectionImpl
57
+ include Feature::GeometryCollection
58
+ include ImplHelper::ValidityCheck
43
59
  include FFIGeometryMethods
44
60
  include FFIGeometryCollectionMethods
45
61
  end
46
62
 
47
- class FFIMultiPointImpl # :nodoc:
63
+ class FFIMultiPointImpl
64
+ include Feature::MultiPoint
65
+ include ImplHelper::ValidityCheck
48
66
  include FFIGeometryMethods
49
67
  include FFIGeometryCollectionMethods
50
68
  include FFIMultiPointMethods
51
69
  end
52
70
 
53
- class FFIMultiLineStringImpl # :nodoc:
71
+ class FFIMultiLineStringImpl
72
+ include Feature::MultiLineString
73
+ include ImplHelper::ValidityCheck
54
74
  include FFIGeometryMethods
55
75
  include FFIGeometryCollectionMethods
56
76
  include FFIMultiLineStringMethods
57
77
  end
58
78
 
59
- class FFIMultiPolygonImpl # :nodoc:
79
+ class FFIMultiPolygonImpl
80
+ include Feature::MultiPolygon
81
+ include ImplHelper::ValidityCheck
60
82
  include FFIGeometryMethods
61
83
  include FFIGeometryCollectionMethods
62
84
  include FFIMultiPolygonMethods
63
85
  end
86
+
87
+ ImplHelper::ValidityCheck.override_classes
64
88
  end
65
89
  end
@@ -6,6 +6,8 @@
6
6
  #
7
7
  # -----------------------------------------------------------------------------
8
8
 
9
+ require "ffi-geos"
10
+
9
11
  module RGeo
10
12
  module Geos
11
13
  module FFIGeometryMethods # :nodoc:
@@ -75,6 +77,14 @@ module RGeo
75
77
  Utils.ffi_compute_dimension(@fg_geom)
76
78
  end
77
79
 
80
+ def coordinate_dimension
81
+ factory.coordinate_dimension
82
+ end
83
+
84
+ def spatial_dimension
85
+ factory.spatial_dimension
86
+ end
87
+
78
88
  def geometry_type
79
89
  Feature::Geometry
80
90
  end
@@ -95,11 +105,9 @@ module RGeo
95
105
  end
96
106
 
97
107
  def boundary
98
- if self.class == FFIGeometryCollectionImpl
99
- nil
100
- else
101
- @factory.wrap_fg_geom(@fg_geom.boundary, nil)
102
- end
108
+ @factory.wrap_fg_geom(@fg_geom.boundary, nil)
109
+ rescue ::Geos::GEOSException
110
+ raise Error::InvalidGeometry, "Operation not supported by GeometryCollection"
103
111
  end
104
112
 
105
113
  def as_text
@@ -131,6 +139,32 @@ module RGeo
131
139
  simple?
132
140
  end
133
141
 
142
+ def is_3d?
143
+ factory.property(:has_z_coordinate)
144
+ end
145
+
146
+ def measured?
147
+ factory.property(:has_m_coordinate)
148
+ end
149
+
150
+ def valid?
151
+ @fg_geom.valid?
152
+ end
153
+
154
+ def invalid_reason
155
+ # valid_detail gives solely the reason, or nil if valid, which is
156
+ # what we want.
157
+ fg_geom.valid_detail&.dig(:detail)&.force_encoding(Encoding::UTF_8)
158
+ end
159
+
160
+ # (see RGeo::ImplHelper::ValidityCheck#make_valid)
161
+ # Only available since GEOS 3.8+
162
+ def make_valid
163
+ @factory.wrap_fg_geom(@fg_geom.make_valid, nil)
164
+ rescue ::Geos::GEOSException
165
+ raise Error::UnsupportedOperation
166
+ end if ::Geos::FFIGeos.respond_to?(:GEOSMakeValid_r)
167
+
134
168
  def equals?(rhs)
135
169
  return false unless rhs.is_a?(RGeo::Feature::Instance)
136
170
  fg = factory.convert_to_fg_geometry(rhs)
@@ -116,13 +116,6 @@ module RGeo
116
116
  # Specifies which native interface to use. Possible values are
117
117
  # <tt>:capi</tt> and <tt>:ffi</tt>. The default is the value
118
118
  # of the preferred_native_interface.
119
- # [<tt>:uses_lenient_multi_polygon_assertions</tt>]
120
- # If set to true, assertion checking on MultiPolygon is disabled.
121
- # This may speed up creation of MultiPolygon objects, at the
122
- # expense of not doing the proper checking for OGC MultiPolygon
123
- # compliance. See RGeo::Feature::MultiPolygon for details on
124
- # the MultiPolygon assertions. Default is false. Also called
125
- # <tt>:lenient_multi_polygon_assertions</tt>.
126
119
  # [<tt>:buffer_resolution</tt>]
127
120
  # The resolution of buffers around geometries created by this
128
121
  # factory. This controls the number of line segments used to
@@ -142,11 +135,6 @@ module RGeo
142
135
  # The coordinate system in OGC form, either as a subclass of
143
136
  # CoordSys::CS::CoordinateSystem, or as a string in WKT format.
144
137
  # Optional.
145
- # [<tt>:srs_database</tt>]
146
- # Optional. If provided, the object should respond to #get and
147
- # #clear_cache. If both this and an SRID are
148
- # provided, they are used to look up the proj4 and coord_sys
149
- # objects from a spatial reference system database.
150
138
  # [<tt>:has_z_coordinate</tt>]
151
139
  # Support <tt>z_coordinate</tt>. Default is false.
152
140
  # [<tt>:has_m_coordinate</tt>]
@@ -201,18 +189,6 @@ module RGeo
201
189
  end
202
190
  end
203
191
  end
204
-
205
- # Returns a Feature::FactoryGenerator that creates Geos-backed
206
- # factories. The given options are used as the default options.
207
- #
208
- # A common case for this is to provide the <tt>:srs_database</tt>
209
- # as a default. Then, the factory generator need only be passed
210
- # an SRID and it will automatically fetch the appropriate Proj4
211
- # and CoordSys objects.
212
-
213
- def factory_generator(defaults = {})
214
- proc { |c| factory(defaults.merge(c)) }
215
- end
216
192
  end
217
193
  end
218
194
  end
@@ -44,17 +44,8 @@ module RGeo
44
44
  proj4 = opts[:proj4]
45
45
  coord_sys = opts[:coord_sys]
46
46
  srid = opts[:srid]
47
- if (!proj4 || !coord_sys) && srid && (db = opts[:srs_database])
48
- entry = db.get(srid.to_i)
49
- if entry
50
- proj4 ||= entry.proj4
51
- coord_sys ||= entry.coord_sys
52
- end
53
- end
54
47
  srid ||= coord_sys.authority_code if coord_sys
55
48
  config = {
56
- uses_lenient_multi_polygon_assertions: opts[:lenient_multi_polygon_assertions] ||
57
- opts[:uses_lenient_multi_polygon_assertions],
58
49
  buffer_resolution: opts[:buffer_resolution], auto_prepare: opts[:auto_prepare],
59
50
  wkt_generator: opts[:wkt_generator], wkt_parser: opts[:wkt_parser],
60
51
  wkb_generator: opts[:wkb_generator], wkb_parser: opts[:wkb_parser],
@@ -109,7 +100,6 @@ module RGeo
109
100
  "wkbg" => @wkb_generator.properties,
110
101
  "wktp" => @wkt_parser.properties,
111
102
  "wkbp" => @wkb_parser.properties,
112
- "lmpa" => @zfactory.lenient_multi_polygon_assertions?,
113
103
  "apre" => @zfactory.property(:auto_prepare) == :simple,
114
104
  "nffi" => @zfactory.is_a?(FFIFactory)
115
105
  }
@@ -142,7 +132,6 @@ module RGeo
142
132
  wkb_generator: symbolize_hash(data["wkbg"]),
143
133
  wkt_parser: symbolize_hash(data["wktp"]),
144
134
  wkb_parser: symbolize_hash(data["wkbp"]),
145
- uses_lenient_multi_polygon_assertions: data["lmpa"],
146
135
  auto_prepare: (data["apre"] ? :simple : :disabled),
147
136
  proj4: proj4,
148
137
  coord_sys: coord_sys
@@ -154,7 +143,6 @@ module RGeo
154
143
  def encode_with(coder) # :nodoc:
155
144
  coder["srid"] = @zfactory.srid
156
145
  coder["buffer_resolution"] = @zfactory.buffer_resolution
157
- coder["lenient_multi_polygon_assertions"] = @zfactory.lenient_multi_polygon_assertions?
158
146
  coder["wkt_generator"] = @wkt_generator.properties
159
147
  coder["wkb_generator"] = @wkb_generator.properties
160
148
  coder["wkt_parser"] = @wkt_parser.properties
@@ -197,7 +185,6 @@ module RGeo
197
185
  wkt_parser: symbolize_hash(coder["wkt_parser"]),
198
186
  wkb_parser: symbolize_hash(coder["wkb_parser"]),
199
187
  auto_prepare: coder["auto_prepare"] == "disabled" ? :disabled : :simple,
200
- uses_lenient_multi_polygon_assertions: coder["lenient_multi_polygon_assertions"],
201
188
  proj4: proj4,
202
189
  coord_sys: coord_sys
203
190
  )
@@ -216,12 +203,6 @@ module RGeo
216
203
  @zfactory.buffer_resolution
217
204
  end
218
205
 
219
- # Returns true if this factory is lenient with MultiPolygon assertions
220
-
221
- def lenient_multi_polygon_assertions?
222
- @zfactory.lenient_multi_polygon_assertions?
223
- end
224
-
225
206
  # Returns the z-only factory corresponding to this factory.
226
207
 
227
208
  def z_factory