Skip to content

CoveredBy

julia
export coveredby

What is coveredby?

The coveredby function checks if one geometry is covered by another geometry. This is an extension of within that does not require the interiors of the two geometries to intersect, but still does require that the interior and boundary of the first geometry isn't outside of the second geometry.

To provide an example, consider this point and line:

julia
import GeometryOps as GO
import GeoInterface as GI
using Makie
using CairoMakie

p1 = (0.0, 0.0)
l1 = GI.Line([p1, (1.0, 1.0)])
f, a, p = lines(GI.getpoint(l1))
scatter!(p1, color = :red)
f

As we can see, p1 is on the endpoint of l1. This means it is not within, but it does meet the definition of coveredby.

julia
GO.coveredby(p1, l1)  # true
true

Implementation

This is the GeoInterface-compatible implementation.

First, we implement a wrapper method that dispatches to the correct implementation based on the geometry trait.

Each of these calls a method in the geom_geom_processors file. The methods in this file determine if the given geometries meet a set of criteria. For the coveredby function and arguments g1 and g2, this criteria is as follows: - points of g1 are allowed to be in the interior of g2 (either through overlap or crossing for lines) - points of g1 are allowed to be on the boundary of g2 - points of g1 are not allowed to be in the exterior of g2 - no points of g1 are required to be in the interior of g2 - no points of g1 are required to be on the boundary of g2 - no points of g1 are required to be in the exterior of g2

The code for the specific implementations is in the geom_geom_processors file.

julia
const COVEREDBY_ALLOWS = (in_allow = true, on_allow = true, out_allow = false)
const COVEREDBY_CURVE_ALLOWS = (over_allow = true, cross_allow = true, on_allow = true, out_allow = false)
const COVEREDBY_CURVE_REQUIRES = (in_require = false, on_require = false, out_require = false)
const COVEREDBY_POLYGON_REQUIRES = (in_require = true, on_require = false, out_require = false,)
const COVEREDBY_EXACT = (exact = _False(),)

"""
    coveredby(g1, g2)::Bool

Return `true` if the first geometry is completely covered by the second
geometry. The interior and boundary of the primary geometry (g1) must not
intersect the exterior of the secondary geometry (g2).

Furthermore, `coveredby` returns the exact opposite result of `covers`. They are
equivalent with the order of the arguments swapped.

# Examples
```jldoctest setup=:(using GeometryOps, GeometryBasics)
import GeometryOps as GO, GeoInterface as GI
p1 = GI.Point(0.0, 0.0)
p2 = GI.Point(1.0, 1.0)
l1 = GI.Line([p1, p2])

GO.coveredby(p1, l1)

output

julia
true
```
"""
coveredby(g1, g2) = _coveredby(trait(g1), g1, trait(g2), g2)

Convert features to geometries

julia
_coveredby(::GI.FeatureTrait, g1, ::Any, g2) = coveredby(GI.geometry(g1), g2)
_coveredby(::Any, g1, t2::GI.FeatureTrait, g2) = coveredby(g1, GI.geometry(g2))
_coveredby(::FeatureTrait, g1, ::FeatureTrait, g2) = coveredby(GI.geometry(g1), GI.geometry(g2))

Points coveredby geometries

Point is coveredby another point if those points are equal

julia
_coveredby(
    ::GI.PointTrait, g1,
    ::GI.PointTrait, g2,
) = equals(g1, g2)

Point is coveredby a line/linestring if it is on a line vertex or an edge

julia
_coveredby(
    ::GI.PointTrait, g1,
    ::Union{GI.LineTrait, GI.LineStringTrait}, g2,
) = _point_curve_process(
    g1, g2;
    COVEREDBY_ALLOWS...,
    closed_curve = false,
)

Point is coveredby a linearring if it is on a vertex or an edge of ring

julia
_coveredby(
    ::GI.PointTrait, g1,
    ::GI.LinearRingTrait, g2,
) = _point_curve_process(
    g1, g2;
    COVEREDBY_ALLOWS...,
    closed_curve = true,
)

Point is coveredby a polygon if it is inside polygon, including edges/vertices

julia
_coveredby(
    ::GI.PointTrait, g1,
    ::GI.PolygonTrait, g2,
) = _point_polygon_process(
    g1, g2;
    COVEREDBY_ALLOWS...,
    COVEREDBY_EXACT...,
)

Points cannot cover any geometry other than points

julia
_coveredby(
    ::Union{GI.AbstractCurveTrait, GI.PolygonTrait}, g1,
    ::GI.PointTrait, g2,
) = false

Lines coveredby geometries

julia
#= Linestring is coveredby a line if all interior and boundary points of the
first line are on the interior/boundary points of the second line. =#
_coveredby(
    ::Union{GI.LineTrait, GI.LineStringTrait}, g1,
    ::Union{GI.LineTrait, GI.LineStringTrait}, g2,
) = _line_curve_process(
    g1, g2;
    COVEREDBY_CURVE_ALLOWS...,
    COVEREDBY_CURVE_REQUIRES...,
    COVEREDBY_EXACT...,
    closed_line = false,
    closed_curve = false,
)

#= Linestring is coveredby a ring if all interior and boundary points of the
line are on the edges of the ring. =#
_coveredby(
    ::Union{GI.LineTrait, GI.LineStringTrait}, g1,
    ::GI.LinearRingTrait, g2,
) = _line_curve_process(
    g1, g2;
    COVEREDBY_CURVE_ALLOWS...,
    COVEREDBY_CURVE_REQUIRES...,
    COVEREDBY_EXACT...,
    closed_line = false,
    closed_curve = true,
)

#= Linestring is coveredby a polygon if all interior and boundary points of the
line are in the polygon interior or on its edges, including hole edges. =#
_coveredby(
    ::Union{GI.LineTrait, GI.LineStringTrait}, g1,
    ::GI.PolygonTrait, g2,
) = _line_polygon_process(
    g1, g2;
    COVEREDBY_ALLOWS...,
    COVEREDBY_CURVE_REQUIRES...,
    COVEREDBY_EXACT...,
    closed_line = false,
)

Rings covered by geometries

julia
#= Linearring is covered by a line if all vertices and edges of the ring are on
the edges and vertices of the line. =#
_coveredby(
    ::GI.LinearRingTrait, g1,
    ::Union{GI.LineTrait, GI.LineStringTrait}, g2,
) = _line_curve_process(
    g1, g2;
    COVEREDBY_CURVE_ALLOWS...,
    COVEREDBY_CURVE_REQUIRES...,
    COVEREDBY_EXACT...,
    closed_line = true,
    closed_curve = false,
)

#= Linearring is covered by another linear ring if all vertices and edges of the
first ring are on the edges/vertices of the second ring. =#
_coveredby(
    ::GI.LinearRingTrait, g1,
    ::GI.LinearRingTrait, g2,
) = _line_curve_process(
    g1, g2;
    COVEREDBY_CURVE_ALLOWS...,
    COVEREDBY_CURVE_REQUIRES...,
    COVEREDBY_EXACT...,
    closed_line = true,
    closed_curve = true,
)

#= Linearring is coveredby a polygon if all vertices and edges of the ring are
in the polygon interior or on the polygon edges, including hole edges. =#
_coveredby(
    ::GI.LinearRingTrait, g1,
    ::GI.PolygonTrait, g2,
) = _line_polygon_process(
    g1, g2;
    COVEREDBY_ALLOWS...,
    COVEREDBY_CURVE_REQUIRES...,
    COVEREDBY_EXACT...,
    closed_line = true,
)

Polygons covered by geometries

julia
#= Polygon is covered by another polygon if if the interior and edges of the
first polygon are in the second polygon interior or on polygon edges, including
hole edges.=#
_coveredby(
    ::GI.PolygonTrait, g1,
    ::GI.PolygonTrait, g2,
) = _polygon_polygon_process(
    g1, g2;
    COVEREDBY_ALLOWS...,
    COVEREDBY_POLYGON_REQUIRES...,
    COVEREDBY_EXACT...,
)

Polygons cannot covered by any curves

julia
_coveredby(
    ::GI.PolygonTrait, g1,
    ::GI.AbstractCurveTrait, g2,
) = false

Geometries coveredby multi-geometry/geometry collections

julia
#= Geometry is covered by a multi-geometry or a collection if one of the elements
of the collection cover the geometry. =#
function _coveredby(
    ::Union{GI.PointTrait, GI.AbstractCurveTrait, GI.PolygonTrait}, g1,
    ::Union{
        GI.MultiPointTrait, GI.AbstractMultiCurveTrait,
        GI.MultiPolygonTrait, GI.GeometryCollectionTrait,
    }, g2,
)
    for sub_g2 in GI.getgeom(g2)
        coveredby(g1, sub_g2) && return true
    end
    return false
end

Multi-geometry/geometry collections coveredby geometries

julia
#= Multi-geometry or a geometry collection is covered by a geometry if all
elements of the collection are covered by the geometry. =#
function _coveredby(
    ::Union{
        GI.MultiPointTrait, GI.AbstractMultiCurveTrait,
        GI.MultiPolygonTrait, GI.GeometryCollectionTrait,
    }, g1,
    ::GI.AbstractGeometryTrait, g2,
)
    for sub_g1 in GI.getgeom(g1)
        !coveredby(sub_g1, g2) && return false
    end
    return true
end

This page was generated using Literate.jl.