Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow vectors with mixed single and multi geometries to be plotted in Makie #136

Merged
merged 12 commits into from
Jun 28, 2024
2 changes: 1 addition & 1 deletion GeoInterfaceMakie/Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "GeoInterfaceMakie"
uuid = "0edc0954-3250-4c18-859d-ec71c1660c08"
authors = ["JuliaGeo and contributors"]
version = "0.1.6"
version = "0.1.7"

[deps]
GeoInterface = "cf35fbd7-0cd7-5166-be24-54bfbe79505f"
Expand Down
53 changes: 53 additions & 0 deletions GeoInterfaceMakie/src/GeoInterfaceMakie.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,32 @@ function _convert_arguments(t, geom)::Tuple
geob = GI.convert(GB, geom)
MC.convert_arguments(t, geob)
end

function _convert_array_arguments(t, geoms::AbstractArray{T})::Tuple where T
if Missing <: T
geob = map(geom -> GI.convert(GB, geom), skipmissing(geoms))
else
geob = map(geom -> GI.convert(GB, geom), geoms)
end
if !(eltype(geob) <: GB.AbstractGeometry) || eltype(geob) isa Union # Unions are bad
if isempty(geob)
geob = geob
end
first_trait = GI.geomtrait(first(geob))
last_trait = GI.geomtrait(last(geob))
asinghvi17 marked this conversation as resolved.
Show resolved Hide resolved
if first_trait == last_trait
# This should never happen, if the traits are the same, unless the dimensions are wrong.
# error("GeoInterfaceMakie: Geometry traits are the same, this should never happen.")
elseif first_trait isa GI.PolygonTrait || first_trait isa GI.MultiPolygonTrait
if last_trait isa GI.PolygonTrait || last_trait isa GI.MultiPolygonTrait
geob = to_multipoly(geob)
end
elseif first_trait isa GI.LineStringTrait || first_trait isa GI.MultiLineStringTrait
if last_trait isa GI.LineStringTrait || last_trait isa GI.MultiLineStringTrait
geob = to_multilinestring(geob)
end
end
end
return MC.convert_arguments(t, geob)
end

Expand Down Expand Up @@ -109,6 +129,39 @@ end
# Enable Makie.jl for GeoInterface wrappers
@enable GeoInterface.Wrappers.WrapperGeometry


# Munging utilities for mixed geometry arrays
# Taken from GeoMakie.jl

# TODO: this takes double the amount of time in convert args
# than it does using the functions straight, so something is wrong here.
# Maybe its actually a good idea, to call these functions directly, or move
# the detection code before the actual conversion...

to_multipoly(poly::GB.Polygon) = GB.MultiPolygon([poly])
to_multipoly(poly::Vector{GB.Polygon}) = GB.MultiPolygon(poly)
to_multipoly(mp::GB.MultiPolygon) = mp
to_multipoly(geom) = to_multipoly(GeoInterface.trait(geom), geom)
to_multipoly(::Nothing, geom::AbstractVector) = to_multipoly.(GeoInterface.trait.(geom), geom)
to_multipoly(::GeoInterface.PolygonTrait, geom) = GB.MultiPolygon([GeoInterface.convert(GB, geom)])
to_multipoly(::GeoInterface.MultiPolygonTrait, geom) = GeoInterface.convert(GB, geom)

to_multilinestring(poly::GB.LineString) = GB.MultiLineString([poly])
to_multilinestring(poly::Vector{GB.Polygon}) = GB.MultiLineString(poly)
to_multilinestring(mp::GB.MultiLineString) = mp
to_multilinestring(geom) = to_multilinestring(GeoInterface.trait(geom), geom)
to_multilinestring(geom::AbstractVector) = to_multilinestring.(GeoInterface.trait.(geom), geom)
to_multilinestring(::GeoInterface.LineStringTrait, geom) = GB.MultiLineString([GeoInterface.convert(GB, geom)])
to_multilinestring(::GeoInterface.MultiLineStringTrait, geom) = GeoInterface.convert(GB, geom)

to_multipoint(poly::GB.Point) = GB.MultiPoint([poly])
to_multipoint(poly::Vector{GB.Point}) = GB.MultiPoint(poly)
to_multipoint(mp::GB.MultiPoint) = mp
to_multipoint(geom) = to_multipoint(GeoInterface.trait(geom), geom)
to_multipoint(geom::AbstractVector) = to_multipoint.(GeoInterface.trait.(geom), geom)
to_multipoint(::GeoInterface.PointTrait, geom) = GB.MultiPoint([GeoInterface.convert(GB, geom)])
to_multipoint(::GeoInterface.MultiPointTrait, geom) = GeoInterface.convert(GB, geom)

# TODO
# Features and Feature collections
# https://github.com/JuliaGeo/GeoInterface.jl/pull/72#issue-1406325596
Expand Down
8 changes: 7 additions & 1 deletion GeoInterfaceMakie/test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ end
geoms = [
unitsquare,
GI.difference(bigsquare, smallsquare),
boundary(unitsquare),
LibGEOS.boundary(unitsquare),
multipolygon,
point,
multipoint,
Expand Down Expand Up @@ -54,3 +54,9 @@ end
lines = [GI.LineString([(1, 2), (3, 4)]), GI.LineString([(5, 4), (5, 6)]), missing]
Makie.plot(lines)
end

@testset "Mixed geometry types work" begin
poly = GI.Polygon([GI.LinearRing([(0, 0), (1, 0), (1, 1), (0, 0)])])
multipoly = GI.MultiPolygon([poly, poly])
@test_nowarn Makie.plot([poly, multipoly])
end
Loading