ffi-geos 2.2.0 → 2.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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,
|