Class: Charta::Geometry

Inherits:
Object
  • Object
show all
Defined in:
lib/charta/geometry.rb

Overview

Represents a Geometry with SRID

Direct Known Subclasses

GeometryCollection, LineString, Point, Polygon

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(feature, properties = {}) ⇒ Geometry

Returns a new instance of Geometry.



9
10
11
12
# File 'lib/charta/geometry.rb', line 9

def initialize(feature, properties = {})
  self.feature = feature
  @properties = properties
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args, &block) ⇒ Object



261
262
263
264
265
266
267
268
# File 'lib/charta/geometry.rb', line 261

def method_missing(name, *args, &block)
  target = to_rgeo
  if target.respond_to? name
    target.send name, *args
  else
    raise StandardError.new("Method #{name} does not exist for #{self.class.name}")
  end
end

Class Method Details

.factory(srid = 4326) ⇒ Object



280
281
282
283
# File 'lib/charta/geometry.rb', line 280

def factory(srid = 4326)
  return projected_factory(srid) if srid.to_i == 4326
  geos_factory(srid)
end

.feature(ewkt_or_rgeo) ⇒ Object



285
286
287
288
# File 'lib/charta/geometry.rb', line 285

def feature(ewkt_or_rgeo)
  return from_rgeo(ewkt_or_rgeo) if ewkt_or_rgeo.is_a? RGeo::Feature::Instance
  from_ewkt(ewkt_or_rgeo)
end

.from_ewkt(ewkt) ⇒ Object



295
296
297
298
299
300
301
302
303
304
305
# File 'lib/charta/geometry.rb', line 295

def from_ewkt(ewkt)
  # Cleans empty geometries
  ewkt = ewkt.gsub(/(GEOMETRYCOLLECTION|GEOMETRY|((MULTI)?(POINT|LINESTRING|POLYGON)))\(\)/, '\1 EMPTY')
  srs = ewkt.split(/[\=\;]+/)[0..1]
  srid = nil
  srid = srs[1] if srs[0] =~ /srid/i
  srid ||= 4326
  factory(srid).parse_wkt(ewkt)
rescue RGeo::Error::ParseError => e
  raise "Invalid EWKT (#{e.class.name}: #{e.message}): #{ewkt}"
end

.from_rgeo(rgeo) ⇒ Object



290
291
292
293
# File 'lib/charta/geometry.rb', line 290

def from_rgeo(rgeo)
  srid = rgeo.srid
  RGeo::Feature.cast(rgeo, factory: Geometry.factory(srid))
end

.srs_databaseObject



276
277
278
# File 'lib/charta/geometry.rb', line 276

def srs_database
  @srs_database ||= RGeo::CoordSys::SRSDatabase::Proj4Data.new('epsg', authority: 'EPSG', cache: true)
end

Instance Method Details

#!=(other) ⇒ Object

Test if the other measure is equal to self



104
105
106
107
108
109
# File 'lib/charta/geometry.rb', line 104

def !=(other)
  other_geometry = Charta.new_geometry(other).transform(srid)
  return true if empty? && other_geometry.empty?
  return inspect == other_geometry.inspect if collection? && other_geometry.collection?
  !feature.equals?(other_geometry.feature)
end

#==(other) ⇒ Object

Test if the other measure is equal to self



96
97
98
99
100
101
# File 'lib/charta/geometry.rb', line 96

def ==(other)
  other_geometry = Charta.new_geometry(other).transform(srid)
  return true if empty? && other_geometry.empty?
  return inspect == other_geometry.inspect if collection? && other_geometry.collection?
  feature.equals?(other_geometry.feature)
end

#areaObject

Returns area in unit corresponding to the SRS



117
118
119
# File 'lib/charta/geometry.rb', line 117

def area
  surface? ? feature.area : 0
end

#bounding_boxObject



215
216
217
218
219
220
221
222
223
224
225
# File 'lib/charta/geometry.rb', line 215

def bounding_box
  unless defined? @bounding_box
    bbox = RGeo::Cartesian::BoundingBox.create_from_geometry(feature)
    instance_variable_set('@x_min', bbox.min_x || 0)
    instance_variable_set('@y_min', bbox.min_y || 0)
    instance_variable_set('@x_max', bbox.max_x || 0)
    instance_variable_set('@y_max', bbox.max_y || 0)
    @bounding_box = BoundingBox.new(@y_min, @x_min, @y_max, @x_max)
  end
  @bounding_box
end

#buffer(radius) ⇒ Object

Produces buffer



192
193
194
# File 'lib/charta/geometry.rb', line 192

def buffer(radius)
  feature.buffer(radius)
end

#centroidObject

Computes the geometric center of a geometry, or equivalently, the center of mass of the geometry as a POINT.



131
132
133
134
135
# File 'lib/charta/geometry.rb', line 131

def centroid
  return nil unless surface? && !feature.is_empty?
  point = feature.centroid
  [point.y, point.x]
end

#collection?Boolean

Returns the type of the geometry as a string. EG: ‘ST_Linestring’, ‘ST_Polygon’, ‘ST_MultiPolygon’ etc. This function differs from GeometryType(geometry) in the case of the string and ST in front that is returned, as well as the fact that it will not indicate whether the geometry is measured.

Returns:

  • (Boolean)


28
29
30
# File 'lib/charta/geometry.rb', line 28

def collection?
  feature.geometry_type == RGeo::Feature::GeometryCollection
end

#convert_to(new_type) ⇒ Object



144
145
146
147
148
149
150
151
# File 'lib/charta/geometry.rb', line 144

def convert_to(new_type)
  case new_type
  when type then self
  when :multi_point then flatten_multi(:point)
  when :multi_line_string then flatten_multi(:line_string)
  when :multi_polygon then flatten_multi(:polygon)
  end
end

#difference(other) ⇒ Object Also known as: -



208
209
210
211
# File 'lib/charta/geometry.rb', line 208

def difference(other)
  other_geometry = Charta.new_geometry(other).transform(srid)
  feature.difference(other_geometry.feature)
end

#empty?Boolean Also known as: blank?

Returns true if this Geometry is an empty geometrycollection, polygon, point etc.

Returns:

  • (Boolean)


123
124
125
# File 'lib/charta/geometry.rb', line 123

def empty?
  feature.is_empty?
end

#ewktObject



53
54
55
56
# File 'lib/charta/geometry.rb', line 53

def ewkt
  puts 'DEPRECATION WARNING: Charta::Geometry.ewkt is deprecated. Please use Charta::Geometry.to_ewkt instead'
  to_ewkt
end

#featureObject

Returns the underlaying object managed by Charta: the RGeo feature



238
239
240
241
242
243
244
245
246
247
248
# File 'lib/charta/geometry.rb', line 238

def feature
  unless defined? @feature
    if defined? @ewkt
      @feature = ::Charta::Geometry.from_ewkt(@ewkt)
      @properties = @options.dup if @options
    else
      raise StandardError, 'Invalid geometry (no feature, no EWKT)'
    end
  end
  @feature.dup
end

#feature=(new_feature) ⇒ Object

Raises:

  • (ArgumentError)


252
253
254
255
# File 'lib/charta/geometry.rb', line 252

def feature=(new_feature)
  raise ArgumentError, "Feature can't be nil" if new_feature.nil?
  @feature = new_feature
end

#find_srid(name_or_srid) ⇒ Object



233
234
235
# File 'lib/charta/geometry.rb', line 233

def find_srid(name_or_srid)
  Charta.find_srid(name_or_srid)
end

#flatten_multi(as_type) ⇒ Object



153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/charta/geometry.rb', line 153

def flatten_multi(as_type)
  items = []
  as_multi_type = "multi_#{as_type}".to_sym
  if type == as_type
    items << feature
  elsif type == :geometry_collection
    feature.each do |geom|
      type_name = Charta.underscore(geom.geometry_type.type_name).to_sym
      if type_name == as_type
        items << geom
      elsif type_name == as_multi_type
        geom.each do |item|
          items << item
        end
      end
    end
  end
  Charta.new_geometry(feature.factory.send(as_multi_type, items))
end

#inspectObject



14
15
16
# File 'lib/charta/geometry.rb', line 14

def inspect
  "<#{self.class.name}(#{to_ewkt})>"
end

#intersection(other) ⇒ Object



203
204
205
206
# File 'lib/charta/geometry.rb', line 203

def intersection(other)
  other_geometry = Charta.new_geometry(other).transform(srid)
  feature.intersection(other_geometry.feature)
end

#merge(other) ⇒ Object Also known as: +



196
197
198
199
# File 'lib/charta/geometry.rb', line 196

def merge(other)
  other_geometry = Charta.new_geometry(other).transform(srid)
  feature.union(other_geometry.feature)
end

#point_on_surfaceObject

Returns a POINT guaranteed to lie on the surface.



138
139
140
141
142
# File 'lib/charta/geometry.rb', line 138

def point_on_surface
  return nil unless surface?
  point = feature.point_on_surface
  [point.y, point.x]
end

#respond_to_missing?(name, include_private = false) ⇒ Boolean

Returns:

  • (Boolean)


270
271
272
273
# File 'lib/charta/geometry.rb', line 270

def respond_to_missing?(name, include_private = false)
  return false if name == :init_with
  super
end

#sridObject

Return the spatial reference identifier for the ST_Geometry



33
34
35
# File 'lib/charta/geometry.rb', line 33

def srid
  feature.srid.to_i
end

#surface?Boolean

Returns true if Geometry is a Surface

Returns:

  • (Boolean)


112
113
114
# File 'lib/charta/geometry.rb', line 112

def surface?
  [RGeo::Feature::Polygon, RGeo::Feature::MultiPolygon].include? feature.geometry_type
end

#to_binaryObject Also known as: to_ewkb

Return the Well-Known Binary (WKB) representation of the geometry with SRID meta data.



59
60
61
62
# File 'lib/charta/geometry.rb', line 59

def to_binary
  generator = RGeo::WKRep::WKBGenerator.new(tag_format: :ewkbt, emit_ewkbt_srid: true)
  generator.generate(feature)
end

#to_ewktObject Also known as: to_s

Returns EWKT: WKT with its SRID



47
48
49
# File 'lib/charta/geometry.rb', line 47

def to_ewkt
  Charta.generate_ewkt(feature).to_s
end

#to_geojsonObject Also known as: to_json

Return the geometry as a Geometry Javascript Object Notation (GeoJSON) element.



84
85
86
# File 'lib/charta/geometry.rb', line 84

def to_geojson
  to_json_object.to_json
end

#to_json_feature(properties = {}) ⇒ Object



257
258
259
# File 'lib/charta/geometry.rb', line 257

def to_json_feature(properties = {})
  { type: 'Feature', properties: properties, geometry: to_json_object }
end

#to_json_objectObject

Returns object in JSON (Hash)



91
92
93
# File 'lib/charta/geometry.rb', line 91

def to_json_object
  RGeo::GeoJSON.encode(feature)
end

#to_rgeoObject

Returns the underlaying object managed by Charta: the RGeo feature



250
251
252
253
254
255
256
257
258
259
260
# File 'lib/charta/geometry.rb', line 250

def feature
  unless defined? @feature
    if defined? @ewkt
      @feature = ::Charta::Geometry.from_ewkt(@ewkt)
      @properties = @options.dup if @options
    else
      raise StandardError, 'Invalid geometry (no feature, no EWKT)'
    end
  end
  @feature.dup
end

#to_svg(options = {}) ⇒ Object

Pas bien compris le fonctionnement



67
68
69
70
71
72
73
74
75
76
# File 'lib/charta/geometry.rb', line 67

def to_svg(options = {})
  svg = '<svg xmlns="http://www.w3.org/2000/svg" version="1.1"'
  { preserve_aspect_ratio: 'xMidYMid meet',
    width: 180, height: 180,
    view_box: bounding_box.svg_view_box.join(' ') }.merge(options).each do |attr, value|
    svg << " #{Charta.camelcase(attr.to_s, :lower)}=\"#{value}\""
  end
  svg << "><path d=\"#{to_svg_path}\"/></svg>"
  svg
end

#to_svg_pathObject

Return the geometry as Scalar Vector Graphics (SVG) path data.



79
80
81
# File 'lib/charta/geometry.rb', line 79

def to_svg_path
  RGeo::SVG.encode(feature)
end

#to_textObject Also known as: as_text, to_wkt

Returns the Well-Known Text (WKT) representation of the geometry/geography without SRID metadata



39
40
41
# File 'lib/charta/geometry.rb', line 39

def to_text
  feature.as_text.match(/\ASRID=.*;(.*)/)[1]
end

#transform(new_srid) ⇒ Object

Returns a new geometry with the coordinates converted into the new SRS



174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/charta/geometry.rb', line 174

def transform(new_srid)
  return self if new_srid == srid
  raise 'Proj is not supported. Cannot tranform' unless RGeo::CoordSys::Proj4.supported?
  new_srid = Charta::SRS[new_srid] || new_srid
  database = self.class.srs_database
  new_proj_entry = database.get(new_srid)
  raise "Cannot find proj for SRID: #{new_srid}" if new_proj_entry.nil?
  new_feature = RGeo::CoordSys::Proj4.transform(
    database.get(srid).proj4,
    feature,
    new_proj_entry.proj4,
    self.class.factory(new_srid)
  )
  generator = RGeo::WKRep::WKTGenerator.new(tag_format: :ewkt, emit_ewkt_srid: true)
  Charta.new_geometry(generator.generate(new_feature))
end

#typeObject

Returns the type of the geometry as a string. Example: point, multi_polygon, geometry_collection…



20
21
22
# File 'lib/charta/geometry.rb', line 20

def type
  Charta.underscore(feature.geometry_type.type_name).to_sym
end