ffi-geos 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -12,12 +12,11 @@ Ruby versions known to work:
12
12
  * Ruby MRI 1.8.7 and 1.9.2, x86_64, OSX 10.6.5+
13
13
  * Ruby MRI 1.8.7 and 1.9.2, i386, linux
14
14
  * Ruby MRI 1.8.7, x86_64, linux
15
+ * JRuby 1.6.3, x86_64 OSX 10.6.5+
15
16
 
16
- Note that versions of JRuby prior to the as-of-yet (25 June 2011) unreleased
17
- version 1.6.3 have problems in their ffi implementation when dealing with
18
- AutoPointers that can lead to segfaults during garbage collection. Upcoming
19
- versions of JRuby should have the problem licked. For details, check out
20
- http://jira.codehaus.org/browse/JRUBY-5813.
17
+ Note that versions of JRuby prior to version 1.6.3 have problems in their ffi
18
+ implementation when dealing with AutoPointers that can lead to segfaults during
19
+ garbage collection.
21
20
 
22
21
  == Features
23
22
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.1
1
+ 0.0.2
data/ffi-geos.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{ffi-geos}
8
- s.version = "0.0.1"
8
+ s.version = "0.0.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["J Smith"]
12
- s.date = %q{2011-06-25}
12
+ s.date = %q{2011-07-22}
13
13
  s.description = %q{An ffi wrapper for GEOS, a C++ port of the Java Topology Suite (JTS).}
14
14
  s.email = %q{dark.panda@gmail.com}
15
15
  s.extra_rdoc_files = [
@@ -56,7 +56,7 @@ Gem::Specification.new do |s|
56
56
  ]
57
57
  s.homepage = %q{http://github.com/dark-panda/ffi-geos}
58
58
  s.require_paths = ["lib"]
59
- s.rubygems_version = %q{1.7.2}
59
+ s.rubygems_version = %q{1.6.2}
60
60
  s.summary = %q{An ffi wrapper for GEOS, a C++ port of the Java Topology Suite (JTS).}
61
61
 
62
62
  if s.respond_to? :specification_version then
data/lib/ffi-geos.rb CHANGED
@@ -1026,10 +1026,10 @@ module Geos
1026
1026
  VERSION = File.read(File.join(GEOS_BASE, %w{ .. .. VERSION })).strip
1027
1027
  GEOS_JTS_PORT = Geos.jts_port
1028
1028
  GEOS_VERSION,
1029
- GEOS_VERSION_MAJOR, GEOS_VERSION_MINOR, GEOS_VERISON_PATCH, GEOS_VERSION_PRERELEASE,
1029
+ GEOS_VERSION_MAJOR, GEOS_VERSION_MINOR, GEOS_VERSION_PATCH, GEOS_VERSION_PRERELEASE,
1030
1030
  GEOS_CAPI_VERSION,
1031
1031
  GEOS_CAPI_VERSION_MAJOR, GEOS_CAPI_VERSION_MINOR, GEOS_CAPI_VERSION_PATCH =
1032
- if !(versions = Geos.version.scan(/^((\d+)\.(\d+)\.(\d+)((?:rc|beta|alpha)\d+)?)-CAPI-((\d+)\.(\d+)\.(\d+))$/)).empty?
1032
+ if !(versions = Geos.version.scan(/^((\d+)\.(\d+)\.(\d+)((?:dev|rc|beta|alpha)\d*)?)-CAPI-((\d+)\.(\d+)\.(\d+))$/)).empty?
1033
1033
  versions = versions[0]
1034
1034
  [
1035
1035
  versions[0],
@@ -3,23 +3,53 @@ module Geos
3
3
 
4
4
  # A CoordinateSequence is a list of coordinates in a Geometry.
5
5
  class CoordinateSequence
6
+ class ParseError < ArgumentError
7
+ end
8
+
6
9
  include Enumerable
7
10
 
8
11
  attr_reader :ptr
9
12
 
10
13
  # :call-seq:
11
14
  # new(ptr, auto_free = true)
12
- # new(size, dims = 0)
15
+ # new(size = 0, dims = 0)
16
+ # new(points)
13
17
  #
14
18
  # The ptr version of the initializer is for internal use.
19
+ #
20
+ # new(points) will try to glean the size and dimensions of your
21
+ # CoordinateSequence from an Array of points. The Array should contain
22
+ # uniform-sized Arrays which represent the [ x, y, z ] values of your
23
+ # coordinates.
15
24
  def initialize(*args)
25
+ points = nil # forward declaration we can use later
26
+
16
27
  ptr, auto_free = if args.first.is_a?(FFI::Pointer)
17
28
  [ args.first, args[1] ]
18
29
  else
19
- size, dims = if !args.length.between?(1, 2)
20
- raise ArgumentError.new("wrong number of arguments (#{args.length} for 1-2)")
30
+ size, dims = if args.first.is_a?(Array)
31
+ points = if args.first.first.is_a?(Array)
32
+ args.first
33
+ else
34
+ args
35
+ end
36
+ lengths = points.collect(&:length).uniq
37
+
38
+ if lengths.empty?
39
+ [ 0, 0 ]
40
+ elsif lengths.length != 1
41
+ raise ParseError.new("Different sized points found in Array")
42
+ elsif !lengths.first.between?(1, 3)
43
+ raise ParseError.new("Expected points to contain 1-3 elements")
44
+ else
45
+ [ points.length, points.first.length ]
46
+ end
21
47
  else
22
- [ args[0], args[1] || 0]
48
+ if !args.length.between?(0, 2)
49
+ raise ArgumentError.new("wrong number of arguments (#{args.length} for 0-2)")
50
+ else
51
+ [ args[0] || 0, args[1] || 0 ]
52
+ end
23
53
  end
24
54
 
25
55
  [ FFIGeos.GEOSCoordSeq_create_r(Geos.current_handle, size, dims), true ]
@@ -33,6 +63,14 @@ module Geos
33
63
  if !auto_free
34
64
  @ptr.autorelease = false
35
65
  end
66
+
67
+ if points
68
+ points.each_with_index do |point, idx|
69
+ point.each_with_index do |val, dim|
70
+ self.set_ordinate(idx, dim, val)
71
+ end
72
+ end
73
+ end
36
74
  end
37
75
 
38
76
  def initialize_copy(source)
@@ -122,6 +160,18 @@ module Geos
122
160
  }.read_int
123
161
  end
124
162
 
163
+ def to_linear_ring
164
+ Geos.create_linear_ring(self)
165
+ end
166
+
167
+ def to_line_string
168
+ Geos.create_line_string(self)
169
+ end
170
+
171
+ def to_polygon
172
+ Geos.create_polygon(self)
173
+ end
174
+
125
175
  protected
126
176
 
127
177
  def check_bounds(idx) #:nodoc:
@@ -5,10 +5,16 @@ module Geos
5
5
 
6
6
  # Yields each Geometry in the GeometryCollection.
7
7
  def each
8
- self.num_geometries.times do |n|
9
- yield self.get_geometry_n(n)
8
+ if block_given?
9
+ self.num_geometries.times do |n|
10
+ yield self.get_geometry_n(n)
11
+ end
12
+ self
13
+ else
14
+ self.num_geometries.times.collect { |n|
15
+ self.get_geometry_n(n)
16
+ }.to_enum
10
17
  end
11
- nil
12
18
  end
13
19
 
14
20
  def get_geometry_n(n)
@@ -4,10 +4,16 @@ module Geos
4
4
  include Enumerable
5
5
 
6
6
  def each
7
- self.num_points.times do |n|
8
- yield self.point_n(n)
7
+ if block_given?
8
+ self.num_points.times do |n|
9
+ yield self.point_n(n)
10
+ end
11
+ self
12
+ else
13
+ self.num_points.times.collect { |n|
14
+ self.point_n(n)
15
+ }.to_enum
9
16
  end
10
- nil
11
17
  end
12
18
 
13
19
  if FFIGeos.respond_to?(:GEOSGeomGetNumPoints_r)
@@ -8,7 +8,33 @@ module Geos
8
8
 
9
9
  undef :clone, :dup
10
10
 
11
- def initialize(capacity)
11
+ # :call-seq:
12
+ # new(capacity)
13
+ # new(geoms_and_objects)
14
+ #
15
+ def initialize(*args)
16
+ geoms_and_objects = nil # forward declaration
17
+
18
+ capacity = if args.length == 1 && args.first.is_a?(Fixnum)
19
+ args.first
20
+ else
21
+ geoms_and_objects = if args.first.first.is_a?(Array)
22
+ args.first
23
+ else
24
+ args
25
+ end
26
+
27
+ geoms_and_objects.each do |geom, obj|
28
+ check_geometry(geom)
29
+ end
30
+
31
+ geoms_and_objects.length
32
+ end
33
+
34
+ if capacity <= 0
35
+ raise ArgumentError.new("STRtree capacity must be greater than 0")
36
+ end
37
+
12
38
  ptr = FFIGeos.GEOSSTRtree_create_r(Geos.current_handle, capacity)
13
39
 
14
40
  @ptr = FFI::AutoPointer.new(
@@ -17,9 +43,16 @@ module Geos
17
43
  )
18
44
 
19
45
  @storage = {}
20
- @storage_pointers = {}
46
+ @ptrs = {}
47
+
21
48
  @storage_key = 0
22
49
  @built = false
50
+
51
+ if geoms_and_objects
52
+ geoms_and_objects.each do |geom, obj|
53
+ self.insert(geom, obj)
54
+ end
55
+ end
23
56
  end
24
57
 
25
58
  def self.release(ptr) #:nodoc:
@@ -36,17 +69,21 @@ module Geos
36
69
  private :next_key
37
70
 
38
71
  def insert(geom, item)
39
- check_geometry(geom)
40
-
41
72
  if self.built?
42
73
  raise RuntimeError.new("STRtree has already been built")
43
74
  else
75
+ check_geometry(geom)
76
+
44
77
  key = next_key
45
78
  key_ptr = FFI::MemoryPointer.new(:pointer)
46
79
  key_ptr.write_int(key)
47
80
 
48
- @storage[key] = item
49
- @storage_pointers[key] = key_ptr
81
+ @storage[key] = {
82
+ :item => item,
83
+ :geometry => geom
84
+ }
85
+ @ptrs[key] = key_ptr
86
+
50
87
  FFIGeos.GEOSSTRtree_insert_r(Geos.current_handle, self.ptr, geom.ptr, key_ptr)
51
88
  end
52
89
  end
@@ -54,41 +91,36 @@ module Geos
54
91
  def remove(geom, item)
55
92
  check_geometry(geom)
56
93
 
57
- key = if @storage.respond_to?(:key)
58
- @storage.key(item)
59
- else
60
- @storage.index(item)
94
+ key = if storage = @storage.detect { |k, v| v[:item] == item }
95
+ storage[0]
61
96
  end
62
97
 
63
98
  if key
64
- key_ptr = @storage_pointers[key]
99
+ key_ptr = @ptrs[key]
65
100
  result = FFIGeos.GEOSSTRtree_remove_r(Geos.current_handle, self.ptr, geom.ptr, key_ptr)
66
101
  @built = true
67
102
 
68
103
  if result == 1
69
- @storage[key] = nil
70
- @storage_pointers[key] = nil
104
+ @storage.delete(key)
71
105
  end
72
106
  end
73
107
  end
74
108
 
75
- def query(geom)
109
+ def query_all(geom)
76
110
  check_geometry(geom)
77
111
 
78
112
  @built = true
79
- retval = nil
113
+ retval = []
80
114
 
81
- callback = if block_given?
82
- proc { |*args|
83
- key = args.first.read_int
84
- yield(@storage[key])
85
- }
86
- else
87
- retval = []
88
- proc { |*args|
89
- retval << @storage[args.first.read_int]
90
- }
91
- end
115
+ callback = proc { |*args|
116
+ key = args.first.read_int
117
+ storage = @storage[key]
118
+ retval << storage
119
+
120
+ if block_given?
121
+ yield(storage)
122
+ end
123
+ }
92
124
 
93
125
  FFIGeos.GEOSSTRtree_query_r(
94
126
  Geos.current_handle,
@@ -98,12 +130,42 @@ module Geos
98
130
  nil
99
131
  )
100
132
 
101
- if retval
102
- retval.compact
103
- end
104
133
  retval
105
134
  end
106
135
 
136
+ def query(geom, ret = :item)
137
+ self.query_all(geom).collect { |storage|
138
+ item = if ret.is_a?(Array)
139
+ storage.inject({}) do |memo, k|
140
+ memo.tap {
141
+ memo[k] = storage[k]
142
+ }
143
+ end
144
+ elsif ret == :all
145
+ storage
146
+ else
147
+ storage[ret]
148
+ end
149
+
150
+ item.tap {
151
+ if block_given?
152
+ yield(item)
153
+ end
154
+ }
155
+ }.compact
156
+ end
157
+
158
+ def query_geometries(geom)
159
+ self.query_all(geom).collect { |storage|
160
+ storage[:geometry].tap { |val|
161
+ if block_given?
162
+ yield(val)
163
+ end
164
+ }
165
+ }.compact
166
+ end
167
+ alias :query_geoms :query_geometries
168
+
107
169
  def iterate
108
170
  @storage.values.each do |v|
109
171
  yield(v)
@@ -63,16 +63,15 @@ module Geos
63
63
  end
64
64
 
65
65
  def create_polygon(outer, *inner)
66
- inner = Array(inner).flatten.tap { |i|
67
- if i.detect { |g| !g.is_a?(Geos::LinearRing) }
68
- raise TypeError.new("Expected inner Array to contain Geometry::LinearRing objects")
69
- end
66
+ inner_clones = Array(inner).flatten.collect { |i|
67
+ force_to_linear_ring(i) or
68
+ raise TypeError.new("Expected inner Array to contain Geos::LinearRing or Geos::CoordinateSequence objects")
70
69
  }
71
70
 
72
- outer_clone = outer.clone
73
- inner_clones = inner.map(&:clone)
71
+ outer_clone = force_to_linear_ring(outer) or
72
+ raise TypeError.new("Expected outer shell to be a Geos::LinearRing or Geos::CoordinateSequence")
74
73
 
75
- ary = FFI::MemoryPointer.new(:pointer, inner.length)
74
+ ary = FFI::MemoryPointer.new(:pointer, inner_clones.length)
76
75
  ary.write_array_of_pointer(inner_clones.map(&:ptr))
77
76
 
78
77
  cast_geometry_ptr(FFIGeos.GEOSGeom_createPolygon_r(Geos.current_handle, outer_clone.ptr, ary, inner_clones.length)).tap {
@@ -161,6 +160,16 @@ module Geos
161
160
  def create_geometry_collection(*geoms)
162
161
  create_collection(:geometry_collection, *geoms)
163
162
  end
163
+
164
+ private
165
+ def force_to_linear_ring(geom)
166
+ case geom
167
+ when Geos::CoordinateSequence
168
+ geom.to_linear_ring
169
+ when Geos::LinearRing
170
+ geom.clone
171
+ end
172
+ end
164
173
  end
165
174
  end
166
175
  end
@@ -7,21 +7,22 @@ class CoordinateSequenceTests < Test::Unit::TestCase
7
7
 
8
8
  def setup
9
9
  @cs = Geos::CoordinateSequence.new(3, 0)
10
+ super
10
11
  end
11
12
 
12
13
  def test_set_and_get_x
13
14
  @cs.set_x(0, 10.01)
14
- assert_in_delta(10.01, @cs.get_x(0), 0.0000001)
15
+ assert_in_delta(10.01, @cs.get_x(0), TOLERANCE)
15
16
  end
16
17
 
17
18
  def test_set_and_get_y
18
19
  @cs.set_y(0, 20.02)
19
- assert_in_delta(20.02, @cs.get_y(0), 0.0000001)
20
+ assert_in_delta(20.02, @cs.get_y(0), TOLERANCE)
20
21
  end
21
22
 
22
23
  def test_set_and_get_z
23
24
  @cs.set_z(0, 20.02)
24
- assert_in_delta(20.02, @cs.get_z(0), 0.0000001)
25
+ assert_in_delta(20.02, @cs.get_z(0), TOLERANCE)
25
26
  end
26
27
 
27
28
  def test_set_and_get_ordinate
@@ -29,9 +30,9 @@ class CoordinateSequenceTests < Test::Unit::TestCase
29
30
  @cs.set_ordinate(0, 1, 20.02)
30
31
  @cs.set_ordinate(0, 2, 30.03)
31
32
 
32
- assert_in_delta(10.01, @cs.get_ordinate(0, 0), 0.0000001)
33
- assert_in_delta(20.02, @cs.get_ordinate(0, 1), 0.0000001)
34
- assert_in_delta(30.03, @cs.get_ordinate(0, 2), 0.0000001)
33
+ assert_in_delta(10.01, @cs.get_ordinate(0, 0), TOLERANCE)
34
+ assert_in_delta(20.02, @cs.get_ordinate(0, 1), TOLERANCE)
35
+ assert_in_delta(30.03, @cs.get_ordinate(0, 2), TOLERANCE)
35
36
  end
36
37
 
37
38
  def test_length
@@ -89,4 +90,89 @@ class CoordinateSequenceTests < Test::Unit::TestCase
89
90
  assert_equal(@cs.get_y(0), cs_b.get_y(0))
90
91
  assert_equal(@cs.dimensions, cs_b.dimensions)
91
92
  end
93
+
94
+ def test_with_no_arguments
95
+ cs = Geos::CoordinateSequence.new
96
+ assert_equal(0, cs.size)
97
+ assert_equal(3, cs.dimensions)
98
+ end
99
+
100
+ def test_read_from_array
101
+ cs = Geos::CoordinateSequence.new([
102
+ [ 0, 0 ],
103
+ [ 1, 1 ],
104
+ [ 2, 2 ],
105
+ [ 3, 3 ],
106
+ [ 4, 4 ]
107
+ ])
108
+
109
+ assert_equal(2, cs.dimensions)
110
+ assert_equal(5, cs.length)
111
+
112
+ assert_raise(Geos::CoordinateSequence::ParseError) do
113
+ cs = Geos::CoordinateSequence.new([
114
+ [ 1, 2 ],
115
+ [ 1, 2, 3 ]
116
+ ])
117
+ end
118
+
119
+ assert_raise(Geos::CoordinateSequence::ParseError) do
120
+ cs = Geos::CoordinateSequence.new([
121
+ [ 1, 2, 3, 4 ]
122
+ ])
123
+ end
124
+ end
125
+
126
+ def test_to_to_linear_ring
127
+ cs = Geos::CoordinateSequence.new([
128
+ [ 0, 0 ],
129
+ [ 0, 5 ],
130
+ [ 5, 5 ],
131
+ [ 5, 0 ],
132
+ [ 0, 0 ]
133
+ ])
134
+
135
+ assert_equal('LINEARRING (0 0, 0 5, 5 5, 5 0, 0 0)', write(cs.to_linear_ring, :trim => true))
136
+ end
137
+
138
+ def test_to_empty_linear_ring
139
+ cs = Geos::CoordinateSequence.new
140
+
141
+ assert_equal('LINEARRING EMPTY', write(cs.to_linear_ring, :trim => true))
142
+ end
143
+
144
+ def test_to_line_string
145
+ cs = Geos::CoordinateSequence.new([
146
+ [ 0, 0 ],
147
+ [ 0, 5 ],
148
+ [ 5, 5 ],
149
+ [ 5, 0 ]
150
+ ])
151
+
152
+ assert_equal('LINESTRING (0 0, 0 5, 5 5, 5 0)', write(cs.to_line_string, :trim => true))
153
+ end
154
+
155
+ def test_to_empty_line_string
156
+ cs = Geos::CoordinateSequence.new
157
+
158
+ assert_equal('LINESTRING EMPTY', write(cs.to_line_string, :trim => true))
159
+ end
160
+
161
+ def test_to_polygon
162
+ cs = Geos::CoordinateSequence.new([
163
+ [ 0, 0 ],
164
+ [ 0, 5 ],
165
+ [ 5, 5 ],
166
+ [ 5, 0 ],
167
+ [ 0, 0 ]
168
+ ])
169
+
170
+ assert_equal('POLYGON ((0 0, 0 5, 5 5, 5 0, 0 0))', write(cs.to_polygon, :trim => true))
171
+ end
172
+
173
+ def test_to_empty_polygon
174
+ cs = Geos::CoordinateSequence.new
175
+
176
+ assert_equal('POLYGON EMPTY', write(cs.to_polygon, :trim => true))
177
+ end
92
178
  end
@@ -1530,4 +1530,18 @@ class GeometryTests < Test::Unit::TestCase
1530
1530
 
1531
1531
  assert(geom_a.eql?(geom_b))
1532
1532
  end
1533
+
1534
+ def test_geometry_collection_enumerator
1535
+ geom = read('GEOMETRYCOLLECTION(POINT(0 0))')
1536
+ assert_kind_of(Enumerable, geom.each)
1537
+ assert_kind_of(Enumerable, geom.to_enum)
1538
+ assert_equal(geom, geom.each {})
1539
+ end
1540
+
1541
+ def test_line_string_enumerator
1542
+ geom = read('LINESTRING(0 0, 10 10))')
1543
+ assert_kind_of(Enumerable, geom.each)
1544
+ assert_kind_of(Enumerable, geom.to_enum)
1545
+ assert_equal(geom, geom.each {})
1546
+ end
1533
1547
  end
@@ -34,10 +34,106 @@ if defined?(Geos::STRtree)
34
34
  def test_query
35
35
  setup_tree
36
36
 
37
- assert_equal(1, @tree.query(read('LINESTRING(5 5, 6 6)')).length)
38
- assert_equal(0, @tree.query(read('LINESTRING(20 0, 30 10)')).length)
39
- assert_equal(2, @tree.query(read('LINESTRING(25 25, 26 26)')).length)
40
- assert_equal(3, @tree.query(read('LINESTRING(0 0, 100 100)')).length)
37
+ assert_equal([@item_1],
38
+ @tree.query(read('LINESTRING(5 5, 6 6)')))
39
+
40
+ assert_equal([],
41
+ @tree.query(read('LINESTRING(20 0, 30 10)')))
42
+
43
+ assert_equal([@item_2, @item_3],
44
+ @tree.query(read('LINESTRING(25 25, 26 26)')))
45
+
46
+ assert_equal([@item_1, @item_2, @item_3],
47
+ @tree.query(read('LINESTRING(0 0, 100 100)')))
48
+ end
49
+
50
+ def test_query_with_ret_keys
51
+ setup_tree
52
+
53
+ assert_equal([@item_1],
54
+ @tree.query(read('LINESTRING(5 5, 6 6)'), :item))
55
+
56
+ assert_equal([],
57
+ @tree.query(read('LINESTRING(20 0, 30 10)'), :item))
58
+
59
+ assert_equal([@item_2, @item_3],
60
+ @tree.query(read('LINESTRING(25 25, 26 26)'), :item))
61
+
62
+ assert_equal([@item_1, @item_2, @item_3],
63
+ @tree.query(read('LINESTRING(0 0, 100 100)'), :item))
64
+
65
+
66
+ assert_equal([@geom_1],
67
+ @tree.query(read('LINESTRING(5 5, 6 6)'), :geometry))
68
+
69
+ assert_equal([],
70
+ @tree.query(read('LINESTRING(20 0, 30 10)'), :geometry))
71
+
72
+ assert_equal([@geom_2, @geom_3],
73
+ @tree.query(read('LINESTRING(25 25, 26 26)'), :geometry))
74
+
75
+ assert_equal([@geom_1, @geom_2, @geom_3],
76
+ @tree.query(read('LINESTRING(0 0, 100 100)'), :geometry))
77
+
78
+
79
+ assert_equal(
80
+ [
81
+ { :item => @item_1, :geometry => @geom_1 }
82
+ ],
83
+ @tree.query(read('LINESTRING(5 5, 6 6)'), :all)
84
+ )
85
+
86
+ assert_equal([],
87
+ @tree.query(read('LINESTRING(20 0, 30 10)'), :all))
88
+
89
+ assert_equal(
90
+ [
91
+ { :item => @item_2, :geometry => @geom_2 },
92
+ { :item => @item_3, :geometry => @geom_3 }
93
+ ],
94
+ @tree.query(read('LINESTRING(25 25, 26 26)'), :all)
95
+ )
96
+
97
+ assert_equal(
98
+ [
99
+ { :item => @item_1, :geometry => @geom_1 },
100
+ { :item => @item_2, :geometry => @geom_2 },
101
+ { :item => @item_3, :geometry => @geom_3 }
102
+ ],
103
+ @tree.query(read('LINESTRING(0 0, 100 100)'), :all)
104
+ )
105
+ end
106
+
107
+ def test_query_all
108
+ setup_tree
109
+
110
+ assert_equal([@item_1],
111
+ @tree.query_all(read('LINESTRING(5 5, 6 6)')).collect { |v| v[:item] })
112
+
113
+ assert_equal([],
114
+ @tree.query_all(read('LINESTRING(20 0, 30 10)')))
115
+
116
+ assert_equal([@item_2, @item_3],
117
+ @tree.query_all(read('LINESTRING(25 25, 26 26)')).collect { |v| v[:item] })
118
+
119
+ assert_equal([@item_1, @item_2, @item_3],
120
+ @tree.query_all(read('LINESTRING(0 0, 100 100)')).collect { |v| v[:item] })
121
+ end
122
+
123
+ def test_query_geometries
124
+ setup_tree
125
+
126
+ assert_equal([@geom_1],
127
+ @tree.query_geometries(read('LINESTRING(5 5, 6 6)')))
128
+
129
+ assert_equal([],
130
+ @tree.query_geometries(read('LINESTRING(20 0, 30 10)')))
131
+
132
+ assert_equal([@geom_2, @geom_3],
133
+ @tree.query_geometries(read('LINESTRING(25 25, 26 26)')))
134
+
135
+ assert_equal([@geom_1, @geom_2, @geom_3],
136
+ @tree.query_geometries(read('LINESTRING(0 0, 100 100)')))
41
137
  end
42
138
 
43
139
  def test_remove
@@ -45,10 +141,17 @@ if defined?(Geos::STRtree)
45
141
 
46
142
  @tree.remove(read('POINT(5 5)'), @item_1)
47
143
 
48
- assert_equal(0, @tree.query(read('LINESTRING(5 5, 6 6)')).length)
49
- assert_equal(0, @tree.query(read('LINESTRING(20 0, 30 10)')).length)
50
- assert_equal(2, @tree.query(read('LINESTRING(25 25, 26 26)')).length)
51
- assert_equal(2, @tree.query(read('LINESTRING(0 0, 100 100)')).length)
144
+ assert_equal([],
145
+ @tree.query(read('LINESTRING(5 5, 6 6)')))
146
+
147
+ assert_equal([],
148
+ @tree.query(read('LINESTRING(20 0, 30 10)')))
149
+
150
+ assert_equal([@item_2, @item_3],
151
+ @tree.query(read('LINESTRING(25 25, 26 26)')))
152
+
153
+ assert_equal([@item_2, @item_3],
154
+ @tree.query(read('LINESTRING(0 0, 100 100)')))
52
155
  end
53
156
 
54
157
  def test_cant_clone
@@ -62,5 +165,37 @@ if defined?(Geos::STRtree)
62
165
  Geos::STRtree.new(3).dup
63
166
  end
64
167
  end
168
+
169
+ def test_setup_with_array
170
+ tree = Geos::STRtree.new(
171
+ [ read('LINESTRING(0 0, 10 10)'), item_1 = { :item_1 => :test } ],
172
+ [ read('LINESTRING(20 20, 30 30)'), item_2 = [ :test ] ],
173
+ [ read('LINESTRING(20 20, 30 30)'), item_3 = Object.new ]
174
+ )
175
+
176
+ assert_equal([item_1],
177
+ tree.query(read('LINESTRING(5 5, 6 6)')))
178
+
179
+ assert_equal([],
180
+ tree.query(read('LINESTRING(20 0, 30 10)')))
181
+
182
+ assert_equal([item_2, item_3],
183
+ tree.query(read('LINESTRING(25 25, 26 26)')))
184
+
185
+ assert_equal([item_1, item_2, item_3],
186
+ tree.query(read('LINESTRING(0 0, 100 100)')))
187
+ end
188
+
189
+ def test_capacity
190
+ assert_raise(ArgumentError) do
191
+ Geos::STRtree.new(0)
192
+ end
193
+ end
194
+
195
+ def test_geometries
196
+ assert_raise(TypeError) do
197
+ Geos::STRtree.new([])
198
+ end
199
+ end
65
200
  end
66
201
  end
data/test/utils_tests.rb CHANGED
@@ -131,66 +131,71 @@ class UtilsTests < Test::Unit::TestCase
131
131
  end
132
132
 
133
133
  def test_create_polygon
134
- cs = Geos::CoordinateSequence.new(5, 2)
135
- cs.set_x(0, 0)
136
- cs.set_y(0, 0)
137
-
138
- cs.set_x(1, 0)
139
- cs.set_y(1, 10)
134
+ cs = Geos::CoordinateSequence.new([
135
+ [ 0, 0 ],
136
+ [ 0, 10 ],
137
+ [ 10, 10 ],
138
+ [ 10, 0 ],
139
+ [ 0, 0 ]
140
+ ])
140
141
 
141
- cs.set_x(2, 10)
142
- cs.set_y(2, 10)
142
+ exterior_ring = Geos::create_linear_ring(cs)
143
143
 
144
- cs.set_x(3, 10)
145
- cs.set_y(3, 0)
144
+ geom = Geos::create_polygon(exterior_ring)
145
+ assert_instance_of(Geos::Polygon, geom)
146
+ assert_equal('Polygon', geom.geom_type)
147
+ assert_equal(Geos::GEOS_POLYGON, geom.type_id)
148
+ assert_equal('POLYGON ((0 0, 0 10, 10 10, 10 0, 0 0))', write(geom, :trim => true))
149
+ end
146
150
 
147
- cs.set_x(4, 0)
148
- cs.set_y(4, 0)
151
+ def test_create_polygon_with_coordinate_sequences
152
+ outer = Geos::CoordinateSequence.new(
153
+ [ 0, 0 ],
154
+ [ 0, 10 ],
155
+ [ 10, 10 ],
156
+ [ 10, 0 ],
157
+ [ 0, 0 ]
158
+ )
149
159
 
150
- exterior_ring = Geos::create_linear_ring(cs)
160
+ inner = Geos::CoordinateSequence.new(
161
+ [ 2, 2 ],
162
+ [ 2, 4 ],
163
+ [ 4, 4 ],
164
+ [ 4, 2 ],
165
+ [ 2, 2 ]
166
+ )
151
167
 
152
- geom = Geos::create_polygon(exterior_ring)
168
+ geom = Geos::create_polygon(outer, inner)
153
169
  assert_instance_of(Geos::Polygon, geom)
154
170
  assert_equal('Polygon', geom.geom_type)
155
171
  assert_equal(Geos::GEOS_POLYGON, geom.type_id)
156
- assert(read('POLYGON ((0 0, 0 10, 10 10, 10 0, 0 0))').eql_exact?(geom, TOLERANCE))
172
+ assert_equal('POLYGON ((0 0, 0 10, 10 10, 10 0, 0 0), (2 2, 2 4, 4 4, 4 2, 2 2))', write(geom, :trim => true))
157
173
  end
158
174
 
159
175
  def test_create_polygon_with_holes
160
- create_ring = lambda { |*points|
161
- Geos.create_linear_ring(
162
- Geos::CoordinateSequence.new(points.length, 2).tap { |cs|
163
- points.each_with_index do |(x, y), i|
164
- cs.set_x(i, x)
165
- cs.set_y(i, y)
166
- end
167
- }
168
- )
169
- }
170
-
171
- exterior_ring = create_ring[
176
+ exterior_ring = Geos::CoordinateSequence.new(
172
177
  [ 0, 0 ],
173
178
  [ 0, 10 ],
174
179
  [ 10, 10 ],
175
180
  [ 10, 0 ],
176
181
  [ 0, 0 ]
177
- ]
182
+ )
178
183
 
179
- hole_1 = create_ring[
184
+ hole_1 = Geos::CoordinateSequence.new(
180
185
  [ 2, 2 ],
181
186
  [ 2, 4 ],
182
187
  [ 4, 4 ],
183
188
  [ 4, 2 ],
184
189
  [ 2, 2 ]
185
- ]
190
+ )
186
191
 
187
- hole_2 = create_ring[
192
+ hole_2 = Geos::CoordinateSequence.new(
188
193
  [ 6, 6 ],
189
194
  [ 6, 8 ],
190
195
  [ 8, 8 ],
191
196
  [ 8, 6 ],
192
197
  [ 6, 6 ]
193
- ]
198
+ )
194
199
 
195
200
  geom = Geos::create_polygon(exterior_ring, [ hole_1, hole_2 ])
196
201
  assert_instance_of(Geos::Polygon, geom)
metadata CHANGED
@@ -1,32 +1,24 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: ffi-geos
3
- version: !ruby/object:Gem::Version
4
- hash: 29
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
5
  prerelease:
6
- segments:
7
- - 0
8
- - 0
9
- - 1
10
- version: 0.0.1
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - J Smith
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2011-06-25 00:00:00 Z
12
+ date: 2011-07-22 00:00:00.000000000 -04:00
13
+ default_executable:
19
14
  dependencies: []
20
-
21
15
  description: An ffi wrapper for GEOS, a C++ port of the Java Topology Suite (JTS).
22
16
  email: dark.panda@gmail.com
23
17
  executables: []
24
-
25
18
  extensions: []
26
-
27
- extra_rdoc_files:
19
+ extra_rdoc_files:
28
20
  - README.rdoc
29
- files:
21
+ files:
30
22
  - MIT-LICENSE
31
23
  - README.rdoc
32
24
  - Rakefile
@@ -64,38 +56,29 @@ files:
64
56
  - test/wkb_writer_tests.rb
65
57
  - test/wkt_reader_tests.rb
66
58
  - test/wkt_writer_tests.rb
59
+ has_rdoc: true
67
60
  homepage: http://github.com/dark-panda/ffi-geos
68
61
  licenses: []
69
-
70
62
  post_install_message:
71
63
  rdoc_options: []
72
-
73
- require_paths:
64
+ require_paths:
74
65
  - lib
75
- required_ruby_version: !ruby/object:Gem::Requirement
66
+ required_ruby_version: !ruby/object:Gem::Requirement
76
67
  none: false
77
- requirements:
78
- - - ">="
79
- - !ruby/object:Gem::Version
80
- hash: 3
81
- segments:
82
- - 0
83
- version: "0"
84
- required_rubygems_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ! '>='
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
85
73
  none: false
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- hash: 3
90
- segments:
91
- - 0
92
- version: "0"
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
93
78
  requirements: []
94
-
95
79
  rubyforge_project:
96
- rubygems_version: 1.7.2
80
+ rubygems_version: 1.6.2
97
81
  signing_key:
98
82
  specification_version: 3
99
83
  summary: An ffi wrapper for GEOS, a C++ port of the Java Topology Suite (JTS).
100
84
  test_files: []
101
-