Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
module AdaptivelySampledDistanceFields
using StaticArrays
using RegionTrees
import RegionTrees: needs_refinement, refine_data
using Interpolations
@generated function evaluate(itp::AbstractInterpolation, point::SVector{N}) where N
Expr(:call, :itp, [:(point[$i]) for i in 1:N]...)
end
function evaluate(itp::AbstractInterpolation, point::AbstractArray)
itp(point...)
end
function evaluate(cell::Cell{D}, point::AbstractArray) where D <: AbstractInterpolation
leaf = findleaf(cell, point)
evaluate(leaf.data, leaf.boundary, point)
end
function evaluate(interp::AbstractInterpolation, boundary::HyperRectangle, point::AbstractArray)
coords = (point .- boundary.origin) ./ boundary.widths .+ 1
evaluate(interp, coords)
end
mutable struct SignedDistanceRefinery{F <: Function} <: AbstractRefinery
signed_distance_func::F
atol::Float64
rtol::Float64
end
function needs_refinement(refinery::SignedDistanceRefinery, cell::Cell)
minimum(cell.boundary.widths) > refinery.atol && needs_refinement(cell, refinery.signed_distance_func, refinery.atol, refinery.rtol)
end
function needs_refinement(cell::Cell, signed_distance_func, atol, rtol)
for c in body_and_face_centers(cell.boundary)
value_interp = evaluate(cell, c)
value_true = signed_distance_func(c)
if !isapprox(value_interp, value_true, rtol=rtol, atol=atol)
return true
end
end
false
end
function refine_data(refinery::SignedDistanceRefinery, cell::Cell, indices)
refine_data(refinery, child_boundary(cell, indices))
end
function refine_data(refinery::SignedDistanceRefinery, boundary::HyperRectangle)
interpolate!(refinery.signed_distance_func.(vertices(boundary)),
BSpline(Linear()))
end
function ASDF(signed_distance::Function, origin::AbstractArray,
widths::AbstractArray,
rtol=1e-2,
atol=1e-2)
refinery = SignedDistanceRefinery(signed_distance, atol, rtol)
boundary = HyperRectangle(origin, widths)
root = Cell(boundary, refine_data(refinery, boundary))
adaptivesampling!(root, refinery)
end
end