diff --git a/src/wrappers.jl b/src/wrappers.jl index 5ddfac0..4c15c8d 100644 --- a/src/wrappers.jl +++ b/src/wrappers.jl @@ -171,6 +171,79 @@ for (geomtype, trait, childtype, child_trait, length_check, nesting) in ( convert(::Type{$geomtype}, ::$trait, geom) = $geomtype(geom) # But not if geom is already a WrapperGeometry convert(::Type{$geomtype}, ::$trait, geom::$geomtype) = geom + + function Base.show(io::IO, ::MIME"text/plain", geom::$geomtype{Z, M, T, E, C}; show_mz::Bool = true, screen_ncols::Int = displaysize(io)[2]) where {Z, M, T, E <: Union{Nothing,Extents.Extent}, C} + compact = get(io, :compact, false) + spacing = compact ? "" : " " + show_mz &= !compact + + extent_str = "" + crs_str = "" + if !compact + if !isnothing(geom.extent) + extent_str = ",$(spacing)extent$(spacing)=$(spacing)$(repr(MIME("text/plain"), geom.extent))" + end + if !isnothing(geom.crs) + crs_str = ",$(spacing)crs$(spacing)=$(spacing)$(repr(MIME("text/plain"), geom.crs))" + end + end + + str = "$($geomtype)" + if show_mz + str *= "{$Z,$(spacing)$M}" + end + str *= "(" + this_geom = getgeom(trait(geom), geom) + # keep track of how much space we've used + make sure we give this info to any child geoms so they don't go over the limit + currently_used_space = textwidth(str) + textwidth(extent_str) + textwidth(crs_str) + if this_geom isa AbstractVector + # check here if we have enough room to display the whole object or if we need to condense the string + str *= "[" + currently_used_space += 2 # +2 for brackets + available_space = screen_ncols - currently_used_space + + space_per_object = floor(Int, available_space / length(this_geom)) + + length_of_one_object_in_chars = textwidth(_nice_geom_str(this_geom[1], false, compact, space_per_object)) + + # this makes sure that if we have 1 or 2 geometries here, we show both, but any more and we skip them + num_objects_to_show = min(length(this_geom), max(2, floor(Int, (available_space - 1 #=triple dot character =#) / length_of_one_object_in_chars))) + + # separately track how many objects to show to the left and right of the ...()... + num_objects_left = num_objects_to_show == 1 ? 0 : ceil(Int, num_objects_to_show/2) + num_objects_right = max(1, floor(Int, num_objects_to_show/2)) + + # how many objects are we skipping? + num_missing = length(this_geom) - (num_objects_left + num_objects_right) + + for i ∈ 1:num_objects_left + str *= "$(_nice_geom_str(this_geom[i], false, compact, space_per_object)),$(spacing)" + end + + if num_missing > 0 + # report how many geometries aren't shown here + str *= "…$(spacing)($(num_missing))$(spacing)…$(spacing),$(spacing)" + end + + for i ∈ 1:num_objects_right + str *= _nice_geom_str(this_geom[end - num_objects_right + i], false, compact, space_per_object) + if i != num_objects_right + str *= ",$(spacing)" + end + end + + str *= "]" + else + str *= _nice_geom_str(g, false, compact, screen_ncols - currently_used_space) + end + + str *= extent_str + str *= crs_str + + str *= ")" + print(io, str) + return nothing + end end @eval function $geomtype{Z,M}(geom::T; extent::E=nothing, crs::C=nothing) where {Z,M,T,E,C} @@ -235,6 +308,42 @@ for (geomtype, trait, childtype, child_trait, length_check, nesting) in ( end end +function _nice_geom_str(geom, ::Bool, ::Bool, ::Int) + io = IOBuffer() + show(io, MIME("text/plain"), geom) + return String(take!(io)) +end +# need a work around to pass the show_mz variable through - put string to a temp IOBuffer then read it +function _nice_geom_str(geom::WrapperGeometry, show_mz::Bool, compact::Bool, screen_ncols::Int) + buf = IOBuffer() + io = IOContext(IOContext(buf, :compact => compact)) + show(io, MIME("text/plain"), geom; show_mz = show_mz, screen_ncols = screen_ncols) + return String(take!(buf)) +end +# handle tuples/vectors explicitly +function _nice_geom_str(geom::AbstractVector, ::Bool, compact::Bool, ::Int) + spacing = compact ? "" : " " + str = "[" + str *= _add_elements_with_spacing(geom, spacing) + str *= "]" + return str +end +function _nice_geom_str(geom::Tuple, ::Bool, compact::Bool, ::Int) + spacing = compact ? "" : " " + str = "(" + str *= _add_elements_with_spacing(geom, spacing) + str *= ")" + return str +end + +function _add_elements_with_spacing(itr, spacing::String = "") + str = "" + for x ∈ itr[1:end - 1] + str *= "$(x),$(spacing)" + end + str *= "$(itr[end])" +end + @noinline _wrong_child_error(geomtype, C, child) = throw(ArgumentError("$geomtype must have child objects with trait $C, got $(typeof(child)) with trait $(geomtrait(child))")) @noinline _argument_error(T, A) = throw(ArgumentError("$T does not have $A")) @noinline _length_error(T, f, x) = throw(ArgumentError("Length of array must be $(f.f) $(f.x) for $T")) @@ -340,6 +449,36 @@ function Base.:(==)(g1::Point, g2::Point) end Base.:(!=)(g1::Point, g2::Point) = !(g1 == g2) +function Base.show(io::IO, ::MIME"text/plain", point::Point{Z, M, T, C}; show_mz::Bool = true) where {Z,M,T,C} + print(io, "Point") + this_crs = crs(point) + + compact = get(io, :compact, false) + spacing = compact ? "" : " " + + if !compact && show_mz + print(io, "{$Z, $M}") + end + print(io, "(") + trait = geomtrait(point) + print(io, "($(x(trait, point)),$(spacing)$(y(trait, point))") + if Z + print(io, ",$(spacing)$(z(trait, point))") + end + if M + print(io, ",$(spacing)$(m(trait, point))") + end + print(io, ")") + + if !compact && !isnothing(this_crs) + print(io, ",$(spacing)crs$(spacing)=$(spacing)") + show(io, MIME("text/plain"), this_crs) + end + print(io, ")") + + return nothing +end + @noinline _coord_length_error(Z, M, l) = throw(ArgumentError("Number of coordinates must be $(2 + Z + M) when `Z` is $Z and `M` is $M. Got $l")) @noinline _no_z_error() = throw(ArgumentError("Point has no `Z` coordinate")) @@ -384,6 +523,36 @@ function Feature(geometry=nothing; properties=(;), crs=nothing, extent=nothing) end end +function Base.show(io::IO, ::MIME"text/plain", f::Feature; show_mz::Bool = true) + compact = get(io, :compact, false) + spacing = compact ? "" : " " + print(io, "Feature(") + show(io, MIME("text/plain"), f.parent.geometry; show_mz = show_mz) + non_geom_props = filter(!=(:geometry), propertynames(f.parent)) + if !isempty(non_geom_props) + print(io, ",$(spacing)properties$(spacing)=$(spacing)(") + for (i, property) ∈ enumerate(non_geom_props) + print(io, "$(property)$(spacing)=$(spacing)") + show(io, getproperty(f.parent, property)) + if i != length(non_geom_props) + print(io, ",$(spacing)") + end + end + print(io, ")") + end + if !compact + if !isnothing(f.extent) + print(io, ", extent$(spacing)=$(spacing)") + show(io, MIME("text/plain"), f.extent) + end + if !isnothing(f.crs) + print(io, ", crs$(spacing)=$(spacing)") + show(io, MIME("text/plain"), f.crs) + end + end + print(io, ")") +end + Base.parent(f::Feature) = f.parent isfeature(::Type{<:Feature}) = true @@ -449,6 +618,33 @@ function FeatureCollection(parent; crs=nothing, extent=nothing) end end +function Base.show(io::IO, ::MIME"text/plain", fc::FeatureCollection) + print(io, "FeatureCollection(") + compact = get(io, :compact, false) + spacing = compact ? "" : " " + features = _parent_is_fc(fc) ? getfeature(trait(fc), parent(fc)) : parent(fc) + print(io, "[") + for (i, f) ∈ enumerate(features) + show(io, MIME("text/plain"), f; show_mz = !compact) + if i != length(features) + print(io, ",$(spacing)") + end + end + print(io, "]") + if !compact + if !isnothing(fc.crs) + print(io, ",$(spacing)crs$(spacing)=$(spacing)") + show(io, MIME("text/plain"), fc.crs) + end + if !isnothing(fc.extent) + print(io, ",$(spacing)extent$(spacing)=$(spacing)") + show(io, MIME("text/plain"), fc.extent) + end + end + print(io, ")") + return nothing +end + Base.parent(fc::FeatureCollection) = fc.parent _child_feature_error() = throw(ArgumentError("child objects must be features")) @@ -469,4 +665,4 @@ crs(fc::FeatureCollection) = _parent_is_fc(x) = isfeaturecollection(parent(x)) -end # module +end # module \ No newline at end of file diff --git a/test/test_wrappers.jl b/test/test_wrappers.jl index 47b4020..f8e25e4 100644 --- a/test/test_wrappers.jl +++ b/test/test_wrappers.jl @@ -1,5 +1,20 @@ using Test, GeoFormatTypes, Extents import GeoInterface as GI +using GeoInterface.Wrappers + +# use this to test our string representations for geoms +buf = IOBuffer() +compact_buf = IOContext(buf, :compact => true) + +# checks that our string display for geoms in regular/compact form is as expected +function test_display(geom, expected_str, expected_compact_str) + # checks non-compact string repr + show(buf, MIME"text/plain"(), geom) + @test expected_str == String(take!(buf)) + # checks compact string repr + show(compact_buf, MIME"text/plain"(), geom) + @test expected_compact_str == String(take!(buf)) +end # Point point = GI.Point(1, 2) @@ -16,9 +31,11 @@ GI.getcoord(point, 1) @test_throws ArgumentError GI.Point(1, 2, 3, 4, 5) @test GI.testgeometry(point) @test GI.convert(GI, (1, 2)) isa GI.Point +test_display(point, "Point{false, false}((1, 2))", "Point((1,2))") point_crs = GI.Point(point; crs=EPSG(4326)) @test parent(point_crs) === parent(point) @test GI.crs(point_crs) === EPSG(4326) +test_display(point_crs, "Point{false, false}((1, 2), crs = EPSG{1}((4326,)))", "Point((1,2))") # 3D Point pointz = GI.Point(1, 2, 3) @@ -29,6 +46,7 @@ pointz = GI.Point(1, 2, 3) @test GI.testgeometry(pointz) @test GI.convert(GI, pointz) === pointz @test GI.extent(pointz) == Extents.Extent(X=(1, 1), Y=(2, 2), Z=(3, 3)) +test_display(pointz, "Point{true, false}((1, 2, 3))", "Point((1,2,3))") # 3D measured point pointzm = GI.Point(; X=1, Y=2, Z=3, M=4) @@ -45,6 +63,7 @@ pointzm = GI.Point(; X=1, Y=2, Z=3, M=4) pointzm_crs = GI.Point(; X=1, Y=2, Z=3, M=4, crs=EPSG(4326)) @test parent(pointzm_crs) === parent(pointzm) @test GI.crs(pointzm_crs) === EPSG(4326) +test_display(pointzm, "Point{true, true}((1, 2, 3, 4))", "Point((1,2,3,4))") # Measured point pointm = GI.Point((X=1, Y=2, M=3)) @@ -57,9 +76,11 @@ pointm = GI.Point((X=1, Y=2, M=3)) @test (GI.x(pointm), GI.y(pointm), GI.m(pointm)) == (1, 2, 3) @test_throws ArgumentError GI.z(pointm) @test GI.testgeometry(pointm) +test_display(pointm, "Point{false, true}((1, 2, 3))", "Point((1,2,3))") pointm_crs = GI.Point((X=1, Y=2, M=3); crs=EPSG(4326)) @test parent(pointm_crs) === parent(pointm) @test GI.crs(pointm_crs) === EPSG(4326) +test_display(pointm_crs, "Point{false, true}((1, 2, 3), crs = EPSG{1}((4326,)))", "Point((1,2,3))") # Forced measured point with a tuple pointtm = GI.Point{false,true}(1, 2, 3) @@ -70,9 +91,11 @@ pointtm = GI.Point{false,true}(1, 2, 3) @test (GI.x(pointtm), GI.y(pointtm), GI.m(pointtm)) == (1, 2, 3) @test_throws ArgumentError GI.z(pointtm) @test GI.testgeometry(pointtm) +test_display(pointtm, "Point{false, true}((1, 2, 3))", "Point((1,2,3))") pointtm_crs = GI.Point{false,true}(1, 2, 3; crs=EPSG(4326)) @test parent(pointtm_crs) === parent(pointtm) @test GI.crs(pointtm_crs) === EPSG(4326) +test_display(pointtm_crs, "Point{false, true}((1, 2, 3), crs = EPSG{1}((4326,)))", "Point((1,2,3))") # Point made from an array pointa = GI.Point([1, 2]) @@ -81,6 +104,7 @@ pointa = GI.Point([1, 2]) @test GI.ncoord(pointa) == 2 @test (GI.x(pointa), GI.y(pointa)) == (1, 2) @test GI.testgeometry(pointa) +test_display(pointa, "Point{false, false}((1, 2))", "Point((1,2))") pointaz = GI.Point([1, 2, 3]) @test !GI.ismeasured(pointaz) @@ -88,6 +112,7 @@ pointaz = GI.Point([1, 2, 3]) @test GI.ncoord(pointaz) == 3 @test (GI.x(pointaz), GI.y(pointaz), GI.z(pointaz)) == (1, 2, 3) @test GI.testgeometry(pointaz) +test_display(pointaz, "Point{true, false}((1, 2, 3))", "Point((1,2,3))") pointazm = GI.Point([1, 2, 3, 4]) @test GI.ismeasured(pointazm) @@ -95,6 +120,7 @@ pointazm = GI.Point([1, 2, 3, 4]) @test GI.ncoord(pointazm) == 4 @test (GI.x(pointazm), GI.y(pointazm), GI.z(pointazm), GI.m(pointazm)) == (1, 2, 3, 4) @test GI.testgeometry(pointazm) +test_display(pointazm, "Point{true, true}((1, 2, 3, 4))", "Point((1,2,3,4))") # We can force a vector point to be measured pointam = GI.Point{false,true}([1, 2, 3]) @@ -104,6 +130,7 @@ pointam = GI.Point{false,true}([1, 2, 3]) @test (GI.x(pointam), GI.y(pointam), GI.m(pointam)) == (1, 2, 3) @test_throws ArgumentError GI.z(pointam) @test GI.testgeometry(pointam) +test_display(pointam, "Point{false, true}((1, 2, 3))", "Point((1,2,3))") @test_throws ArgumentError GI.Point(1, 2, 3, 4, 5) # Line @@ -115,12 +142,14 @@ line = GI.Line([(1, 2), (3, 4)]) @test !GI.is3d(line) @test GI.ncoord(line) == 2 @test GI.extent(line) == Extent(X=(1, 3), Y=(2, 4)) +test_display(line, "Line{false, false}([(1, 2), (3, 4)])", "Line([(1,2),(3,4)])") @test_throws ArgumentError GI.Line(point) @test_throws ArgumentError GI.Line([(1, 2)]) @test_throws ArgumentError GI.Line([line, line]) line_crs = GI.Line(line; crs=EPSG(4326)) @test parent(line_crs) === parent(line) @test GI.crs(line_crs) === EPSG(4326) +test_display(line_crs, "Line{false, false}([(1, 2), (3, 4)], crs = EPSG{1}((4326,)))", "Line([(1,2),(3,4)])") # LineString linestring = GI.LineString([(1, 2), (3, 4)]) @@ -130,11 +159,13 @@ linestring = GI.LineString([(1, 2), (3, 4)]) @test GI.testgeometry(linestring) @test !GI.is3d(linestring) @test GI.ncoord(linestring) == 2 +test_display(linestring, "LineString{false, false}([(1, 2), (3, 4)])", "LineString([(1,2),(3,4)])") @test @inferred(GI.extent(linestring)) == Extent(X=(1, 3), Y=(2, 4)) @test_throws ArgumentError GI.LineString([(1, 2)]) linestring_crs = GI.LineString(linestring; crs=EPSG(4326)) @test parent(linestring_crs) === parent(linestring) @test GI.crs(linestring_crs) === EPSG(4326) +test_display(linestring_crs, "LineString{false, false}([(1, 2), (3, 4)], crs = EPSG{1}((4326,)))", "LineString([(1,2),(3,4)])") # LinearRing linearring = GI.LinearRing([(1, 2), (3, 4), (5, 6), (1, 2)]) @@ -144,11 +175,13 @@ linearring = GI.LinearRing([(1, 2), (3, 4), (5, 6), (1, 2)]) @test GI.testgeometry(linearring) @test !GI.is3d(linearring) @test GI.ncoord(linearring) == 2 +test_display(linearring, "LinearRing{false, false}([(1, 2), (3, 4), (5, 6), (1, 2)])", "LinearRing([(1,2),(3,4),(5,6),(1,2)])") @test @inferred(GI.extent(linearring)) == Extent(X=(1, 5), Y=(2, 6)) @test_throws ArgumentError GI.LinearRing([(1, 2)]) linearring_crs = GI.LinearRing(linearring; crs=EPSG(4326)) @test parent(linearring_crs) === parent(linearring) @test GI.crs(linearring_crs) === EPSG(4326) +test_display(linearring_crs, "LinearRing{false, false}([(1, 2), (3, 4), (5, 6), (1, 2)], crs = EPSG{1}((4326,)))", "LinearRing([(1,2),(3,4),(5,6),(1,2)])") # Polygon polygon = GI.Polygon([linearring, linearring]) @@ -163,19 +196,26 @@ polygon = GI.Polygon([linearring, linearring]) @test @inferred(GI.extent(polygon)) == Extent(X=(1, 5), Y=(2, 6)) @test GI.convert(GI, MyPolygon()) isa GI.Polygon @test GI.convert(GI, polygon) === polygon +test_display(polygon, "Polygon{false, false}([LinearRing([(1, 2), … (2) … , (1, 2)]), LinearRing([(1, 2), … (2) … , (1, 2)])])", + "Polygon([LinearRing([(1,2),(3,4),(5,6),(1,2)]),LinearRing([(1,2),(3,4),(5,6),(1,2)])])") polygon_crs = GI.Polygon(polygon; crs=EPSG(4326)) @test parent(polygon_crs) === parent(polygon) @test GI.crs(polygon_crs) === EPSG(4326) +test_display(polygon_crs, "Polygon{false, false}([LinearRing([(1, 2), … (2) … , (1, 2)]), LinearRing([(1, 2), … (2) … , (1, 2)])], crs = EPSG{1}((4326,)))", + "Polygon([LinearRing([(1,2),(3,4),(5,6),(1,2)]),LinearRing([(1,2),(3,4),(5,6),(1,2)])])") # Make sure `linestring` is also ok in polygons polygon = GI.Polygon([linestring, linestring]) @test GI.getgeom(polygon, 1) === linestring @test collect(GI.getgeom(polygon)) == [linestring, linestring] +test_display(polygon, "Polygon{false, false}([LineString([(1, 2), (3, 4)]), LineString([(1, 2), (3, 4)])])", + "Polygon([LineString([(1,2),(3,4)]),LineString([(1,2),(3,4)])])") linearring3d = GI.LinearRing([(1, 2, 3), (3, 4, 5), (5, 6, 7), (1, 2, 3)]) polygon3d = GI.Polygon([linearring3d, linearring3d]) @test GI.is3d(polygon3d) @test GI.ncoord(polygon3d) == 3 @test GI.extent(polygon3d) == Extents.Extent(X=(1, 5), Y=(2, 6), Z=(3, 7)) +test_display(linearring3d, "LinearRing{true, false}([(1, 2, 3), (3, 4, 5), (5, 6, 7), (1, 2, 3)])", "LinearRing([(1,2,3),(3,4,5),(5,6,7),(1,2,3)])") # MultiPoint multipoint = GI.MultiPoint([(1, 2), (3, 4), (3, 2), (1, 4), (7, 8), (9, 10)]) @@ -187,9 +227,11 @@ multipoint = GI.MultiPoint([(1, 2), (3, 4), (3, 2), (1, 4), (7, 8), (9, 10)]) @test @inferred(GI.extent(multipoint)) == Extent(X=(1, 9), Y=(2, 10)) @test_throws ArgumentError GI.MultiPoint([[(1, 2), (3, 4), (3, 2), (1, 4), (7, 8), (9, 10)]]) @test GI.testgeometry(multipoint) +test_display(multipoint, "MultiPoint{false, false}([(1, 2), (3, 4), (3, 2), (1, 4), (7, 8), (9, 10)])", "MultiPoint([(1,2),(3,4),(3,2),(1,4),(7,8),(9,10)])") multipoint_crs = GI.MultiPoint(multipoint; crs=EPSG(4326)) @test parent(multipoint_crs) == parent(multipoint) @test GI.crs(multipoint_crs) === EPSG(4326) +test_display(multipoint_crs, "MultiPoint{false, false}([(1, 2), (3, 4), … (2) … , (7, 8), (9, 10)], crs = EPSG{1}((4326,)))", "MultiPoint([(1,2),(3,4),(3,2),(1,4),(7,8),(9,10)])") # GeometryCollection geoms = [line, linestring, linearring, multipoint, (1, 2)] @@ -201,9 +243,13 @@ collection = GI.GeometryCollection(geoms) @test !GI.is3d(collection) @test GI.ncoord(collection) == 2 @test GI.extent(collection) == reduce(Extents.union, map(GI.extent, geoms)) +test_display(collection, "GeometryCollection{false, false}([Line([(1, 2), (3, 4)]), … (3) … , (1, 2)])", + "GeometryCollection([Line([(1,2),(3,4)]),LineString([(1,2),(3,4)]),…(2)…,(1,2)])") collection_crs = GI.GeometryCollection(collection; crs=EPSG(4326)) @test parent(collection_crs) == parent(collection) @test GI.crs(collection_crs) === EPSG(4326) +test_display(collection_crs, "GeometryCollection{false, false}([Line([(1, 2), (3, 4)]), … (3) … , (1, 2)], crs = EPSG{1}((4326,)))", + "GeometryCollection([Line([(1,2),(3,4)]),LineString([(1,2),(3,4)]),…(2)…,(1,2)])") # MultiCurve multicurve = GI.MultiCurve([linestring, linearring]) @@ -216,10 +262,13 @@ multicurve = GI.MultiCurve([linestring, linearring]) @test GI.extent(multicurve) == Extent(X=(1, 5), Y=(2, 6)) @test_throws ArgumentError GI.MultiCurve([pointz, polygon]) @test GI.testgeometry(multicurve) +test_display(multicurve, "MultiCurve{false, false}([LineString([(1, 2), (3, 4)]), LinearRing([(1, 2), … (2) … , (1, 2)])])", + "MultiCurve([LineString([(1,2),(3,4)]),LinearRing([(1,2),(3,4),…(1)…,(1,2)])])") multicurve_crs = GI.MultiCurve(multicurve; crs=EPSG(4326)) @test parent(multicurve_crs) == parent(multicurve) @test GI.crs(multicurve_crs) === EPSG(4326) - +test_display(multicurve_crs, "MultiCurve{false, false}([LineString([(1, 2), (3, 4)]), LinearRing([(1, 2), … (2) … , (1, 2)])], crs = EPSG{1}((4326,)))", + "MultiCurve([LineString([(1,2),(3,4)]),LinearRing([(1,2),(3,4),…(1)…,(1,2)])])") # MultiPolygon polygon = GI.Polygon([linearring, linearring]) @@ -229,8 +278,8 @@ multipolygon = GI.MultiPolygon([polygon]) @test GI.getgeom(multipolygon, 1) === polygon @test !GI.is3d(multipolygon) @test GI.ncoord(multipolygon) == 2 -@show polygon -@show GI.getgeom(polygon, 1) +test_display(multipolygon, "MultiPolygon{false, false}([Polygon([LinearRing([(1, 2), … (2) … , (1, 2)]), LinearRing([(1, 2), … (2) … , (1, 2)])])])", + "MultiPolygon([Polygon([LinearRing([(1,2),…(2)…,(1,2)]),LinearRing([(1,2),…(2)…,(1,2)])])])") # MultiPolygon extent does not infer, maybe due to nesting @test GI.extent(multipolygon) == Extent(X=(1, 5), Y=(2, 6)) @test collect(GI.getpoint(multipolygon)) == collect(GI.getpoint(polygon)) @@ -239,6 +288,8 @@ multipolygon = GI.MultiPolygon([polygon]) multipolygon_crs = GI.MultiPolygon(multipolygon; crs=EPSG(4326)) @test parent(multipolygon_crs) == parent(multipolygon) @test GI.crs(multipolygon_crs) === EPSG(4326) +test_display(multipolygon_crs, "MultiPolygon{false, false}([Polygon([LinearRing([(1, 2), … (2) … , (1, 2)]), LinearRing([(1, 2), … (2) … , (1, 2)])])], crs = EPSG{1}((4326,)))", + "MultiPolygon([Polygon([LinearRing([(1,2),…(2)…,(1,2)]),LinearRing([(1,2),…(2)…,(1,2)])])])") # PolyhedralSurface polyhedralsurface = GI.PolyhedralSurface([polygon, polygon]) @@ -252,14 +303,20 @@ polyhedralsurface = GI.PolyhedralSurface([polygon, polygon]) @test GI.getgeom(polyhedralsurface, 1) == polygon @test collect(GI.getpoint(polyhedralsurface)) == vcat(collect(GI.getpoint(polygon)), collect(GI.getpoint(polygon))) @test GI.testgeometry(polyhedralsurface) +test_display(polyhedralsurface, "PolyhedralSurface{false, false}([Polygon([LinearRing([(1, 2), … (2) … , (1, 2)]), LinearRing([(1, 2), … (2) … , (1, 2)])]), Polygon([LinearRing([(1, 2), … (2) … , (1, 2)]), LinearRing([(1, 2), … (2) … , (1, 2)])])])", + "PolyhedralSurface([Polygon([LinearRing([(1,2),…(2)…,(1,2)]),LinearRing([(1,2),…(2)…,(1,2)])]),Polygon([LinearRing([(1,2),…(2)…,(1,2)]),LinearRing([(1,2),…(2)…,(1,2)])])])") polyhedralsurface_crs = GI.PolyhedralSurface(polyhedralsurface; crs=EPSG(4326)) @test parent(polyhedralsurface_crs) == parent(polyhedralsurface) @test GI.crs(polyhedralsurface_crs) === EPSG(4326) +test_display(polyhedralsurface_crs, "PolyhedralSurface{false, false}([Polygon([LinearRing([(1, 2), … (2) … , (1, 2)]), LinearRing([(1, 2), … (2) … , (1, 2)])]), Polygon([LinearRing([(1, 2), … (2) … , (1, 2)]), LinearRing([(1, 2), … (2) … , (1, 2)])])], crs = EPSG{1}((4326,)))", + "PolyhedralSurface([Polygon([LinearRing([(1,2),…(2)…,(1,2)]),LinearRing([(1,2),…(2)…,(1,2)])]),Polygon([LinearRing([(1,2),…(2)…,(1,2)]),LinearRing([(1,2),…(2)…,(1,2)])])])") # Round-trip coordinates multipolygon_coords = [[[[1, 2], [3, 4], [3, 2], [1, 4]]]] multipolygon = GI.MultiPolygon(multipolygon_coords) @test GI.coordinates(multipolygon) == multipolygon_coords +test_display(multipolygon, "MultiPolygon{false, false}([Polygon([LinearRing([[1, 2], [3, 4], [3, 2], [1, 4]])])])", + "MultiPolygon([Polygon([LinearRing([[1,2],[3,4],[3,2],[1,4]])])])") # Wrong parent type @test_throws ArgumentError GI.Point(nothing) @@ -276,9 +333,13 @@ feature = GI.Feature(multipolygon; properties=(x=1, y=2, z=3)) @test GI.crs(feature) == nothing @test GI.extent(feature) == GI.extent(multipolygon) @test GI.testfeature(feature) +test_display(feature, "Feature(MultiPolygon{false, false}([Polygon([LinearRing([[1, 2], [3, 4], [3, 2], [1, 4]])])]), properties = (x = 1, y = 2, z = 3))", + "Feature(MultiPolygon([Polygon([LinearRing([[1,2],[3,4],[3,2],[1,4]])])]),properties=(x=1,y=2,z=3))") feature = GI.Feature(multipolygon; properties=(x=1, y=2, z=3), crs=EPSG(4326), extent=extent(multipolygon) ) +test_display(feature, "Feature(MultiPolygon{false, false}([Polygon([LinearRing([[1, 2], [3, 4], [3, 2], [1, 4]])])]), properties = (x = 1, y = 2, z = 3), crs = EPSG{1}((4326,)))", + "Feature(MultiPolygon([Polygon([LinearRing([[1,2],[3,4],[3,2],[1,4]])])]),properties=(x=1,y=2,z=3))") @test GI.geometry(feature) === multipolygon @test GI.properties(feature) === (x=1, y=2, z=3) @test GI.crs(feature) == EPSG(4326) @@ -298,6 +359,8 @@ fc = GI.FeatureCollection(fc_unwrapped.parent; crs=EPSG(4326), extent=GI.extent( @test GI.extent(fc) == fc.extent @test first(GI.getfeature(fc)) == GI.getfeature(fc, 1) === feature @test GI.testfeaturecollection(fc) +test_display(fc, "FeatureCollection([Feature(MultiPolygon{false, false}([Polygon([LinearRing([[1, 2], [3, 4], [3, 2], [1, 4]])])]), properties = (x = 1, y = 2, z = 3), crs = EPSG{1}((4326,)))], crs = EPSG{1}((4326,)), extent = Extent(X = (1, 3), Y = (2, 4)))", + "FeatureCollection([Feature(MultiPolygon([Polygon([LinearRing([[1,2],[3,4],[3,2],[1,4]])])]),properties=(x=1,y=2,z=3))])") @test_throws ArgumentError GI.FeatureCollection([1]) vecfc = GI.FeatureCollection([(geometry=(1,2), a=1, b=2)]) @test GI.getfeature(vecfc, 1) == (geometry=(1,2), a=1, b=2)