Module: Geos::Utils

Extended by:
GeomTypes, Tools
Defined in:
lib/ffi-geos/utils.rb

Constant Summary

Constants included from GeomTypes

GeomTypes::GEOS_GEOMETRYCOLLECTION, GeomTypes::GEOS_LINEARRING, GeomTypes::GEOS_LINESTRING, GeomTypes::GEOS_MULTILINESTRING, GeomTypes::GEOS_MULTIPOINT, GeomTypes::GEOS_MULTIPOLYGON, GeomTypes::GEOS_POINT, GeomTypes::GEOS_POLYGON

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Tools

bool_result, cast_geometry_ptr, check_enum_value, check_geometry, pick_srid_according_to_policy, pick_srid_from_geoms, symbol_for_enum

Class Method Details

.create_collection(t, *args) ⇒ Object



163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
# File 'lib/ffi-geos/utils.rb', line 163

def create_collection(t, *args)
  check_enum_value(Geos::GeometryTypes, t)

  klass = case t
    when GEOS_MULTIPOINT, :multi_point
      Geos::Point
    when GEOS_MULTILINESTRING, :multi_line_string
      Geos::LineString
    when GEOS_MULTIPOLYGON, :multi_polygon
      Geos::Polygon
    when GEOS_GEOMETRYCOLLECTION, :geometry_collection
      Geos::Geometry
  end

  options = if args.last.is_a?(Hash)
    args.pop
  else
    {}
  end

  geoms = Array(args).flatten.tap { |i|
    if i.detect { |g| !g.is_a?(klass) }
      raise TypeError.new("Expected geoms Array to contain #{klass} objects")
    end
  }

  geoms_dups = geoms.map(&:dup)
  geoms_dups.each { |i|
    i.ptr.autorelease = false
  }

  ary = FFI::MemoryPointer.new(:pointer, geoms.length)
  ary.write_array_of_pointer(geoms_dups.map(&:ptr))

  cast_geometry_ptr(FFIGeos.GEOSGeom_createCollection_r(Geos.current_handle, t, ary, geoms_dups.length), {
    :srid => options[:srid]
  })
end

.create_empty_collection(t, options = {}) ⇒ Object



136
137
138
139
140
141
# File 'lib/ffi-geos/utils.rb', line 136

def create_empty_collection(t, options = {})
  check_enum_value(Geos::GeometryTypes, t)
  cast_geometry_ptr(FFIGeos.GEOSGeom_createEmptyCollection_r(Geos.current_handle, t), {
    :srid => options[:srid]
  })
end

.create_empty_geometry_collection(options = {}) ⇒ Object



155
156
157
# File 'lib/ffi-geos/utils.rb', line 155

def create_empty_geometry_collection(options = {})
  create_empty_collection(:geometry_collection, options)
end

.create_empty_line_string(options = {}) ⇒ Object



124
125
126
127
128
# File 'lib/ffi-geos/utils.rb', line 124

def create_empty_line_string(options = {})
  cast_geometry_ptr(FFIGeos.GEOSGeom_createEmptyLineString_r(Geos.current_handle), {
    :srid => options[:srid]
  })
end

.create_empty_linear_ring(options = {}) ⇒ Object



159
160
161
# File 'lib/ffi-geos/utils.rb', line 159

def create_empty_linear_ring(options = {})
  Geos::WktReader.new.read('LINEARRING EMPTY', options)
end

.create_empty_multi_line_string(options = {}) ⇒ Object



147
148
149
# File 'lib/ffi-geos/utils.rb', line 147

def create_empty_multi_line_string(options = {})
  create_empty_collection(:multi_line_string, options)
end

.create_empty_multi_point(options = {}) ⇒ Object



143
144
145
# File 'lib/ffi-geos/utils.rb', line 143

def create_empty_multi_point(options = {})
  create_empty_collection(:multi_point, options)
end

.create_empty_multi_polygon(options = {}) ⇒ Object



151
152
153
# File 'lib/ffi-geos/utils.rb', line 151

def create_empty_multi_polygon(options = {})
  create_empty_collection(:multi_polygon, options)
end

.create_empty_point(options = {}) ⇒ Object



118
119
120
121
122
# File 'lib/ffi-geos/utils.rb', line 118

def create_empty_point(options = {})
  cast_geometry_ptr(FFIGeos.GEOSGeom_createEmptyPoint_r(Geos.current_handle), {
    :srid => options[:srid]
  })
end

.create_empty_polygon(options = {}) ⇒ Object



130
131
132
133
134
# File 'lib/ffi-geos/utils.rb', line 130

def create_empty_polygon(options = {})
  cast_geometry_ptr(FFIGeos.GEOSGeom_createEmptyPolygon_r(Geos.current_handle), {
    :srid => options[:srid]
  })
end

.create_geometry_collection(*args) ⇒ Object



214
215
216
# File 'lib/ffi-geos/utils.rb', line 214

def create_geometry_collection(*args)
  create_collection(:geometry_collection, *args)
end

.create_line_string(cs, options = {}) ⇒ Object



61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/ffi-geos/utils.rb', line 61

def create_line_string(cs, options = {})
  cs = cs_from_cs_or_geom(cs)

  if cs.length <= 1 && cs.length != 0
    raise RuntimeError.new("IllegalArgumentException: point array must contain 0 or >1 elements")
  end

  cs_dup = cs.dup
  cs_dup.ptr.autorelease = false

  cast_geometry_ptr(FFIGeos.GEOSGeom_createLineString_r(Geos.current_handle, cs_dup.ptr), {
    :srid => options[:srid]
  })
end

.create_linear_ring(cs, options = {}) ⇒ Object



76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/ffi-geos/utils.rb', line 76

def create_linear_ring(cs, options = {})
  cs = cs_from_cs_or_geom(cs)

  if cs.length <= 1 && cs.length != 0
    raise RuntimeError.new("IllegalArgumentException: point array must contain 0 or >1 elements")
  end

  cs.ptr.autorelease = false

  ret = cast_geometry_ptr(FFIGeos.GEOSGeom_createLinearRing_r(Geos.current_handle, cs.ptr), {
    :srid => options[:srid]
  })
end

.create_multi_line_string(*args) ⇒ Object



206
207
208
# File 'lib/ffi-geos/utils.rb', line 206

def create_multi_line_string(*args)
  create_collection(:multi_line_string, *args)
end

.create_multi_point(*args) ⇒ Object



202
203
204
# File 'lib/ffi-geos/utils.rb', line 202

def create_multi_point(*args)
  create_collection(:multi_point, *args)
end

.create_multi_polygon(*args) ⇒ Object



210
211
212
# File 'lib/ffi-geos/utils.rb', line 210

def create_multi_polygon(*args)
  create_collection(:multi_polygon, *args)
end

.create_point(*args) ⇒ Object



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/ffi-geos/utils.rb', line 30

def create_point(*args)
  options = if args.last.is_a?(Hash)
    args.pop
  else
    {}
  end

  if args.length == 1
    cs = args.first
  elsif args.length == 2
    cs = CoordinateSequence.new(1, 2)
    cs.x[0], cs.y[0] = args[0].to_f, args[1].to_f
  elsif args.length == 3
    cs = CoordinateSequence.new(1, 3)
    cs.x[0], cs.y[0], cs.z[0] = args.map(&:to_f)
  else
    raise ArgumentError.new("Wrong number of arguments (#{args.length} for 1-3)")
  end

  if cs.length != 1
    raise RuntimeError.new("IllegalArgumentException: Point coordinate list must contain a single element")
  end

  cs_dup = cs.dup
  cs_dup.ptr.autorelease = false

  cast_geometry_ptr(FFIGeos.GEOSGeom_createPoint_r(Geos.current_handle, cs_dup.ptr), {
    :srid => options[:srid]
  })
end

.create_polygon(outer, *args) ⇒ Object



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/ffi-geos/utils.rb', line 90

def create_polygon(outer, *args)
  options = if args.last.is_a?(Hash)
    args.pop
  else
    {}
  end

  inner_dups = Array(args).flatten.collect { |i|
    force_to_linear_ring(i) or
      raise TypeError.new("Expected inner Array to contain Geos::LinearRing or Geos::CoordinateSequence objects")
  }

  outer_dup = force_to_linear_ring(outer) or
    raise TypeError.new("Expected outer shell to be a Geos::LinearRing or Geos::CoordinateSequence")

  ary = FFI::MemoryPointer.new(:pointer, inner_dups.length)
  ary.write_array_of_pointer(inner_dups.map(&:ptr))

  outer_dup.ptr.autorelease = false
  inner_dups.each { |i|
    i.ptr.autorelease = false
  }

  cast_geometry_ptr(FFIGeos.GEOSGeom_createPolygon_r(Geos.current_handle, outer_dup.ptr, ary, inner_dups.length), {
    :srid => options[:srid]
  })
end

Instance Method Details

#orientation_index(ax, ay, bx, by, px, py) ⇒ Object

  • -1 if reaching P takes a counter-clockwise (left) turn

  • 1 if reaching P takes a clockwise (right) turn

  • 0 if P is collinear with A-B

Available in GEOS 3.3.0+.



15
16
17
18
19
20
# File 'lib/ffi-geos/utils.rb', line 15

def orientation_index(ax, ay, bx, by, px, py)
  FFIGeos.GEOSOrientationIndex_r(
    Geos.current_handle,
    ax, ay, bx, by, px, py
  )
end

#relate_match(mat, pat) ⇒ Object

Available in GEOS 3.3.0+.



25
26
27
# File 'lib/ffi-geos/utils.rb', line 25

def relate_match(mat, pat)
  bool_result(FFIGeos.GEOSRelatePatternMatch_r(Geos.current_handle, mat, pat))
end