Skip to content

Commit cb1bcf0

Browse files
eliascarvjuliohm
andauthored
Add ValidCoords transform (#1152)
* Add 'InDomain' transform * Add docstring * Add to documentation && Add to exports * Add tests * Update docstring * Update example * Add more tests * More adjustments * Rename InDomain to ValidCoords * Rename helper * Apply suggestions * Apply suggestions * Apply suggestions from code review Co-authored-by: Júlio Hoffimann <[email protected]> * Use the correct parent type * Apply suggestions from code review Co-authored-by: Júlio Hoffimann <[email protected]> * Apply suggestions * Add more tests * Adjust code order --------- Co-authored-by: Júlio Hoffimann <[email protected]>
1 parent f76f9a3 commit cb1bcf0

File tree

5 files changed

+174
-0
lines changed

5 files changed

+174
-0
lines changed

docs/src/transforms.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,26 @@ using Unitful: m, cm
173173
Point(1m, 2m, 3m) |> LengthUnit(cm)
174174
```
175175

176+
## ValidCoords
177+
178+
```@docs
179+
ValidCoords
180+
```
181+
182+
```@example transforms
183+
# load coordinate reference system
184+
using CoordRefSystems: LatLon
185+
186+
# regular grid with LatLon coordinates
187+
grid = RegularGrid(Point(LatLon(-90, -180)), Point(LatLon(90, 180)), dims=(10, 10))
188+
189+
# retain elements in the projection domain
190+
subgrid = grid |> ValidCoords(Mercator)
191+
192+
# plot the projected grid
193+
viz(subgrid |> Proj(Mercator), showsegments=true)
194+
```
195+
176196
## Shadow
177197

178198
```@docs

src/Meshes.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,7 @@ export
542542
Proj,
543543
Morphological,
544544
LengthUnit,
545+
ValidCoords,
545546
Shadow,
546547
Slice,
547548
Repair,

src/transforms.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ include("transforms/stdcoords.jl")
9696
include("transforms/proj.jl")
9797
include("transforms/morphological.jl")
9898
include("transforms/lengthunit.jl")
99+
include("transforms/validcoords.jl")
99100
include("transforms/shadow.jl")
100101
include("transforms/slice.jl")
101102
include("transforms/repair.jl")

src/transforms/validcoords.jl

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# ------------------------------------------------------------------
2+
# Licensed under the MIT License. See LICENSE in the project root.
3+
# ------------------------------------------------------------------
4+
5+
"""
6+
ValidCoords(CRS)
7+
ValidCoords(code)
8+
9+
Retain the geometries within the domain of the
10+
projection of type `CRS` or with EPSG/ESRI `code`.
11+
"""
12+
struct ValidCoords{CRS} <: GeometricTransform end
13+
14+
ValidCoords(CRS) = ValidCoords{CRS}()
15+
16+
ValidCoords(code::Type{<:EPSG}) = ValidCoords(CoordRefSystems.get(code))
17+
18+
ValidCoords(code::Type{<:ESRI}) = ValidCoords(CoordRefSystems.get(code))
19+
20+
parameters(::ValidCoords{CRS}) where {CRS} = (; CRS)
21+
22+
preprocess(t::ValidCoords, d::Domain) = findall(g -> _isvalid(t, g), d)
23+
24+
function preprocess(t::ValidCoords, d::Mesh)
25+
points = vertices(d)
26+
topo = topology(d)
27+
findall(elements(topo)) do elem
28+
is = indices(elem)
29+
all(_isvalid(t, points[i]) for i in is)
30+
end
31+
end
32+
33+
apply(t::ValidCoords, d::Domain) = view(d, preprocess(t, d)), nothing
34+
35+
# -----------
36+
# IO METHODS
37+
# -----------
38+
39+
Base.show(io::IO, ::ValidCoords{CRS}) where {CRS} = print(io, "ValidCoords(CRS: $CRS)")
40+
41+
function Base.show(io::IO, ::MIME"text/plain", t::ValidCoords{CRS}) where {CRS}
42+
summary(io, t)
43+
println(io)
44+
print(io, "└─ CRS: $CRS")
45+
end
46+
47+
# -----------------
48+
# HELPER FUNCTIONS
49+
# -----------------
50+
51+
_isvalid(::ValidCoords{CRS}, p::Point) where {CRS} = indomain(CRS, coords(p))
52+
_isvalid(t::ValidCoords, g::Polytope) = all(p -> _isvalid(t, p), eachvertex(g))
53+
_isvalid(t::ValidCoords, g::MultiPolytope) = all(p -> _isvalid(t, p), eachvertex(g))
54+
_isvalid(t::ValidCoords, g::Geometry) = all(p -> _isvalid(t, p), pointify(g))

test/transforms.jl

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1782,6 +1782,104 @@ end
17821782
@test r SimpleMesh(f.(vertices(d)), topology(d))
17831783
end
17841784

1785+
@testitem "ValidCoords" setup = [Setup] begin
1786+
@test !isaffine(ValidCoords(Mercator))
1787+
@test !TB.isrevertible(ValidCoords(Mercator))
1788+
@test !TB.isinvertible(ValidCoords(Mercator))
1789+
@test TB.parameters(ValidCoords(Mercator)) == (; CRS=Mercator)
1790+
@test TB.parameters(ValidCoords(EPSG{3395})) == (; CRS=Mercator{WGS84Latest})
1791+
@test TB.parameters(ValidCoords(ESRI{54017})) == (; CRS=Behrmann{WGS84Latest})
1792+
f = ValidCoords(Mercator)
1793+
@test sprint(show, f) == "ValidCoords(CRS: CoordRefSystems.Mercator)"
1794+
@test sprint(show, MIME"text/plain"(), f) == """
1795+
ValidCoords transform
1796+
└─ CRS: CoordRefSystems.Mercator"""
1797+
1798+
# ---------
1799+
# POINTSET
1800+
# ---------
1801+
1802+
f = ValidCoords(Mercator)
1803+
d = PointSet([latlon(-90, 0), latlon(-45, 0), latlon(0, 0), latlon(45, 0), latlon(90, 0)])
1804+
r, c = TB.apply(f, d)
1805+
@test r == PointSet([latlon(-45, 0), latlon(0, 0), latlon(45, 0)])
1806+
1807+
# ------------
1808+
# GEOMETRYSET
1809+
# ------------
1810+
1811+
f = ValidCoords(Mercator)
1812+
t1 = Triangle(latlon(-90, 0), latlon(-45, 30), latlon(-45, -30))
1813+
t2 = Triangle(latlon(-45, 0), latlon(0, 30), latlon(0, -30))
1814+
t3 = Triangle(latlon(0, -30), latlon(0, 30), latlon(45, 0))
1815+
t4 = Triangle(latlon(45, -30), latlon(45, 30), latlon(90, 0))
1816+
d = GeometrySet([t1, t2, t3, t4])
1817+
r, c = TB.apply(f, d)
1818+
@test r == GeometrySet([t2, t3])
1819+
1820+
f = ValidCoords(Mercator)
1821+
t1 = Triangle(latlon(-90, 0), latlon(-45, 30), latlon(-45, -30))
1822+
t2 = Triangle(latlon(-45, 0), latlon(0, 30), latlon(0, -30))
1823+
t3 = Triangle(latlon(0, -30), latlon(0, 30), latlon(45, 0))
1824+
t4 = Triangle(latlon(45, -30), latlon(45, 30), latlon(90, 0))
1825+
m1 = Multi([t1, t4])
1826+
m2 = Multi([t2, t3])
1827+
d = GeometrySet([m1, m2])
1828+
r, c = TB.apply(f, d)
1829+
@test r == GeometrySet([m2])
1830+
1831+
f = ValidCoords(Mercator)
1832+
b1 = Box(latlon(-90, -30), latlon(-30, 30))
1833+
b2 = Box(latlon(-30, -30), latlon(30, 30))
1834+
b3 = Box(latlon(30, -30), latlon(90, 30))
1835+
d = GeometrySet([b1, b2, b3])
1836+
r, c = TB.apply(f, d)
1837+
@test r == GeometrySet([b2])
1838+
1839+
# --------------
1840+
# CARTESIANGRID
1841+
# --------------
1842+
1843+
f = ValidCoords(Mercator)
1844+
d = RegularGrid(latlon(-90, -180), latlon(90, 180), dims=(3, 3))
1845+
r, c = TB.apply(f, d)
1846+
linds = LinearIndices(size(d))
1847+
@test r == view(d, [linds[2, 1], linds[2, 2], linds[2, 3]])
1848+
1849+
# ----------------
1850+
# RECTILINEARGRID
1851+
# ----------------
1852+
1853+
f = ValidCoords(Mercator)
1854+
g = RegularGrid(latlon(-90, -180), latlon(90, 180), dims=(3, 3))
1855+
d = convert(RectilinearGrid, g)
1856+
r, c = TB.apply(f, d)
1857+
linds = LinearIndices(size(d))
1858+
@test r == view(d, [linds[2, 1], linds[2, 2], linds[2, 3]])
1859+
1860+
# ---------------
1861+
# STRUCTUREDGRID
1862+
# ---------------
1863+
1864+
f = ValidCoords(Mercator)
1865+
g = RegularGrid(latlon(-90, -180), latlon(90, 180), dims=(3, 3))
1866+
d = convert(StructuredGrid, g)
1867+
r, c = TB.apply(f, d)
1868+
linds = LinearIndices(size(d))
1869+
@test r == view(d, [linds[2, 1], linds[2, 2], linds[2, 3]])
1870+
1871+
# -----------
1872+
# SIMPLEMESH
1873+
# -----------
1874+
1875+
f = ValidCoords(Mercator)
1876+
g = RegularGrid(latlon(-90, -180), latlon(90, 180), dims=(3, 3))
1877+
d = convert(SimpleMesh, g)
1878+
r, c = TB.apply(f, d)
1879+
linds = LinearIndices(size(d))
1880+
@test r == view(d, [linds[2, 1], linds[2, 2], linds[2, 3]])
1881+
end
1882+
17851883
@testitem "Shadow" setup = [Setup] begin
17861884
@test !isaffine(Shadow(:xy))
17871885
@test !TB.isrevertible(Shadow("xy"))

0 commit comments

Comments
 (0)