Module: Charta

Defined in:
lib/charta.rb,
lib/charta/gml.rb,
lib/charta/kml.rb,
lib/charta/point.rb,
lib/charta/polygon.rb,
lib/charta/geo_json.rb,
lib/charta/geometry.rb,
lib/charta/line_string.rb,
lib/charta/bounding_box.rb,
lib/charta/multi_polygon.rb,
lib/charta/geometry_collection.rb

Overview

Charta aims to supply easy geom/geog tools

Defined Under Namespace

Classes: BoundingBox, GML, GeoJSON, Geometry, GeometryCollection, KML, LineString, MultiPolygon, Point, Polygon

Class Method Summary collapse

Class Method Details

.clean_for_active_record(value, options = {}) ⇒ Object


134
135
136
137
138
139
140
141
142
# File 'lib/charta.rb', line 134

def clean_for_active_record(value, options = {})
  return nil if value.blank?
  value = if value.is_a?(Hash) || (value.is_a?(String) && value =~ /\A\{.*\}\z/)
            from_geojson(value)
          else
            new_geometry(value)
          end
  value.flatten.convert_to(options[:type]).to_rgeo
end

.empty_geometry(srid = :WGS84) ⇒ Object


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

def empty_geometry(srid = :WGS84)
  GeometryCollection.empty(srid)
end

.find_srid(srname_or_srid) ⇒ Object

Check and returns the SRID matching with srname or SRID.


103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/charta.rb', line 103

def find_srid(srname_or_srid)
  item = if srname_or_srid.is_a?(Symbol) || srname_or_srid.is_a?(String)
           if srname_or_srid =~ /\Aurn:ogc:def:crs:.*\z/
             # first, find full-defined urn
             found = systems.find_by(urn: srname_or_srid)

             # or, match with authority reference
             unless found
               auth_ref = /\Aurn:ogc:def:crs:(.*)\z/.match(srname_or_srid)
               if auth_ref.present?
                 srid = /\AEPSG::?(\d{4,5})\z/.match(auth_ref[1])
                 if srid.present?
                   found = systems.find_by(srid: srid[1].to_i)
                 end
               end
             end
             found
           else
             srid = /\AEPSG::?(\d{4,5})\z/.match(srname_or_srid)
             if srid.present?
               systems.find_by(srid: srid[1].to_i)
             else
               systems.items[srname_or_srid]
             end
           end
         else
           systems.find_by(srid: srname_or_srid)
         end
  (item ? item.srid : nil)
end

.from(format, data) ⇒ Object


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

def from(format, data)
  unless respond_to?("from_#{format}")
    raise "Unknown format: #{format.inspect}"
  end
  send("from_#{format}", data)
end

.from_geojson(data, srid = nil) ⇒ Object


159
160
161
# File 'lib/charta.rb', line 159

def from_geojson(data, srid = nil)
  new_geometry(::Charta::GeoJSON.new(data, srid).to_ewkt)
end

.from_gml(data, srid = nil, flatten_collection = false) ⇒ Object


151
152
153
# File 'lib/charta.rb', line 151

def from_gml(data, srid = nil, flatten_collection = false)
  new_geometry(::Charta::GML.new(data, srid).to_ewkt, nil, nil, flatten_collection)
end

.from_kml(data, flatten_collection = false) ⇒ Object


155
156
157
# File 'lib/charta.rb', line 155

def from_kml(data, flatten_collection = false)
  new_geometry(::Charta::KML.new(data).to_ewkt, nil, nil, flatten_collection)
end

.make_line(points, options = {}) ⇒ Object


72
73
74
75
76
77
# File 'lib/charta.rb', line 72

def make_line(points, options = {})
  options[:srid] ||= new_geometry(points.first).srid if points.any?
  options[:srid] ||= 4326
  list = points.map { |p| new_geometry(p).geom }
  new_geometry(select_value("SELECT ST_AsEWKT(ST_MakeLine(ARRAY[#{list.join(', ')}]))"))
end

.new_geometry(coordinates, srs = nil, format = nil, flatten_collection = true) ⇒ Object


15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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
60
61
62
63
64
65
66
# File 'lib/charta.rb', line 15

def new_geometry(coordinates, srs = nil, format = nil, flatten_collection = true)
  geom_ewkt = nil
  if coordinates.blank?
    geom_ewkt = empty_geometry(srs).to_ewkt
  elsif coordinates.is_a?(::Charta::Geometry)
    geom_ewkt = coordinates.ewkt
  elsif coordinates.is_a?(Hash) || (coordinates.is_a?(String) && ::Charta::GeoJSON.valid?(coordinates)) # GeoJSON
    srid = srs ? find_srid(srs) : :WGS84
    geom_ewkt = select_value("SELECT ST_AsEWKT(ST_GeomFromEWKT('#{::Charta::GeoJSON.new(coordinates, srid).to_ewkt}'))")
  elsif coordinates.is_a?(String)
    geom_ewkt = if coordinates =~ /\A[A-F0-9]+\z/ # WKB
                  if srs && srid = find_srid(srs)
                    select_value("SELECT ST_AsEWKT(ST_GeomFromText(E'\\\\x#{coordinates}', #{srid}))")
                  else
                    select_value("SELECT ST_AsEWKT(ST_GeomFromEWKB(E'\\\\x#{coordinates}'))")
                  end
                elsif format == 'gml' && ::Charta::GML.valid?(coordinates)
                  # required format 'cause kml geometries return empty instead of failing
                  ::Charta::GML.new(coordinates, srid).to_ewkt
                elsif format == 'kml' && ::Charta::KML.valid?(coordinates)
                  ::Charta::KML.new(coordinates).to_ewkt
                else # WKT expected
                  if srs && srid = find_srid(srs)
                    select_value("SELECT ST_AsEWKT(ST_GeomFromText('#{coordinates}', #{srid}))")
                  else
                    select_value("SELECT ST_AsEWKT(ST_GeomFromEWKT('#{coordinates}'))")
                  end
                end
  else
    geom_ewkt = select_value("SELECT ST_AsEWKT(ST_GeomFromText('#{coordinates.as_text}', #{coordinates.srid}))")
  end
  if geom_ewkt.blank?
    raise ArgumentError, "Invalid data: coordinates=#{coordinates.inspect}, srid=#{srid.inspect}"
  end
  type = select_value("SELECT GeometryType(ST_GeomFromEWKT('#{geom_ewkt}'))").to_s.strip
  geom = case type
         when 'POINT' then
           Point.new(geom_ewkt)
         when 'LINESTRING' then
           LineString.new(geom_ewkt)
         when 'POLYGON' then
           Polygon.new(geom_ewkt)
         when 'MULTIPOLYGON' then
           MultiPolygon.new(geom_ewkt)
         when 'GEOMETRYCOLLECTION' then
           GeometryCollection.new(geom_ewkt, flatten_collection)
         else
           Geometry.new(geom_ewkt)
         end

  geom
end

.new_point(lat, lon, srid = 4326) ⇒ Object


68
69
70
# File 'lib/charta.rb', line 68

def new_point(lat, lon, srid = 4326)
  Point.new("SRID=#{srid};POINT(#{lon} #{lat})")
end

.select_row(query) ⇒ Object

Execute a query


93
94
95
# File 'lib/charta.rb', line 93

def select_row(query)
  ActiveRecord::Base.connection.select_rows(query).first
end

.select_value(query) ⇒ Object

Execute a query


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

def select_value(query)
  ActiveRecord::Base.connection.select_value(query)
end

.select_values(query) ⇒ Object


88
89
90
# File 'lib/charta.rb', line 88

def select_values(query)
  ActiveRecord::Base.connection.select_values(query)
end

.systemsObject

Link to the nomenclature


98
99
100
# File 'lib/charta.rb', line 98

def systems
  Nomen::SpatialReferenceSystem
end