Class: Tina4::Point
- Inherits:
-
Object
- Object
- Tina4::Point
- Defined in:
- lib/tina4/point.rb
Overview
Immutable SRID-aware longitude/latitude point (ADR-0057).
Constant Summary collapse
- DEFAULT_SRID =
4326- EWKB_SRID =
0x20000000- EWKB_M =
0x40000000- EWKB_Z =
0x80000000
Instance Attribute Summary collapse
-
#lat ⇒ Object
readonly
Returns the value of attribute lat.
-
#lon ⇒ Object
readonly
Returns the value of attribute lon.
-
#srid ⇒ Object
readonly
Returns the value of attribute srid.
Class Method Summary collapse
Instance Method Summary collapse
- #ewkt ⇒ Object
- #geojson ⇒ Object
-
#initialize(lon, lat, srid: DEFAULT_SRID) ⇒ Point
constructor
A new instance of Point.
- #to_a ⇒ Object
- #to_h ⇒ Object
- #to_json(*args) ⇒ Object
- #wkt ⇒ Object
Constructor Details
#initialize(lon, lat, srid: DEFAULT_SRID) ⇒ Point
Returns a new instance of Point.
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# File 'lib/tina4/point.rb', line 17 def initialize(lon, lat, srid: DEFAULT_SRID) raise ArgumentError, "Point longitude and latitude must be numbers" if lon == true || lon == false || lat == true || lat == false @lon = Float(lon) @lat = Float(lat) @srid = Integer(srid) raise ArgumentError, "Point longitude and latitude must be finite" unless @lon.finite? && @lat.finite? if @srid == DEFAULT_SRID raise ArgumentError, "Point longitude #{@lon} is outside -180..180; Tina4 uses longitude, latitude order" unless (-180.0..180.0).cover?(@lon) raise ArgumentError, "Point latitude #{@lat} is outside -90..90; Tina4 uses longitude, latitude order" unless (-90.0..90.0).cover?(@lat) end freeze rescue TypeError, ArgumentError => e raise e if e..start_with?("Point ") raise ArgumentError, "Point longitude, latitude and SRID must be numeric" end |
Instance Attribute Details
#lat ⇒ Object (readonly)
Returns the value of attribute lat.
15 16 17 |
# File 'lib/tina4/point.rb', line 15 def lat @lat end |
#lon ⇒ Object (readonly)
Returns the value of attribute lon.
15 16 17 |
# File 'lib/tina4/point.rb', line 15 def lon @lon end |
#srid ⇒ Object (readonly)
Returns the value of attribute srid.
15 16 17 |
# File 'lib/tina4/point.rb', line 15 def srid @srid end |
Class Method Details
.geometry_binding(value, srid: DEFAULT_SRID) ⇒ Object
58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/tina4/point.rb', line 58 def self.geometry_binding(value, srid: DEFAULT_SRID) return [parse(value, srid: srid).ewkt, :ewkt] if value.is_a?(Point) || value.is_a?(Array) if value.is_a?(Hash) geometry = value.fetch(:type, value["type"]).to_s.downcase == "feature" ? (value[:geometry] || value["geometry"]) : value type = (geometry[:type] || geometry["type"]).to_s.downcase allowed = %w[point linestring polygon multipoint multilinestring multipolygon geometrycollection] raise ArgumentError, "GeoJSON geometry has an unsupported type" unless allowed.include?(type) return [JSON.generate(geometry), :geojson] end if value.is_a?(String) && value.match?(/\A\s*(?:SRID\s*=\s*\d+\s*;\s*)?(?:POINT|LINESTRING|POLYGON|MULTIPOINT|MULTILINESTRING|MULTIPOLYGON|GEOMETRYCOLLECTION)\b/i) return [value.match?(/\A\s*SRID/i) ? value.strip : "SRID=#{srid};#{value.strip}", :ewkt] end raise ArgumentError, "Geometry must be Point, coordinate pair, WKT/EWKT or GeoJSON" end |
.parse(value, srid: DEFAULT_SRID) ⇒ Object
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/tina4/point.rb', line 40 def self.parse(value, srid: DEFAULT_SRID) return value if value.is_a?(Point) if value.is_a?(Array) raise ArgumentError, "Point coordinate pair needs longitude and latitude" if value.length < 2 return new(value[0], value[1], srid: srid) end return from_geojson(value, srid) if value.is_a?(Hash) if value.is_a?(String) text = value.strip match = text.match(/\A(?:SRID\s*=\s*(\d+)\s*;\s*)?POINT\s*(?:Z|M|ZM)?\s*\(\s*([-+0-9.eE]+)\s+([-+0-9.eE]+)(?:\s+[-+0-9.eE]+)*\s*\)\z/i) return new(match[2], match[3], srid: match[1] ? match[1].to_i : srid) if match raw = [text].pack("H*") if text.length >= 42 && text.length.even? && text.match?(/\A[0-9a-f]+\z/i) raw ||= value.b if [0, 1].include?(value.getbyte(0)) return from_wkb(raw, srid) if raw end raise ArgumentError, "Point must be Point, [longitude, latitude], WKT/EWKT, GeoJSON or WKB/EWKB" end |
Instance Method Details
#ewkt ⇒ Object
34 |
# File 'lib/tina4/point.rb', line 34 def ewkt = "SRID=#{@srid};#{wkt}" |
#geojson ⇒ Object
35 |
# File 'lib/tina4/point.rb', line 35 def geojson = { type: "Point", coordinates: [@lon, @lat] } |
#to_a ⇒ Object
37 |
# File 'lib/tina4/point.rb', line 37 def to_a = [@lon, @lat] |
#to_h ⇒ Object
36 |
# File 'lib/tina4/point.rb', line 36 def to_h = geojson |
#to_json(*args) ⇒ Object
38 |
# File 'lib/tina4/point.rb', line 38 def to_json(*args) = geojson.to_json(*args) |
#wkt ⇒ Object
33 |
# File 'lib/tina4/point.rb', line 33 def wkt = "POINT(#{format_coordinate(@lon)} #{format_coordinate(@lat)})" |