ffi-geos 2.2.0 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/main.yml +49 -0
- data/.rubocop-minitest.yml +240 -0
- data/.rubocop.yml +497 -111
- data/.rubocop_todo.yml +100 -0
- data/Gemfile +3 -6
- data/MIT-LICENSE +1 -1
- data/README.rdoc +2 -0
- data/ffi-geos.gemspec +5 -0
- data/lib/ffi-geos/buffer_params.rb +1 -1
- data/lib/ffi-geos/coordinate_sequence.rb +32 -32
- data/lib/ffi-geos/geojson_reader.rb +35 -0
- data/lib/ffi-geos/geojson_writer.rb +49 -0
- data/lib/ffi-geos/geometry.rb +11 -5
- data/lib/ffi-geos/geometry_collection.rb +5 -5
- data/lib/ffi-geos/line_string.rb +11 -11
- data/lib/ffi-geos/multi_line_string.rb +1 -1
- data/lib/ffi-geos/point.rb +4 -4
- data/lib/ffi-geos/polygon.rb +5 -5
- data/lib/ffi-geos/prepared_geometry.rb +21 -1
- data/lib/ffi-geos/strtree.rb +1 -1
- data/lib/ffi-geos/version.rb +1 -1
- data/lib/ffi-geos/wkb_reader.rb +1 -1
- data/lib/ffi-geos/wkb_writer.rb +14 -2
- data/lib/ffi-geos/wkt_reader.rb +1 -1
- data/lib/ffi-geos/wkt_writer.rb +2 -2
- data/lib/ffi-geos.rb +92 -4
- data/sonar-project.properties +4 -4
- data/test/coordinate_sequence_tests.rb +6 -6
- data/test/geojson_reader_tests.rb +170 -0
- data/test/geojson_writer_tests.rb +103 -0
- data/test/geometry_collection_tests.rb +4 -4
- data/test/geometry_tests.rb +75 -32
- data/test/line_string_tests.rb +13 -5
- data/test/point_tests.rb +3 -3
- data/test/polygon_tests.rb +3 -3
- data/test/prepared_geometry_tests.rb +30 -0
- data/test/strtree_tests.rb +8 -8
- data/test/test_helper.rb +43 -12
- data/test/wkb_writer_tests.rb +20 -0
- metadata +15 -6
- data/.travis.yml +0 -32
data/lib/ffi-geos/wkb_reader.rb
CHANGED
data/lib/ffi-geos/wkb_writer.rb
CHANGED
@@ -20,7 +20,7 @@ module Geos
|
|
20
20
|
set_options(options)
|
21
21
|
end
|
22
22
|
|
23
|
-
def self.release(ptr)
|
23
|
+
def self.release(ptr) # :nodoc:
|
24
24
|
FFIGeos.GEOSWKBWriter_destroy_r(Geos.current_handle_pointer, ptr)
|
25
25
|
end
|
26
26
|
|
@@ -83,9 +83,21 @@ module Geos
|
|
83
83
|
FFIGeos.GEOSWKBWriter_setByteOrder_r(Geos.current_handle_pointer, ptr, val)
|
84
84
|
end
|
85
85
|
|
86
|
+
if FFIGeos.respond_to?(:GEOSWKBWriter_getFlavor_r)
|
87
|
+
def flavor
|
88
|
+
FFIGeos.GEOSWKBWriter_getFlavor_r(Geos.current_handle_pointer, ptr)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
if FFIGeos.respond_to?(:GEOSWKBWriter_setFlavor_r)
|
93
|
+
def flavor=(val)
|
94
|
+
FFIGeos.GEOSWKBWriter_setFlavor_r(Geos.current_handle_pointer, ptr, val)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
86
98
|
private
|
87
99
|
|
88
|
-
def set_options(options)
|
100
|
+
def set_options(options) # :nodoc:
|
89
101
|
self.include_srid = options[:include_srid] if options.key?(:include_srid)
|
90
102
|
end
|
91
103
|
end
|
data/lib/ffi-geos/wkt_reader.rb
CHANGED
data/lib/ffi-geos/wkt_writer.rb
CHANGED
@@ -21,11 +21,11 @@ module Geos
|
|
21
21
|
set_options(options)
|
22
22
|
end
|
23
23
|
|
24
|
-
def self.release(ptr)
|
24
|
+
def self.release(ptr) # :nodoc:
|
25
25
|
FFIGeos.GEOSWKTWriter_destroy_r(Geos.current_handle_pointer, ptr)
|
26
26
|
end
|
27
27
|
|
28
|
-
def set_options(options)
|
28
|
+
def set_options(options) # :nodoc:
|
29
29
|
[:trim, :old_3d, :rounding_precision, :output_dimensions].each do |k|
|
30
30
|
send("#{k}=", options[k]) if respond_to?("#{k}=") && options.key?(k)
|
31
31
|
end
|
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,
|
@@ -56,7 +60,13 @@ module Geos
|
|
56
60
|
elsif FFI::Platform::IS_WINDOWS
|
57
61
|
ENV['PATH'].split(File::PATH_SEPARATOR)
|
58
62
|
else
|
59
|
-
[
|
63
|
+
[
|
64
|
+
'/usr/local/{lib64,lib}',
|
65
|
+
'/opt/local/{lib64,lib}',
|
66
|
+
'/usr/{lib64,lib}',
|
67
|
+
'/opt/homebrew/lib',
|
68
|
+
'/usr/lib/{x86_64,i386,aarch64}-linux-gnu'
|
69
|
+
]
|
60
70
|
end
|
61
71
|
end
|
62
72
|
|
@@ -98,6 +108,11 @@ module Geos
|
|
98
108
|
:ndr, 1 # Little Endian
|
99
109
|
])
|
100
110
|
|
111
|
+
Geos::Flavors = enum(:flavor, [
|
112
|
+
:extended, 1,
|
113
|
+
:iso, 2
|
114
|
+
])
|
115
|
+
|
101
116
|
Geos::BufferCapStyles = enum(:buffer_cap_style, [
|
102
117
|
:round, 1,
|
103
118
|
:flat, 2,
|
@@ -581,6 +596,11 @@ module Geos
|
|
581
596
|
:pointer, :pointer, :pointer, :double, :int
|
582
597
|
],
|
583
598
|
|
599
|
+
GEOSConstrainedDelaunayTriangulation_r: [
|
600
|
+
# *geom, *handle, *geom
|
601
|
+
:pointer, :pointer, :pointer
|
602
|
+
],
|
603
|
+
|
584
604
|
GEOSVoronoiDiagram_r: [
|
585
605
|
# *geom, *handle, *geom, *envelope, tolerance, only_edges
|
586
606
|
:pointer, :pointer, :pointer, :pointer, :double, :int
|
@@ -721,6 +741,11 @@ module Geos
|
|
721
741
|
:int, :pointer, :pointer, :pointer, :pointer
|
722
742
|
],
|
723
743
|
|
744
|
+
GEOSDistanceWithin_r: [
|
745
|
+
# (0 on exception, 1 otherwise), *handle, *geom_a, *geom_b, double distance
|
746
|
+
:char, :pointer, :pointer, :pointer, :double
|
747
|
+
],
|
748
|
+
|
724
749
|
GEOSHausdorffDistance_r: [
|
725
750
|
# (0 on exception, 1 otherwise), *handle, *geom_a, *geom_b, (double *) distance
|
726
751
|
:int, :pointer, :pointer, :pointer, :pointer
|
@@ -949,6 +974,21 @@ module Geos
|
|
949
974
|
# (2 on exception, 1 on true, 0 on false), *handle, *prepared, *geom
|
950
975
|
:char, :pointer, :pointer, :pointer
|
951
976
|
],
|
977
|
+
|
978
|
+
GEOSPreparedDistance_r: [
|
979
|
+
# (1 on success, 0 on failure), *handle, *prepared, *geom, *distance
|
980
|
+
:int, :pointer, :pointer, :pointer, :pointer
|
981
|
+
],
|
982
|
+
|
983
|
+
GEOSPreparedDistanceWithin_r: [
|
984
|
+
# (1 on true, 0 on false), *handle, *prepared, *geom, max_distance
|
985
|
+
:char, :pointer, :pointer, :pointer, :double
|
986
|
+
],
|
987
|
+
|
988
|
+
GEOSPreparedNearestPoints_r: [
|
989
|
+
# *coord_seq, *handle, *prepared, *geom
|
990
|
+
:pointer, :pointer, :pointer, :pointer
|
991
|
+
],
|
952
992
|
#### /PreparedGeometry functions ####
|
953
993
|
|
954
994
|
#### WktReader functions ####
|
@@ -1082,8 +1122,52 @@ module Geos
|
|
1082
1122
|
# void, *handle, *geom, bool
|
1083
1123
|
:void, :pointer, :pointer, :char
|
1084
1124
|
],
|
1125
|
+
|
1126
|
+
GEOSWKBWriter_getFlavor_r: [
|
1127
|
+
# flavor, *handle, *geom
|
1128
|
+
:flavor, :pointer, :pointer
|
1129
|
+
],
|
1130
|
+
|
1131
|
+
GEOSWKBWriter_setFlavor_r: [
|
1132
|
+
# void, *handle, *geom, flavor
|
1133
|
+
:void, :pointer, :pointer, :flavor
|
1134
|
+
],
|
1085
1135
|
#### /WkbWriter functions ####
|
1086
1136
|
|
1137
|
+
#### GeoJSONReader functions ####
|
1138
|
+
GEOSGeoJSONReader_create_r: [
|
1139
|
+
# *geojson_reader, *handle
|
1140
|
+
:pointer, :pointer
|
1141
|
+
],
|
1142
|
+
|
1143
|
+
GEOSGeoJSONReader_readGeometry_r: [
|
1144
|
+
# *geom, *handle, *geojson_reader, string
|
1145
|
+
:pointer, :pointer, :pointer, :string
|
1146
|
+
],
|
1147
|
+
|
1148
|
+
GEOSGeoJSONReader_destroy_r: [
|
1149
|
+
# void, *handle, *geojson_reader
|
1150
|
+
:void, :pointer, :pointer
|
1151
|
+
],
|
1152
|
+
#### /GeoJSONReader functions ###
|
1153
|
+
|
1154
|
+
#### GeoJSONWriter functions ####
|
1155
|
+
GEOSGeoJSONWriter_create_r: [
|
1156
|
+
# *geojson_writer, *handle
|
1157
|
+
:pointer, :pointer
|
1158
|
+
],
|
1159
|
+
|
1160
|
+
GEOSGeoJSONWriter_destroy_r: [
|
1161
|
+
# void, *handle, *geojson_writer
|
1162
|
+
:void, :pointer, :pointer
|
1163
|
+
],
|
1164
|
+
|
1165
|
+
GEOSGeoJSONWriter_writeGeometry_r: [
|
1166
|
+
# string, *handle, *geojson_writer, :geom, :indent
|
1167
|
+
:string, :pointer, :pointer, :pointer, :int
|
1168
|
+
],
|
1169
|
+
#### /GeoJSONWriter functions ####
|
1170
|
+
|
1087
1171
|
#### Linearref functions ####
|
1088
1172
|
GEOSProject_r: [
|
1089
1173
|
# distance, *handle, *geom_a, *geom_b
|
@@ -1363,12 +1447,14 @@ module Geos
|
|
1363
1447
|
GEOS_CAPI_VERSION,
|
1364
1448
|
GEOS_CAPI_VERSION_MAJOR, GEOS_CAPI_VERSION_MINOR, GEOS_CAPI_VERSION_PATCH,
|
1365
1449
|
GEOS_SVN_REVISION =
|
1366
|
-
if
|
1450
|
+
if (versions = Geos.version.scan(/^
|
1367
1451
|
((\d+)\.(\d+)\.(\d+)((?:dev|rc|beta|alpha)\d*)?)
|
1368
1452
|
-CAPI-
|
1369
1453
|
((\d+)\.(\d+)\.(\d+))
|
1370
1454
|
(?:\s+r?(\h+))?
|
1371
1455
|
$/x)).empty?
|
1456
|
+
['0.0.0', 0, 0, 0, nil, '0.0.0', 0, 0, 0]
|
1457
|
+
else
|
1372
1458
|
versions = versions[0]
|
1373
1459
|
[
|
1374
1460
|
versions[0],
|
@@ -1382,11 +1468,13 @@ module Geos
|
|
1382
1468
|
versions[8].to_i,
|
1383
1469
|
versions[9]&.to_i
|
1384
1470
|
]
|
1385
|
-
else
|
1386
|
-
['0.0.0', 0, 0, 0, nil, '0.0.0', 0, 0, 0]
|
1387
1471
|
end
|
1388
1472
|
GEOS_CAPI_FIRST_INTERFACE = GEOS_CAPI_VERSION_MAJOR.to_i
|
1389
1473
|
GEOS_CAPI_LAST_INTERFACE = GEOS_CAPI_VERSION_MAJOR.to_i + GEOS_CAPI_VERSION_MINOR.to_i
|
1474
|
+
|
1475
|
+
GEOS_NICE_VERSION = [GEOS_VERSION_MAJOR, GEOS_VERSION_MINOR, GEOS_VERSION_PATCH].collect { |version|
|
1476
|
+
version.to_s.rjust(2, '0')
|
1477
|
+
}.join
|
1390
1478
|
end
|
1391
1479
|
|
1392
1480
|
module Constants
|
data/sonar-project.properties
CHANGED
@@ -2,15 +2,15 @@ sonar.projectKey=dark-panda_ffi-geos
|
|
2
2
|
sonar.organization=dark-panda
|
3
3
|
|
4
4
|
# This is the name and version displayed in the SonarCloud UI.
|
5
|
-
|
6
|
-
|
5
|
+
sonar.projectName=ffi-geos
|
6
|
+
sonar.projectVersion=1.0
|
7
7
|
|
8
8
|
# Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows.
|
9
9
|
sonar.sources=lib, test
|
10
10
|
|
11
11
|
# Encoding of the source code. Default is default system encoding
|
12
|
-
|
12
|
+
sonar.sourceEncoding=UTF-8
|
13
13
|
|
14
14
|
# Additional reports
|
15
15
|
sonar.ruby.rubocop.reportPaths=rubocop-report.json
|
16
|
-
sonar.ruby.coverage.reportPaths=coverage
|
16
|
+
sonar.ruby.coverage.reportPaths=coverage/coverage.json
|
@@ -515,16 +515,16 @@ class CoordinateSequenceTests < Minitest::Test
|
|
515
515
|
end
|
516
516
|
|
517
517
|
undef :affine_tester
|
518
|
-
def affine_tester(method, expected, coords, *args)
|
518
|
+
def affine_tester(method, expected, coords, *args, **options)
|
519
519
|
cs = Geos::CoordinateSequence.new(coords)
|
520
|
-
cs.
|
520
|
+
cs.__safe_send__("#{method}!", *args, **options)
|
521
521
|
|
522
522
|
expected.length.times do |i|
|
523
523
|
assert_in_delta(expected[i], cs.get_ordinate(0, i), TOLERANCE)
|
524
524
|
end
|
525
525
|
|
526
526
|
cs = Geos::CoordinateSequence.new(coords)
|
527
|
-
cs_2 = cs.
|
527
|
+
cs_2 = cs.__safe_send__(method, *args, **options)
|
528
528
|
|
529
529
|
expected.length.times do |i|
|
530
530
|
assert_in_delta(coords[i], cs.get_ordinate(0, i), TOLERANCE)
|
@@ -542,21 +542,21 @@ class CoordinateSequenceTests < Minitest::Test
|
|
542
542
|
def test_rotate_x
|
543
543
|
affine_tester(:rotate_x, [1, -1, -1], [1, 1, 1], Math::PI)
|
544
544
|
affine_tester(:rotate_x, [1, -1, 1], [1, 1, 1], Math::PI / 2)
|
545
|
-
affine_tester(:rotate_x, [1, 1, -1], [1, 1, 1], Math::PI + Math::PI / 2)
|
545
|
+
affine_tester(:rotate_x, [1, 1, -1], [1, 1, 1], Math::PI + (Math::PI / 2))
|
546
546
|
affine_tester(:rotate_x, [1, 1, 1], [1, 1, 1], Math::PI * 2)
|
547
547
|
end
|
548
548
|
|
549
549
|
def test_rotate_y
|
550
550
|
affine_tester(:rotate_y, [-1, 1, -1], [1, 1, 1], Math::PI)
|
551
551
|
affine_tester(:rotate_y, [1, 1, -1], [1, 1, 1], Math::PI / 2)
|
552
|
-
affine_tester(:rotate_y, [-1, 1, 1], [1, 1, 1], Math::PI + Math::PI / 2)
|
552
|
+
affine_tester(:rotate_y, [-1, 1, 1], [1, 1, 1], Math::PI + (Math::PI / 2))
|
553
553
|
affine_tester(:rotate_y, [1, 1, 1], [1, 1, 1], Math::PI * 2)
|
554
554
|
end
|
555
555
|
|
556
556
|
def test_rotate_z
|
557
557
|
affine_tester(:rotate_z, [-1, -1], [1, 1], Math::PI)
|
558
558
|
affine_tester(:rotate_z, [-1, 1], [1, 1], Math::PI / 2)
|
559
|
-
affine_tester(:rotate_z, [1, -1], [1, 1], Math::PI + Math::PI / 2)
|
559
|
+
affine_tester(:rotate_z, [1, -1], [1, 1], Math::PI + (Math::PI / 2))
|
560
560
|
affine_tester(:rotate_z, [1, 1], [1, 1], Math::PI * 2)
|
561
561
|
end
|
562
562
|
|
@@ -0,0 +1,170 @@
|
|
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
|
+
'MULTIPOINT (10.000 40.000, 40.000 30.000, 20.000 20.000, 30.000 10.000)',
|
59
|
+
'{"type":"MultiPoint","coordinates":[[10, 40], [40, 30], [20, 20], [30, 10]]}'
|
60
|
+
)
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_multi_line_string
|
64
|
+
geojson_tester(
|
65
|
+
'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))',
|
66
|
+
'{"type":"MultiLineString","coordinates":[[[10, 10], [20, 20], [10, 40]],[[40, 40], [30, 30], [40, 20], [30, 10]]]}'
|
67
|
+
)
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_multi_polygon
|
71
|
+
geojson_tester(
|
72
|
+
'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)))',
|
73
|
+
'{"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]]]]}'
|
74
|
+
)
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_geometry_collection
|
78
|
+
geojson_tester(
|
79
|
+
'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)))',
|
80
|
+
'{"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]]]}]}'
|
81
|
+
)
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_feature_collection
|
85
|
+
geojson_tester(
|
86
|
+
'GEOMETRYCOLLECTION (POINT (-117.000 33.000), POINT (-122.000 45.000))',
|
87
|
+
'{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-117.0,33.0]}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-122.0,45.0]}}]}'
|
88
|
+
)
|
89
|
+
end
|
90
|
+
|
91
|
+
def test_empty_point
|
92
|
+
geojson_tester(
|
93
|
+
'POINT EMPTY',
|
94
|
+
'{"type":"Point","coordinates":[]}'
|
95
|
+
)
|
96
|
+
end
|
97
|
+
|
98
|
+
def test_empty_line_string
|
99
|
+
geojson_tester(
|
100
|
+
'LINESTRING EMPTY',
|
101
|
+
'{"type":"LineString","coordinates":[]}'
|
102
|
+
)
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_empty_polygon
|
106
|
+
geojson_tester(
|
107
|
+
'POLYGON EMPTY',
|
108
|
+
'{"type":"Polygon","coordinates":[]}'
|
109
|
+
)
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_empty_multi_point
|
113
|
+
geojson_tester(
|
114
|
+
'MULTIPOINT EMPTY',
|
115
|
+
'{"type":"MultiPoint","coordinates":[]}'
|
116
|
+
)
|
117
|
+
end
|
118
|
+
|
119
|
+
def test_empty_multi_line_string
|
120
|
+
geojson_tester(
|
121
|
+
'MULTILINESTRING EMPTY',
|
122
|
+
'{"type":"MultiLineString","coordinates":[]}'
|
123
|
+
)
|
124
|
+
end
|
125
|
+
|
126
|
+
def test_empty_multi_polygon
|
127
|
+
geojson_tester(
|
128
|
+
'MULTIPOLYGON EMPTY',
|
129
|
+
'{"type": "MultiPolygon", "coordinates": []}'
|
130
|
+
)
|
131
|
+
end
|
132
|
+
|
133
|
+
def test_empty_geometry_collection
|
134
|
+
geojson_tester(
|
135
|
+
'GEOMETRYCOLLECTION EMPTY',
|
136
|
+
'{"type": "GeometryCollection","geometries": []}'
|
137
|
+
)
|
138
|
+
end
|
139
|
+
|
140
|
+
def test_incomplete_geojson
|
141
|
+
assert_raises(Geos::GeoJSONReader::ParseError) do
|
142
|
+
json_reader.read('{"type":"Point","coordinates":[-117.0]}')
|
143
|
+
end
|
144
|
+
|
145
|
+
assert_raises(Geos::GeoJSONReader::ParseError) do
|
146
|
+
json_reader.read('{"type":"LineString","coordinates":[[1,2],[2]]}')
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def test_broken_geojson
|
151
|
+
assert_raises(Geos::GeoJSONReader::ParseError) do
|
152
|
+
json_reader.read('<gml>NOT_GEO_JSON</gml>')
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def test_incompatible_type
|
157
|
+
assert_raises(Geos::GeoJSONReader::ParseError) do
|
158
|
+
json_reader.read('{"type":"Line","coordinates":[[1,2],[2,3]]}')
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def test_srid_from_options
|
163
|
+
geom = json_reader.read(
|
164
|
+
'{"type":"Point","coordinates":[-117.0,33.0]}',
|
165
|
+
srid: 3857
|
166
|
+
)
|
167
|
+
|
168
|
+
assert_equal(geom.srid, 3857)
|
169
|
+
end
|
170
|
+
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
|
@@ -174,7 +174,7 @@ class GeometryCollectionTests < Minitest::Test
|
|
174
174
|
|
175
175
|
def test_snap_to_grid
|
176
176
|
wkt = 'GEOMETRYCOLLECTION (LINESTRING (-10.12 0, -10.12 5, -10.12 5, -10.12 6, -10.12 6, -10.12 6, -10.12 7, -10.12 7, -10.12 7, -10.12 8, -10.12 8, -9 8, -9 9, -10.12 0), ' \
|
177
|
-
|
177
|
+
'POLYGON ((-10.12 0, -10.12 5, -10.12 5, -10.12 6, -10.12 6, -10.12 6, -10.12 7, -10.12 7, -10.12 7, -10.12 8, -10.12 8, -9 8, -9 9, -10.12 0)), POINT (10.12 10.12))'
|
178
178
|
|
179
179
|
expected = 'GEOMETRYCOLLECTION (LINESTRING (-10 0, -10 5, -10 5, -10 6, -10 6, -10 6, -10 7, -10 7, -10 7, -10 8, -10 8, -9 8, -9 9, -10 0), POLYGON ((-10 0, -10 5, -10 5, -10 6, -10 6, -10 6, -10 7, -10 7, -10 7, -10 8, -10 8, -9 8, -9 9, -10 0)), POINT (10 10))'
|
180
180
|
|
@@ -255,7 +255,7 @@ class GeometryCollectionTests < Minitest::Test
|
|
255
255
|
affine_tester(:rotate_x,
|
256
256
|
'GEOMETRYCOLLECTION Z (POINT Z (1 1 -1), LINESTRING Z (1 1 -1, 10 10 -10), POLYGON Z ((0 0 0, 5 0 0, 5 0 -5, 0 0 -5, 0 0 0)))',
|
257
257
|
wkt,
|
258
|
-
Math::PI + Math::PI / 2)
|
258
|
+
Math::PI + (Math::PI / 2))
|
259
259
|
|
260
260
|
affine_tester(:rotate_x,
|
261
261
|
wkt,
|
@@ -282,7 +282,7 @@ class GeometryCollectionTests < Minitest::Test
|
|
282
282
|
affine_tester(:rotate_y,
|
283
283
|
'GEOMETRYCOLLECTION Z (POINT Z (-1 1 1), LINESTRING Z (-1 1 1, -10 10 10), POLYGON Z ((0 0 0, 0 0 5, 0 5 5, 0 5 0, 0 0 0)))',
|
284
284
|
wkt,
|
285
|
-
Math::PI + Math::PI / 2)
|
285
|
+
Math::PI + (Math::PI / 2))
|
286
286
|
|
287
287
|
affine_tester(:rotate_y,
|
288
288
|
wkt,
|
@@ -308,7 +308,7 @@ class GeometryCollectionTests < Minitest::Test
|
|
308
308
|
affine_tester(:rotate_z,
|
309
309
|
'GEOMETRYCOLLECTION (POINT (1 -1), LINESTRING (0 0, 10 -10), POLYGON ((0 0, 0 -5, 5 -5, 5 0, 0 0)))',
|
310
310
|
wkt,
|
311
|
-
Math::PI + Math::PI / 2)
|
311
|
+
Math::PI + (Math::PI / 2))
|
312
312
|
|
313
313
|
affine_tester(:rotate_z,
|
314
314
|
wkt,
|