ffi-geos 2.3.1 → 2.5.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.
Files changed (115) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/main.yml +2 -2
  3. data/.rbenv-vars +1 -0
  4. data/.rubocop-minitest.yml +40 -17
  5. data/.rubocop.yml +664 -120
  6. data/.rubocop_todo.yml +30 -19
  7. data/MIT-LICENSE +1 -1
  8. data/README.rdoc +2 -0
  9. data/ffi-geos.gemspec +2 -2
  10. data/lib/ffi-geos/coordinate_sequence.rb +2 -1
  11. data/lib/ffi-geos/geojson_reader.rb +35 -0
  12. data/lib/ffi-geos/geojson_writer.rb +49 -0
  13. data/lib/ffi-geos/geometry.rb +101 -1
  14. data/lib/ffi-geos/geometry_collection.rb +1 -1
  15. data/lib/ffi-geos/line_string.rb +1 -1
  16. data/lib/ffi-geos/point.rb +9 -0
  17. data/lib/ffi-geos/polygon.rb +1 -1
  18. data/lib/ffi-geos/prepared_geometry.rb +20 -0
  19. data/lib/ffi-geos/version.rb +1 -1
  20. data/lib/ffi-geos/wkb_writer.rb +12 -0
  21. data/lib/ffi-geos.rb +156 -3
  22. data/test/coordinate_sequence_tests.rb +22 -4
  23. data/test/geojson_reader_tests.rb +174 -0
  24. data/test/geojson_writer_tests.rb +103 -0
  25. data/test/geometry/area_tests.rb +18 -0
  26. data/test/geometry/boundary_tests.rb +36 -0
  27. data/test/geometry/buffer_tests.rb +116 -0
  28. data/test/geometry/build_area_tests.rb +20 -0
  29. data/test/geometry/centroid_tests.rb +37 -0
  30. data/test/geometry/clip_by_rect_tests.rb +56 -0
  31. data/test/geometry/clone_tests.rb +29 -0
  32. data/test/geometry/concave_hull_of_polygons_tests.rb +28 -0
  33. data/test/geometry/concave_hull_tests.rb +38 -0
  34. data/test/geometry/convex_hull_tests.rb +26 -0
  35. data/test/geometry/coord_seq_tests.rb +27 -0
  36. data/test/geometry/delaunay_triangulation_tests.rb +82 -0
  37. data/test/geometry/densify_tests.rb +95 -0
  38. data/test/geometry/difference_tests.rb +108 -0
  39. data/test/geometry/dimensions_tests.rb +46 -0
  40. data/test/geometry/distance_tests.rb +29 -0
  41. data/test/geometry/dump_points_tests.rb +60 -0
  42. data/test/geometry/dup_tests.rb +29 -0
  43. data/test/geometry/empty_tests.rb +23 -0
  44. data/test/geometry/envelope_tests.rb +26 -0
  45. data/test/geometry/equal_identical_tests.rb +78 -0
  46. data/test/geometry/equal_tests.rb +62 -0
  47. data/test/geometry/exterior_ring_tests.rb +27 -0
  48. data/test/geometry/extract_unique_points_tests.rb +41 -0
  49. data/test/geometry/frecet_distance_tests.rb +24 -0
  50. data/test/geometry/get_geometry_n_tests.rb +21 -0
  51. data/test/geometry/hausdorff_distance_tests.rb +46 -0
  52. data/test/geometry/hilbert_code_tests.rb +45 -0
  53. data/test/geometry/interior_ring_n_tests.rb +64 -0
  54. data/test/geometry/interior_rings_tests.rb +36 -0
  55. data/test/geometry/interpolate_tests.rb +49 -0
  56. data/test/geometry/intersection_tests.rb +49 -0
  57. data/test/geometry/largest_empty_circle_tests.rb +26 -0
  58. data/test/geometry/length_tests.rb +18 -0
  59. data/test/geometry/line_merge_directed_tests.rb +28 -0
  60. data/test/geometry/line_merge_tests.rb +25 -0
  61. data/test/geometry/line_string_enumerator_tests.rb +20 -0
  62. data/test/geometry/line_substring_tests.rb +76 -0
  63. data/test/geometry/make_valid_tests.rb +27 -0
  64. data/test/geometry/maximum_inscribed_circle_tests.rb +21 -0
  65. data/test/geometry/minimum_bounding_circle_tests.rb +23 -0
  66. data/test/geometry/minimum_clearance_tests.rb +58 -0
  67. data/test/geometry/minimum_rotated_rectangle_tests.rb +28 -0
  68. data/test/geometry/minimum_width_tests.rb +26 -0
  69. data/test/geometry/misc_tests.rb +24 -0
  70. data/test/geometry/nearest_points_tests.rb +46 -0
  71. data/test/geometry/node_tests.rb +22 -0
  72. data/test/geometry/normalize_tests.rb +34 -0
  73. data/test/geometry/num_coordinates_tests.rb +39 -0
  74. data/test/geometry/num_goemetries_tests.rb +35 -0
  75. data/test/geometry/num_interior_rings_tests.rb +28 -0
  76. data/test/geometry/orient_polygons_tests.rb +101 -0
  77. data/test/geometry/point_on_surface_tests.rb +37 -0
  78. data/test/geometry/polygon_hull_simplify_tests.rb +55 -0
  79. data/test/geometry/polygonize_tests.rb +173 -0
  80. data/test/geometry/precision_tests.rb +42 -0
  81. data/test/geometry/project_tests.rb +56 -0
  82. data/test/geometry/relate_tests.rb +73 -0
  83. data/test/geometry/relationships_tests.rb +138 -0
  84. data/test/geometry/reverse_tests.rb +44 -0
  85. data/test/geometry/ring_tests.rb +18 -0
  86. data/test/geometry/shared_path_tests.rb +31 -0
  87. data/test/geometry/simple_tests.rb +18 -0
  88. data/test/geometry/simplify_tests.rb +21 -0
  89. data/test/geometry/snap_tests.rb +20 -0
  90. data/test/geometry/srid_copy_policy_tests.rb +94 -0
  91. data/test/geometry/start_and_end_point_tests.rb +24 -0
  92. data/test/geometry/sym_difference_tests.rb +114 -0
  93. data/test/geometry/topology_preserve_simplify_tests.rb +21 -0
  94. data/test/geometry/union_tests.rb +216 -0
  95. data/test/geometry/valid_tests.rb +56 -0
  96. data/test/geometry/voronoi_diagram_tests.rb +62 -0
  97. data/test/geometry_collection_tests.rb +14 -2
  98. data/test/interrupt_tests.rb +1 -1
  99. data/test/line_string_tests.rb +24 -3
  100. data/test/misc_tests.rb +1 -1
  101. data/test/point/has_m_tests.rb +43 -0
  102. data/test/point/x_y_z_m_tests.rb +51 -0
  103. data/test/point_tests.rb +25 -3
  104. data/test/polygon_tests.rb +14 -1
  105. data/test/prepared_geometry_tests.rb +31 -0
  106. data/test/strtree_tests.rb +11 -18
  107. data/test/test_helper.rb +2 -0
  108. data/test/tools_tests.rb +7 -0
  109. data/test/utils_tests.rb +14 -3
  110. data/test/wkb_reader_tests.rb +1 -0
  111. data/test/wkb_writer_tests.rb +46 -5
  112. data/test/wkt_reader_tests.rb +2 -0
  113. data/test/wkt_writer_tests.rb +20 -2
  114. metadata +160 -7
  115. data/test/geometry_tests.rb +0 -2096
data/lib/ffi-geos.rb CHANGED
@@ -15,6 +15,10 @@ module Geos
15
15
  File.join(GEOS_BASE, 'wkb_reader')
16
16
  autoload :WkbWriter,
17
17
  File.join(GEOS_BASE, 'wkb_writer')
18
+ autoload :GeoJSONReader,
19
+ File.join(GEOS_BASE, 'geojson_reader')
20
+ autoload :GeoJSONWriter,
21
+ File.join(GEOS_BASE, 'geojson_writer')
18
22
  autoload :CoordinateSequence,
19
23
  File.join(GEOS_BASE, 'coordinate_sequence')
20
24
  autoload :Geometry,
@@ -50,7 +54,7 @@ module Geos
50
54
 
51
55
  module FFIGeos
52
56
  def self.search_paths
53
- @search_paths ||= \
57
+ @search_paths ||=
54
58
  if ENV['GEOS_LIBRARY_PATH']
55
59
  [ENV['GEOS_LIBRARY_PATH']]
56
60
  elsif FFI::Platform::IS_WINDOWS
@@ -77,7 +81,7 @@ module Geos
77
81
  end
78
82
 
79
83
  def self.geos_library_path
80
- @geos_library_path ||= \
84
+ @geos_library_path ||=
81
85
  # On MingW the libraries have version numbers
82
86
  find_lib('{lib,}geos_c{,-?}')
83
87
  end
@@ -104,6 +108,11 @@ module Geos
104
108
  :ndr, 1 # Little Endian
105
109
  ])
106
110
 
111
+ Geos::Flavors = enum(:flavor, [
112
+ :extended, 1,
113
+ :iso, 2
114
+ ])
115
+
107
116
  Geos::BufferCapStyles = enum(:buffer_cap_style, [
108
117
  :round, 1,
109
118
  :flat, 2,
@@ -144,6 +153,11 @@ module Geos
144
153
  :keep_collapsed, 1 << 1
145
154
  ])
146
155
 
156
+ Geos::PolygonHullSimplifyModes = enum(:polygon_hull_simplify_mode, [
157
+ :vertex_ratio, 1,
158
+ :area_ratio, 2
159
+ ])
160
+
147
161
  FFI_LAYOUT = {
148
162
  #### Utility functions ####
149
163
 
@@ -430,6 +444,11 @@ module Geos
430
444
  :pointer, :pointer, :pointer, :double, :int, :buffer_cap_style, :buffer_join_style, :double
431
445
  ],
432
446
 
447
+ GEOSDensify_r: [
448
+ # *geom, *handle, *geom, tolerence
449
+ :pointer, :pointer, :pointer, :double
450
+ ],
451
+
433
452
  # Deprecated in GEOS 3.3.0.
434
453
  GEOSSingleSidedBuffer_r: [
435
454
  # *geom, *handle, *geom, width, quad_segs, buffer_join_style, mitre_limit, is_left
@@ -446,6 +465,26 @@ module Geos
446
465
  :pointer, :pointer, :pointer
447
466
  ],
448
467
 
468
+ GEOSConcaveHull_r: [
469
+ # *geom, *handle, *geom, ratio, allow_holes
470
+ :pointer, :pointer, :pointer, :double, :uint
471
+ ],
472
+
473
+ GEOSConcaveHullByLength_r: [
474
+ # *geom, *handle, *geom, length, allow_holes
475
+ :pointer, :pointer, :pointer, :double, :uint
476
+ ],
477
+
478
+ GEOSPolygonHullSimplify_r: [
479
+ # *geom, *handle, *geom, is_outer, vertex_num_fraction
480
+ :pointer, :pointer, :pointer, :uint, :double
481
+ ],
482
+
483
+ GEOSPolygonHullSimplifyMode_r: [
484
+ # *geom, *handle, *geom, is_outer, parameter_mode, parameter
485
+ :pointer, :pointer, :pointer, :uint, :uint, :double
486
+ ],
487
+
449
488
  GEOSDifference_r: [
450
489
  # *geom, *handle, *geom_a, *geom_b
451
490
  :pointer, :pointer, :pointer, :pointer
@@ -486,6 +525,11 @@ module Geos
486
525
  :pointer, :pointer, :pointer
487
526
  ],
488
527
 
528
+ GEOSDisjointSubsetUnion_r: [
529
+ # *geom, *handle, *geom
530
+ :pointer, :pointer, :pointer
531
+ ],
532
+
489
533
  GEOSUnaryUnion_r: [
490
534
  # *geom, *handle, *geom
491
535
  :pointer, :pointer, :pointer
@@ -522,6 +566,11 @@ module Geos
522
566
  :pointer, :pointer, :pointer
523
567
  ],
524
568
 
569
+ GEOSHilbertCode_r: [
570
+ # int, *handler, *geom, *extent, level, *code
571
+ :int, :pointer, :pointer, :pointer, :uint, :pointer
572
+ ],
573
+
525
574
  GEOSMinimumBoundingCircle_r: [
526
575
  # *geom, *handle, *geom, *double radius, **geom center
527
576
  :pointer, :pointer, :pointer, :pointer, :pointer
@@ -537,6 +586,16 @@ module Geos
537
586
  :pointer, :pointer, :pointer
538
587
  ],
539
588
 
589
+ GEOSLineMergeDirected_r: [
590
+ # *geom, *handle, *geom
591
+ :pointer, :pointer, :pointer
592
+ ],
593
+
594
+ GEOSLineSubstring_r: [
595
+ # *geom, *handle, *geom, start_fraction, end_fraction
596
+ :pointer, :pointer, :pointer, :double, :double
597
+ ],
598
+
540
599
  GEOSGeom_getXMin_r: [
541
600
  # 0 on exception, *handle, (double *) value
542
601
  :int, :pointer, :pointer, :pointer
@@ -587,6 +646,11 @@ module Geos
587
646
  :pointer, :pointer, :pointer, :double, :int
588
647
  ],
589
648
 
649
+ GEOSConstrainedDelaunayTriangulation_r: [
650
+ # *geom, *handle, *geom
651
+ :pointer, :pointer, :pointer
652
+ ],
653
+
590
654
  GEOSVoronoiDiagram_r: [
591
655
  # *geom, *handle, *geom, *envelope, tolerance, only_edges
592
656
  :pointer, :pointer, :pointer, :pointer, :double, :int
@@ -667,6 +731,11 @@ module Geos
667
731
  :char, :pointer, :pointer, :pointer, :double
668
732
  ],
669
733
 
734
+ GEOSEqualsIdentical_r: [
735
+ # (2 on exception, 1 on true, 2 on false), *handle, *geom_a, *geom_b
736
+ :char, :pointer, :pointer, :pointer
737
+ ],
738
+
670
739
  GEOSisEmpty_r: [
671
740
  # (2 on exception, 1 on true, 2 on false), *handle, *geom
672
741
  :char, :pointer, :pointer
@@ -702,6 +771,11 @@ module Geos
702
771
  :char, :pointer, :pointer
703
772
  ],
704
773
 
774
+ GEOSHasM_r: [
775
+ # (2 on exception, 1 on true, 2 on false), *handle, *geom
776
+ :char, :pointer, :pointer
777
+ ],
778
+
705
779
  GEOSisClosed_r: [
706
780
  # (2 on exception, 1 on true, 2 on false), *handle, *geom
707
781
  :char, :pointer, :pointer
@@ -727,6 +801,11 @@ module Geos
727
801
  :int, :pointer, :pointer, :pointer, :pointer
728
802
  ],
729
803
 
804
+ GEOSDistanceWithin_r: [
805
+ # (0 on exception, 1 otherwise), *handle, *geom_a, *geom_b, double distance
806
+ :char, :pointer, :pointer, :pointer, :double
807
+ ],
808
+
730
809
  GEOSHausdorffDistance_r: [
731
810
  # (0 on exception, 1 otherwise), *handle, *geom_a, *geom_b, (double *) distance
732
811
  :int, :pointer, :pointer, :pointer, :pointer
@@ -757,6 +836,11 @@ module Geos
757
836
  :int, :pointer, :pointer
758
837
  ],
759
838
 
839
+ GEOSOrientPolygons_r: [
840
+ # -1 on exception, *handle, *geom, exterior_cw
841
+ :int, :pointer, :pointer, :int
842
+ ],
843
+
760
844
  GEOSGetInteriorRingN_r: [
761
845
  # *geom, *handle, *geom, n
762
846
  :pointer, :pointer, :pointer, :int
@@ -787,6 +871,11 @@ module Geos
787
871
  :int, :pointer, :pointer, :pointer
788
872
  ],
789
873
 
874
+ GEOSGeomGetM_r: [
875
+ # -1 on exception, *handle, *geom, *point
876
+ :int, :pointer, :pointer, :pointer
877
+ ],
878
+
790
879
  GEOSGeomGetPointN_r: [
791
880
  # *point, *handle, *geom, n
792
881
  :pointer, :pointer, :pointer, :int
@@ -812,6 +901,11 @@ module Geos
812
901
  :double, :pointer, :pointer
813
902
  ],
814
903
 
904
+ GEOSConcaveHullOfPolygons_r: [
905
+ # *geom, *handle, *geom, length_ratio, tight, allow_holes
906
+ :pointer, :pointer, :pointer, :double, :uint, :uint
907
+ ],
908
+
815
909
  GEOSMinimumRotatedRectangle_r: [
816
910
  # *geom, *handle, *geom
817
911
  :pointer, :pointer, :pointer
@@ -955,6 +1049,21 @@ module Geos
955
1049
  # (2 on exception, 1 on true, 0 on false), *handle, *prepared, *geom
956
1050
  :char, :pointer, :pointer, :pointer
957
1051
  ],
1052
+
1053
+ GEOSPreparedDistance_r: [
1054
+ # (1 on success, 0 on failure), *handle, *prepared, *geom, *distance
1055
+ :int, :pointer, :pointer, :pointer, :pointer
1056
+ ],
1057
+
1058
+ GEOSPreparedDistanceWithin_r: [
1059
+ # (1 on true, 0 on false), *handle, *prepared, *geom, max_distance
1060
+ :char, :pointer, :pointer, :pointer, :double
1061
+ ],
1062
+
1063
+ GEOSPreparedNearestPoints_r: [
1064
+ # *coord_seq, *handle, *prepared, *geom
1065
+ :pointer, :pointer, :pointer, :pointer
1066
+ ],
958
1067
  #### /PreparedGeometry functions ####
959
1068
 
960
1069
  #### WktReader functions ####
@@ -1088,8 +1197,52 @@ module Geos
1088
1197
  # void, *handle, *geom, bool
1089
1198
  :void, :pointer, :pointer, :char
1090
1199
  ],
1200
+
1201
+ GEOSWKBWriter_getFlavor_r: [
1202
+ # flavor, *handle, *geom
1203
+ :flavor, :pointer, :pointer
1204
+ ],
1205
+
1206
+ GEOSWKBWriter_setFlavor_r: [
1207
+ # void, *handle, *geom, flavor
1208
+ :void, :pointer, :pointer, :flavor
1209
+ ],
1091
1210
  #### /WkbWriter functions ####
1092
1211
 
1212
+ #### GeoJSONReader functions ####
1213
+ GEOSGeoJSONReader_create_r: [
1214
+ # *geojson_reader, *handle
1215
+ :pointer, :pointer
1216
+ ],
1217
+
1218
+ GEOSGeoJSONReader_readGeometry_r: [
1219
+ # *geom, *handle, *geojson_reader, string
1220
+ :pointer, :pointer, :pointer, :string
1221
+ ],
1222
+
1223
+ GEOSGeoJSONReader_destroy_r: [
1224
+ # void, *handle, *geojson_reader
1225
+ :void, :pointer, :pointer
1226
+ ],
1227
+ #### /GeoJSONReader functions ###
1228
+
1229
+ #### GeoJSONWriter functions ####
1230
+ GEOSGeoJSONWriter_create_r: [
1231
+ # *geojson_writer, *handle
1232
+ :pointer, :pointer
1233
+ ],
1234
+
1235
+ GEOSGeoJSONWriter_destroy_r: [
1236
+ # void, *handle, *geojson_writer
1237
+ :void, :pointer, :pointer
1238
+ ],
1239
+
1240
+ GEOSGeoJSONWriter_writeGeometry_r: [
1241
+ # string, *handle, *geojson_writer, :geom, :indent
1242
+ :string, :pointer, :pointer, :pointer, :int
1243
+ ],
1244
+ #### /GeoJSONWriter functions ####
1245
+
1093
1246
  #### Linearref functions ####
1094
1247
  GEOSProject_r: [
1095
1248
  # distance, *handle, *geom_a, *geom_b
@@ -1252,7 +1405,7 @@ module Geos
1252
1405
  end
1253
1406
 
1254
1407
  def default_error_handler(*args)
1255
- raise Geos::GEOSException, args[0] % args[1]
1408
+ raise Geos::GEOSException, sprintf(args[0], *args[1])
1256
1409
  end
1257
1410
  end
1258
1411
 
@@ -12,16 +12,19 @@ class CoordinateSequenceTests < Minitest::Test
12
12
 
13
13
  def test_set_and_get_x
14
14
  @cs.set_x(0, 10.01)
15
+
15
16
  assert_in_delta(10.01, @cs.get_x(0), TOLERANCE)
16
17
  end
17
18
 
18
19
  def test_set_and_get_y
19
20
  @cs.set_y(0, 20.02)
21
+
20
22
  assert_in_delta(20.02, @cs.get_y(0), TOLERANCE)
21
23
  end
22
24
 
23
25
  def test_set_and_get_z
24
26
  @cs.set_z(0, 20.02)
27
+
25
28
  assert_in_delta(20.02, @cs.get_z(0), TOLERANCE)
26
29
  end
27
30
 
@@ -53,7 +56,7 @@ class CoordinateSequenceTests < Minitest::Test
53
56
  [0, 0]
54
57
  ])
55
58
 
56
- assert(cs.counter_clockwise?)
59
+ assert_predicate(cs, :counter_clockwise?)
57
60
 
58
61
  cs = Geos::CoordinateSequence.new([
59
62
  [0, 0],
@@ -62,7 +65,7 @@ class CoordinateSequenceTests < Minitest::Test
62
65
  [0, 0]
63
66
  ])
64
67
 
65
- refute(cs.counter_clockwise?)
68
+ refute_predicate(cs, :counter_clockwise?)
66
69
  end
67
70
 
68
71
  def test_check_bounds
@@ -115,6 +118,7 @@ class CoordinateSequenceTests < Minitest::Test
115
118
 
116
119
  def test_with_no_arguments
117
120
  cs = Geos::CoordinateSequence.new
121
+
118
122
  assert_equal(0, cs.size)
119
123
  assert_equal(3, cs.dimensions)
120
124
  end
@@ -153,6 +157,7 @@ class CoordinateSequenceTests < Minitest::Test
153
157
 
154
158
  def test_to_point
155
159
  cs = Geos::CoordinateSequence.new([5, 7])
160
+
156
161
  assert_equal('POINT (5 7)', write(cs.to_point, trim: true))
157
162
  end
158
163
 
@@ -170,9 +175,11 @@ class CoordinateSequenceTests < Minitest::Test
170
175
 
171
176
  def test_empty
172
177
  cs = Geos::CoordinateSequence.new
178
+
173
179
  assert_geom_empty(cs)
174
180
 
175
181
  cs = Geos::CoordinateSequence.new([4, 1])
182
+
176
183
  refute_geom_empty(cs)
177
184
  end
178
185
 
@@ -219,11 +226,13 @@ class CoordinateSequenceTests < Minitest::Test
219
226
 
220
227
  def test_to_s_2d
221
228
  cs = Geos::CoordinateSequence.new([[1, 2], [10, 11]])
229
+
222
230
  assert_equal('1.0 2.0, 10.0 11.0', cs.to_s)
223
231
  end
224
232
 
225
233
  def test_to_s_3d
226
234
  cs = Geos::CoordinateSequence.new([[1, 2, 3], [10, 11, 12]])
235
+
227
236
  assert_equal('1.0 2.0 3.0, 10.0 11.0 12.0', cs.to_s)
228
237
  end
229
238
 
@@ -358,37 +367,45 @@ class CoordinateSequenceTests < Minitest::Test
358
367
 
359
368
  def test_x_max
360
369
  cs = Geos::CoordinateSequence.new([-10, -15], [0, 5], [10, 20])
370
+
361
371
  assert_equal(10, cs.x_max)
362
372
  end
363
373
 
364
374
  def test_x_min
365
375
  cs = Geos::CoordinateSequence.new([-10, -15], [0, 5], [10, 20])
376
+
366
377
  assert_equal(-10, cs.x_min)
367
378
  end
368
379
 
369
380
  def test_y_max
370
381
  cs = Geos::CoordinateSequence.new([-10, -15], [0, 5], [10, 20])
382
+
371
383
  assert_equal(20, cs.y_max)
372
384
  end
373
385
 
374
386
  def test_y_min
375
387
  cs = Geos::CoordinateSequence.new([-10, -15], [0, 5], [10, 20])
388
+
376
389
  assert_equal(-15, cs.y_min)
377
390
  end
378
391
 
379
392
  def test_z_max
380
393
  cs = Geos::CoordinateSequence.new([-10, -15], [0, 5], [10, 20])
381
- assert(cs.z_max.nan?, ' Expected NaN')
394
+
395
+ assert_predicate(cs.z_max, :nan?, ' Expected NaN')
382
396
 
383
397
  cs = Geos::CoordinateSequence.new([-10, -15, -20], [0, 5, 10], [10, 20, 30])
398
+
384
399
  assert_equal(30, cs.z_max)
385
400
  end
386
401
 
387
402
  def test_z_min
388
403
  cs = Geos::CoordinateSequence.new([-10, -15], [0, 5], [10, 20])
389
- assert(cs.z_min.nan?, ' Expected NaN')
404
+
405
+ assert_predicate(cs.z_min, :nan?, ' Expected NaN')
390
406
 
391
407
  cs = Geos::CoordinateSequence.new([-10, -15, -20], [0, 5, 10], [10, 20, 30])
408
+
392
409
  assert_equal(-20, cs.z_min)
393
410
  end
394
411
 
@@ -422,6 +439,7 @@ class CoordinateSequenceTests < Minitest::Test
422
439
 
423
440
  cs = Geos::CoordinateSequence.new(*coordinates)
424
441
  snapped = cs.snap_to_grid(10 ** -i)
442
+
425
443
  assert_equal(coordinates, cs.to_a)
426
444
  assert_equal(expected[i].inspect, snapped.to_a.inspect)
427
445
  end
@@ -0,0 +1,174 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ class GeoJSONReaderTests < Minitest::Test
6
+ include TestHelper
7
+
8
+ attr_reader :json_reader
9
+
10
+ def setup
11
+ super
12
+
13
+ skip unless ENV['FORCE_TESTS'] || Geos::FFIGeos.respond_to?(:GEOSGeoJSONReader_create_r)
14
+
15
+ @json_reader = Geos::GeoJSONReader.new
16
+
17
+ @writer.rounding_precision = 3
18
+ end
19
+
20
+ def json_read(*args, **options)
21
+ json_reader.read(*args, **options)
22
+ end
23
+
24
+ def geojson_tester(expected, json, **options)
25
+ assert_equal(expected, write(json_read(json, **options)))
26
+ end
27
+
28
+ def test_point
29
+ geojson_tester(
30
+ 'POINT (-117.000 33.000)',
31
+ '{"type":"Point","coordinates":[-117.0,33.0]}'
32
+ )
33
+ end
34
+
35
+ def test_line_string
36
+ geojson_tester(
37
+ 'LINESTRING (102.000 0.000, 103.000 1.000, 104.000 0.000, 105.000 1.000)',
38
+ '{"type":"LineString","coordinates":[[102.0,0.0],[103.0,1.0],[104.0,0.0],[105.0,1.0]]}'
39
+ )
40
+ end
41
+
42
+ def test_polygon
43
+ geojson_tester(
44
+ 'POLYGON ((30.000 10.000, 40.000 40.000, 20.000 40.000, 10.000 20.000, 30.000 10.000))',
45
+ '{"type":"Polygon","coordinates":[[[30,10],[40,40],[20,40],[10,20],[30,10]]]}'
46
+ )
47
+ end
48
+
49
+ def test_polygon_with_inner_ring
50
+ geojson_tester(
51
+ 'POLYGON ((35.000 10.000, 45.000 45.000, 15.000 40.000, 10.000 20.000, 35.000 10.000), (20.000 30.000, 35.000 35.000, 30.000 20.000, 20.000 30.000))',
52
+ '{"type":"Polygon","coordinates":[[[35,10],[45,45],[15,40],[10,20],[35,10]],[[20,30],[35,35],[30,20],[20,30]]]}'
53
+ )
54
+ end
55
+
56
+ def test_multi_point
57
+ geojson_tester(
58
+ if Geos::GEOS_NICE_VERSION >= '031200'
59
+ 'MULTIPOINT ((10.000 40.000), (40.000 30.000), (20.000 20.000), (30.000 10.000))'
60
+ else
61
+ 'MULTIPOINT (10.000 40.000, 40.000 30.000, 20.000 20.000, 30.000 10.000)'
62
+ end,
63
+ '{"type":"MultiPoint","coordinates":[[10, 40], [40, 30], [20, 20], [30, 10]]}'
64
+ )
65
+ end
66
+
67
+ def test_multi_line_string
68
+ geojson_tester(
69
+ 'MULTILINESTRING ((10.000 10.000, 20.000 20.000, 10.000 40.000), (40.000 40.000, 30.000 30.000, 40.000 20.000, 30.000 10.000))',
70
+ '{"type":"MultiLineString","coordinates":[[[10, 10], [20, 20], [10, 40]],[[40, 40], [30, 30], [40, 20], [30, 10]]]}'
71
+ )
72
+ end
73
+
74
+ def test_multi_polygon
75
+ geojson_tester(
76
+ 'MULTIPOLYGON (((40.000 40.000, 20.000 45.000, 45.000 30.000, 40.000 40.000)), ((20.000 35.000, 10.000 30.000, 10.000 10.000, 30.000 5.000, 45.000 20.000, 20.000 35.000), (30.000 20.000, 20.000 15.000, 20.000 25.000, 30.000 20.000)))',
77
+ '{"type": "MultiPolygon", "coordinates": [[[[40, 40], [20, 45], [45, 30], [40, 40]]], [[[20, 35], [10, 30], [10, 10], [30, 5], [45, 20], [20, 35]], [[30, 20], [20, 15], [20, 25], [30, 20]]]]}'
78
+ )
79
+ end
80
+
81
+ def test_geometry_collection
82
+ geojson_tester(
83
+ 'GEOMETRYCOLLECTION (POINT (40.000 10.000), LINESTRING (10.000 10.000, 20.000 20.000, 10.000 40.000), POLYGON ((40.000 40.000, 20.000 45.000, 45.000 30.000, 40.000 40.000)))',
84
+ '{"type": "GeometryCollection","geometries": [{"type": "Point","coordinates": [40, 10]},{"type": "LineString","coordinates": [[10, 10], [20, 20], [10, 40]]},{"type": "Polygon","coordinates": [[[40, 40], [20, 45], [45, 30], [40, 40]]]}]}'
85
+ )
86
+ end
87
+
88
+ def test_feature_collection
89
+ geojson_tester(
90
+ 'GEOMETRYCOLLECTION (POINT (-117.000 33.000), POINT (-122.000 45.000))',
91
+ '{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-117.0,33.0]}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-122.0,45.0]}}]}'
92
+ )
93
+ end
94
+
95
+ def test_empty_point
96
+ geojson_tester(
97
+ 'POINT EMPTY',
98
+ '{"type":"Point","coordinates":[]}'
99
+ )
100
+ end
101
+
102
+ def test_empty_line_string
103
+ geojson_tester(
104
+ 'LINESTRING EMPTY',
105
+ '{"type":"LineString","coordinates":[]}'
106
+ )
107
+ end
108
+
109
+ def test_empty_polygon
110
+ geojson_tester(
111
+ 'POLYGON EMPTY',
112
+ '{"type":"Polygon","coordinates":[]}'
113
+ )
114
+ end
115
+
116
+ def test_empty_multi_point
117
+ geojson_tester(
118
+ 'MULTIPOINT EMPTY',
119
+ '{"type":"MultiPoint","coordinates":[]}'
120
+ )
121
+ end
122
+
123
+ def test_empty_multi_line_string
124
+ geojson_tester(
125
+ 'MULTILINESTRING EMPTY',
126
+ '{"type":"MultiLineString","coordinates":[]}'
127
+ )
128
+ end
129
+
130
+ def test_empty_multi_polygon
131
+ geojson_tester(
132
+ 'MULTIPOLYGON EMPTY',
133
+ '{"type": "MultiPolygon", "coordinates": []}'
134
+ )
135
+ end
136
+
137
+ def test_empty_geometry_collection
138
+ geojson_tester(
139
+ 'GEOMETRYCOLLECTION EMPTY',
140
+ '{"type": "GeometryCollection","geometries": []}'
141
+ )
142
+ end
143
+
144
+ def test_incomplete_geojson
145
+ assert_raises(Geos::GeoJSONReader::ParseError) do
146
+ json_reader.read('{"type":"Point","coordinates":[-117.0]}')
147
+ end
148
+
149
+ assert_raises(Geos::GeoJSONReader::ParseError) do
150
+ json_reader.read('{"type":"LineString","coordinates":[[1,2],[2]]}')
151
+ end
152
+ end
153
+
154
+ def test_broken_geojson
155
+ assert_raises(Geos::GeoJSONReader::ParseError) do
156
+ json_reader.read('<gml>NOT_GEO_JSON</gml>')
157
+ end
158
+ end
159
+
160
+ def test_incompatible_type
161
+ assert_raises(Geos::GeoJSONReader::ParseError) do
162
+ json_reader.read('{"type":"Line","coordinates":[[1,2],[2,3]]}')
163
+ end
164
+ end
165
+
166
+ def test_srid_from_options
167
+ geom = json_reader.read(
168
+ '{"type":"Point","coordinates":[-117.0,33.0]}',
169
+ srid: 3857
170
+ )
171
+
172
+ assert_equal(3857, geom.srid)
173
+ end
174
+ end
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ class GeoJSONWriterTests < Minitest::Test
6
+ include TestHelper
7
+
8
+ attr_reader :json_writer
9
+
10
+ def setup
11
+ super
12
+
13
+ skip unless ENV['FORCE_TESTS'] || Geos::FFIGeos.respond_to?(:GEOSGeoJSONWriter_create_r)
14
+
15
+ @json_writer = Geos::GeoJSONWriter.new
16
+ end
17
+
18
+ def json_write(*args, **options)
19
+ json_writer.write(*args, **options)
20
+ end
21
+
22
+ def geojson_tester(expected, geom, **options)
23
+ assert_equal(expected, json_write(read(geom), **options))
24
+ end
25
+
26
+ def test_point
27
+ geojson_tester('{"type":"Point","coordinates":[-117.0,33.0]}', 'POINT(-117 33)')
28
+ end
29
+
30
+ def test_line_string
31
+ geojson_tester('{"type":"LineString","coordinates":[[102.0,0.0],[103.0,1.0],[104.0,0.0],[105.0,1.0]]}', 'LINESTRING(102.0 0.0, 103.0 1.0, 104.0 0.0, 105.0 1.0)')
32
+ end
33
+
34
+ def test_polygon
35
+ geojson_tester('{"type":"Polygon","coordinates":[[[30.0,10.0],[40.0,40.0],[20.0,40.0],[10.0,20.0],[30.0,10.0]]]}', 'POLYGON((30 10, 40 40, 20 40, 10 20, 30 10))')
36
+ end
37
+
38
+ def test_polygon_with_inner_ring
39
+ geojson_tester('{"type":"Polygon","coordinates":[[[35.0,10.0],[45.0,45.0],[15.0,40.0],[10.0,20.0],[35.0,10.0]],[[20.0,30.0],[35.0,35.0],[30.0,20.0],[20.0,30.0]]]}', 'POLYGON((35 10, 45 45, 15 40, 10 20, 35 10), (20 30, 35 35, 30 20, 20 30))')
40
+ end
41
+
42
+ def test_multi_point
43
+ geojson_tester('{"type":"MultiPoint","coordinates":[[10.0,40.0],[40.0,30.0],[20.0,20.0],[30.0,10.0]]}', 'MULTIPOINT ((10 40), (40 30), (20 20), (30 10))')
44
+ end
45
+
46
+ def test_multi_line_string
47
+ geojson_tester('{"type":"MultiLineString","coordinates":[[[10.0,10.0],[20.0,20.0],[10.0,40.0]],[[40.0,40.0],[30.0,30.0],[40.0,20.0],[30.0,10.0]]]}', 'MULTILINESTRING ((10 10, 20 20, 10 40),(40 40, 30 30, 40 20, 30 10))')
48
+ end
49
+
50
+ def test_multi_polygon
51
+ geojson_tester('{"type":"MultiPolygon","coordinates":[[[[30.0,20.0],[45.0,40.0],[10.0,40.0],[30.0,20.0]]],[[[15.0,5.0],[40.0,10.0],[10.0,20.0],[5.0,10.0],[15.0,5.0]]]]}', 'MULTIPOLYGON (((30 20, 45 40, 10 40, 30 20)),((15 5, 40 10, 10 20, 5 10, 15 5)))')
52
+ end
53
+
54
+ def test_geometry_collection
55
+ geojson_tester('{"type":"GeometryCollection","geometries":[{"type":"Point","coordinates":[1.0,1.0]},{"type":"Point","coordinates":[2.0,2.0]}]}', 'GEOMETRYCOLLECTION(POINT(1 1),POINT(2 2))')
56
+ end
57
+
58
+ def test_write_with_indentation
59
+ geojson_tester(<<~JSON.strip, 'LINESTRING(102.0 0.0, 103.0 1.0, 104.0 0.0, 105.0 1.0)', indentation: 2)
60
+ {
61
+ "type": "LineString",
62
+ "coordinates": [
63
+ [
64
+ 102.0,
65
+ 0.0
66
+ ],
67
+ [
68
+ 103.0,
69
+ 1.0
70
+ ],
71
+ [
72
+ 104.0,
73
+ 0.0
74
+ ],
75
+ [
76
+ 105.0,
77
+ 1.0
78
+ ]
79
+ ]
80
+ }
81
+ JSON
82
+ end
83
+
84
+ def test_empty_point
85
+ geojson_tester('{"type":"Point","coordinates":[]}', 'POINT EMPTY')
86
+ end
87
+
88
+ def test_empty_line_string
89
+ geojson_tester('{"type":"LineString","coordinates":[]}', 'LINESTRING EMPTY')
90
+ end
91
+
92
+ def test_empty_polygon
93
+ geojson_tester('{"type":"Polygon","coordinates":[[]]}', 'POLYGON EMPTY')
94
+ end
95
+
96
+ def test_empty_geometry_collection
97
+ geojson_tester('{"type":"GeometryCollection","geometries":[]}', 'GEOMETRYCOLLECTION EMPTY')
98
+ end
99
+
100
+ def test_linear_ring
101
+ geojson_tester('{"type":"LineString","coordinates":[[0.0,0.0],[1.0,1.0],[1.0,0.0],[0.0,0.0]]}', 'LINEARRING (0 0, 1 1, 1 0, 0 0)')
102
+ end
103
+ end