Skip to content

Commit f82d8cf

Browse files
Add MaxLengthDiscretization (#1068)
* Add 'MaxLengthDiscretization' * Add more methods * Update src/discretization/maxlength.jl Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Update code * Apply suggestions * Update code * Format Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Add tests --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
1 parent d3dad62 commit f82d8cf

File tree

4 files changed

+104
-2
lines changed

4 files changed

+104
-2
lines changed

src/Meshes.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,7 @@ export
506506
DelaunayTriangulation,
507507
ManualDiscretization,
508508
RegularDiscretization,
509+
MaxLengthDiscretization,
509510
discretize,
510511
discretizewithin,
511512
simplexify,

src/discretization.jl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,8 +190,6 @@ simplexify(box::Box{𝔼{2}}) = discretize(box, FanTriangulation())
190190

191191
simplexify(box::Box{𝔼{3}}) = discretize(box, ManualDiscretization())
192192

193-
simplexify(seg::Segment) = SimpleMesh(pointify(seg), GridTopology(1))
194-
195193
function simplexify(chain::Chain)
196194
np = nvertices(chain) + isclosed(chain)
197195
ip = isperiodic(chain)
@@ -263,3 +261,4 @@ include("discretization/held.jl")
263261
include("discretization/delaunay.jl")
264262
include("discretization/manual.jl")
265263
include("discretization/regular.jl")
264+
include("discretization/maxlength.jl")

src/discretization/maxlength.jl

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# ------------------------------------------------------------------
2+
# Licensed under the MIT License. See LICENSE in the project root.
3+
# ------------------------------------------------------------------
4+
5+
"""
6+
MaxLengthDiscretization(length)
7+
8+
Discretize geometries into parts with sides of maximum `length` in length units (default to meters).
9+
"""
10+
struct MaxLengthDiscretization{ℒ<:Len} <: DiscretizationMethod
11+
length::ℒ
12+
MaxLengthDiscretization(length::ℒ) where {ℒ<:Len} = new{float(ℒ)}(length)
13+
end
14+
15+
MaxLengthDiscretization(length) = MaxLengthDiscretization(addunit(length, u"m"))
16+
17+
function discretize(box::Box, method::MaxLengthDiscretization)
18+
sizes = ceil.(Int, _sides(box) ./ method.length)
19+
discretize(box, RegularDiscretization(sizes))
20+
end
21+
22+
function discretize(segment::Segment, method::MaxLengthDiscretization)
23+
size = ceil(Int, _measure(segment) / method.length)
24+
discretize(segment, RegularDiscretization(size))
25+
end
26+
27+
discretize(chain::Chain, method::MaxLengthDiscretization) =
28+
mapreduce(s -> discretize(s, method), merge, segments(chain))
29+
30+
# -----------------
31+
# HELPER FUNCTIONS
32+
# -----------------
33+
34+
_sides(box::Box{<:𝔼}) = sides(box)
35+
36+
function _sides(box::Box{<:🌐})
37+
A, B = extrema(box)
38+
a = convert(LatLon, coords(A))
39+
b = convert(LatLon, coords(B))
40+
P = withcrs(box, (a.lat, b.lon), LatLon)
41+
42+
AP = Segment(A, P)
43+
PB = Segment(P, B)
44+
(_measure(AP), _measure(PB))
45+
end
46+
47+
_measure(segment::Segment{<:𝔼}) = measure(segment)
48+
49+
# TODO: Haversine returns the shortest distance between two points
50+
# this is not always equal to the distance between two directed points
51+
function _measure(segment::Segment{<:🌐})
52+
T = numtype(lentype(segment))
53+
🌎 = ellipsoid(datum(crs(segment)))
54+
r = numconvert(T, majoraxis(🌎))
55+
56+
A, B = extrema(segment)
57+
evaluate(Haversine(r), A, B)
58+
end

test/discretization.jl

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,50 @@ end
425425
@test all(intersects(poly), mesh)
426426
end
427427

428+
@testitem "MaxLengthDiscretization" setup = [Setup] begin
429+
box = Box(cart(0, 0), cart(10, 10))
430+
mesh = discretize(box, MaxLengthDiscretization(T(1)))
431+
@test nvertices(mesh) == 11 * 11
432+
@test nelements(mesh) == 10 * 10
433+
@test eltype(mesh) <: Quadrangle
434+
@test nvertices.(mesh) [4]
435+
436+
box = Box(latlon(0, 0), latlon(45, 45))
437+
mesh = discretize(box, MaxLengthDiscretization(T(1e5)))
438+
@test nvertices(mesh) == 52 * 52
439+
@test nelements(mesh) == 51 * 51
440+
@test eltype(mesh) <: Quadrangle
441+
@test nvertices.(mesh) [4]
442+
443+
seg = Segment(cart(0, 0), cart(0, 1))
444+
mesh = discretize(seg, MaxLengthDiscretization(T(0.1)))
445+
@test nvertices(mesh) == 11
446+
@test nelements(mesh) == 10
447+
@test eltype(mesh) <: Segment
448+
@test nvertices.(mesh) [2]
449+
450+
seg = Segment(latlon(0, 0), latlon(0, 45))
451+
mesh = discretize(seg, MaxLengthDiscretization(T(1e5)))
452+
@test nvertices(mesh) == 52
453+
@test nelements(mesh) == 51
454+
@test eltype(mesh) <: Segment
455+
@test nvertices.(mesh) [2]
456+
457+
rope = Rope(cart(0, 0), cart(1, 0), cart(0, 1))
458+
mesh = discretize(rope, MaxLengthDiscretization(T(0.1)))
459+
@test nvertices(mesh) == 27
460+
@test nelements(mesh) == 25
461+
@test eltype(mesh) <: Segment
462+
@test nvertices.(mesh) [2]
463+
464+
ring = Ring(latlon(-45, 90), latlon(45, 90), latlon(45, -90), latlon(-45, -90))
465+
mesh = discretize(ring, MaxLengthDiscretization(T(1e5)))
466+
@test nvertices(mesh) == 408
467+
@test nelements(mesh) == 404
468+
@test eltype(mesh) <: Segment
469+
@test nvertices.(mesh) [2]
470+
end
471+
428472
@testitem "Discretize" setup = [Setup] begin
429473
ball = Ball(cart(0, 0), T(1))
430474
mesh = discretize(ball)

0 commit comments

Comments
 (0)