rgeo 0.3.13 → 0.3.14

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 (51) hide show
  1. data/History.rdoc +8 -0
  2. data/README.rdoc +4 -4
  3. data/Version +1 -1
  4. data/ext/geos_c_impl/extconf.rb +1 -0
  5. data/ext/geos_c_impl/factory.c +118 -5
  6. data/ext/geos_c_impl/factory.h +24 -1
  7. data/ext/geos_c_impl/geometry.c +42 -53
  8. data/ext/geos_c_impl/geometry_collection.c +137 -54
  9. data/ext/geos_c_impl/geometry_collection.h +9 -0
  10. data/ext/geos_c_impl/line_string.c +88 -45
  11. data/ext/geos_c_impl/point.c +31 -17
  12. data/ext/geos_c_impl/polygon.c +50 -22
  13. data/ext/geos_c_impl/polygon.h +9 -0
  14. data/ext/geos_c_impl/preface.h +10 -0
  15. data/lib/rgeo/cartesian/factory.rb +9 -1
  16. data/lib/rgeo/coord_sys/cs/entities.rb +10 -1
  17. data/lib/rgeo/coord_sys/proj4.rb +1 -1
  18. data/lib/rgeo/feature/types.rb +29 -5
  19. data/lib/rgeo/geographic/factory.rb +5 -0
  20. data/lib/rgeo/geographic/projected_feature_classes.rb +3 -47
  21. data/lib/rgeo/geographic/projected_feature_methods.rb +69 -0
  22. data/lib/rgeo/geographic/spherical_feature_classes.rb +1 -74
  23. data/lib/rgeo/geographic/spherical_feature_methods.rb +84 -0
  24. data/lib/rgeo/geographic/spherical_math.rb +3 -3
  25. data/lib/rgeo/geos.rb +17 -9
  26. data/lib/rgeo/geos/{factory.rb → capi_factory.rb} +36 -15
  27. data/lib/rgeo/geos/{impl_additions.rb → capi_feature_classes.rb} +127 -16
  28. data/lib/rgeo/geos/ffi_factory.rb +55 -41
  29. data/lib/rgeo/geos/ffi_feature_classes.rb +168 -0
  30. data/lib/rgeo/geos/{ffi_classes.rb → ffi_feature_methods.rb} +56 -57
  31. data/lib/rgeo/geos/interface.rb +5 -5
  32. data/lib/rgeo/geos/utils.rb +7 -0
  33. data/lib/rgeo/geos/zm_factory.rb +40 -12
  34. data/lib/rgeo/geos/zm_feature_classes.rb +165 -0
  35. data/lib/rgeo/geos/{zm_impl.rb → zm_feature_methods.rb} +33 -52
  36. data/lib/rgeo/impl_helper/basic_geometry_collection_methods.rb +8 -0
  37. data/lib/rgeo/impl_helper/basic_line_string_methods.rb +8 -0
  38. data/lib/rgeo/impl_helper/basic_point_methods.rb +5 -0
  39. data/lib/rgeo/impl_helper/basic_polygon_methods.rb +8 -0
  40. data/test/common/factory_tests.rb +8 -2
  41. data/test/common/geometry_collection_tests.rb +23 -0
  42. data/test/common/line_string_tests.rb +25 -0
  43. data/test/common/multi_line_string_tests.rb +7 -0
  44. data/test/common/multi_point_tests.rb +7 -0
  45. data/test/common/multi_polygon_tests.rb +7 -0
  46. data/test/common/point_tests.rb +21 -0
  47. data/test/common/polygon_tests.rb +15 -0
  48. data/test/coord_sys/tc_proj4.rb +8 -1
  49. data/test/geos_capi/tc_misc.rb +1 -1
  50. data/test/tc_mixins.rb +1 -1
  51. metadata +9 -7
@@ -39,12 +39,10 @@ module RGeo
39
39
  module Geos
40
40
 
41
41
 
42
- class FFIGeometryImpl # :nodoc:
42
+ module FFIGeometryMethods # :nodoc:
43
43
 
44
44
  include Feature::Instance
45
45
 
46
- Feature::MixinCollection::GLOBAL.for_type(Feature::Geometry).include_in_class(self)
47
-
48
46
 
49
47
  def initialize(factory_, fg_geom_, klasses_)
50
48
  @factory = factory_
@@ -143,7 +141,7 @@ module RGeo
143
141
  if fg_geom_.type_id == ::Geos::GeomTypes::GEOS_POINT && fg_geom_.empty?
144
142
  fg_geom_ = ::Geos::Utils.create_geometry_collection
145
143
  end
146
- @factory.wrap_fg_geom(fg_geom_)
144
+ @factory._wrap_fg_geom(fg_geom_, nil)
147
145
  end
148
146
 
149
147
 
@@ -151,7 +149,7 @@ module RGeo
151
149
  if self.class == FFIGeometryCollectionImpl
152
150
  nil
153
151
  else
154
- @factory.wrap_fg_geom(@fg_geom.boundary)
152
+ @factory._wrap_fg_geom(@fg_geom.boundary, nil)
155
153
  end
156
154
  end
157
155
 
@@ -286,18 +284,18 @@ module RGeo
286
284
 
287
285
 
288
286
  def buffer(distance_)
289
- @factory.wrap_fg_geom(@fg_geom.buffer(distance_, @factory.buffer_resolution))
287
+ @factory._wrap_fg_geom(@fg_geom.buffer(distance_, @factory.buffer_resolution), nil)
290
288
  end
291
289
 
292
290
 
293
291
  def convex_hull
294
- @factory.wrap_fg_geom(@fg_geom.convex_hull)
292
+ @factory._wrap_fg_geom(@fg_geom.convex_hull, nil)
295
293
  end
296
294
 
297
295
 
298
296
  def intersection(rhs_)
299
297
  fg_ = factory._convert_to_fg_geometry(rhs_)
300
- fg_ ? @factory.wrap_fg_geom(@fg_geom.intersection(fg_)) : nil
298
+ fg_ ? @factory._wrap_fg_geom(@fg_geom.intersection(fg_), nil) : nil
301
299
  end
302
300
 
303
301
  alias_method :*, :intersection
@@ -305,7 +303,7 @@ module RGeo
305
303
 
306
304
  def union(rhs_)
307
305
  fg_ = factory._convert_to_fg_geometry(rhs_)
308
- fg_ ? @factory.wrap_fg_geom(@fg_geom.union(fg_)) : nil
306
+ fg_ ? @factory._wrap_fg_geom(@fg_geom.union(fg_), nil) : nil
309
307
  end
310
308
 
311
309
  alias_method :+, :union
@@ -313,7 +311,7 @@ module RGeo
313
311
 
314
312
  def difference(rhs_)
315
313
  fg_ = factory._convert_to_fg_geometry(rhs_)
316
- fg_ ? @factory.wrap_fg_geom(@fg_geom.difference(fg_)) : nil
314
+ fg_ ? @factory._wrap_fg_geom(@fg_geom.difference(fg_), nil) : nil
317
315
  end
318
316
 
319
317
  alias_method :-, :difference
@@ -321,7 +319,7 @@ module RGeo
321
319
 
322
320
  def sym_difference(rhs_)
323
321
  fg_ = factory._convert_to_fg_geometry(rhs_)
324
- fg_ ? @factory.wrap_fg_geom(@fg_geom.sym_difference(fg_)) : nil
322
+ fg_ ? @factory._wrap_fg_geom(@fg_geom.sym_difference(fg_), nil) : nil
325
323
  end
326
324
 
327
325
 
@@ -355,9 +353,7 @@ module RGeo
355
353
  end
356
354
 
357
355
 
358
- class FFIPointImpl < FFIGeometryImpl # :nodoc:
359
-
360
- Feature::MixinCollection::GLOBAL.for_type(Feature::Point).include_in_class(self)
356
+ module FFIPointMethods # :nodoc:
361
357
 
362
358
 
363
359
  def x
@@ -399,14 +395,15 @@ module RGeo
399
395
  end
400
396
 
401
397
 
402
- end
398
+ def hash
399
+ @hash ||= Utils.ffi_coord_seq_hash(@fg_geom.coord_seq, [@factory, geometry_type].hash)
400
+ end
403
401
 
404
402
 
405
- class FFILineStringImpl < FFIGeometryImpl # :nodoc:
403
+ end
406
404
 
407
405
 
408
- Feature::MixinCollection::GLOBAL.for_type(Feature::Curve).include_in_class(self)
409
- Feature::MixinCollection::GLOBAL.for_type(Feature::LineString).include_in_class(self)
406
+ module FFILineStringMethods # :nodoc:
410
407
 
411
408
 
412
409
  def geometry_type
@@ -475,13 +472,15 @@ module RGeo
475
472
  end
476
473
 
477
474
 
478
- end
475
+ def hash
476
+ @hash ||= Utils.ffi_coord_seq_hash(@fg_geom.coord_seq, [@factory, geometry_type].hash)
477
+ end
479
478
 
480
479
 
481
- class FFILinearRingImpl < FFILineStringImpl # :nodoc:
480
+ end
482
481
 
483
482
 
484
- Feature::MixinCollection::GLOBAL.for_type(Feature::LinearRing).include_in_class(self)
483
+ module FFILinearRingMethods # :nodoc:
485
484
 
486
485
 
487
486
  def geometry_type
@@ -492,10 +491,7 @@ module RGeo
492
491
  end
493
492
 
494
493
 
495
- class FFILineImpl < FFILineStringImpl # :nodoc:
496
-
497
-
498
- Feature::MixinCollection::GLOBAL.for_type(Feature::Line).include_in_class(self)
494
+ module FFILineMethods # :nodoc:
499
495
 
500
496
 
501
497
  def geometry_type
@@ -506,11 +502,7 @@ module RGeo
506
502
  end
507
503
 
508
504
 
509
- class FFIPolygonImpl < FFIGeometryImpl # :nodoc:
510
-
511
-
512
- Feature::MixinCollection::GLOBAL.for_type(Feature::Surface).include_in_class(self)
513
- Feature::MixinCollection::GLOBAL.for_type(Feature::Polygon).include_in_class(self)
505
+ module FFIPolygonMethods # :nodoc:
514
506
 
515
507
 
516
508
  def geometry_type
@@ -524,17 +516,17 @@ module RGeo
524
516
 
525
517
 
526
518
  def centroid
527
- @factory.wrap_fg_geom(@fg_geom.centroid, FFIPointImpl)
519
+ @factory._wrap_fg_geom(@fg_geom.centroid, FFIPointImpl)
528
520
  end
529
521
 
530
522
 
531
523
  def point_on_surface
532
- @factory.wrap_fg_geom(@fg_geom.point_on_surface, FFIPointImpl)
524
+ @factory._wrap_fg_geom(@fg_geom.point_on_surface, FFIPointImpl)
533
525
  end
534
526
 
535
527
 
536
528
  def exterior_ring
537
- @factory.wrap_fg_geom(@fg_geom.exterior_ring, FFILinearRingImpl)
529
+ @factory._wrap_fg_geom(@fg_geom.exterior_ring, FFILinearRingImpl)
538
530
  end
539
531
 
540
532
 
@@ -545,7 +537,7 @@ module RGeo
545
537
 
546
538
  def interior_ring_n(n_)
547
539
  if n_ >= 0 && n_ < @fg_geom.num_interior_rings
548
- @factory.wrap_fg_geom(@fg_geom.interior_ring_n(n_), FFILinearRingImpl)
540
+ @factory._wrap_fg_geom(@fg_geom.interior_ring_n(n_), FFILinearRingImpl)
549
541
  else
550
542
  nil
551
543
  end
@@ -554,7 +546,7 @@ module RGeo
554
546
 
555
547
  def interior_rings
556
548
  ::Array.new(@fg_geom.num_interior_rings) do |n_|
557
- @factory.wrap_fg_geom(@fg_geom.interior_ring_n(n_), FFILinearRingImpl)
549
+ @factory._wrap_fg_geom(@fg_geom.interior_ring_n(n_), FFILinearRingImpl)
558
550
  end
559
551
  end
560
552
 
@@ -576,13 +568,21 @@ module RGeo
576
568
  end
577
569
 
578
570
 
579
- end
571
+ def hash
572
+ @hash ||= begin
573
+ hash_ = Utils.ffi_coord_seq_hash(@fg_geom.exterior_ring.coord_seq,
574
+ [@factory, geometry_type].hash)
575
+ @fg_geom.interior_rings.inject(hash_) do |h_, r_|
576
+ Utils.ffi_coord_seq_hash(r_.coord_seq, h_)
577
+ end
578
+ end
579
+ end
580
580
 
581
581
 
582
- class FFIGeometryCollectionImpl < FFIGeometryImpl # :nodoc:
582
+ end
583
583
 
584
584
 
585
- Feature::MixinCollection::GLOBAL.for_type(Feature::GeometryCollection).include_in_class(self)
585
+ module FFIGeometryCollectionMethods # :nodoc:
586
586
 
587
587
 
588
588
  def geometry_type
@@ -612,7 +612,7 @@ module RGeo
612
612
 
613
613
  def geometry_n(n_)
614
614
  if n_ >= 0 && n_ < @fg_geom.num_geometries
615
- @factory.wrap_fg_geom(@fg_geom.get_geometry_n(n_),
615
+ @factory._wrap_fg_geom(@fg_geom.get_geometry_n(n_),
616
616
  @_klasses ? @_klasses[n_] : nil)
617
617
  else
618
618
  nil
@@ -623,7 +623,7 @@ module RGeo
623
623
  def [](n_)
624
624
  n_ += @fg_geom.num_geometries if n_ < 0
625
625
  if n_ >= 0 && n_ < @fg_geom.num_geometries
626
- @factory.wrap_fg_geom(@fg_geom.get_geometry_n(n_),
626
+ @factory._wrap_fg_geom(@fg_geom.get_geometry_n(n_),
627
627
  @_klasses ? @_klasses[n_] : nil)
628
628
  else
629
629
  nil
@@ -631,10 +631,20 @@ module RGeo
631
631
  end
632
632
 
633
633
 
634
+ def hash
635
+ @hash ||= begin
636
+ hash_ = [@factory, geometry_type].hash
637
+ (0...num_geometries).inject(hash_) do |h_, i_|
638
+ (1664525 * h_ + geometry_n(i_).hash).hash
639
+ end
640
+ end
641
+ end
642
+
643
+
634
644
  def each
635
645
  if block_given?
636
646
  @fg_geom.num_geometries.times do |n_|
637
- yield @factory.wrap_fg_geom(@fg_geom.get_geometry_n(n_),
647
+ yield @factory._wrap_fg_geom(@fg_geom.get_geometry_n(n_),
638
648
  @_klasses ? @_klasses[n_] : nil)
639
649
  end
640
650
  self
@@ -649,10 +659,7 @@ module RGeo
649
659
  end
650
660
 
651
661
 
652
- class FFIMultiPointImpl < FFIGeometryCollectionImpl # :nodoc:
653
-
654
-
655
- Feature::MixinCollection::GLOBAL.for_type(Feature::MultiPoint).include_in_class(self)
662
+ module FFIMultiPointMethods # :nodoc:
656
663
 
657
664
 
658
665
  def geometry_type
@@ -663,11 +670,7 @@ module RGeo
663
670
  end
664
671
 
665
672
 
666
- class FFIMultiLineStringImpl < FFIGeometryCollectionImpl # :nodoc:
667
-
668
-
669
- Feature::MixinCollection::GLOBAL.for_type(Feature::MultiCurve).include_in_class(self)
670
- Feature::MixinCollection::GLOBAL.for_type(Feature::MultiLineString).include_in_class(self)
673
+ module FFIMultiLineStringMethods # :nodoc:
671
674
 
672
675
 
673
676
  def geometry_type
@@ -692,11 +695,7 @@ module RGeo
692
695
  end
693
696
 
694
697
 
695
- class FFIMultiPolygonImpl < FFIGeometryCollectionImpl # :nodoc:
696
-
697
-
698
- Feature::MixinCollection::GLOBAL.for_type(Feature::MultiSurface).include_in_class(self)
699
- Feature::MixinCollection::GLOBAL.for_type(Feature::MultiPolygon).include_in_class(self)
698
+ module FFIMultiPolygonMethods # :nodoc:
700
699
 
701
700
 
702
701
  def geometry_type
@@ -710,12 +709,12 @@ module RGeo
710
709
 
711
710
 
712
711
  def centroid
713
- @factory.wrap_fg_geom(@fg_geom.centroid, FFIPointImpl)
712
+ @factory._wrap_fg_geom(@fg_geom.centroid, FFIPointImpl)
714
713
  end
715
714
 
716
715
 
717
716
  def point_on_surface
718
- @factory.wrap_fg_geom(@fg_geom.point_on_surface, FFIPointImpl)
717
+ @factory._wrap_fg_geom(@fg_geom.point_on_surface, FFIPointImpl)
719
718
  end
720
719
 
721
720
 
@@ -67,9 +67,9 @@ module RGeo
67
67
  # the given factory is a CAPI GEOS factory.
68
68
 
69
69
  def is_capi_geos?(object_)
70
- Factory === object_ || GeometryImpl === object_ ||
71
- ZMFactory === object_ && Factory === object_.z_factory ||
72
- ZMGeometryImpl === object_ && GeometryImpl === object_.z_geometry
70
+ CAPIFactory === object_ || CAPIGeometryImpl === object_ ||
71
+ ZMFactory === object_ && CAPIFactory === object_.z_factory ||
72
+ ZMGeometryImpl === object_ && CAPIGeometryImpl === object_.z_geometry
73
73
  end
74
74
 
75
75
 
@@ -87,7 +87,7 @@ module RGeo
87
87
  # factory is a GEOS factory. Does not distinguish between CAPI and FFI.
88
88
 
89
89
  def is_geos?(object_)
90
- Factory === object_ || GeometryImpl === object_ ||
90
+ CAPIFactory === object_ || CAPIGeometryImpl === object_ ||
91
91
  FFIFactory === object_ || FFIGeometryImpl === object_ ||
92
92
  ZMFactory === object_ || ZMGeometryImpl === object_
93
93
  end
@@ -204,7 +204,7 @@ module RGeo
204
204
  elsif native_interface_ == :ffi
205
205
  FFIFactory.new(opts_)
206
206
  else
207
- Factory.create(opts_)
207
+ CAPIFactory.create(opts_)
208
208
  end
209
209
  else
210
210
  nil
@@ -85,6 +85,13 @@ module RGeo
85
85
  end
86
86
 
87
87
 
88
+ def ffi_coord_seq_hash(cs_, hash_=0)
89
+ (0...cs_.length).inject(hash_) do |h_, i_|
90
+ [hash_, cs_.get_x(i_), cs_.get_y(i_), cs_.get_z(i_)].hash
91
+ end
92
+ end
93
+
94
+
88
95
  def _init
89
96
  if FFI_SUPPORTED
90
97
  @ffi_supports_prepared_level_1 = ::Geos::FFIGeos.respond_to?(:GEOSPreparedContains_r)
@@ -46,6 +46,23 @@ module RGeo
46
46
  include Feature::Factory::Instance
47
47
 
48
48
 
49
+ # :stopdoc:
50
+
51
+ TYPE_KLASSES = {
52
+ Feature::Point => ZMPointImpl,
53
+ Feature::LineString => ZMLineStringImpl,
54
+ Feature::Line => ZMLineImpl,
55
+ Feature::LinearRing => ZMLinearRingImpl,
56
+ Feature::Polygon => ZMPolygonImpl,
57
+ Feature::GeometryCollection => ZMGeometryCollectionImpl,
58
+ Feature::MultiPoint => ZMMultiPointImpl,
59
+ Feature::MultiLineString => ZMMultiLineStringImpl,
60
+ Feature::MultiPolygon => ZMMultiPolygonImpl,
61
+ }.freeze
62
+
63
+ # :startdoc:
64
+
65
+
49
66
  class << self
50
67
 
51
68
 
@@ -86,8 +103,8 @@ module RGeo
86
103
  @zfactory = FFIFactory.new(config_.merge(:has_z_coordinate => true))
87
104
  @mfactory = FFIFactory.new(config_.merge(:has_m_coordinate => true))
88
105
  else
89
- @zfactory = Factory.create(config_.merge(:has_z_coordinate => true))
90
- @mfactory = Factory.create(config_.merge(:has_m_coordinate => true))
106
+ @zfactory = CAPIFactory.create(config_.merge(:has_z_coordinate => true))
107
+ @mfactory = CAPIFactory.create(config_.merge(:has_m_coordinate => true))
91
108
  end
92
109
 
93
110
  wkt_generator_ = opts_[:wkt_generator]
@@ -270,6 +287,11 @@ module RGeo
270
287
  alias_method :==, :eql?
271
288
 
272
289
 
290
+ def hash
291
+ @hash ||= [@zfactory, @mfactory].hash
292
+ end
293
+
294
+
273
295
  # See ::RGeo::Feature::Factory#property
274
296
 
275
297
  def property(name_)
@@ -299,63 +321,63 @@ module RGeo
299
321
  # See ::RGeo::Feature::Factory#point
300
322
 
301
323
  def point(x_, y_, z_=0, m_=0)
302
- ZMPointImpl.create(self, @zfactory.point(x_, y_, z_), @mfactory.point(x_, y_, m_))
324
+ _create_feature(ZMPointImpl, @zfactory.point(x_, y_, z_), @mfactory.point(x_, y_, m_))
303
325
  end
304
326
 
305
327
 
306
328
  # See ::RGeo::Feature::Factory#line_string
307
329
 
308
330
  def line_string(points_)
309
- ZMLineStringImpl.create(self, @zfactory.line_string(points_), @mfactory.line_string(points_))
331
+ _create_feature(ZMLineStringImpl, @zfactory.line_string(points_), @mfactory.line_string(points_))
310
332
  end
311
333
 
312
334
 
313
335
  # See ::RGeo::Feature::Factory#line
314
336
 
315
337
  def line(start_, end_)
316
- ZMLineStringImpl.create(self, @zfactory.line(start_, end_), @mfactory.line(start_, end_))
338
+ _create_feature(ZMLineImpl, @zfactory.line(start_, end_), @mfactory.line(start_, end_))
317
339
  end
318
340
 
319
341
 
320
342
  # See ::RGeo::Feature::Factory#linear_ring
321
343
 
322
344
  def linear_ring(points_)
323
- ZMLineStringImpl.create(self, @zfactory.linear_ring(points_), @mfactory.linear_ring(points_))
345
+ _create_feature(ZMLinearRingImpl, @zfactory.linear_ring(points_), @mfactory.linear_ring(points_))
324
346
  end
325
347
 
326
348
 
327
349
  # See ::RGeo::Feature::Factory#polygon
328
350
 
329
351
  def polygon(outer_ring_, inner_rings_=nil)
330
- ZMPolygonImpl.create(self, @zfactory.polygon(outer_ring_, inner_rings_), @mfactory.polygon(outer_ring_, inner_rings_))
352
+ _create_feature(ZMPolygonImpl, @zfactory.polygon(outer_ring_, inner_rings_), @mfactory.polygon(outer_ring_, inner_rings_))
331
353
  end
332
354
 
333
355
 
334
356
  # See ::RGeo::Feature::Factory#collection
335
357
 
336
358
  def collection(elems_)
337
- ZMGeometryCollectionImpl.create(self, @zfactory.collection(elems_), @mfactory.collection(elems_))
359
+ _create_feature(ZMGeometryCollectionImpl, @zfactory.collection(elems_), @mfactory.collection(elems_))
338
360
  end
339
361
 
340
362
 
341
363
  # See ::RGeo::Feature::Factory#multi_point
342
364
 
343
365
  def multi_point(elems_)
344
- ZMGeometryCollectionImpl.create(self, @zfactory.multi_point(elems_), @mfactory.multi_point(elems_))
366
+ _create_feature(ZMMultiPointImpl, @zfactory.multi_point(elems_), @mfactory.multi_point(elems_))
345
367
  end
346
368
 
347
369
 
348
370
  # See ::RGeo::Feature::Factory#multi_line_string
349
371
 
350
372
  def multi_line_string(elems_)
351
- ZMMultiLineStringImpl.create(self, @zfactory.multi_line_string(elems_), @mfactory.multi_line_string(elems_))
373
+ _create_feature(ZMMultiLineStringImpl, @zfactory.multi_line_string(elems_), @mfactory.multi_line_string(elems_))
352
374
  end
353
375
 
354
376
 
355
377
  # See ::RGeo::Feature::Factory#multi_polygon
356
378
 
357
379
  def multi_polygon(elems_)
358
- ZMMultiPolygonImpl.create(self, @zfactory.multi_polygon(elems_), @mfactory.multi_polygon(elems_))
380
+ _create_feature(ZMMultiPolygonImpl, @zfactory.multi_polygon(elems_), @mfactory.multi_polygon(elems_))
359
381
  end
360
382
 
361
383
 
@@ -383,7 +405,7 @@ module RGeo
383
405
  type_ = original_.geometry_type
384
406
  ntype_ = type_ if keep_subtype_ && type_.include?(ntype_)
385
407
  case original_
386
- when ZMGeometryImpl
408
+ when ZMGeometryMethods
387
409
  # Optimization if we're just changing factories, but to
388
410
  # another ZM factory.
389
411
  if original_.factory != self && ntype_ == type_ &&
@@ -410,6 +432,12 @@ module RGeo
410
432
  end
411
433
 
412
434
 
435
+ def _create_feature(klass_, zgeometry_, mgeometry_) # :nodoc:
436
+ klass_ ||= TYPE_KLASSES[zgeometry_.geometry_type] || ZMGeometryImpl
437
+ zgeometry_ && mgeometry_ ? klass_.new(self, zgeometry_, mgeometry_) : nil
438
+ end
439
+
440
+
413
441
  def _marshal_wkb_generator # :nodoc:
414
442
  unless defined?(@marshal_wkb_generator)
415
443
  @marshal_wkb_generator = ::RGeo::WKRep::WKBGenerator.new(