rgeo 3.0.0.pre.rc.3 → 3.0.1

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 (64) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +11 -3
  3. data/ext/geos_c_impl/extconf.rb +1 -0
  4. data/ext/geos_c_impl/factory.c +43 -5
  5. data/ext/geos_c_impl/factory.h +13 -2
  6. data/ext/geos_c_impl/geometry.c +178 -122
  7. data/ext/geos_c_impl/geometry_collection.c +17 -19
  8. data/ext/geos_c_impl/line_string.c +46 -36
  9. data/ext/geos_c_impl/point.c +0 -2
  10. data/ext/geos_c_impl/polygon.c +10 -11
  11. data/ext/geos_c_impl/polygon.h +1 -1
  12. data/ext/geos_c_impl/preface.h +3 -0
  13. data/ext/geos_c_impl/ruby_more.c +7 -0
  14. data/ext/geos_c_impl/ruby_more.h +8 -0
  15. data/lib/rgeo/cartesian/analysis.rb +5 -3
  16. data/lib/rgeo/cartesian/bounding_box.rb +74 -79
  17. data/lib/rgeo/cartesian/calculations.rb +20 -26
  18. data/lib/rgeo/cartesian/factory.rb +47 -49
  19. data/lib/rgeo/cartesian/planar_graph.rb +10 -16
  20. data/lib/rgeo/cartesian/sweepline_intersector.rb +1 -3
  21. data/lib/rgeo/cartesian/valid_op.rb +1 -3
  22. data/lib/rgeo/coord_sys/cs/entities.rb +91 -101
  23. data/lib/rgeo/coord_sys/cs/factories.rb +0 -2
  24. data/lib/rgeo/coord_sys/cs/wkt_parser.rb +70 -29
  25. data/lib/rgeo/feature/curve.rb +0 -1
  26. data/lib/rgeo/feature/factory.rb +25 -27
  27. data/lib/rgeo/feature/factory_generator.rb +3 -4
  28. data/lib/rgeo/feature/geometry.rb +41 -30
  29. data/lib/rgeo/feature/geometry_collection.rb +3 -4
  30. data/lib/rgeo/feature/line_string.rb +1 -2
  31. data/lib/rgeo/feature/linear_ring.rb +0 -1
  32. data/lib/rgeo/feature/multi_curve.rb +0 -1
  33. data/lib/rgeo/feature/multi_surface.rb +0 -1
  34. data/lib/rgeo/feature/point.rb +0 -1
  35. data/lib/rgeo/feature/polygon.rb +1 -2
  36. data/lib/rgeo/feature/surface.rb +0 -1
  37. data/lib/rgeo/feature/types.rb +69 -85
  38. data/lib/rgeo/geographic/factory.rb +87 -80
  39. data/lib/rgeo/geographic/interface.rb +44 -27
  40. data/lib/rgeo/geographic/projected_feature_methods.rb +2 -6
  41. data/lib/rgeo/geographic/projected_window.rb +35 -21
  42. data/lib/rgeo/geographic/simple_mercator_projector.rb +27 -15
  43. data/lib/rgeo/geographic/spherical_feature_methods.rb +8 -3
  44. data/lib/rgeo/geographic/spherical_math.rb +17 -20
  45. data/lib/rgeo/geos/capi_factory.rb +50 -50
  46. data/lib/rgeo/geos/ffi_factory.rb +50 -49
  47. data/lib/rgeo/geos/ffi_feature_methods.rb +72 -98
  48. data/lib/rgeo/geos/interface.rb +16 -16
  49. data/lib/rgeo/geos/utils.rb +5 -5
  50. data/lib/rgeo/geos/zm_factory.rb +50 -42
  51. data/lib/rgeo/geos/zm_feature_methods.rb +15 -9
  52. data/lib/rgeo/impl_helper/basic_geometry_collection_methods.rb +4 -4
  53. data/lib/rgeo/impl_helper/basic_geometry_methods.rb +1 -2
  54. data/lib/rgeo/impl_helper/basic_line_string_methods.rb +18 -24
  55. data/lib/rgeo/impl_helper/basic_point_methods.rb +1 -3
  56. data/lib/rgeo/impl_helper/basic_polygon_methods.rb +15 -16
  57. data/lib/rgeo/impl_helper/utils.rb +3 -9
  58. data/lib/rgeo/impl_helper/valid_op.rb +12 -16
  59. data/lib/rgeo/version.rb +1 -1
  60. data/lib/rgeo/wkrep/wkb_generator.rb +42 -47
  61. data/lib/rgeo/wkrep/wkb_parser.rb +17 -18
  62. data/lib/rgeo/wkrep/wkt_generator.rb +23 -16
  63. data/lib/rgeo/wkrep/wkt_parser.rb +23 -13
  64. metadata +6 -6
@@ -266,6 +266,7 @@ method_geometry_as_text(VALUE self)
266
266
  wkt_writer = factory_data->wkt_writer;
267
267
  if (!wkt_writer) {
268
268
  wkt_writer = GEOSWKTWriter_create();
269
+ GEOSWKTWriter_setOutputDimension(wkt_writer, 2);
269
270
  GEOSWKTWriter_setTrim(wkt_writer, 1);
270
271
  factory_data->wkt_writer = wkt_writer;
271
272
  }
@@ -304,6 +305,7 @@ method_geometry_as_binary(VALUE self)
304
305
 
305
306
  if (!wkb_writer) {
306
307
  wkb_writer = GEOSWKBWriter_create();
308
+ GEOSWKBWriter_setOutputDimension(wkb_writer, 2);
307
309
  factory_data->wkb_writer = wkb_writer;
308
310
  }
309
311
  str = (char*)GEOSWKBWriter_write(wkb_writer, self_geom, &size);
@@ -367,7 +369,6 @@ method_geometry_equals(VALUE self, VALUE rhs)
367
369
  RGeo_GeometryData* self_data;
368
370
  const GEOSGeometry* self_geom;
369
371
  const GEOSGeometry* rhs_geom;
370
- char val;
371
372
 
372
373
  // Shortcut when self and rhs are the same object.
373
374
  if (self == rhs) {
@@ -385,12 +386,7 @@ method_geometry_equals(VALUE self, VALUE rhs)
385
386
  if (GEOSisEmpty(self_geom) == 1 && GEOSisEmpty(rhs_geom) == 1) {
386
387
  result = Qtrue;
387
388
  } else {
388
- val = GEOSEquals(self_geom, rhs_geom);
389
- if (val == 0) {
390
- result = Qfalse;
391
- } else if (val == 1) {
392
- result = Qtrue;
393
- }
389
+ result = GEOSEquals(self_geom, rhs_geom) ? Qtrue : Qfalse;
394
390
  }
395
391
  }
396
392
  }
@@ -411,7 +407,7 @@ method_geometry_disjoint(VALUE self, VALUE rhs)
411
407
  RGeo_GeometryData* self_data;
412
408
  const GEOSGeometry* self_geom;
413
409
  const GEOSGeometry* rhs_geom;
414
- char val;
410
+ int state = 0;
415
411
  #ifdef RGEO_GEOS_SUPPORTS_PREPARED2
416
412
  const GEOSPreparedGeometry* prep;
417
413
  #endif
@@ -420,21 +416,18 @@ method_geometry_disjoint(VALUE self, VALUE rhs)
420
416
  self_data = RGEO_GEOMETRY_DATA_PTR(self);
421
417
  self_geom = self_data->geom;
422
418
  if (self_geom) {
423
- rhs_geom = rgeo_convert_to_geos_geometry(self_data->factory, rhs, Qnil);
424
- if (rhs_geom) {
419
+ rhs_geom =
420
+ rgeo_convert_to_geos_geometry(self_data->factory, rhs, Qnil, &state);
421
+ if (state) {
422
+ rb_jump_tag(state);
423
+ }
425
424
  #ifdef RGEO_GEOS_SUPPORTS_PREPARED2
426
- prep = rgeo_request_prepared_geometry(self_data);
427
- if (prep)
428
- val = GEOSPreparedDisjoint(prep, rhs_geom);
429
- else
425
+ prep = rgeo_request_prepared_geometry(self_data);
426
+ if (prep)
427
+ result = GEOSPreparedDisjoint(prep, rhs_geom) ? Qtrue : Qfalse;
428
+ else
430
429
  #endif
431
- val = GEOSDisjoint(self_geom, rhs_geom);
432
- if (val == 0) {
433
- result = Qfalse;
434
- } else if (val == 1) {
435
- result = Qtrue;
436
- }
437
- }
430
+ result = GEOSDisjoint(self_geom, rhs_geom) ? Qtrue : Qfalse;
438
431
  }
439
432
  return result;
440
433
  }
@@ -447,6 +440,7 @@ method_geometry_intersects(VALUE self, VALUE rhs)
447
440
  const GEOSGeometry* self_geom;
448
441
  const GEOSGeometry* rhs_geom;
449
442
  char val;
443
+ int state = 0;
450
444
  #ifdef RGEO_GEOS_SUPPORTS_PREPARED1
451
445
  const GEOSPreparedGeometry* prep;
452
446
  #endif
@@ -455,20 +449,22 @@ method_geometry_intersects(VALUE self, VALUE rhs)
455
449
  self_data = RGEO_GEOMETRY_DATA_PTR(self);
456
450
  self_geom = self_data->geom;
457
451
  if (self_geom) {
458
- rhs_geom = rgeo_convert_to_geos_geometry(self_data->factory, rhs, Qnil);
459
- if (rhs_geom) {
452
+ rhs_geom =
453
+ rgeo_convert_to_geos_geometry(self_data->factory, rhs, Qnil, &state);
454
+ if (state) {
455
+ rb_jump_tag(state);
456
+ }
460
457
  #ifdef RGEO_GEOS_SUPPORTS_PREPARED1
461
- prep = rgeo_request_prepared_geometry(self_data);
462
- if (prep)
463
- val = GEOSPreparedIntersects(prep, rhs_geom);
464
- else
458
+ prep = rgeo_request_prepared_geometry(self_data);
459
+ if (prep)
460
+ val = GEOSPreparedIntersects(prep, rhs_geom);
461
+ else
465
462
  #endif
466
- val = GEOSIntersects(self_geom, rhs_geom);
467
- if (val == 0) {
468
- result = Qfalse;
469
- } else if (val == 1) {
470
- result = Qtrue;
471
- }
463
+ val = GEOSIntersects(self_geom, rhs_geom);
464
+ if (val == 0) {
465
+ result = Qfalse;
466
+ } else if (val == 1) {
467
+ result = Qtrue;
472
468
  }
473
469
  }
474
470
  return result;
@@ -482,6 +478,7 @@ method_geometry_touches(VALUE self, VALUE rhs)
482
478
  const GEOSGeometry* self_geom;
483
479
  const GEOSGeometry* rhs_geom;
484
480
  char val;
481
+ int state = 0;
485
482
  #ifdef RGEO_GEOS_SUPPORTS_PREPARED2
486
483
  const GEOSPreparedGeometry* prep;
487
484
  #endif
@@ -490,20 +487,22 @@ method_geometry_touches(VALUE self, VALUE rhs)
490
487
  self_data = RGEO_GEOMETRY_DATA_PTR(self);
491
488
  self_geom = self_data->geom;
492
489
  if (self_geom) {
493
- rhs_geom = rgeo_convert_to_geos_geometry(self_data->factory, rhs, Qnil);
494
- if (rhs_geom) {
490
+ rhs_geom =
491
+ rgeo_convert_to_geos_geometry(self_data->factory, rhs, Qnil, &state);
492
+ if (state) {
493
+ rb_jump_tag(state);
494
+ }
495
495
  #ifdef RGEO_GEOS_SUPPORTS_PREPARED2
496
- prep = rgeo_request_prepared_geometry(self_data);
497
- if (prep)
498
- val = GEOSPreparedTouches(prep, rhs_geom);
499
- else
496
+ prep = rgeo_request_prepared_geometry(self_data);
497
+ if (prep)
498
+ val = GEOSPreparedTouches(prep, rhs_geom);
499
+ else
500
500
  #endif
501
- val = GEOSTouches(self_geom, rhs_geom);
502
- if (val == 0) {
503
- result = Qfalse;
504
- } else if (val == 1) {
505
- result = Qtrue;
506
- }
501
+ val = GEOSTouches(self_geom, rhs_geom);
502
+ if (val == 0) {
503
+ result = Qfalse;
504
+ } else if (val == 1) {
505
+ result = Qtrue;
507
506
  }
508
507
  }
509
508
  return result;
@@ -517,6 +516,7 @@ method_geometry_crosses(VALUE self, VALUE rhs)
517
516
  const GEOSGeometry* self_geom;
518
517
  const GEOSGeometry* rhs_geom;
519
518
  char val;
519
+ int state = 0;
520
520
  #ifdef RGEO_GEOS_SUPPORTS_PREPARED2
521
521
  const GEOSPreparedGeometry* prep;
522
522
  #endif
@@ -525,20 +525,22 @@ method_geometry_crosses(VALUE self, VALUE rhs)
525
525
  self_data = RGEO_GEOMETRY_DATA_PTR(self);
526
526
  self_geom = self_data->geom;
527
527
  if (self_geom) {
528
- rhs_geom = rgeo_convert_to_geos_geometry(self_data->factory, rhs, Qnil);
529
- if (rhs_geom) {
528
+ rhs_geom =
529
+ rgeo_convert_to_geos_geometry(self_data->factory, rhs, Qnil, &state);
530
+ if (state) {
531
+ rb_jump_tag(state);
532
+ }
530
533
  #ifdef RGEO_GEOS_SUPPORTS_PREPARED2
531
- prep = rgeo_request_prepared_geometry(self_data);
532
- if (prep)
533
- val = GEOSPreparedCrosses(prep, rhs_geom);
534
- else
534
+ prep = rgeo_request_prepared_geometry(self_data);
535
+ if (prep)
536
+ val = GEOSPreparedCrosses(prep, rhs_geom);
537
+ else
535
538
  #endif
536
- val = GEOSCrosses(self_geom, rhs_geom);
537
- if (val == 0) {
538
- result = Qfalse;
539
- } else if (val == 1) {
540
- result = Qtrue;
541
- }
539
+ val = GEOSCrosses(self_geom, rhs_geom);
540
+ if (val == 0) {
541
+ result = Qfalse;
542
+ } else if (val == 1) {
543
+ result = Qtrue;
542
544
  }
543
545
  }
544
546
  return result;
@@ -552,6 +554,7 @@ method_geometry_within(VALUE self, VALUE rhs)
552
554
  const GEOSGeometry* self_geom;
553
555
  const GEOSGeometry* rhs_geom;
554
556
  char val;
557
+ int state = 0;
555
558
  #ifdef RGEO_GEOS_SUPPORTS_PREPARED2
556
559
  const GEOSPreparedGeometry* prep;
557
560
  #endif
@@ -560,20 +563,22 @@ method_geometry_within(VALUE self, VALUE rhs)
560
563
  self_data = RGEO_GEOMETRY_DATA_PTR(self);
561
564
  self_geom = self_data->geom;
562
565
  if (self_geom) {
563
- rhs_geom = rgeo_convert_to_geos_geometry(self_data->factory, rhs, Qnil);
564
- if (rhs_geom) {
566
+ rhs_geom =
567
+ rgeo_convert_to_geos_geometry(self_data->factory, rhs, Qnil, &state);
568
+ if (state) {
569
+ rb_jump_tag(state);
570
+ }
565
571
  #ifdef RGEO_GEOS_SUPPORTS_PREPARED2
566
- prep = rgeo_request_prepared_geometry(self_data);
567
- if (prep)
568
- val = GEOSPreparedWithin(prep, rhs_geom);
569
- else
572
+ prep = rgeo_request_prepared_geometry(self_data);
573
+ if (prep)
574
+ val = GEOSPreparedWithin(prep, rhs_geom);
575
+ else
570
576
  #endif
571
- val = GEOSWithin(self_geom, rhs_geom);
572
- if (val == 0) {
573
- result = Qfalse;
574
- } else if (val == 1) {
575
- result = Qtrue;
576
- }
577
+ val = GEOSWithin(self_geom, rhs_geom);
578
+ if (val == 0) {
579
+ result = Qfalse;
580
+ } else if (val == 1) {
581
+ result = Qtrue;
577
582
  }
578
583
  }
579
584
  return result;
@@ -587,6 +592,7 @@ method_geometry_contains(VALUE self, VALUE rhs)
587
592
  const GEOSGeometry* self_geom;
588
593
  const GEOSGeometry* rhs_geom;
589
594
  char val;
595
+ int state = 0;
590
596
  #ifdef RGEO_GEOS_SUPPORTS_PREPARED1
591
597
  const GEOSPreparedGeometry* prep;
592
598
  #endif
@@ -595,20 +601,22 @@ method_geometry_contains(VALUE self, VALUE rhs)
595
601
  self_data = RGEO_GEOMETRY_DATA_PTR(self);
596
602
  self_geom = self_data->geom;
597
603
  if (self_geom) {
598
- rhs_geom = rgeo_convert_to_geos_geometry(self_data->factory, rhs, Qnil);
599
- if (rhs_geom) {
604
+ rhs_geom =
605
+ rgeo_convert_to_geos_geometry(self_data->factory, rhs, Qnil, &state);
606
+ if (state) {
607
+ rb_jump_tag(state);
608
+ }
600
609
  #ifdef RGEO_GEOS_SUPPORTS_PREPARED1
601
- prep = rgeo_request_prepared_geometry(self_data);
602
- if (prep)
603
- val = GEOSPreparedContains(prep, rhs_geom);
604
- else
610
+ prep = rgeo_request_prepared_geometry(self_data);
611
+ if (prep)
612
+ val = GEOSPreparedContains(prep, rhs_geom);
613
+ else
605
614
  #endif
606
- val = GEOSContains(self_geom, rhs_geom);
607
- if (val == 0) {
608
- result = Qfalse;
609
- } else if (val == 1) {
610
- result = Qtrue;
611
- }
615
+ val = GEOSContains(self_geom, rhs_geom);
616
+ if (val == 0) {
617
+ result = Qfalse;
618
+ } else if (val == 1) {
619
+ result = Qtrue;
612
620
  }
613
621
  }
614
622
  return result;
@@ -622,6 +630,7 @@ method_geometry_overlaps(VALUE self, VALUE rhs)
622
630
  const GEOSGeometry* self_geom;
623
631
  const GEOSGeometry* rhs_geom;
624
632
  char val;
633
+ int state = 0;
625
634
  #ifdef RGEO_GEOS_SUPPORTS_PREPARED2
626
635
  const GEOSPreparedGeometry* prep;
627
636
  #endif
@@ -630,20 +639,22 @@ method_geometry_overlaps(VALUE self, VALUE rhs)
630
639
  self_data = RGEO_GEOMETRY_DATA_PTR(self);
631
640
  self_geom = self_data->geom;
632
641
  if (self_geom) {
633
- rhs_geom = rgeo_convert_to_geos_geometry(self_data->factory, rhs, Qnil);
634
- if (rhs_geom) {
642
+ rhs_geom =
643
+ rgeo_convert_to_geos_geometry(self_data->factory, rhs, Qnil, &state);
644
+ if (state) {
645
+ rb_jump_tag(state);
646
+ }
635
647
  #ifdef RGEO_GEOS_SUPPORTS_PREPARED2
636
- prep = rgeo_request_prepared_geometry(self_data);
637
- if (prep)
638
- val = GEOSPreparedOverlaps(prep, rhs_geom);
639
- else
648
+ prep = rgeo_request_prepared_geometry(self_data);
649
+ if (prep)
650
+ val = GEOSPreparedOverlaps(prep, rhs_geom);
651
+ else
640
652
  #endif
641
- val = GEOSOverlaps(self_geom, rhs_geom);
642
- if (val == 0) {
643
- result = Qfalse;
644
- } else if (val == 1) {
645
- result = Qtrue;
646
- }
653
+ val = GEOSOverlaps(self_geom, rhs_geom);
654
+ if (val == 0) {
655
+ result = Qfalse;
656
+ } else if (val == 1) {
657
+ result = Qtrue;
647
658
  }
648
659
  }
649
660
  return result;
@@ -657,19 +668,23 @@ method_geometry_relate(VALUE self, VALUE rhs, VALUE pattern)
657
668
  const GEOSGeometry* self_geom;
658
669
  const GEOSGeometry* rhs_geom;
659
670
  char val;
671
+ int state = 0;
660
672
 
661
673
  result = Qnil;
662
674
  self_data = RGEO_GEOMETRY_DATA_PTR(self);
663
675
  self_geom = self_data->geom;
664
676
  if (self_geom) {
665
- rhs_geom = rgeo_convert_to_geos_geometry(self_data->factory, rhs, Qnil);
666
- if (rhs_geom) {
667
- val = GEOSRelatePattern(self_geom, rhs_geom, StringValuePtr(pattern));
668
- if (val == 0) {
669
- result = Qfalse;
670
- } else if (val == 1) {
671
- result = Qtrue;
672
- }
677
+ rhs_geom =
678
+ rgeo_convert_to_geos_geometry(self_data->factory, rhs, Qnil, &state);
679
+ if (state) {
680
+ rb_jump_tag(state);
681
+ }
682
+
683
+ val = GEOSRelatePattern(self_geom, rhs_geom, StringValuePtr(pattern));
684
+ if (val == 0) {
685
+ result = Qfalse;
686
+ } else if (val == 1) {
687
+ result = Qtrue;
673
688
  }
674
689
  }
675
690
  return result;
@@ -683,16 +698,20 @@ method_geometry_distance(VALUE self, VALUE rhs)
683
698
  const GEOSGeometry* self_geom;
684
699
  const GEOSGeometry* rhs_geom;
685
700
  double dist;
701
+ int state = 0;
686
702
 
687
703
  result = Qnil;
688
704
  self_data = RGEO_GEOMETRY_DATA_PTR(self);
689
705
  self_geom = self_data->geom;
690
706
  if (self_geom) {
691
- rhs_geom = rgeo_convert_to_geos_geometry(self_data->factory, rhs, Qnil);
692
- if (rhs_geom) {
693
- if (GEOSDistance(self_geom, rhs_geom, &dist)) {
694
- result = rb_float_new(dist);
695
- }
707
+ rhs_geom =
708
+ rgeo_convert_to_geos_geometry(self_data->factory, rhs, Qnil, &state);
709
+ if (state) {
710
+ rb_jump_tag(state);
711
+ }
712
+
713
+ if (GEOSDistance(self_geom, rhs_geom, &dist)) {
714
+ result = rb_float_new(dist);
696
715
  }
697
716
  }
698
717
  return result;
@@ -721,6 +740,27 @@ method_geometry_buffer(VALUE self, VALUE distance)
721
740
  return result;
722
741
  }
723
742
 
743
+ #ifdef RGEO_GEOS_SUPPORTS_DENSIFY
744
+ static VALUE
745
+ method_geometry_segmentize(VALUE self, VALUE max_segment_length)
746
+ {
747
+ VALUE result;
748
+ RGeo_GeometryData* self_data;
749
+ const GEOSGeometry* self_geom;
750
+ VALUE factory;
751
+
752
+ result = Qnil;
753
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
754
+ self_geom = self_data->geom;
755
+ if (self_geom) {
756
+ factory = self_data->factory;
757
+ result = rgeo_wrap_geos_geometry(
758
+ factory, GEOSDensify(self_geom, rb_num2dbl(max_segment_length)), Qnil);
759
+ }
760
+ return result;
761
+ }
762
+ #endif
763
+
724
764
  static VALUE
725
765
  method_geometry_buffer_with_style(VALUE self,
726
766
  VALUE distance,
@@ -816,17 +856,20 @@ method_geometry_intersection(VALUE self, VALUE rhs)
816
856
  const GEOSGeometry* self_geom;
817
857
  VALUE factory;
818
858
  const GEOSGeometry* rhs_geom;
859
+ int state = 0;
819
860
 
820
861
  result = Qnil;
821
862
  self_data = RGEO_GEOMETRY_DATA_PTR(self);
822
863
  self_geom = self_data->geom;
823
864
  if (self_geom) {
824
865
  factory = self_data->factory;
825
- rhs_geom = rgeo_convert_to_geos_geometry(factory, rhs, Qnil);
826
- if (rhs_geom) {
827
- result = rgeo_wrap_geos_geometry(
828
- factory, GEOSIntersection(self_geom, rhs_geom), Qnil);
866
+ rhs_geom = rgeo_convert_to_geos_geometry(factory, rhs, Qnil, &state);
867
+ if (state) {
868
+ rb_jump_tag(state);
829
869
  }
870
+
871
+ result = rgeo_wrap_geos_geometry(
872
+ factory, GEOSIntersection(self_geom, rhs_geom), Qnil);
830
873
  }
831
874
  return result;
832
875
  }
@@ -839,17 +882,20 @@ method_geometry_union(VALUE self, VALUE rhs)
839
882
  const GEOSGeometry* self_geom;
840
883
  VALUE factory;
841
884
  const GEOSGeometry* rhs_geom;
885
+ int state = 0;
842
886
 
843
887
  result = Qnil;
844
888
  self_data = RGEO_GEOMETRY_DATA_PTR(self);
845
889
  self_geom = self_data->geom;
846
890
  if (self_geom) {
847
891
  factory = self_data->factory;
848
- rhs_geom = rgeo_convert_to_geos_geometry(factory, rhs, Qnil);
849
- if (rhs_geom) {
850
- result =
851
- rgeo_wrap_geos_geometry(factory, GEOSUnion(self_geom, rhs_geom), Qnil);
892
+ rhs_geom = rgeo_convert_to_geos_geometry(factory, rhs, Qnil, &state);
893
+ if (state) {
894
+ rb_jump_tag(state);
852
895
  }
896
+
897
+ result =
898
+ rgeo_wrap_geos_geometry(factory, GEOSUnion(self_geom, rhs_geom), Qnil);
853
899
  }
854
900
  return result;
855
901
  }
@@ -880,17 +926,20 @@ method_geometry_difference(VALUE self, VALUE rhs)
880
926
  const GEOSGeometry* self_geom;
881
927
  VALUE factory;
882
928
  const GEOSGeometry* rhs_geom;
929
+ int state = 0;
883
930
 
884
931
  result = Qnil;
885
932
  self_data = RGEO_GEOMETRY_DATA_PTR(self);
886
933
  self_geom = self_data->geom;
887
934
  if (self_geom) {
888
935
  factory = self_data->factory;
889
- rhs_geom = rgeo_convert_to_geos_geometry(factory, rhs, Qnil);
890
- if (rhs_geom) {
891
- result = rgeo_wrap_geos_geometry(
892
- factory, GEOSDifference(self_geom, rhs_geom), Qnil);
936
+ rhs_geom = rgeo_convert_to_geos_geometry(factory, rhs, Qnil, &state);
937
+ if (state) {
938
+ rb_jump_tag(state);
893
939
  }
940
+
941
+ result = rgeo_wrap_geos_geometry(
942
+ factory, GEOSDifference(self_geom, rhs_geom), Qnil);
894
943
  }
895
944
  return result;
896
945
  }
@@ -903,17 +952,20 @@ method_geometry_sym_difference(VALUE self, VALUE rhs)
903
952
  const GEOSGeometry* self_geom;
904
953
  VALUE factory;
905
954
  const GEOSGeometry* rhs_geom;
955
+ int state = 0;
906
956
 
907
957
  result = Qnil;
908
958
  self_data = RGEO_GEOMETRY_DATA_PTR(self);
909
959
  self_geom = self_data->geom;
910
960
  if (self_geom) {
911
961
  factory = self_data->factory;
912
- rhs_geom = rgeo_convert_to_geos_geometry(factory, rhs, Qnil);
913
- if (rhs_geom) {
914
- result = rgeo_wrap_geos_geometry(
915
- factory, GEOSSymDifference(self_geom, rhs_geom), Qnil);
962
+ rhs_geom = rgeo_convert_to_geos_geometry(factory, rhs, Qnil, &state);
963
+ if (state) {
964
+ rb_jump_tag(state);
916
965
  }
966
+
967
+ result = rgeo_wrap_geos_geometry(
968
+ factory, GEOSSymDifference(self_geom, rhs_geom), Qnil);
917
969
  }
918
970
  return result;
919
971
  }
@@ -1277,6 +1329,10 @@ rgeo_init_geos_geometry()
1277
1329
  geos_geometry_methods, "make_valid", method_geometry_make_valid, 0);
1278
1330
  rb_define_method(
1279
1331
  geos_geometry_methods, "polygonize", method_geometry_polygonize, 0);
1332
+ #ifdef RGEO_GEOS_SUPPORTS_DENSIFY
1333
+ rb_define_method(
1334
+ geos_geometry_methods, "segmentize", method_geometry_segmentize, 1);
1335
+ #endif
1280
1336
  }
1281
1337
 
1282
1338
  RGEO_END_C
@@ -31,7 +31,6 @@ create_geometry_collection(VALUE module, int type, VALUE factory, VALUE array)
31
31
  VALUE result;
32
32
  unsigned int len;
33
33
  GEOSGeometry** geoms;
34
- RGeo_FactoryData* factory_data;
35
34
  VALUE klass;
36
35
  unsigned int i;
37
36
  unsigned int j;
@@ -49,7 +48,6 @@ create_geometry_collection(VALUE module, int type, VALUE factory, VALUE array)
49
48
  rb_raise(rb_eRGeoError, "not enough memory available");
50
49
  }
51
50
 
52
- factory_data = RGEO_FACTORY_DATA_PTR(factory);
53
51
  klasses = Qnil;
54
52
  cast_type = Qnil;
55
53
  switch (type) {
@@ -66,9 +64,14 @@ create_geometry_collection(VALUE module, int type, VALUE factory, VALUE array)
66
64
  for (i = 0; i < len; ++i) {
67
65
  geom = rgeo_convert_to_detached_geos_geometry(
68
66
  rb_ary_entry(array, i), factory, cast_type, &klass, &state);
69
- if (state || !geom) {
70
- break;
67
+ if (state) {
68
+ for (j = 0; j < i; j++) {
69
+ GEOSGeom_destroy(geoms[j]);
70
+ }
71
+ FREE(geoms);
72
+ rb_jump_tag(state);
71
73
  }
74
+
72
75
  geoms[i] = geom;
73
76
  if (!NIL_P(klass) && NIL_P(klasses)) {
74
77
  klasses = rb_ary_new2(len);
@@ -80,24 +83,19 @@ create_geometry_collection(VALUE module, int type, VALUE factory, VALUE array)
80
83
  rb_ary_push(klasses, klass);
81
84
  }
82
85
  }
83
- if (i != len) {
84
- for (j = 0; j < i; ++j) {
85
- GEOSGeom_destroy(geoms[j]);
86
- }
87
- } else {
88
- collection = GEOSGeom_createCollection(type, geoms, len);
89
- if (collection) {
90
- result = rgeo_wrap_geos_geometry(factory, collection, module);
91
- RGEO_GEOMETRY_DATA_PTR(result)->klasses = klasses;
92
- }
93
- // NOTE: We are assuming that GEOS will do its own cleanup of the
94
- // element geometries if it fails to create the collection, so we
95
- // are not doing that ourselves. If that turns out not to be the
96
- // case, this will be a memory leak.
86
+ collection = GEOSGeom_createCollection(type, geoms, len);
87
+ if (collection) {
88
+ result = rgeo_wrap_geos_geometry(factory, collection, module);
89
+ RGEO_GEOMETRY_DATA_PTR(result)->klasses = klasses;
97
90
  }
91
+
92
+ // NOTE: We are assuming that GEOS will do its own cleanup of the
93
+ // element geometries if it fails to create the collection, so we
94
+ // are not doing that ourselves. If that turns out not to be the
95
+ // case, this will be a memory leak.
98
96
  FREE(geoms);
99
97
  if (state) {
100
- rb_exc_raise(rb_errinfo()); // raise $!
98
+ rb_jump_tag(state);
101
99
  }
102
100
 
103
101
  return result;