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