ffi-geos 0.2.1 → 0.3.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 +7 -0
- data/MIT-LICENSE +1 -1
- data/README.rdoc +81 -65
- data/lib/ffi-geos.rb +30 -0
- data/lib/ffi-geos/coordinate_sequence.rb +4 -3
- data/lib/ffi-geos/geometry.rb +26 -1
- data/lib/ffi-geos/interrupt.rb +73 -0
- data/lib/ffi-geos/version.rb +1 -1
- data/lib/ffi-geos/wkb_writer.rb +7 -7
- data/test/geometry_tests.rb +87 -0
- data/test/interrupt_tests.rb +192 -0
- data/test/misc_tests.rb +9 -0
- data/test/test_helper.rb +1 -0
- metadata +13 -14
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: ceab1a4b690aced547fbaea6008072689e803a35
|
4
|
+
data.tar.gz: 3e0c22f99d9a9884a9d755c0dd09698b68dbe6bf
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 96aa99fbd28ad9fb6bfffaa08e77b5a788107c2e608976baf4b20e7a38e711942fcedc9de9eb8795174a9f7e9af5cf1641ccc40559122ce6080d993994067ae1
|
7
|
+
data.tar.gz: 1307315dc60642d103c41df11c82c810c7c08f6b6d2c4b70e23aae224ea5bcf08fec0fe3ed1d816214f9bf306622b8b7fffda762402c85d7d4dddf53915d22da
|
data/MIT-LICENSE
CHANGED
data/README.rdoc
CHANGED
@@ -9,9 +9,9 @@
|
|
9
9
|
|
10
10
|
Ruby versions known to work:
|
11
11
|
|
12
|
-
* Ruby MRI 1.8.7, 1.9.2
|
13
|
-
* Ruby MRI 1.8.7
|
14
|
-
* Ruby MRI 1.8.7, 1.9.2
|
12
|
+
* Ruby MRI 1.8.7, 1.9.2, 1.9.3, 2.0.0 x86_64, OSX 10.6.5+
|
13
|
+
* Ruby MRI 1.8.7, 1.9.2, 1.9.3, 2.0.0 i386, linux
|
14
|
+
* Ruby MRI 1.8.7, 1.9.2, 1.9.3, 2.0.0 x86_64, linux
|
15
15
|
* JRuby 1.6, x86_64 OSX 10.6.5+
|
16
16
|
|
17
17
|
=== JRuby Notes
|
@@ -58,6 +58,10 @@ Ruby bindings along with the following enhancements and additions:
|
|
58
58
|
* Geos::PreparedGeometry class and Geos::Geometry#to_prepared method to
|
59
59
|
allow for prepared geometries and more efficient relationship testing.
|
60
60
|
|
61
|
+
* Geos::Interrupt module that allows you to interrupt certain calls to the
|
62
|
+
GEOS library and perform other work or cancel GEOS calls outright. The
|
63
|
+
interruption API was added in GEOS 3.4.0.
|
64
|
+
|
61
65
|
== New Methods and Additions (not exhaustive)
|
62
66
|
|
63
67
|
* SRIDs can be copied on many operations. GEOS doesn't usually copy SRIDs
|
@@ -69,88 +73,100 @@ Ruby bindings along with the following enhancements and additions:
|
|
69
73
|
|
70
74
|
=== Geos
|
71
75
|
|
72
|
-
* Geos.
|
73
|
-
|
74
|
-
* Geos.create_multi_line_string
|
75
|
-
|
76
|
-
* Geos.create_multi_polygon
|
77
|
-
|
78
|
-
* Geos.create_geometry_collection
|
79
|
-
|
80
|
-
* Geos.create_collection
|
81
|
-
|
82
|
-
* Geos.create_empty_point
|
83
|
-
|
84
|
-
* Geos.create_empty_polygon
|
85
|
-
|
86
|
-
* Geos.create_empty_line_string
|
87
|
-
|
88
|
-
* Geos.create_empty_multi_point
|
89
|
-
|
90
|
-
* Geos.create_empty_multi_line_string
|
76
|
+
* Many new Geos.create_* methods, such as Geos.create_linear_ring, etc.
|
91
77
|
|
92
|
-
* Geos.
|
93
|
-
|
94
|
-
* Geos.create_empty_geometry_collection
|
78
|
+
* Geos.srid_copy_policy, srid_copy_policy=, srid_copy_policy_default and
|
79
|
+
srid_copy_policy_default=.
|
95
80
|
|
96
81
|
=== Geos::Geometry
|
97
82
|
|
98
|
-
* Geos::
|
99
|
-
|
100
|
-
* Geos::
|
83
|
+
* Geos::almost_equals?
|
84
|
+
* Geos::coord_seq
|
85
|
+
* Geos::covered_by?
|
86
|
+
* Geos::covers?
|
87
|
+
* Geos::delaunay_triangulation
|
88
|
+
* Geos::end_point
|
89
|
+
* Geos::eql_almost?
|
90
|
+
* Geos::equals?
|
91
|
+
* Geos::equals_almost?
|
92
|
+
* Geos::equals_exact?
|
93
|
+
* Geos::exactly_equals?
|
94
|
+
* Geos::extract_unique_points - Geos::Geometry#unique_points
|
95
|
+
* Geos::hausdorff_distance
|
96
|
+
* Geos::interpolate
|
97
|
+
* Geos::interpolate_normalized
|
98
|
+
* Geos::nearest_points
|
99
|
+
* Geos::node
|
100
|
+
* Geos::normalize!
|
101
|
+
* Geos::num_coordinates
|
102
|
+
* Geos::polygonize
|
103
|
+
* Geos::polygonize_cut_edges
|
104
|
+
* Geos::polygonize_full
|
105
|
+
* Geos::project
|
106
|
+
* Geos::project_normalized
|
107
|
+
* Geos::relate_boundary_node_rule
|
108
|
+
* Geos::representative_point
|
109
|
+
* Geos::shared_paths
|
110
|
+
* Geos::snap
|
111
|
+
* Geos::snap_to
|
112
|
+
* Geos::start_point
|
113
|
+
* Geos::symmetric_difference
|
114
|
+
* Geos::to_prepared
|
115
|
+
* Geos::unary_union
|
116
|
+
* Geos::union_cascaded - Geos::Geometry#union can also be called
|
101
117
|
without a geometry argument to produce the same effect.
|
102
|
-
|
103
|
-
* Geos::
|
104
|
-
|
105
|
-
* Geos::Geometry#valid_reason
|
106
|
-
|
107
|
-
* Geos::Geometry#valid_detail
|
108
|
-
|
109
|
-
* Geos::Geometry#project
|
110
|
-
|
111
|
-
* Geos::Geometry#project_normalized
|
112
|
-
|
113
|
-
* Geos::Geometry#interpolate
|
114
|
-
|
115
|
-
* Geos::Geometry#interpolate_normalized
|
116
|
-
|
117
|
-
* Geos::Geometry#start_point
|
118
|
-
|
119
|
-
* Geos::Geometry#end_point
|
120
|
-
|
121
|
-
* Geos::Geometry#hausdorff_distance
|
122
|
-
|
123
|
-
* Geos::Geometry#snap
|
124
|
-
|
125
|
-
* Geos::Geometry#shared_paths
|
126
|
-
|
127
|
-
* Geos::Geometry#polygonize_full
|
128
|
-
|
129
|
-
* Geos::Geometry#polygonize
|
130
|
-
|
131
|
-
* Geos::Geometry#polygonize_cut_edges
|
132
|
-
|
133
|
-
* Geos::Geometry#to_prepared
|
118
|
+
* Geos::unique_points - Geos::Geometry#extract_unique_points
|
119
|
+
* Geos::valid_detail
|
120
|
+
* Geos::valid_reason
|
134
121
|
|
135
122
|
=== Geos::LineString and Geos::LinearRing
|
136
123
|
|
124
|
+
* Geos::LineString#[]
|
125
|
+
* Geos::LineString#closed?
|
126
|
+
* Geos::LineString#each
|
137
127
|
* Geos::LineString#num_points
|
138
|
-
|
128
|
+
* Geos::LineString#offset_curve
|
139
129
|
* Geos::LineString#point_n
|
140
|
-
|
141
|
-
* Geos::
|
130
|
+
* Geos::LineString#slice
|
131
|
+
* Geos::LinearRing#to_line_string
|
132
|
+
* Geos::LinearRing#to_polygon
|
142
133
|
|
143
134
|
=== Geos::WktWriter
|
144
135
|
|
136
|
+
* Geos::WktWriter#old_3d
|
137
|
+
* Geos::WktWriter#old_3d=
|
138
|
+
* Geos::WktWriter#output_dimensions
|
139
|
+
* Geos::WktWriter#output_dimensions=
|
140
|
+
* Geos::WktWriter#rounding_precision
|
141
|
+
* Geos::WktWriter#rounding_precision=
|
142
|
+
* Geos::WktWriter#trim
|
145
143
|
* Geos::WktWriter#trim=
|
146
144
|
|
147
|
-
|
145
|
+
=== Geos::CoordinateSequence
|
148
146
|
|
149
|
-
* Geos::
|
147
|
+
* Geos::CoordinateSequence#has_z?
|
148
|
+
* Geos::CoordinateSequence#to_line_string
|
149
|
+
* Geos::CoordinateSequence#to_linear_ring
|
150
|
+
* Geos::CoordinateSequence#to_point
|
151
|
+
* Geos::CoordinateSequence#to_polygon
|
152
|
+
|
153
|
+
=== Geos::Polygon
|
154
|
+
|
155
|
+
* Geos::Polygon#interior_ring
|
156
|
+
* Geos::Polygon#interior_rings
|
150
157
|
|
151
158
|
=== Geos::Utils
|
152
159
|
|
153
160
|
* Geos::Utils.orientation_index
|
161
|
+
* Geos::Utils.relate_match
|
162
|
+
|
163
|
+
=== Geos::Interrupt
|
164
|
+
|
165
|
+
* Geos::Interrupt.available?
|
166
|
+
* Geos::Interrupt.register
|
167
|
+
* Geos::Interrupt.request
|
168
|
+
* Geos::Interrupt.cancel
|
169
|
+
* Geos::Interrupt.clear
|
154
170
|
|
155
171
|
== Thanks
|
156
172
|
|
data/lib/ffi-geos.rb
CHANGED
@@ -45,6 +45,8 @@ module Geos
|
|
45
45
|
File.join(GEOS_BASE, 'tools')
|
46
46
|
autoload :Utils,
|
47
47
|
File.join(GEOS_BASE, 'utils')
|
48
|
+
autoload :Interrupt,
|
49
|
+
File.join(GEOS_BASE, 'interrupt')
|
48
50
|
|
49
51
|
module FFIGeos
|
50
52
|
def self.search_paths
|
@@ -151,6 +153,19 @@ module Geos
|
|
151
153
|
:void, :pointer
|
152
154
|
],
|
153
155
|
|
156
|
+
:GEOS_interruptRegisterCallback => [
|
157
|
+
:pointer,
|
158
|
+
callback([], :void)
|
159
|
+
],
|
160
|
+
|
161
|
+
:GEOS_interruptRequest => [
|
162
|
+
:void
|
163
|
+
],
|
164
|
+
|
165
|
+
:GEOS_interruptCancel => [
|
166
|
+
:void
|
167
|
+
],
|
168
|
+
|
154
169
|
:GEOSversion => [
|
155
170
|
:string
|
156
171
|
],
|
@@ -399,6 +414,11 @@ module Geos
|
|
399
414
|
:pointer, :pointer, :pointer
|
400
415
|
],
|
401
416
|
|
417
|
+
:GEOSNode_r => [
|
418
|
+
# *geom, *handle, *geom
|
419
|
+
:pointer, :pointer, :pointer
|
420
|
+
],
|
421
|
+
|
402
422
|
# Deprecated in GEOS 3.3.0. Use GEOSUnaryUnion_r instead.
|
403
423
|
:GEOSUnionCascaded_r => [
|
404
424
|
# *geom, *handle, *geom
|
@@ -450,6 +470,11 @@ module Geos
|
|
450
470
|
:pointer, :pointer, :pointer, :pointer, :double
|
451
471
|
],
|
452
472
|
|
473
|
+
:GEOSDelaunayTriangulation_r => [
|
474
|
+
# *geom, *handle, *geom, tolerance, only_edges
|
475
|
+
:pointer, :pointer, :pointer, :double, :int
|
476
|
+
],
|
477
|
+
|
453
478
|
:GEOSRelate_r => [
|
454
479
|
# string, *handle, *geom_a, *geom_b
|
455
480
|
:string, :pointer, :pointer, :pointer
|
@@ -590,6 +615,11 @@ module Geos
|
|
590
615
|
:int, :pointer, :pointer, :pointer, :double, :pointer
|
591
616
|
],
|
592
617
|
|
618
|
+
:GEOSNearestPoints_r => [
|
619
|
+
# (NULL on exception, pointer to CoordinateSequence otherwise), *handle, *geom, *geom
|
620
|
+
:pointer, :pointer, :pointer, :pointer
|
621
|
+
],
|
622
|
+
|
593
623
|
:GEOSGetGeometryN_r => [
|
594
624
|
# *geom, *handle, *geom, n
|
595
625
|
:pointer, :pointer, :pointer, :int
|
@@ -44,7 +44,7 @@ module Geos
|
|
44
44
|
attr_reader :ptr, :x, :y, :z
|
45
45
|
|
46
46
|
# :call-seq:
|
47
|
-
# new(ptr, auto_free = true)
|
47
|
+
# new(ptr, auto_free = true, parent = nil)
|
48
48
|
# new(size = 0, dimensions = 0)
|
49
49
|
# new(options)
|
50
50
|
# new(points)
|
@@ -58,8 +58,8 @@ module Geos
|
|
58
58
|
def initialize(*args)
|
59
59
|
points = nil # forward declaration we can use later
|
60
60
|
|
61
|
-
ptr, auto_free = if args.first.is_a?(FFI::Pointer)
|
62
|
-
|
61
|
+
ptr, auto_free, parent = if args.first.is_a?(FFI::Pointer)
|
62
|
+
args.first(3)
|
63
63
|
else
|
64
64
|
size, dimensions = if args.first.is_a?(Array)
|
65
65
|
points = if args.first.first.is_a?(Array)
|
@@ -100,6 +100,7 @@ module Geos
|
|
100
100
|
)
|
101
101
|
|
102
102
|
@ptr.autorelease = auto_free
|
103
|
+
@parent = parent if parent
|
103
104
|
|
104
105
|
@x = CoordinateAccessor.new(self, 0)
|
105
106
|
@y = CoordinateAccessor.new(self, 1)
|
data/lib/ffi-geos/geometry.rb
CHANGED
@@ -76,7 +76,7 @@ module Geos
|
|
76
76
|
end
|
77
77
|
|
78
78
|
def coord_seq
|
79
|
-
CoordinateSequence.new(FFIGeos.GEOSGeom_getCoordSeq_r(Geos.current_handle, self.ptr), false)
|
79
|
+
CoordinateSequence.new(FFIGeos.GEOSGeom_getCoordSeq_r(Geos.current_handle, self.ptr), false, self)
|
80
80
|
end
|
81
81
|
|
82
82
|
def intersection(geom)
|
@@ -189,6 +189,13 @@ module Geos
|
|
189
189
|
end
|
190
190
|
end
|
191
191
|
|
192
|
+
if FFIGeos.respond_to?(:GEOSNode_r)
|
193
|
+
# Available in GEOS 3.3.4+
|
194
|
+
def node
|
195
|
+
cast_geometry_ptr(FFIGeos.GEOSNode_r(Geos.current_handle, self.ptr))
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
192
199
|
def point_on_surface
|
193
200
|
cast_geometry_ptr(FFIGeos.GEOSPointOnSurface_r(Geos.current_handle, self.ptr), :srid_copy => self.srid)
|
194
201
|
end
|
@@ -473,6 +480,18 @@ module Geos
|
|
473
480
|
double_ptr.read_double
|
474
481
|
end
|
475
482
|
|
483
|
+
if FFIGeos.respond_to?(:GEOSNearestPoints_r)
|
484
|
+
# Available in GEOS 3.4+.
|
485
|
+
def nearest_points(geom)
|
486
|
+
check_geometry(geom)
|
487
|
+
ptr = FFIGeos.GEOSNearestPoints_r(Geos.current_handle, self.ptr, geom.ptr)
|
488
|
+
|
489
|
+
if !ptr.null?
|
490
|
+
CoordinateSequence.new(ptr)
|
491
|
+
end
|
492
|
+
end
|
493
|
+
end
|
494
|
+
|
476
495
|
def snap(geom, tolerance)
|
477
496
|
check_geometry(geom)
|
478
497
|
cast_geometry_ptr(FFIGeos.GEOSSnap_r(Geos.current_handle, self.ptr, geom.ptr, tolerance), {
|
@@ -533,6 +552,12 @@ module Geos
|
|
533
552
|
cast_geometry_ptr(FFIGeos.GEOSPolygonizer_getCutEdges_r(Geos.current_handle, ary, 1), :srid_copy => self.srid).to_a
|
534
553
|
end
|
535
554
|
|
555
|
+
if FFIGeos.respond_to?(:GEOSDelaunayTriangulation_r)
|
556
|
+
def delaunay_triangulation(tolerance, options = {})
|
557
|
+
cast_geometry_ptr(FFIGeos.GEOSDelaunayTriangulation_r(Geos.current_handle, self.ptr, tolerance, options[:only_edges] ? 1 : 0))
|
558
|
+
end
|
559
|
+
end
|
560
|
+
|
536
561
|
def to_prepared
|
537
562
|
Geos::PreparedGeometry.new(self)
|
538
563
|
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
|
2
|
+
module Geos
|
3
|
+
module Interrupt
|
4
|
+
class << self
|
5
|
+
if FFIGeos.respond_to?(:GEOS_interruptRegisterCallback)
|
6
|
+
# Check for the availability of the GEOS interruption API. The
|
7
|
+
# interruption API was added in GEOS 3.4.0.
|
8
|
+
def available?
|
9
|
+
true
|
10
|
+
end
|
11
|
+
|
12
|
+
# Registers an interrupt method or block that may be called during
|
13
|
+
# certain operations such as Geos::Geometry#buffer. During these
|
14
|
+
# blocks you can interrupt the current operation using
|
15
|
+
# Geos.request_interrupt and cancel that interrupt request using
|
16
|
+
# Geos.clear_interrupt.
|
17
|
+
#
|
18
|
+
# The return value for Geos.register_interrupt is a reference to the
|
19
|
+
# previously registered callback, allowing you to chain interrupt
|
20
|
+
# calls together by calling #call on the previously registered callback.
|
21
|
+
#
|
22
|
+
# HUGE NOTE CONCERNING INTERRUPTS: be careful when using interrupt
|
23
|
+
# blocks and how they reference other ruby objects. The ruby garbage
|
24
|
+
# collector may not play nicely with GEOS and objects may get cleaned
|
25
|
+
# up in unexpected ways while interrupts are firing.
|
26
|
+
def register(method_or_block = nil, &block)
|
27
|
+
if method_or_block.nil? && !block_given?
|
28
|
+
raise ArgumentError.new("Expected either a method or a block for Geos.register_interrupt")
|
29
|
+
elsif !method_or_block.nil? && block_given?
|
30
|
+
raise ArgumentError.new("Cannot use both a method and a block for Geos.register_interrupt")
|
31
|
+
else
|
32
|
+
retval = @current_interrupt_callback
|
33
|
+
|
34
|
+
@current_interrupt_callback = if method_or_block
|
35
|
+
FFIGeos.GEOS_interruptRegisterCallback(method_or_block)
|
36
|
+
method_or_block
|
37
|
+
elsif block_given?
|
38
|
+
FFIGeos.GEOS_interruptRegisterCallback(&block)
|
39
|
+
block
|
40
|
+
end
|
41
|
+
|
42
|
+
retval
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Interrupt the current operation. This method should generally be
|
47
|
+
# called from within a callback registered with Geos.register_interrupt
|
48
|
+
# but can be called at any time to interrupt the next interruptable
|
49
|
+
# operation.
|
50
|
+
def request
|
51
|
+
FFIGeos.GEOS_interruptRequest
|
52
|
+
end
|
53
|
+
|
54
|
+
# Cancel a request to interrupt the current operation. This method
|
55
|
+
# should be called from within a callback registered with
|
56
|
+
# Geos.register_interrupt but can be called at any time all the same.
|
57
|
+
def cancel
|
58
|
+
FFIGeos.GEOS_interruptCancel
|
59
|
+
end
|
60
|
+
|
61
|
+
def clear
|
62
|
+
FFIGeos.GEOS_interruptRegisterCallback(nil)
|
63
|
+
@current_interrupt_callback = nil
|
64
|
+
end
|
65
|
+
else
|
66
|
+
def available?
|
67
|
+
false
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
data/lib/ffi-geos/version.rb
CHANGED
data/lib/ffi-geos/wkb_writer.rb
CHANGED
@@ -24,13 +24,6 @@ module Geos
|
|
24
24
|
FFIGeos.GEOSWKBWriter_destroy_r(Geos.current_handle, ptr)
|
25
25
|
end
|
26
26
|
|
27
|
-
def set_options(options = {}) #:nodoc:
|
28
|
-
[ :include_srid ].each do |k|
|
29
|
-
self.send("#{k}=", options[k]) if options.has_key?(k)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
private :set_options
|
33
|
-
|
34
27
|
# Options can be set temporarily for individual writes using an options
|
35
28
|
# Hash. The only option currently available is :include_srid.
|
36
29
|
def write(geom, options = nil)
|
@@ -92,5 +85,12 @@ module Geos
|
|
92
85
|
check_enum_value(Geos::ByteOrders, val)
|
93
86
|
FFIGeos.GEOSWKBWriter_setByteOrder_r(Geos.current_handle, self.ptr, val)
|
94
87
|
end
|
88
|
+
|
89
|
+
private
|
90
|
+
def set_options(options) #:nodoc:
|
91
|
+
[ :include_srid ].each do |k|
|
92
|
+
self.send("#{k}=", options[k]) if options.has_key?(k)
|
93
|
+
end
|
94
|
+
end
|
95
95
|
end
|
96
96
|
end
|
data/test/geometry_tests.rb
CHANGED
@@ -481,6 +481,16 @@ class GeometryTests < MiniTest::Unit::TestCase
|
|
481
481
|
)
|
482
482
|
end
|
483
483
|
|
484
|
+
def test_node
|
485
|
+
skip unless ENV['FORCE_TESTS'] || Geos::Geometry.method_defined?(:node)
|
486
|
+
|
487
|
+
self_tester(
|
488
|
+
:node,
|
489
|
+
'LINESTRING(0 0, 10 0, 5 -5, 5 5)',
|
490
|
+
'MULTILINESTRING ((0 0, 5 0), (5 0, 10 0, 5 -5, 5 0), (5 0, 5 5))'
|
491
|
+
)
|
492
|
+
end
|
493
|
+
|
484
494
|
def test_union_without_arguments
|
485
495
|
self_tester(
|
486
496
|
:union,
|
@@ -1299,6 +1309,35 @@ class GeometryTests < MiniTest::Unit::TestCase
|
|
1299
1309
|
tester[9.0, geom_a, 'LINESTRING (3 0 , 10 0)']
|
1300
1310
|
end
|
1301
1311
|
|
1312
|
+
def test_nearest_points
|
1313
|
+
skip unless ENV['FORCE_TESTS'] || Geos::Geometry.method_defined?(:nearest_points)
|
1314
|
+
|
1315
|
+
tester = lambda { |expected, g1, g2|
|
1316
|
+
geom_1 = read(g1)
|
1317
|
+
geom_2 = read(g2)
|
1318
|
+
|
1319
|
+
cs = geom_1.nearest_points(geom_2)
|
1320
|
+
|
1321
|
+
result = if cs
|
1322
|
+
cs.to_s
|
1323
|
+
end
|
1324
|
+
|
1325
|
+
assert_equal(expected, result)
|
1326
|
+
}
|
1327
|
+
|
1328
|
+
tester[
|
1329
|
+
nil,
|
1330
|
+
'POINT EMPTY',
|
1331
|
+
'POINT EMPTY'
|
1332
|
+
]
|
1333
|
+
|
1334
|
+
tester[
|
1335
|
+
'5.0 5.0 NaN, 8.0 8.0 NaN',
|
1336
|
+
'POLYGON((1 1, 1 5, 5 5, 5 1, 1 1))',
|
1337
|
+
'POLYGON((8 8, 9 9, 9 10, 8 8))'
|
1338
|
+
]
|
1339
|
+
end
|
1340
|
+
|
1302
1341
|
def test_snap
|
1303
1342
|
skip unless ENV['FORCE_TESTS'] || Geos::Geometry.method_defined?(:snap)
|
1304
1343
|
|
@@ -1642,4 +1681,52 @@ class GeometryTests < MiniTest::Unit::TestCase
|
|
1642
1681
|
def test_to_s
|
1643
1682
|
assert_match(/^\#<Geos::Point: .+>$/, read('POINT(0 0)').to_s)
|
1644
1683
|
end
|
1684
|
+
|
1685
|
+
def test_delaunay_triangulation
|
1686
|
+
skip unless ENV['FORCE_TESTS'] || Geos::Geometry.method_defined?(:delaunay_triangulation)
|
1687
|
+
|
1688
|
+
tester = lambda { |expected, geom, *args|
|
1689
|
+
geom = read(geom)
|
1690
|
+
geom_tri = geom.delaunay_triangulation(*args)
|
1691
|
+
geom_tri.normalize!
|
1692
|
+
|
1693
|
+
assert_equal(expected, write(geom_tri))
|
1694
|
+
}
|
1695
|
+
|
1696
|
+
writer.trim = true
|
1697
|
+
|
1698
|
+
# empty polygon
|
1699
|
+
tester['GEOMETRYCOLLECTION EMPTY', 'POLYGON EMPTY', 0]
|
1700
|
+
tester['MULTILINESTRING EMPTY', 'POLYGON EMPTY', 0, { :only_edges => true }]
|
1701
|
+
|
1702
|
+
# single point
|
1703
|
+
tester['GEOMETRYCOLLECTION EMPTY', 'POINT (0 0)', 0]
|
1704
|
+
tester['MULTILINESTRING EMPTY', 'POINT (0 0)', 0, { :only_edges => true }]
|
1705
|
+
|
1706
|
+
# three collinear points
|
1707
|
+
tester['GEOMETRYCOLLECTION EMPTY', 'MULTIPOINT(0 0, 5 0, 10 0)', 0]
|
1708
|
+
tester['MULTILINESTRING ((5 0, 10 0), (0 0, 5 0))', 'MULTIPOINT(0 0, 5 0, 10 0)', 0, { :only_edges => true }]
|
1709
|
+
|
1710
|
+
# three points
|
1711
|
+
tester['GEOMETRYCOLLECTION (POLYGON ((0 0, 10 10, 5 0, 0 0)))', 'MULTIPOINT(0 0, 5 0, 10 10)', 0]
|
1712
|
+
tester['MULTILINESTRING ((5 0, 10 10), (0 0, 10 10), (0 0, 5 0))', 'MULTIPOINT(0 0, 5 0, 10 10)', 0, { :only_edges => true }]
|
1713
|
+
|
1714
|
+
# polygon with a hole
|
1715
|
+
tester[
|
1716
|
+
'GEOMETRYCOLLECTION (POLYGON ((8 2, 10 10, 8.5 1, 8 2)), POLYGON ((7 8, 10 10, 8 2, 7 8)), POLYGON ((3 8, 10 10, 7 8, 3 8)), POLYGON ((2 2, 8 2, 8.5 1, 2 2)), POLYGON ((2 2, 7 8, 8 2, 2 2)), POLYGON ((2 2, 3 8, 7 8, 2 2)), POLYGON ((0.5 9, 10 10, 3 8, 0.5 9)), POLYGON ((0.5 9, 3 8, 2 2, 0.5 9)), POLYGON ((0 0, 2 2, 8.5 1, 0 0)), POLYGON ((0 0, 0.5 9, 2 2, 0 0)))',
|
1717
|
+
'POLYGON((0 0, 8.5 1, 10 10, 0.5 9, 0 0),(2 2, 3 8, 7 8, 8 2, 2 2)))',
|
1718
|
+
0
|
1719
|
+
]
|
1720
|
+
|
1721
|
+
tester[
|
1722
|
+
'MULTILINESTRING ((8.5 1, 10 10), (8 2, 10 10), (8 2, 8.5 1), (7 8, 10 10), (7 8, 8 2), (3 8, 10 10), (3 8, 7 8), (2 2, 8.5 1), (2 2, 8 2), (2 2, 7 8), (2 2, 3 8), (0.5 9, 10 10), (0.5 9, 3 8), (0.5 9, 2 2), (0 0, 8.5 1), (0 0, 2 2), (0 0, 0.5 9))',
|
1723
|
+
'POLYGON((0 0, 8.5 1, 10 10, 0.5 9, 0 0),(2 2, 3 8, 7 8, 8 2, 2 2)))',
|
1724
|
+
0, {
|
1725
|
+
:only_edges => true
|
1726
|
+
}
|
1727
|
+
]
|
1728
|
+
|
1729
|
+
# four points with a tolerance making one collapse
|
1730
|
+
tester['MULTILINESTRING ((10 0, 10 10), (0 0, 10 10), (0 0, 10 0))', 'MULTIPOINT(0 0, 10 0, 10 10, 11 10)', 2.0, { :only_edges => true }]
|
1731
|
+
end
|
1645
1732
|
end
|
@@ -0,0 +1,192 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
$: << File.dirname(__FILE__)
|
4
|
+
require 'test_helper'
|
5
|
+
|
6
|
+
class InterruptTests < MiniTest::Unit::TestCase
|
7
|
+
include TestHelper
|
8
|
+
|
9
|
+
def interrupt_method
|
10
|
+
interrupt_called
|
11
|
+
Geos::Interrupt.request
|
12
|
+
end
|
13
|
+
|
14
|
+
def interrupt_tester
|
15
|
+
yield
|
16
|
+
ensure
|
17
|
+
Geos::Interrupt.clear
|
18
|
+
end
|
19
|
+
|
20
|
+
def interrupt_called
|
21
|
+
@interrupt_calls += 1
|
22
|
+
end
|
23
|
+
|
24
|
+
def setup
|
25
|
+
super
|
26
|
+
@interrupt_calls = 0
|
27
|
+
end
|
28
|
+
|
29
|
+
def assert_interrupt_called(times = 0)
|
30
|
+
assert(@interrupt_calls > times, "Expected @interrupt_calls to be > #{times}")
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_interrupt_with_method
|
34
|
+
skip unless ENV['FORCE_TESTS'] || Geos::Interrupt.available?
|
35
|
+
|
36
|
+
interrupt_tester do
|
37
|
+
geom = read('LINESTRING(0 0, 1 0)')
|
38
|
+
|
39
|
+
Geos::Interrupt.register(self.method(:interrupt_method))
|
40
|
+
|
41
|
+
begin
|
42
|
+
buffer = geom.buffer(1, 8)
|
43
|
+
rescue => e
|
44
|
+
assert_match(/^InterruptedException/, e.message)
|
45
|
+
assert_nil(buffer)
|
46
|
+
assert_interrupt_called
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_interrupt_with_block
|
52
|
+
skip unless ENV['FORCE_TESTS'] || Geos::Interrupt.available?
|
53
|
+
|
54
|
+
interrupt_tester do
|
55
|
+
geom = read('LINESTRING(0 0, 1 0)')
|
56
|
+
|
57
|
+
Geos::Interrupt.register do
|
58
|
+
interrupt_called
|
59
|
+
Geos::Interrupt.request
|
60
|
+
end
|
61
|
+
|
62
|
+
begin
|
63
|
+
buffer = geom.buffer(1, 8)
|
64
|
+
rescue => e
|
65
|
+
assert_match(/^InterruptedException/, e.message)
|
66
|
+
assert_nil(buffer)
|
67
|
+
assert_interrupt_called
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_interrupt_with_proc
|
73
|
+
skip unless ENV['FORCE_TESTS'] || Geos::Interrupt.available?
|
74
|
+
|
75
|
+
interrupt_tester do
|
76
|
+
geom = read('LINESTRING(0 0, 1 0)')
|
77
|
+
|
78
|
+
prc = proc {
|
79
|
+
interrupt_called
|
80
|
+
Geos::Interrupt.request
|
81
|
+
}
|
82
|
+
|
83
|
+
Geos::Interrupt.register(prc)
|
84
|
+
|
85
|
+
begin
|
86
|
+
buffer = geom.buffer(1, 8)
|
87
|
+
rescue => e
|
88
|
+
assert_match(/^InterruptedException/, e.message)
|
89
|
+
assert_nil(buffer)
|
90
|
+
assert_interrupt_called
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_chain_interrupts
|
96
|
+
skip unless ENV['FORCE_TESTS'] || Geos::Interrupt.available?
|
97
|
+
|
98
|
+
interrupt_tester do
|
99
|
+
geom = read('LINESTRING(0 0, 1 0)')
|
100
|
+
prev = nil
|
101
|
+
called = []
|
102
|
+
|
103
|
+
prc_0 = proc {
|
104
|
+
interrupt_called
|
105
|
+
called << :prc_0
|
106
|
+
Geos::Interrupt.request
|
107
|
+
}
|
108
|
+
|
109
|
+
prc_1 = proc {
|
110
|
+
interrupt_called
|
111
|
+
called << :prc_1
|
112
|
+
prev.call if prev
|
113
|
+
}
|
114
|
+
|
115
|
+
Geos::Interrupt.register(prc_0)
|
116
|
+
prev = Geos::Interrupt.register(prc_1)
|
117
|
+
|
118
|
+
begin
|
119
|
+
buffer = geom.buffer(1, 8)
|
120
|
+
rescue => e
|
121
|
+
assert_match(/^InterruptedException/, e.message)
|
122
|
+
assert_nil(buffer)
|
123
|
+
assert_interrupt_called(1)
|
124
|
+
assert_equal([ :prc_1, :prc_0 ], called)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def test_cancel_interrupt
|
130
|
+
skip unless ENV['FORCE_TESTS'] || Geos::Interrupt.available?
|
131
|
+
|
132
|
+
interrupt_tester do
|
133
|
+
geom = read('LINESTRING(0 0, 1 0)')
|
134
|
+
|
135
|
+
Geos::Interrupt.register do
|
136
|
+
Geos::Interrupt.request
|
137
|
+
interrupt_called
|
138
|
+
Geos::Interrupt.cancel
|
139
|
+
end
|
140
|
+
|
141
|
+
buffer = geom.buffer(1, 8)
|
142
|
+
|
143
|
+
assert_kind_of(Geos::Polygon, buffer)
|
144
|
+
assert_interrupt_called(1)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def test_request_interrupt_without_a_callback
|
149
|
+
skip unless ENV['FORCE_TESTS'] || Geos::Interrupt.available?
|
150
|
+
|
151
|
+
geom = read('LINESTRING(0 0, 1 0)')
|
152
|
+
Geos::Interrupt.request
|
153
|
+
|
154
|
+
begin
|
155
|
+
buffer = geom.buffer(1, 8)
|
156
|
+
rescue => e
|
157
|
+
assert_match(/^InterruptedException/, e.message)
|
158
|
+
assert_nil(buffer)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def test_cancel_interrupt_without_a_callback
|
163
|
+
skip unless ENV['FORCE_TESTS'] || Geos::Interrupt.available?
|
164
|
+
|
165
|
+
geom = read('LINESTRING(0 0, 1 0)')
|
166
|
+
Geos::Interrupt.request
|
167
|
+
Geos::Interrupt.cancel
|
168
|
+
|
169
|
+
buffer = geom.buffer(1, 8)
|
170
|
+
|
171
|
+
assert_kind_of(Geos::Polygon, buffer)
|
172
|
+
end
|
173
|
+
|
174
|
+
def test_interrupt_with_method_and_block
|
175
|
+
skip unless ENV['FORCE_TESTS'] || Geos::Interrupt.available?
|
176
|
+
|
177
|
+
assert_raises(ArgumentError) do
|
178
|
+
Geos::Interrupt.register(self.method(:interrupt_method)) do
|
179
|
+
# no-op
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
def test_interrupt_without_method_or_block
|
185
|
+
skip unless ENV['FORCE_TESTS'] || Geos::Interrupt.available?
|
186
|
+
|
187
|
+
assert_raises(ArgumentError) do
|
188
|
+
Geos::Interrupt.register
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
data/test/misc_tests.rb
CHANGED
@@ -85,6 +85,15 @@ class MiscTests < MiniTest::Unit::TestCase
|
|
85
85
|
assert_equal(collection_a[0], collection_b[0])
|
86
86
|
end
|
87
87
|
|
88
|
+
def test_segfault_on_coord_seq_parents
|
89
|
+
geom = read('LINESTRING(0 0, 1 0)')
|
90
|
+
cs = geom.envelope.exterior_ring.coord_seq
|
91
|
+
|
92
|
+
GC.start
|
93
|
+
|
94
|
+
assert_equal('0.0 0.0, 1.0 0.0, 1.0 0.0, 0.0 0.0, 0.0 0.0', cs.to_s)
|
95
|
+
end
|
96
|
+
|
88
97
|
def test_cant_clone_buffer_params
|
89
98
|
assert_raises(NoMethodError) do
|
90
99
|
Geos::BufferParams.new.clone
|
data/test/test_helper.rb
CHANGED
metadata
CHANGED
@@ -1,30 +1,27 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ffi-geos
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
version: 0.2.1
|
4
|
+
version: 0.3.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- J Smith
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date: 2013-08-
|
11
|
+
date: 2013-08-26 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: ffi
|
16
|
-
type: :runtime
|
17
15
|
requirement: !ruby/object:Gem::Requirement
|
18
|
-
none: false
|
19
16
|
requirements:
|
20
|
-
- -
|
17
|
+
- - '>='
|
21
18
|
- !ruby/object:Gem::Version
|
22
19
|
version: 1.0.0
|
20
|
+
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- -
|
24
|
+
- - '>='
|
28
25
|
- !ruby/object:Gem::Version
|
29
26
|
version: 1.0.0
|
30
27
|
description: An ffi wrapper for GEOS, a C++ port of the Java Topology Suite (JTS).
|
@@ -46,6 +43,7 @@ files:
|
|
46
43
|
- lib/ffi-geos/coordinate_sequence.rb
|
47
44
|
- lib/ffi-geos/geometry.rb
|
48
45
|
- lib/ffi-geos/geometry_collection.rb
|
46
|
+
- lib/ffi-geos/interrupt.rb
|
49
47
|
- lib/ffi-geos/line_string.rb
|
50
48
|
- lib/ffi-geos/linear_ring.rb
|
51
49
|
- lib/ffi-geos/multi_line_string.rb
|
@@ -65,6 +63,7 @@ files:
|
|
65
63
|
- test/coordinate_sequence_tests.rb
|
66
64
|
- test/geometry_collection_tests.rb
|
67
65
|
- test/geometry_tests.rb
|
66
|
+
- test/interrupt_tests.rb
|
68
67
|
- test/line_string_tests.rb
|
69
68
|
- test/linear_ring_tests.rb
|
70
69
|
- test/misc_tests.rb
|
@@ -81,32 +80,32 @@ files:
|
|
81
80
|
- test/wkt_writer_tests.rb
|
82
81
|
homepage: http://github.com/dark-panda/ffi-geos
|
83
82
|
licenses: []
|
83
|
+
metadata: {}
|
84
84
|
post_install_message:
|
85
85
|
rdoc_options: []
|
86
86
|
require_paths:
|
87
87
|
- lib
|
88
88
|
required_ruby_version: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
89
|
requirements:
|
91
|
-
- -
|
90
|
+
- - '>='
|
92
91
|
- !ruby/object:Gem::Version
|
93
92
|
version: '0'
|
94
93
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
95
|
-
none: false
|
96
94
|
requirements:
|
97
|
-
- -
|
95
|
+
- - '>='
|
98
96
|
- !ruby/object:Gem::Version
|
99
97
|
version: '0'
|
100
98
|
requirements: []
|
101
99
|
rubyforge_project:
|
102
|
-
rubygems_version:
|
100
|
+
rubygems_version: 2.0.3
|
103
101
|
signing_key:
|
104
|
-
specification_version:
|
102
|
+
specification_version: 4
|
105
103
|
summary: An ffi wrapper for GEOS, a C++ port of the Java Topology Suite (JTS).
|
106
104
|
test_files:
|
107
105
|
- test/coordinate_sequence_tests.rb
|
108
106
|
- test/geometry_collection_tests.rb
|
109
107
|
- test/geometry_tests.rb
|
108
|
+
- test/interrupt_tests.rb
|
110
109
|
- test/line_string_tests.rb
|
111
110
|
- test/linear_ring_tests.rb
|
112
111
|
- test/misc_tests.rb
|