diff --git a/Project.toml b/Project.toml index 459f5b57..fc5dd168 100644 --- a/Project.toml +++ b/Project.toml @@ -5,8 +5,6 @@ version = "0.5.9" [deps] EarCut_jll = "5ae413db-bbd1-5e63-b57d-d24a61df00f5" -Extents = "411431e0-e8b7-467b-b5e0-f676ba4f2910" -GeoInterface = "cf35fbd7-0cd7-5166-be24-54bfbe79505f" IterTools = "c8e1da08-722c-5040-9ed9-7db0dc04731e" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" PrecompileTools = "aea7be01-6a6a-4083-8856-8a6e6704d82a" @@ -16,9 +14,6 @@ StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" [compat] Aqua = "0.8" EarCut_jll = "2" -Extents = "0.1" -GeoInterface = "1.0.1" -GeoJSON = "0.7, 0.8" IterTools = "1.3.0" LinearAlgebra = "<0.0.1,1" OffsetArrays = "1" @@ -30,10 +25,9 @@ julia = "1.6" [extras] Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" -GeoJSON = "61d90e0f-e114-555e-ac52-39dfb47a3ef9" OffsetArrays = "6fe1bfb0-de20-5000-8ca7-80f57d26f881" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [targets] -test = ["Aqua", "GeoJSON", "Test", "Random", "OffsetArrays"] +test = ["Aqua", "Test", "Random", "OffsetArrays"] diff --git a/src/GeometryBasics.jl b/src/GeometryBasics.jl index 887e691c..3335082b 100644 --- a/src/GeometryBasics.jl +++ b/src/GeometryBasics.jl @@ -1,8 +1,6 @@ module GeometryBasics using IterTools, LinearAlgebra, StaticArrays -using GeoInterface -import Extents using EarCut_jll import Base: * @@ -27,8 +25,6 @@ include("triangulation.jl") include("lines.jl") include("boundingboxes.jl") -include("geointerface.jl") - export AbstractGeometry, GeometryPrimitive export Mat, Point, Vec export LineFace, Polytope, Line, NgonFace, convert_simplex diff --git a/src/geointerface.jl b/src/geointerface.jl deleted file mode 100644 index f806fc27..00000000 --- a/src/geointerface.jl +++ /dev/null @@ -1,163 +0,0 @@ -# Implementation of trait based interface from https://github.com/JuliaGeo/GeoInterface.jl/ - -GeoInterface.isgeometry(::Type{<:AbstractGeometry}) = true -GeoInterface.isgeometry(::Type{<:AbstractFace}) = true - -GeoInterface.isgeometry(::Type{<:Point}) = true -GeoInterface.isgeometry(::Type{<:AbstractMesh}) = true -GeoInterface.isgeometry(::Type{<:AbstractPolygon}) = true -GeoInterface.isgeometry(::Type{<:LineString}) = true -GeoInterface.isgeometry(::Type{<:MultiPoint}) = true -GeoInterface.isgeometry(::Type{<:MultiLineString}) = true -GeoInterface.isgeometry(::Type{<:MultiPolygon}) = true -GeoInterface.isgeometry(::Type{<:Mesh}) = true - -GeoInterface.geomtrait(::Point) = PointTrait() -GeoInterface.geomtrait(::Line) = LineTrait() -GeoInterface.geomtrait(::LineString) = LineStringTrait() -GeoInterface.geomtrait(::Polygon) = PolygonTrait() -GeoInterface.geomtrait(::MultiPoint) = MultiPointTrait() -GeoInterface.geomtrait(::MultiLineString) = MultiLineStringTrait() -GeoInterface.geomtrait(::MultiPolygon) = MultiPolygonTrait() -GeoInterface.geomtrait(::Ngon) = PolygonTrait() -GeoInterface.geomtrait(::AbstractMesh) = PolyhedralSurfaceTrait() - -# GeoInterface calls this method in `GeoInterface.convert(GeometryBasics, ...)` -geointerface_geomtype(::GeoInterface.PointTrait) = Point -geointerface_geomtype(::GeoInterface.MultiPointTrait) = MultiPoint -geointerface_geomtype(::GeoInterface.LineTrait) = Line -geointerface_geomtype(::GeoInterface.LineStringTrait) = LineString -geointerface_geomtype(::GeoInterface.MultiLineStringTrait) = MultiLineString -geointerface_geomtype(::GeoInterface.PolygonTrait) = Polygon -geointerface_geomtype(::GeoInterface.MultiPolygonTrait) = MultiPolygon -geointerface_geomtype(::GeoInterface.PolyhedralSurfaceTrait) = Mesh - -GeoInterface.geomtrait(::Simplex{Dim,T,1}) where {Dim,T} = PointTrait() -GeoInterface.geomtrait(::Simplex{Dim,T,2}) where {Dim,T} = LineStringTrait() -GeoInterface.geomtrait(::Simplex{Dim,T,3}) where {Dim,T} = PolygonTrait() - -GeoInterface.ncoord(::PointTrait, g::Point) = length(g) -GeoInterface.getcoord(::PointTrait, g::Point, i::Int) = g[i] - -GeoInterface.ngeom(::LineTrait, g::Line) = length(g) -GeoInterface.getgeom(::LineTrait, g::Line, i::Int) = g[i] - - -GeoInterface.ngeom(::LineStringTrait, g::LineString) = length(g) # n connected points -GeoInterface.ncoord(::LineStringTrait, g::LineString{Dim}) where {Dim} = Dim -function GeoInterface.getgeom(::LineStringTrait, g::LineString, i::Int) - return GeometryBasics.coordinates(g)[i] -end - -GeoInterface.ngeom(::PolygonTrait, g::Polygon) = length(g.interiors) + 1 # +1 for exterior -function GeoInterface.getgeom(::PolygonTrait, - g::Polygon, - i::Int) - return i > 1 ? LineString(g.interiors[i - 1]) : LineString(g.exterior) -end - -GeoInterface.ngeom(::MultiPointTrait, g::MultiPoint) = length(g) -GeoInterface.getgeom(::MultiPointTrait, g::MultiPoint, i::Int) = g[i] - -function GeoInterface.ngeom(::MultiLineStringTrait, g::MultiLineString) - return length(g) -end -function GeoInterface.getgeom(::MultiLineStringTrait, g::MultiLineString, i::Int) - return g[i] -end -GeoInterface.ncoord(::MultiLineStringTrait, g::MultiLineString{Dim}) where {Dim} = Dim - -GeoInterface.ngeom(::MultiPolygonTrait, g::MultiPolygon) = length(g) -GeoInterface.getgeom(::MultiPolygonTrait, g::MultiPolygon, i::Int) = g[i] - -function GeoInterface.ncoord(::AbstractGeometryTrait, - ::Simplex{Dim,T,N}) where {Dim,T,N} - return Dim -end -function GeoInterface.ncoord(::AbstractGeometryTrait, - ::AbstractGeometry{Dim,T}) where {Dim,T} - return Dim -end -function GeoInterface.ngeom(::AbstractGeometryTrait, - ::Simplex{Dim,T,N}) where {Dim,T,N} - return N -end -GeoInterface.ngeom(::PolygonTrait, ::Ngon) = 1 # can't have any holes -GeoInterface.getgeom(::PolygonTrait, g::Ngon, _) = LineString([g.points...]) - -function GeoInterface.ncoord(::PolyhedralSurfaceTrait, - ::Mesh{Dim,T,E,V} where {Dim,T,E,V}) - return Dim -end -GeoInterface.ngeom(::PolyhedralSurfaceTrait, g::AbstractMesh) = length(g) -GeoInterface.getgeom(::PolyhedralSurfaceTrait, g::AbstractMesh, i) = g[i] - -function GeoInterface.convert(::Type{Point}, type::PointTrait, geom) - x, y = GeoInterface.x(geom), GeoInterface.y(geom) - if GeoInterface.is3d(geom) - z = GeoInterface.z(geom) - T = promote_type(typeof(x), typeof(y), typeof(z)) - return Point{3,T}(x, y, z) - else - GeoInterface.x(geom), GeoInterface.y(geom) - T = promote_type(typeof(x), typeof(y)) - return Point{2,T}(x, y) - end -end - -# without a function barrier you get a lot of allocations from runtime types -function _collect_with_type(::Type{PT}, geom) where {PT <: Point{2}} - return [PT(GeoInterface.x(p), GeoInterface.y(p)) for p in getgeom(geom)] -end - -function GeoInterface.convert(::Type{LineString}, type::LineStringTrait, geom) - g1 = getgeom(geom, 1) - x, y = GeoInterface.x(g1), GeoInterface.y(g1) - if GeoInterface.is3d(geom) - z = GeoInterface.z(g1) - T = promote_type(typeof(x), typeof(y), typeof(z)) - return LineString([Point{3,T}(GeoInterface.x(p), GeoInterface.y(p), GeoInterface.z(p)) for p in getgeom(geom)]) - else - T = promote_type(typeof(x), typeof(y)) - return LineString(_collect_with_type(Point{2, T}, geom)) - end -end - -function GeoInterface.convert(::Type{Polygon}, type::PolygonTrait, geom) - t = LineStringTrait() - exterior = GeoInterface.convert(LineString, t, GeoInterface.getexterior(geom)) - if GeoInterface.nhole(geom) == 0 - return Polygon(exterior) - else - interiors = map(h -> GeoInterface.convert(LineString, t, h), GeoInterface.gethole(geom)) - return Polygon(exterior, interiors) - end -end - -function GeoInterface.convert(::Type{MultiPoint}, type::MultiPointTrait, geom) - g1 = getgeom(geom, 1) - x, y = GeoInterface.x(g1), GeoInterface.y(g1) - if GeoInterface.is3d(geom) - z = GeoInterface.z(g1) - T = promote_type(typeof(x), typeof(y), typeof(z)) - return MultiPoint([Point{3,T}(GeoInterface.x(p), GeoInterface.y(p), GeoInterface.z(p)) for p in getgeom(geom)]) - else - T = promote_type(typeof(x), typeof(y)) - return MultiPoint([Point{2,T}(GeoInterface.x(p), GeoInterface.y(p)) for p in getgeom(geom)]) - end -end - -function GeoInterface.convert(::Type{MultiLineString}, type::MultiLineStringTrait, geom) - t = LineStringTrait() - return MultiLineString(map(l -> GeoInterface.convert(LineString, t, l), getgeom(geom))) -end - -function GeoInterface.convert(::Type{MultiPolygon}, type::MultiPolygonTrait, geom) - t = PolygonTrait() - return MultiPolygon(map(poly -> GeoInterface.convert(Polygon, t, poly), getgeom(geom))) -end - -function Extents.extent(rect::Rect2) - (xmin, ymin), (xmax, ymax) = extrema(rect) - return Extents.Extent(X=(xmin, xmax), Y=(ymin, ymax)) -end \ No newline at end of file diff --git a/test/geointerface.jl b/test/geointerface.jl deleted file mode 100644 index 31c7de38..00000000 --- a/test/geointerface.jl +++ /dev/null @@ -1,126 +0,0 @@ -@testset "Basic types" begin - point = Point(2, 3) - @test geomtrait(point) isa PointTrait - @test testgeometry(point) - @test ncoord(point) == 2 - @test getcoord(point, 2) == 3 - @test GeoInterface.coordinates(point) == [2, 3] - - line = Line(Point(2, 3), Point(4, 5)) - @test geomtrait(line) isa LineTrait - @test testgeometry(line) - @test ngeom(line) == 2 - @test getgeom(line, 2) == Point(4, 5) - @test GeoInterface.coordinates(line) == [[2, 3], [4, 5]] - - mp = MultiPoint([point, point]) - @test geomtrait(mp) isa MultiPointTrait - @test testgeometry(mp) - @test ngeom(mp) == 2 - @test getgeom(mp, 2) == point - @test GeoInterface.coordinates(mp) == [[2, 3], [2, 3]] - - linestring = LineString(Point{2,Int}[(10, 10), (20, 20), (10, 40)]) - @test geomtrait(linestring) isa LineStringTrait - @test testgeometry(linestring) - @test ngeom(linestring) == 3 - @test ncoord(linestring) == 2 - @test getgeom(linestring, 1) == Point(10, 10) - @test getgeom(linestring, 2) == Point(20, 20) - @test getgeom(linestring, 3) == Point(10, 40) - @test GeoInterface.coordinates(linestring) == [[10, 10], [20, 20], [10, 40]] - - multilinestring = MultiLineString([linestring, linestring]) - @test geomtrait(multilinestring) isa MultiLineStringTrait - @test testgeometry(multilinestring) - @test GeoInterface.coordinates(multilinestring) == - [[[10, 10], [20, 20], [10, 40]], [[10, 10], [20, 20], [10, 40]]] - @test ncoord(multilinestring) == 2 - - poly = Polygon(rand(Point{2,Float32}, 5), [rand(Point{2,Float32}, 5)]) - @test geomtrait(poly) isa PolygonTrait - @test testgeometry(poly) - @test length(GeoInterface.coordinates(poly)) == 2 - @test length(GeoInterface.coordinates(poly)[1]) == 5 - - triangle = Triangle(point, point, point) - @test geomtrait(triangle) isa PolygonTrait # ?? should it be a Triangle trait - @test testgeometry(triangle) - @test length(GeoInterface.coordinates(triangle)) == 1 - @test length(GeoInterface.coordinates(triangle)[1]) == 3 - - polys = MultiPolygon([poly, poly]) - @test geomtrait(polys) isa MultiPolygonTrait - @test testgeometry(polys) - @test length(GeoInterface.coordinates(polys)) == 2 - @test length(GeoInterface.coordinates(polys)[1]) == 2 - @test length(GeoInterface.coordinates(polys)[1][1]) == 5 -end - -@testset "Mesh" begin - mesh = triangle_mesh(Sphere(Point3f(0), 1)) - @test testgeometry(mesh) -end - -@testset "Convert" begin - # convert GeoJSON geometry types to GeometryBasics via the GeoInterface - point_str = """{"type":"Point","coordinates":[30.1,10.1]}""" - point_3d_str = """{"type":"Point","coordinates":[30.1,10.1,5.1]}""" - linestring_str = """{"type":"LineString","coordinates":[[30.1,10.1],[10.1,30.1],[40.1,40.1]]}""" - polygon_str = """{"type":"Polygon","coordinates":[[[30.1,10.1],[40.1,40.1],[20.1,40.1],[10.1,20.1],[30.1,10.1]]]}""" - polygon_hole_str = """{"type":"Polygon","coordinates":[[[35.1,10.1],[45.1,45.1],[15.1,40.1],[10.1,20.1],[35.1,10.1]],[[20.1,30.1],[35.1,35.1],[30.1,20.1],[20.1,30.1]]]}""" - multipoint_str = """{"type":"MultiPoint","coordinates":[[10.1,40.1],[40.1,30.1],[20.1,20.1],[30.1,10.1]]}""" - multilinestring_str = """{"type":"MultiLineString","coordinates":[[[10.1,10.1],[20.1,20.1],[10.1,40.1]],[[40.1,40.1],[30.1,30.1],[40.1,20.1],[30.1,10.1]]]}""" - multipolygon_str = """{"type":"MultiPolygon","coordinates":[[[[30.1,20.1],[45.1,40.1],[10.1,40.1],[30.1,20.1]]],[[[15.1,5.1],[40.1,10.1],[10.1,20.1],[5.1,10.1],[15.1,5.1]]]]}""" - multipolygon_hole_str = """{"type":"MultiPolygon","coordinates":[[[[40.1,40.1],[20.1,45.1],[45.1,30.1],[40.1,40.1]]],[[[20.1,35.1],[10.1,30.1],[10.1,10.1],[30.1,5.1],[45.1,20.1],[20.1,35.1]],[[30.1,20.1],[20.1,15.1],[20.1,25.1],[30.1,20.1]]]]}""" - - point_json = GeoJSON.read(point_str) - point_3d_json = GeoJSON.read(point_3d_str) - linestring_json = GeoJSON.read(linestring_str) - polygon_json = GeoJSON.read(polygon_str) - polygon_hole_json = GeoJSON.read(polygon_hole_str) - multipoint_json = GeoJSON.read(multipoint_str) - multilinestring_json = GeoJSON.read(multilinestring_str) - multipolygon_json = GeoJSON.read(multipolygon_str) - multipolygon_hole_json = GeoJSON.read(multipolygon_hole_str) - - point_gb = GeoInterface.convert(GeometryBasics, point_json) - point_3d_gb = GeoInterface.convert(GeometryBasics, point_3d_json) - linestring_gb = GeoInterface.convert(GeometryBasics, linestring_json) - polygon_gb = GeoInterface.convert(GeometryBasics, polygon_json) - polygon_hole_gb = GeoInterface.convert(GeometryBasics, polygon_hole_json) - multipoint_gb = GeoInterface.convert(GeometryBasics, multipoint_json) - multilinestring_gb = GeoInterface.convert(GeometryBasics, multilinestring_json) - multipolygon_gb = GeoInterface.convert(GeometryBasics, multipolygon_json) - multipolygon_hole_gb = GeoInterface.convert(GeometryBasics, multipolygon_hole_json) - - @test point_gb === Point{2,Float32}(30.1, 10.1) - @test point_3d_gb === Point{3,Float32}(30.1, 10.1, 5.1) - @test linestring_gb isa LineString - # TODO, what should we do exactly with linestrings? - # @test length(linestring_gb) == 2 - # @test eltype(linestring_gb) == Line{2, Float64} - - @test polygon_gb isa Polygon - @test isempty(polygon_gb.interiors) - @test polygon_hole_gb isa Polygon - @test length(polygon_hole_gb.interiors) == 1 - @test multipoint_gb isa MultiPoint - @test length(multipoint_gb) == 4 - @test multipoint_gb[4] === Point{2,Float32}(30.1, 10.1) - @test multilinestring_gb isa MultiLineString - @test length(multilinestring_gb) == 2 - @test multipolygon_gb isa MultiPolygon - @test length(multipolygon_gb) == 2 - @test multipolygon_hole_gb isa MultiPolygon - @test length(multipolygon_hole_gb) == 2 - @test length(multipolygon_hole_gb[1].interiors) == 0 - @test length(multipolygon_hole_gb[2].interiors) == 1 -end - -@testset "Extent" begin - rect = Rect2f(Vec2f(0), Vec2f(1.0)) - ext = extent(rect) - @test ext.X == (0.0f0, 1.0f0) - @test ext.Y == (0.0f0, 1.0f0) -end \ No newline at end of file diff --git a/test/runtests.jl b/test/runtests.jl index 5fb98ded..146b47f5 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -2,9 +2,6 @@ using Test, Random, OffsetArrays using GeometryBasics using LinearAlgebra using GeometryBasics: MetaMesh -using GeoInterface -using GeoJSON -using Extents using StaticArrays @testset "GeometryBasics" begin