Class: Dse::Geometry::Polygon
- Inherits:
-
Object
- Object
- Dse::Geometry::Polygon
- Includes:
- Cassandra::CustomData
- Defined in:
- lib/dse/geometry/polygon.rb
Overview
Encapsulates a polygon consisting of a set of linear-rings in the xy-plane. It corresponds to the
org.apache.cassandra.db.marshal.PolygonType column type in DSE.
A linear-ring is a LineString whose last point is the same as its first point. The first ring specified in a polygon defines the outer edges of the polygon and is called the exterior ring. A polygon may also have holes within it, specified by other linear-rings, and those holes may contain linear-rings indicating islands. All such rings are called interior rings.
Class Method Summary collapse
-
.deserialize(data) ⇒ Polygon
Deserialize the given data into an instance of this domain object class.
-
.type ⇒ Cassandra::Types::Custom
Type of column that is processed by this domain object class.
Instance Method Summary collapse
-
#exterior_ring ⇒ LineString
Linear-ring characterizing the exterior of the polygon.
-
#initialize(*args) ⇒ Polygon
constructor
A new instance of Polygon.
-
#interior_rings ⇒ Array<LineString>
Ordered collection of linear-rings that make up the interior of this polygon.
-
#serialize ⇒ String
Serialize this domain object into a byte array to send to DSE.
-
#to_s ⇒ String
A human-readable English string describing this Polygon.
-
#wkt ⇒ String
Well-known-text representation of this polygon.
Constructor Details
#initialize(*args) ⇒ Polygon
Returns a new instance of Polygon.
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/dse/geometry/polygon.rb', line 44 def initialize(*args) # The constructor has two forms: # 1. 0 or more LineString objects where the first is the exterior ring and the rest are interior rings. # 2. one String arg as the wkt representation. if args.size == 1 && args.first.is_a?(String) # subsitute eol chars in the string with a space. wkt = args.first.gsub(EOL_RE, ' ') # Consolidate whitespace before/after commas and parens. wkt.gsub!(/\s*([,\(\)])\s*/, '\1') if wkt == 'POLYGON EMPTY' @rings = [].freeze else match = wkt.match(WKT_RE) raise ArgumentError, "#{wkt.inspect} is not a valid WKT representation of a polygon" unless match @rings = parse_wkt_internal(match[1]) end else @rings = args.freeze @rings.each do |ring| Cassandra::Util.assert_instance_of(LineString, ring, "#{ring.inspect} is not a LineString") end end end |
Class Method Details
.deserialize(data) ⇒ Polygon
Deserialize the given data into an instance of this domain object class.
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/dse/geometry/polygon.rb', line 150 def self.deserialize(data) buffer = Cassandra::Protocol::CqlByteBuffer.new(data) little_endian = buffer.read(1) != "\x00" # Depending on the endian-ness of the data, we want to read it differently. Wrap the buffer # with an "endian-aware" reader that reads the desired way. buffer = Dse::Util::EndianBuffer.new(buffer, little_endian) type = buffer.read_unsigned raise Cassandra::Errors::DecodingError, "LineString data-type value should be 3, but was #{type}" if type != 3 # Now comes the number of rings. num_rings = buffer.read_unsigned # Read that many line-string's (rings) from the buffer. rings = [] num_rings.times do rings << LineString.deserialize_raw(buffer) end Polygon.new(*rings) end |
.type ⇒ Cassandra::Types::Custom
Returns type of column that is processed by this domain object class.
142 143 144 |
# File 'lib/dse/geometry/polygon.rb', line 142 def self.type TYPE end |
Instance Method Details
#exterior_ring ⇒ LineString
Returns linear-ring characterizing the exterior of the polygon. nil for empty polygon.
85 86 87 |
# File 'lib/dse/geometry/polygon.rb', line 85 def exterior_ring @rings.first end |
#interior_rings ⇒ Array<LineString>
Returns ordered collection of linear-rings that make up the interior of this polygon. Empty if there are no interior rings.
91 92 93 |
# File 'lib/dse/geometry/polygon.rb', line 91 def interior_rings @interior_rings ||= (@rings[1..-1] || []).freeze end |
#serialize ⇒ String
Serialize this domain object into a byte array to send to DSE.
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 |
# File 'lib/dse/geometry/polygon.rb', line 174 def serialize buffer = Cassandra::Protocol::CqlByteBuffer.new # We serialize in little-endian form. buffer << "\x01" # This is a polygon. buffer.append([3].pack(Cassandra::Protocol::Formats::INT_FORMAT_LE)) # Write out the count of how many rings we have. buffer.append([@rings.size].pack(Cassandra::Protocol::Formats::INT_FORMAT_LE)) # Now write out the raw serialization of each ring (e.g. linestring). @rings.each do |ring| ring.serialize_raw(buffer) end buffer end |
#to_s ⇒ String
Returns a human-readable English string describing this Dse::Geometry::Polygon.
111 112 113 114 115 |
# File 'lib/dse/geometry/polygon.rb', line 111 def to_s "Exterior ring: #{@rings.first}\n" \ "Interior rings:\n " + interior_rings.join("\n ") end |
#wkt ⇒ String
Returns well-known-text representation of this polygon.
96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/dse/geometry/polygon.rb', line 96 def wkt return 'POLYGON EMPTY' if @rings.empty? result = 'POLYGON (' first = true @rings.each do |ring| result += ', ' unless first first = false result += "(#{ring.wkt_internal})" end result += ')' result end |