diff --git a/spec/geo/coord_spec.cr b/spec/geo/coord_spec.cr index a95c5db..459f32c 100644 --- a/spec/geo/coord_spec.cr +++ b/spec/geo/coord_spec.cr @@ -111,6 +111,57 @@ describe Geo::Coord do geojson.should be_a(GeoJSON::Coordinates) end + describe "#to_wkt" do + it "generates a Well Known Text format" do + coord = Geo::Coord.new(50.004444, 36.231389) + + ewkt = coord.to_wkt + + ewkt.should eq "POINT(36.231389 50.004444)" + end + end + + describe "#to_wkb" do + it "generates a Well Known Binary format" do + coord = Geo::Coord.new(12, 34) + + ewkb = coord.to_wkb + + ewkb.should eq Bytes[ + 0, # Big-Endian + 0, 0, 0, 1, # POINT + 0, 0, 0, 34, 0, 0, 0, 0, # Longitude encoded as IEEE-754 + 0, 0, 0, 12, 0, 0, 0, 0, # Latitude encoded as IEEE-754 + ] + end + end + + describe "#to_ewkt" do + it "generates an Extended Well Known Text format" do + coord = Geo::Coord.new(50.004444, 36.231389) + + ewkt = coord.to_ewkt + + ewkt.should eq "SRID=4326;POINT(36.231389 50.004444)" + end + end + + describe "#to_ewkb" do + it "generates an Extended Well Known Binary format" do + coord = Geo::Coord.new(12, 34) + + ewkb = coord.to_ewkb + + ewkb.should eq Bytes[ + 0, # Big-Endian + 0, 0, 0, 1, # POINT + 0, 0, 0, 34, 0, 0, 0, 0, # Longitude encoded as IEEE-754 + 0, 0, 0, 12, 0, 0, 0, 0, # Latitude encoded as IEEE-754 + 16, 140, # SRID 4326 + ] + end + end + describe "comparisons" do describe "equality" do pos1 = Geo::Coord.new(45.3142533036254, -93.47527313511819) diff --git a/spec/geo/polygon_spec.cr b/spec/geo/polygon_spec.cr index afaf15b..0b9c7c1 100644 --- a/spec/geo/polygon_spec.cr +++ b/spec/geo/polygon_spec.cr @@ -119,6 +119,19 @@ describe Geo::Polygon do geojson.should be_a(GeoJSON::Polygon) end + describe "#to_wkt" do + it "outputs a Well Known Text format" do + polygon = Geo::Polygon.new([ + Geo::Coord.new(10, 30), + Geo::Coord.new(20, 10), + Geo::Coord.new(40, 20), + Geo::Coord.new(40, 40), + ]) + + polygon.to_wkt.should eq "POLYGON((30 10, 10 20, 20 40, 40 40, 30 10))" + end + end + describe "comparisons" do describe "equality" do polygon1 = Geo::Polygon.new([pos1, pos2]) diff --git a/src/geo/coord.cr b/src/geo/coord.cr index 9d9aa62..de8dab5 100644 --- a/src/geo/coord.cr +++ b/src/geo/coord.cr @@ -170,6 +170,46 @@ module Geo io << strfcoord(%{%latd°%latm'%lats"%lath %lngd°%lngm'%lngs"%lngh}) end + def to_ewkt : String + String.build { |str| to_ewkt str } + end + + def to_ewkt(io : IO, output_type = true, output_parentheses = true) : Nil + # SRID 4326 is used for latitude and longitude + # https://epsg.org/crs_4326/WGS-84.html + io << "SRID=4326;" + to_wkt io, output_type: output_type, output_parentheses: output_parentheses + end + + def to_ewkb(bytes : Bytes = Bytes.new(23), byte_format : IO::ByteFormat = IO::ByteFormat::BigEndian) : Bytes + to_wkb bytes, byte_format + # SRID 4326 is used for latitude and longitude + # https://epsg.org/crs_4326/WGS-84.html + byte_format.encode 4236i16, bytes + 21 + + bytes + end + + def to_wkt : String + String.build { |str| to_wkt str } + end + + def to_wkt(io : IO, output_type = true, output_parentheses = true) : Nil + io << "POINT" if output_type + io << '(' if output_parentheses + io << lng << ' ' << lat + io << ')' if output_parentheses + end + + def to_wkb(bytes : Bytes = Bytes.new(21), byte_format : IO::ByteFormat = IO::ByteFormat::BigEndian) : Bytes + bytes[0] = 0 # Big Endian + byte_format.encode 1u32, bytes + 1 # POINT type + byte_format.encode lng, bytes + 5 + byte_format.encode lat, bytes + 13 + + bytes + end + def ll {lat, lng} end diff --git a/src/geo/polygon.cr b/src/geo/polygon.cr index 3ac2b15..8f9c353 100644 --- a/src/geo/polygon.cr +++ b/src/geo/polygon.cr @@ -106,6 +106,21 @@ module Geo GeoJSON::Polygon.new([coordinates]) end + def to_wkt : String + String.build { |str| to_wkt str } + end + + def to_wkt(io : IO) : Nil + io << "POLYGON((" + @coords.each_with_index 1 do |coord, index| + coord.to_wkt io, output_type: false, output_parentheses: false + if index < @coords.size + io << ", " + end + end + io << "))" + end + private def calculate_centroid : Geo::Coord centroid_lat = 0.0 centroid_lng = 0.0